From 0843e2211c3ede602e1e4e1ee9fd9db8c96f299b Mon Sep 17 00:00:00 2001
From: Philip Rebohle <philip.rebohle@tu-dortmund.de>
Date: Tue, 18 Sep 2018 10:16:23 +0200
Subject: [PATCH] [dxvk] Add new DxvkShaderKey to represent unique shader key

---
 src/dxvk/dxvk_shader.h       |  1 +
 src/dxvk/dxvk_shader_key.cpp | 51 ++++++++++++++++++++++++++++
 src/dxvk/dxvk_shader_key.h   | 65 ++++++++++++++++++++++++++++++++++++
 src/dxvk/meson.build         |  1 +
 4 files changed, 118 insertions(+)
 create mode 100644 src/dxvk/dxvk_shader_key.cpp
 create mode 100644 src/dxvk/dxvk_shader_key.h

diff --git a/src/dxvk/dxvk_shader.h b/src/dxvk/dxvk_shader.h
index 03b92abda..d05f9e759 100644
--- a/src/dxvk/dxvk_shader.h
+++ b/src/dxvk/dxvk_shader.h
@@ -5,6 +5,7 @@
 #include "dxvk_include.h"
 #include "dxvk_limits.h"
 #include "dxvk_pipelayout.h"
+#include "dxvk_shader_key.h"
 
 #include "../spirv/spirv_code_buffer.h"
 
diff --git a/src/dxvk/dxvk_shader_key.cpp b/src/dxvk/dxvk_shader_key.cpp
new file mode 100644
index 000000000..013cf7fb8
--- /dev/null
+++ b/src/dxvk/dxvk_shader_key.cpp
@@ -0,0 +1,51 @@
+#include "dxvk_shader_key.h"
+
+namespace dxvk {
+
+  DxvkShaderKey::DxvkShaderKey()
+  : m_type(0),
+    m_sha1(Sha1Hash::compute(nullptr, 0)) { }
+
+
+  DxvkShaderKey::DxvkShaderKey(
+          VkShaderStageFlagBits shaderStage,
+    const void*                 sourceCode,
+          size_t                sourceSize)
+  : m_type(shaderStage),
+    m_sha1(Sha1Hash::compute(reinterpret_cast<const uint8_t*>(sourceCode), sourceSize)) { }
+  
+
+  std::string DxvkShaderKey::toString() const {
+    const char* prefix = nullptr;
+
+    switch (m_type) {
+      case VK_SHADER_STAGE_VERTEX_BIT:                  prefix = "VS_";  break;
+      case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:    prefix = "TCS_"; break;
+      case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: prefix = "TES_"; break;
+      case VK_SHADER_STAGE_GEOMETRY_BIT:                prefix = "GS_";  break;
+      case VK_SHADER_STAGE_FRAGMENT_BIT:                prefix = "FS_";  break;
+      case VK_SHADER_STAGE_COMPUTE_BIT:                 prefix = "CS_";  break;
+      default:                                          prefix = "";
+    }
+
+    return str::format(prefix, m_sha1.toString());
+  }
+
+  
+  size_t DxvkShaderKey::hash() const {
+    DxvkHashState result;
+    result.add(uint32_t(m_type));
+    
+    for (uint32_t i = 0; i < 5; i++)
+      result.add(m_sha1.dword(i));
+    
+    return result;
+  }
+
+
+  bool DxvkShaderKey::eq(const DxvkShaderKey& key) const {
+    return m_type == key.m_type
+        && m_sha1 == key.m_sha1;
+  }
+
+}
\ No newline at end of file
diff --git a/src/dxvk/dxvk_shader_key.h b/src/dxvk/dxvk_shader_key.h
new file mode 100644
index 000000000..657438f4c
--- /dev/null
+++ b/src/dxvk/dxvk_shader_key.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include "dxvk_hash.h"
+#include "dxvk_include.h"
+
+namespace dxvk {
+
+  /**
+   * \brief Shader key
+   * 
+   * Provides a unique key that can be used
+   * to look up a specific shader within a
+   * structure. This consists of the shader
+   * stage and the source hash, which should
+   * be generated from the original code.
+   */
+  class DxvkShaderKey {
+
+  public:
+
+    /**
+     * \brief Creates default shader key
+     */
+    DxvkShaderKey();
+
+    /**
+     * \brief Creates shader key
+     * 
+     * \param [in] shaderStage Shader stage
+     * \param [in] sourceCode Shader source
+     * \param [in] sourceSize Source length
+     */
+    DxvkShaderKey(
+            VkShaderStageFlagBits shaderStage,
+      const void*                 sourceCode,
+            size_t                sourceSize);
+    
+    /**
+     * \brief Generates string from shader key
+     * \returns String representation of the key
+     */
+    std::string toString() const;
+    
+    /**
+     * \brief Computes lookup hash
+     * \returns Lookup hash
+     */
+    size_t hash() const;
+
+    /**
+     * \brief Checks whether two keys are equal
+     * 
+     * \param [in] key The shader key to compare to
+     * \returns \c true if the two keys are equal
+     */
+    bool eq(const DxvkShaderKey& key) const;
+    
+  private:
+
+    VkShaderStageFlags  m_type;
+    Sha1Hash            m_sha1;
+
+  };
+
+}
\ No newline at end of file
diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build
index 5be8beaab..e64fe748b 100644
--- a/src/dxvk/meson.build
+++ b/src/dxvk/meson.build
@@ -70,6 +70,7 @@ dxvk_src = files([
   'dxvk_resource.cpp',
   'dxvk_sampler.cpp',
   'dxvk_shader.cpp',
+  'dxvk_shader_key.cpp',
   'dxvk_spec_const.cpp',
   'dxvk_staging.cpp',
   'dxvk_stats.cpp',