From fe02c5d6b9505c443d6f22006937aca932d5b77c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 10 Jan 2018 13:44:04 +0100 Subject: [PATCH] [dxvk] Implementing unbound resource handling (3/4) The shader compiler will now generate specialization constants for shader resources, uniform access views, and constant buffers. --- src/dxbc/dxbc_compiler.cpp | 81 +++++++++++++++++++++++++----------- src/dxbc/dxbc_compiler.h | 1 + src/dxbc/dxbc_decoder.h | 7 +++- src/dxvk/dxvk_context.cpp | 2 +- src/dxvk/dxvk_pipelayout.cpp | 5 ++- src/dxvk/dxvk_shader.cpp | 3 +- src/spirv/spirv_module.cpp | 26 ++++++++++++ src/spirv/spirv_module.h | 7 ++++ 8 files changed, 101 insertions(+), 31 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 8abefb37f..83a2334b4 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -536,9 +536,6 @@ namespace dxvk { 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. const uint32_t bindingId = computeResourceSlotId( @@ -548,6 +545,19 @@ namespace dxvk { m_module.decorateDescriptorSet(varId, 0); m_module.decorateBinding(varId, bindingId); + // Declare a specialization constant which will + // store whether or not the resource is bound. + const uint32_t specConstId = m_module.specConstBool(true); + m_module.decorateSpecId(specConstId, bindingId); + m_module.setDebugName(specConstId, + str::format("cb", bufferId, "_bound").c_str()); + + DxbcConstantBuffer buf; + buf.varId = varId; + buf.specId = specConstId; + buf.size = elementCount; + m_constantBuffers.at(bufferId) = buf; + // Store descriptor info for the shader interface DxvkResourceSlot resource; resource.slot = bindingId; @@ -683,11 +693,30 @@ namespace dxvk { m_module.setDebugName(varId, str::format(isUav ? "u" : "t", registerId).c_str()); + // Compute the DXVK binding slot index for the resource. + // D3D11 needs to bind the actual resource to this slot. + const uint32_t bindingId = computeResourceSlotId( + m_version.type(), isUav + ? DxbcBindingType::UnorderedAccessView + : DxbcBindingType::ShaderResource, + registerId); + + m_module.decorateDescriptorSet(varId, 0); + m_module.decorateBinding(varId, bindingId); + + // Declare a specialization constant which will + // store whether or not the resource is bound. + const uint32_t specConstId = m_module.specConstBool(true); + m_module.decorateSpecId(specConstId, bindingId); + m_module.setDebugName(specConstId, + str::format(isUav ? "u" : "t", registerId, "_bound").c_str()); + if (isUav) { DxbcUav uav; uav.type = DxbcResourceType::Typed; uav.imageInfo = typeInfo; uav.varId = varId; + uav.specId = specConstId; uav.sampledType = sampledType; uav.sampledTypeId = sampledTypeId; uav.imageTypeId = imageTypeId; @@ -698,6 +727,7 @@ namespace dxvk { res.type = DxbcResourceType::Typed; res.imageInfo = typeInfo; res.varId = varId; + res.specId = specConstId; res.sampledType = sampledType; res.sampledTypeId = sampledTypeId; res.imageTypeId = imageTypeId; @@ -711,17 +741,6 @@ namespace dxvk { res.structStride = 0; } - // Compute the DXVK binding slot index for the resource. - // D3D11 needs to bind the actual resource to this slot. - const uint32_t bindingId = computeResourceSlotId( - m_version.type(), isUav - ? DxbcBindingType::UnorderedAccessView - : DxbcBindingType::ShaderResource, - registerId); - - m_module.decorateDescriptorSet(varId, 0); - m_module.decorateBinding(varId, bindingId); - // Store descriptor info for the shader interface DxvkResourceSlot resource; resource.slot = bindingId; @@ -785,11 +804,29 @@ namespace dxvk { ? ins.imm[0].u32 : 0; + // Compute the DXVK binding slot index for the resource. + const uint32_t bindingId = computeResourceSlotId( + m_version.type(), isUav + ? DxbcBindingType::UnorderedAccessView + : DxbcBindingType::ShaderResource, + registerId); + + m_module.decorateDescriptorSet(varId, 0); + m_module.decorateBinding(varId, bindingId); + + // Declare a specialization constant which will + // store whether or not the resource is bound. + const uint32_t specConstId = m_module.specConstBool(true); + m_module.decorateSpecId(specConstId, bindingId); + m_module.setDebugName(specConstId, + str::format(isUav ? "u" : "t", registerId, "_bound").c_str()); + if (isUav) { DxbcUav uav; uav.type = resType; uav.imageInfo = typeInfo; uav.varId = varId; + uav.specId = specConstId; uav.sampledType = sampledType; uav.sampledTypeId = sampledTypeId; uav.imageTypeId = resTypeId; @@ -800,6 +837,7 @@ namespace dxvk { res.type = resType; res.imageInfo = typeInfo; res.varId = varId; + res.specId = specConstId; res.sampledType = sampledType; res.sampledTypeId = sampledTypeId; res.imageTypeId = resTypeId; @@ -809,16 +847,6 @@ namespace dxvk { m_textures.at(registerId) = res; } - // Compute the DXVK binding slot index for the resource. - const uint32_t bindingId = computeResourceSlotId( - m_version.type(), isUav - ? DxbcBindingType::UnorderedAccessView - : DxbcBindingType::ShaderResource, - registerId); - - m_module.decorateDescriptorSet(varId, 0); - m_module.decorateBinding(varId, bindingId); - // Store descriptor info for the shader interface DxvkResourceSlot resource; resource.slot = bindingId; @@ -1873,7 +1901,7 @@ namespace dxvk { emitRegisterStore(ins.dst[0], result); } - + void DxbcCompiler::emitBufferLoad(const DxbcShaderInstruction& ins) { // ld_raw takes three arguments: // (dst0) Destination register @@ -4263,6 +4291,7 @@ namespace dxvk { result.type = m_textures.at(registerId).type; result.typeId = m_textures.at(registerId).imageTypeId; result.varId = m_textures.at(registerId).varId; + result.specId = m_textures.at(registerId).specId; result.stride = m_textures.at(registerId).structStride; return result; } break; @@ -4273,6 +4302,7 @@ namespace dxvk { result.type = m_uavs.at(registerId).type; result.typeId = m_uavs.at(registerId).imageTypeId; result.varId = m_uavs.at(registerId).varId; + result.specId = m_uavs.at(registerId).specId; result.stride = m_uavs.at(registerId).structStride; return result; } break; @@ -4285,6 +4315,7 @@ namespace dxvk { getScalarTypeId(DxbcScalarType::Uint32), spv::StorageClassWorkgroup); result.varId = m_gRegs.at(registerId).varId; + result.specId = 0; result.stride = m_gRegs.at(registerId).elementStride; return result; } break; diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 83ad64f94..426f7de1f 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -198,6 +198,7 @@ namespace dxvk { DxbcResourceType type; uint32_t typeId; uint32_t varId; + uint32_t specId; uint32_t stride; }; diff --git a/src/dxbc/dxbc_decoder.h b/src/dxbc/dxbc_decoder.h index 389186630..dffc87f4c 100644 --- a/src/dxbc/dxbc_decoder.h +++ b/src/dxbc/dxbc_decoder.h @@ -35,8 +35,9 @@ namespace dxvk { * access a constant buffer. */ struct DxbcConstantBuffer { - uint32_t varId = 0; - uint32_t size = 0; + uint32_t varId = 0; + uint32_t specId = 0; + uint32_t size = 0; }; /** @@ -72,6 +73,7 @@ namespace dxvk { DxbcResourceType type = DxbcResourceType::Typed; DxbcImageInfo imageInfo; uint32_t varId = 0; + uint32_t specId = 0; DxbcScalarType sampledType = DxbcScalarType::Float32; uint32_t sampledTypeId = 0; uint32_t imageTypeId = 0; @@ -91,6 +93,7 @@ namespace dxvk { DxbcResourceType type = DxbcResourceType::Typed; DxbcImageInfo imageInfo; uint32_t varId = 0; + uint32_t specId = 0; DxbcScalarType sampledType = DxbcScalarType::Float32; uint32_t sampledTypeId = 0; uint32_t imageTypeId = 0; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index d12489a10..022884bcc 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1094,7 +1094,7 @@ namespace dxvk { case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: - if (res.imageView != nullptr && res.imageView->type() != binding.view) { + if (res.imageView != nullptr && res.imageView->type() == binding.view) { updatePipelineState |= bs.setBound(i); m_descriptors[i].image.sampler = VK_NULL_HANDLE; diff --git a/src/dxvk/dxvk_pipelayout.cpp b/src/dxvk/dxvk_pipelayout.cpp index 080b2e726..d766a12bb 100644 --- a/src/dxvk/dxvk_pipelayout.cpp +++ b/src/dxvk/dxvk_pipelayout.cpp @@ -48,8 +48,9 @@ namespace dxvk { : m_vkd(vkd) { m_bindingSlots.resize(bindingCount); - std::memcpy(m_bindingSlots.data(), bindingInfos, - bindingCount * sizeof(DxvkDescriptorSlot)); + + for (uint32_t i = 0; i < bindingCount; i++) + m_bindingSlots[i] = bindingInfos[i]; std::vector bindings; diff --git a/src/dxvk/dxvk_shader.cpp b/src/dxvk/dxvk_shader.cpp index efe5e6096..4b5a1da05 100644 --- a/src/dxvk/dxvk_shader.cpp +++ b/src/dxvk/dxvk_shader.cpp @@ -71,7 +71,8 @@ namespace dxvk { for (auto ins : spirvCode) { if (ins.opCode() == spv::OpDecorate - && ins.arg(2) == spv::DecorationBinding) { + && ((ins.arg(2) == spv::DecorationBinding) + || (ins.arg(2) == spv::DecorationSpecId))) { const uint32_t oldBinding = ins.arg(3); const uint32_t newBinding = mapping.getBindingId(oldBinding); diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index bfe601d98..8c18e3f9c 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -238,6 +238,22 @@ namespace dxvk { m_typeConstDefs.putWord(constIds[i]); return resultId; } + + + uint32_t SpirvModule::specConstBool( + bool v) { + uint32_t typeId = this->defBoolType(); + uint32_t resultId = this->allocateId(); + + const spv::Op op = v + ? spv::OpSpecConstantTrue + : spv::OpSpecConstantFalse; + + m_typeConstDefs.putIns (op, 3); + m_typeConstDefs.putWord (typeId); + m_typeConstDefs.putWord (resultId); + return resultId; + } void SpirvModule::decorate( @@ -316,6 +332,16 @@ namespace dxvk { } + void SpirvModule::decorateSpecId( + uint32_t object, + uint32_t specId) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationSpecId); + m_annotations.putInt32(specId); + } + + void SpirvModule::memberDecorateBuiltIn( uint32_t structId, uint32_t memberId, diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index 65f490d60..d9c845e47 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -124,6 +124,9 @@ namespace dxvk { uint32_t constCount, const uint32_t* constIds); + uint32_t specConstBool( + bool v); + void decorate( uint32_t object, spv::Decoration decoration); @@ -155,6 +158,10 @@ namespace dxvk { uint32_t object, uint32_t location); + void decorateSpecId( + uint32_t object, + uint32_t specId); + void memberDecorateBuiltIn( uint32_t structId, uint32_t memberId,