From 4ae15f3edf5a1e39d11eb68220720481b0871bc1 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 26 May 2018 14:50:00 +0200 Subject: [PATCH] [dxvk] Add global specialization constant data structures Implements a unified way of defining specialization constants for graphics and compute pipelines which can be easily extended in the future. --- src/dxvk/dxvk_shader.h | 16 ++++++++ src/dxvk/dxvk_spec_const.cpp | 43 +++++++++++++++++++++ src/dxvk/dxvk_spec_const.h | 72 ++++++++++++++++++++++++++++++++++++ src/dxvk/meson.build | 1 + 4 files changed, 132 insertions(+) create mode 100644 src/dxvk/dxvk_spec_const.cpp create mode 100644 src/dxvk/dxvk_spec_const.h diff --git a/src/dxvk/dxvk_shader.h b/src/dxvk/dxvk_shader.h index fc6fb4eb..0aa092dc 100644 --- a/src/dxvk/dxvk_shader.h +++ b/src/dxvk/dxvk_shader.h @@ -11,6 +11,22 @@ namespace dxvk { class DxvkShader; + /** + * \brief Built-in specialization constants + * + * These specialization constants allow the SPIR-V + * shaders to access some pipeline state like D3D + * shaders do. They need to be filled in by the + * implementation at pipeline compilation time. + */ + enum class DxvkSpecConstantId : uint32_t { + RasterizerSampleCount = 0x10000, + + SpecConstantIdMin = RasterizerSampleCount, + SpecConstantIdMax = RasterizerSampleCount, + }; + + /** * \brief Shader interface slots * diff --git a/src/dxvk/dxvk_spec_const.cpp b/src/dxvk/dxvk_spec_const.cpp new file mode 100644 index 00000000..8d2565de --- /dev/null +++ b/src/dxvk/dxvk_spec_const.cpp @@ -0,0 +1,43 @@ +#include "dxvk_spec_const.h" + +#include + +#define SET_CONSTANT_ENTRY(specId, member) \ + this->setConstantEntry(specId, \ + offsetof(DxvkSpecConstantData, member), \ + sizeof(DxvkSpecConstantData::member)) + +namespace dxvk { + + DxvkSpecConstantMap g_specConstantMap; + + DxvkSpecConstantMap::DxvkSpecConstantMap() { + SET_CONSTANT_ENTRY(DxvkSpecConstantId::RasterizerSampleCount, rasterizerSampleCount); + + for (uint32_t i = 0; i < MaxNumActiveBindings; i++) + this->setBindingEntry(i); + } + + + void DxvkSpecConstantMap::setConstantEntry( + DxvkSpecConstantId specId, + uint32_t offset, + uint32_t size) { + VkSpecializationMapEntry entry; + entry.constantID = uint32_t(specId); + entry.offset = offset; + entry.size = size; + m_mapEntries[uint32_t(specId) - uint32_t(DxvkSpecConstantId::SpecConstantIdMin)] = entry; + } + + + void DxvkSpecConstantMap::setBindingEntry( + uint32_t binding) { + VkSpecializationMapEntry entry; + entry.constantID = binding; + entry.offset = sizeof(VkBool32) * binding + offsetof(DxvkSpecConstantData, activeBindings); + entry.size = sizeof(VkBool32); + m_mapEntries[MaxNumSpecConstants + binding] = entry; + } + +} \ No newline at end of file diff --git a/src/dxvk/dxvk_spec_const.h b/src/dxvk/dxvk_spec_const.h new file mode 100644 index 00000000..445fba9e --- /dev/null +++ b/src/dxvk/dxvk_spec_const.h @@ -0,0 +1,72 @@ +#pragma once + +#include "dxvk_limits.h" +#include "dxvk_shader.h" + +namespace dxvk { + + constexpr uint32_t MaxNumSpecConstants = 1 + + uint32_t(DxvkSpecConstantId::SpecConstantIdMax) + - uint32_t(DxvkSpecConstantId::SpecConstantIdMin); + + /** + * \brief Spec costant data + * + * The values are derived from the pipeline + * state vector so that they can be used by + * the shaders. + */ + struct DxvkSpecConstantData { + uint32_t rasterizerSampleCount; + VkBool32 activeBindings[MaxNumActiveBindings]; + }; + + + /** + * \brief Spec constant map + * + * Stores the specialization constant map. + * This can be passed to Vulkan when compiling + * both graphics and compute pipelines. + */ + class DxvkSpecConstantMap { + + public: + + DxvkSpecConstantMap(); + + /** + * \brief Map entry count + * + * \param [in] bindingCount Number of active bindings + * \returns The number of map entries to read + */ + uint32_t mapEntryCount() const { + return m_mapEntries.size(); + } + + /** + * \brief Map entry data + * \returns Map entries + */ + const VkSpecializationMapEntry* mapEntryData() const { + return m_mapEntries.data(); + } + + private: + + std::array m_mapEntries; + + void setConstantEntry( + DxvkSpecConstantId specId, + uint32_t offset, + uint32_t size); + + void setBindingEntry( + uint32_t binding); + + }; + + extern DxvkSpecConstantMap g_specConstantMap; + +} \ No newline at end of file diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build index e2a5fabf..3c21bb1b 100644 --- a/src/dxvk/meson.build +++ b/src/dxvk/meson.build @@ -61,6 +61,7 @@ dxvk_src = files([ 'dxvk_resource.cpp', 'dxvk_sampler.cpp', 'dxvk_shader.cpp', + 'dxvk_spec_const.cpp', 'dxvk_staging.cpp', 'dxvk_stats.cpp', 'dxvk_surface.cpp',