From 939faeaf273fe27493439b00c2491a6ff9cf377d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 10 Dec 2017 03:39:35 +0100 Subject: [PATCH] [dxbc] Implemented sampler declaration --- src/dxbc/dxbc_compiler.cpp | 14 ++++++++ src/dxbc/dxbc_compiler.h | 3 ++ src/dxbc/gen/dxbc_gen_common.cpp | 59 +++++++++++++++++++++++++++----- src/dxbc/gen/dxbc_gen_common.h | 19 ++++++++-- 4 files changed, 84 insertions(+), 11 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 87a5343c..9cdf98ab 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -24,6 +24,9 @@ namespace dxvk { case DxbcOpcode::DclConstantBuffer: return this->dclConstantBuffer(ins); + case DxbcOpcode::DclSampler: + return this->dclSampler(ins); + case DxbcOpcode::DclInput: case DxbcOpcode::DclInputSiv: case DxbcOpcode::DclInputSgv: @@ -90,6 +93,17 @@ namespace dxvk { } + void DxbcCompiler::dclSampler(const DxbcInstruction& ins) { + auto op = ins.operand(0); + + if (op.token().indexDimension() != 1) + throw DxvkError("DxbcCompiler::dclSampler: Invalid index dimension"); + + const uint32_t index = op.index(0).immPart(); + m_gen->dclSampler(index); + } + + void DxbcCompiler::dclInterfaceVar(const DxbcInstruction& ins) { auto op = ins.operand(0); auto opcode = ins.token().opcode(); diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index c9b75f7f..70839337 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -35,6 +35,9 @@ namespace dxvk { void dclConstantBuffer( const DxbcInstruction& ins); + void dclSampler( + const DxbcInstruction& ins); + void dclInterfaceVar( const DxbcInstruction& ins); diff --git a/src/dxbc/gen/dxbc_gen_common.cpp b/src/dxbc/gen/dxbc_gen_common.cpp index 0530b5a3..41ebe8e1 100644 --- a/src/dxbc/gen/dxbc_gen_common.cpp +++ b/src/dxbc/gen/dxbc_gen_common.cpp @@ -40,29 +40,39 @@ namespace dxvk { void DxbcCodeGen::dclConstantBuffer( uint32_t bufferId, uint32_t elementCount) { + // Uniform buffer data is stored as a fixed-size array + // of 4x32-bit vectors. SPIR-V requires explicit strides. uint32_t arrayType = m_module.defArrayTypeUnique( this->defValueType(DxbcValueType(DxbcScalarType::Float32, 4)), m_module.constu32(elementCount)); - uint32_t structType = m_module.defStructTypeUnique(1, &arrayType); - m_module.decorateArrayStride(arrayType, 16); + + // SPIR-V requires us to put that array into a + // struct and decorate that struct as a block. + uint32_t structType = m_module.defStructTypeUnique(1, &arrayType); m_module.memberDecorateOffset(structType, 0, 0); m_module.decorateBlock(structType); - uint32_t varIndex = m_module.newVar( + // Variable that we'll use to access the buffer + uint32_t varId = m_module.newVar( m_module.defPointerType(structType, spv::StorageClassUniform), spv::StorageClassUniform); + m_module.setDebugName(varId, + str::format("cb", bufferId).c_str()); + + m_constantBuffers.at(bufferId).varId = varId; + m_constantBuffers.at(bufferId).size = elementCount; + + // Compute the DXVK binding slot index for the buffer. + // D3D11 needs to bind the actual buffers to this slot. uint32_t bindingId = computeResourceSlotId(m_shaderStage, DxbcBindingType::ConstantBuffer, bufferId); - m_module.setDebugName(varIndex, str::format("cb", bufferId).c_str()); - m_module.decorateDescriptorSet(varIndex, 0); - m_module.decorateBinding(varIndex, bindingId); - m_constantBuffers.at(bufferId).varId = varIndex; - m_constantBuffers.at(bufferId).size = elementCount; + m_module.decorateDescriptorSet(varId, 0); + m_module.decorateBinding(varId, bindingId); - // TODO compute resource slot index + // Store descriptor info for the shader interface DxvkResourceSlot resource; resource.slot = bindingId; resource.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; @@ -70,6 +80,37 @@ namespace dxvk { } + void DxbcCodeGen::dclSampler(uint32_t samplerId) { + // The sampler type is opaque, but we still have to + // define a pointer and a variable in oder to use it + uint32_t samplerType = m_module.defSamplerType(); + uint32_t samplerPtrType = m_module.defPointerType( + samplerType, spv::StorageClassUniformConstant); + + // Define the sampler variable + uint32_t varId = m_module.newVar(samplerPtrType, + spv::StorageClassUniformConstant); + + m_module.setDebugName(varId, + str::format("s", samplerId).c_str()); + + m_samplers.at(samplerId).varId = varId; + + // Compute binding slot index for the sampler + uint32_t bindingId = computeResourceSlotId(m_shaderStage, + DxbcBindingType::ImageSampler, samplerId); + + m_module.decorateDescriptorSet(varId, 0); + m_module.decorateBinding(varId, bindingId); + + // Store descriptor info for the shader interface + DxvkResourceSlot resource; + resource.slot = bindingId; + resource.type = VK_DESCRIPTOR_TYPE_SAMPLER; + m_resourceSlots.push_back(resource); + } + + DxbcValue DxbcCodeGen::defConstScalar(uint32_t v) { DxbcValue result; result.type = DxbcValueType(DxbcScalarType::Uint32, 1); diff --git a/src/dxbc/gen/dxbc_gen_common.h b/src/dxbc/gen/dxbc_gen_common.h index c222f1bb..3a7db3d4 100644 --- a/src/dxbc/gen/dxbc_gen_common.h +++ b/src/dxbc/gen/dxbc_gen_common.h @@ -26,8 +26,8 @@ namespace dxvk { /** * \brief Constant buffer binding * - * Stores information about - * a constant buffer. + * Stores information required to + * access a constant buffer. */ struct DxbcConstantBuffer { uint32_t varId = 0; @@ -35,6 +35,16 @@ namespace dxvk { }; + /** + * \brief Sampler binding + * + * Stores a sampler variable. + */ + struct DxbcSampler { + uint32_t varId = 0; + }; + + /** * \brief DXBC code generator * @@ -57,6 +67,9 @@ namespace dxvk { uint32_t bufferId, uint32_t elementCount); + void dclSampler( + uint32_t samplerId); + DxbcValue defConstScalar(uint32_t v); DxbcValue defConstVector( @@ -160,6 +173,8 @@ namespace dxvk { std::vector m_rRegs; std::array m_constantBuffers; + std::array m_samplers; + std::vector m_resourceSlots; uint32_t defScalarType(