Vulkan/Debug: Add ID

vk::dbg::ID is a strongly-typed identifier backed by an int.
ID is used to prevent implicit casts between idenfitifers of different T types.

Bug: b/145351270
Change-Id: Ia51ee8cca19eaa86cab4e009340fdcf9072360e5
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/38891
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvID.hpp b/src/Pipeline/SpirvID.hpp
index aada5a8..9688a45 100644
--- a/src/Pipeline/SpirvID.hpp
+++ b/src/Pipeline/SpirvID.hpp
@@ -22,7 +22,7 @@
 {
 	// SpirvID is a strongly-typed identifier backed by a uint32_t.
 	// The template parameter T is not actually used by the implementation of
-	// ID; instead it is used to prevent implicit casts between idenfitifers of
+	// ID; instead it is used to prevent implicit casts between identifiers of
 	// different T types.
 	// IDs are typically used as a map key to value of type T.
 	template <typename T>
diff --git a/src/Vulkan/Debug/ID.hpp b/src/Vulkan/Debug/ID.hpp
new file mode 100644
index 0000000..709baf5
--- /dev/null
+++ b/src/Vulkan/Debug/ID.hpp
@@ -0,0 +1,67 @@
+// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef VK_DEBUG_ID_HPP_
+#define VK_DEBUG_ID_HPP_
+
+#include <functional>  // std::hash
+
+namespace vk
+{
+namespace dbg
+{
+
+// ID is a strongly-typed identifier backed by a int.
+// The template parameter T is not actually used by the implementation of
+// ID; instead it is used to prevent implicit casts between identifiers of
+// different T types.
+// IDs are typically used as a map key to value of type T.
+template <typename T>
+class ID
+{
+public:
+	inline ID() :
+	    id(0) {}
+	inline ID(int id) :
+	    id(id) {}
+	inline bool operator==(const ID<T>& rhs) const { return id == rhs.id; }
+	inline bool operator!=(const ID<T>& rhs) const { return id != rhs.id; }
+	inline bool operator<(const ID<T>& rhs) const { return id < rhs.id; }
+	inline ID operator++() { return ID(++id); }
+	inline ID operator++(int) { return ID(id++); }
+
+	// value returns the numerical value of the identifier.
+	inline int value() const { return id; }
+
+private:
+	int id;
+};
+
+}  // namespace dbg
+}  // namespace vk
+
+namespace std
+{
+// std::hash implementation for vk::dbg::ID<T>
+template <typename T>
+struct hash<vk::dbg::ID<T> >
+{
+	std::size_t operator()(const vk::dbg::ID<T>& id) const noexcept
+	{
+		return std::hash<int>()(id.value());
+	}
+};
+}  // namespace std
+
+#endif  // VK_DEBUG_ID_HPP_