From c0c1565cba57758da6d7503359493139720f4ecc Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Sun, 8 Aug 2021 04:52:36 +0100 Subject: [PATCH] [d3d9, dxso] Alias color and depth samplers and improve tracking Takes me from 340 -> 460fps in A Hat in Time's main menu when CPU bound. --- src/d3d9/d3d9_device.cpp | 164 +++++++++++++++---------------- src/d3d9/d3d9_device.h | 16 +-- src/d3d9/d3d9_fixed_function.cpp | 2 +- src/d3d9/d3d9_sampler.cpp | 5 +- src/d3d9/d3d9_sampler.h | 1 + src/d3d9/d3d9_spec_constants.h | 4 +- src/dxso/dxso_compiler.cpp | 83 ++++++++-------- src/dxso/dxso_compiler.h | 4 +- src/dxso/dxso_util.cpp | 33 ------- src/dxso/dxso_util.h | 23 +++-- 10 files changed, 160 insertions(+), 175 deletions(-) diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index e2e2365d..a344af5c 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -3710,6 +3710,19 @@ namespace dxvk { DWORD oldUsage = oldTexture != nullptr ? oldTexture->Desc()->Usage : 0; DWORD newUsage = newTexture != nullptr ? newTexture->Desc()->Usage : 0; + if (newTexture != nullptr) { + const bool oldDepth = m_depthTextures & (1u << StateSampler); + const bool newDepth = newTexture->IsShadow(); + + if (oldDepth != newDepth) { + m_depthTextures &= ~(1u << StateSampler); + if (newDepth) + m_depthTextures |= 1u << StateSampler; + + m_dirtySamplerStates |= 1u << StateSampler; + } + } + DWORD combinedUsage = oldUsage | newUsage; TextureChangePrivate(m_state.textures[StateSampler], pTexture); @@ -5703,6 +5716,7 @@ namespace dxvk { key.MipmapLodBias = bit::cast(state[D3DSAMP_MIPMAPLODBIAS]); key.MaxMipLevel = state[D3DSAMP_MAXMIPLEVEL]; key.BorderColor = D3DCOLOR(state[D3DSAMP_BORDERCOLOR]); + key.Depth = m_depthTextures & (1u << Sampler); if (m_d3d9Options.samplerAnisotropy != -1) { if (key.MagFilter == D3DTEXF_LINEAR) @@ -5718,75 +5732,59 @@ namespace dxvk { auto samplerInfo = RemapStateSamplerShader(Sampler); - const uint32_t colorSlot = computeResourceSlotId( - samplerInfo.first, DxsoBindingType::ColorImage, - samplerInfo.second); - - const uint32_t depthSlot = computeResourceSlotId( - samplerInfo.first, DxsoBindingType::DepthImage, + const uint32_t slot = computeResourceSlotId( + samplerInfo.first, DxsoBindingType::Image, samplerInfo.second); EmitCs([this, - cColorSlot = colorSlot, - cDepthSlot = depthSlot, - cKey = key + cSlot = slot, + cKey = key ] (DxvkContext* ctx) { auto pair = m_samplers.find(cKey); if (pair != m_samplers.end()) { - ctx->bindResourceSampler(cColorSlot, pair->second.color); - ctx->bindResourceSampler(cDepthSlot, pair->second.depth); + ctx->bindResourceSampler(cSlot, pair->second); return; } auto mipFilter = DecodeMipFilter(cKey.MipFilter); - DxvkSamplerCreateInfo colorInfo; - colorInfo.addressModeU = DecodeAddressMode(cKey.AddressU); - colorInfo.addressModeV = DecodeAddressMode(cKey.AddressV); - colorInfo.addressModeW = DecodeAddressMode(cKey.AddressW); - colorInfo.compareToDepth = VK_FALSE; - colorInfo.compareOp = VK_COMPARE_OP_NEVER; - colorInfo.magFilter = DecodeFilter(cKey.MagFilter); - colorInfo.minFilter = DecodeFilter(cKey.MinFilter); - colorInfo.mipmapMode = mipFilter.MipFilter; - colorInfo.maxAnisotropy = float(cKey.MaxAnisotropy); - colorInfo.useAnisotropy = cKey.MaxAnisotropy > 1; - colorInfo.mipmapLodBias = cKey.MipmapLodBias; - colorInfo.mipmapLodMin = mipFilter.MipsEnabled ? float(cKey.MaxMipLevel) : 0; - colorInfo.mipmapLodMax = mipFilter.MipsEnabled ? FLT_MAX : 0; - colorInfo.usePixelCoord = VK_FALSE; + DxvkSamplerCreateInfo info; + info.addressModeU = DecodeAddressMode(cKey.AddressU); + info.addressModeV = DecodeAddressMode(cKey.AddressV); + info.addressModeW = DecodeAddressMode(cKey.AddressW); + info.compareToDepth = cKey.Depth; + info.compareOp = cKey.Depth ? VK_COMPARE_OP_LESS_OR_EQUAL : VK_COMPARE_OP_NEVER; + info.magFilter = DecodeFilter(cKey.MagFilter); + info.minFilter = DecodeFilter(cKey.MinFilter); + info.mipmapMode = mipFilter.MipFilter; + info.maxAnisotropy = float(cKey.MaxAnisotropy); + info.useAnisotropy = cKey.MaxAnisotropy > 1; + info.mipmapLodBias = cKey.MipmapLodBias; + info.mipmapLodMin = mipFilter.MipsEnabled ? float(cKey.MaxMipLevel) : 0; + info.mipmapLodMax = mipFilter.MipsEnabled ? FLT_MAX : 0; + info.usePixelCoord = VK_FALSE; - DecodeD3DCOLOR(cKey.BorderColor, colorInfo.borderColor.float32); + DecodeD3DCOLOR(cKey.BorderColor, info.borderColor.float32); if (!m_dxvkDevice->features().extCustomBorderColor.customBorderColorWithoutFormat) { // HACK: Let's get OPAQUE_WHITE border color over // TRANSPARENT_BLACK if the border RGB is white. - if (colorInfo.borderColor.float32[0] == 1.0f - && colorInfo.borderColor.float32[1] == 1.0f - && colorInfo.borderColor.float32[2] == 1.0f + if (info.borderColor.float32[0] == 1.0f + && info.borderColor.float32[1] == 1.0f + && info.borderColor.float32[2] == 1.0f && !m_dxvkDevice->features().extCustomBorderColor.customBorderColors) { // Then set the alpha to 1. - colorInfo.borderColor.float32[3] = 1.0f; + info.borderColor.float32[3] = 1.0f; } } - DxvkSamplerCreateInfo depthInfo = colorInfo; - depthInfo.compareToDepth = VK_TRUE; - depthInfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL; - depthInfo.magFilter = VK_FILTER_LINEAR; - depthInfo.minFilter = VK_FILTER_LINEAR; - try { - D3D9SamplerPair pair; + auto sampler = m_dxvkDevice->createSampler(info); - pair.color = m_dxvkDevice->createSampler(colorInfo); - pair.depth = m_dxvkDevice->createSampler(depthInfo); + m_samplers.insert(std::make_pair(cKey, sampler)); + ctx->bindResourceSampler(cSlot, std::move(sampler)); m_samplerCount++; - - m_samplers.insert(std::make_pair(cKey, pair)); - ctx->bindResourceSampler(cColorSlot, pair.color); - ctx->bindResourceSampler(cDepthSlot, pair.depth); } catch (const DxvkError& e) { Logger::err(e.message()); @@ -5798,11 +5796,8 @@ namespace dxvk { void D3D9DeviceEx::BindTexture(DWORD StateSampler) { auto shaderSampler = RemapStateSamplerShader(StateSampler); - uint32_t colorSlot = computeResourceSlotId(shaderSampler.first, - DxsoBindingType::ColorImage, uint32_t(shaderSampler.second)); - - uint32_t depthSlot = computeResourceSlotId(shaderSampler.first, - DxsoBindingType::DepthImage, uint32_t(shaderSampler.second)); + uint32_t slot = computeResourceSlotId(shaderSampler.first, + DxsoBindingType::Image, uint32_t(shaderSampler.second)); const bool srgb = m_state.samplerStates[StateSampler][D3DSAMP_SRGBTEXTURE] & 0x1; @@ -5829,31 +5824,26 @@ namespace dxvk { if (commonTex != nullptr) { EmitCs([ - cColorSlot = colorSlot, - cDepthSlot = depthSlot, - cDepth = commonTex->IsShadow(), + cSlot = slot, cImageView = commonTex->GetSampleView(srgb) ](DxvkContext* ctx) { - ctx->bindResourceView(cColorSlot, !cDepth ? cImageView : nullptr, nullptr); - ctx->bindResourceView(cDepthSlot, cDepth ? cImageView : nullptr, nullptr); + ctx->bindResourceView(cSlot, cImageView, nullptr); }); } else { EmitCs([ - cColorSlot = colorSlot, - cDepthSlot = depthSlot + cSlot = slot ](DxvkContext* ctx) { - ctx->bindResourceView(cColorSlot, nullptr, nullptr); - ctx->bindResourceView(cDepthSlot, nullptr, nullptr); + ctx->bindResourceView(cSlot, nullptr, nullptr); }); } } - void D3D9DeviceEx::UndirtySamplers() { - for (uint32_t dirty = m_dirtySamplerStates; dirty; dirty &= dirty - 1) + void D3D9DeviceEx::UndirtySamplers(uint32_t mask) { + for (uint32_t dirty = mask; dirty; dirty &= dirty - 1) BindSampler(bit::tzcnt(dirty)); - m_dirtySamplerStates = 0; + m_dirtySamplerStates &= ~mask; } @@ -5914,15 +5904,13 @@ namespace dxvk { FlushBuffer(vbo); } - uint32_t texturesToUpload = m_activeTexturesToUpload; - texturesToUpload &= m_psShaderMasks.samplerMask | m_vsShaderMasks.samplerMask; + const uint32_t usedSamplerMask = m_activeTextures & (m_psShaderMasks.samplerMask | m_vsShaderMasks.samplerMask); + const uint32_t texturesToUpload = m_activeTexturesToUpload & usedSamplerMask; if (unlikely(texturesToUpload != 0)) UploadManagedTextures(texturesToUpload); - uint32_t texturesToGen = m_activeTexturesToGen; - texturesToGen &= m_psShaderMasks.samplerMask | m_vsShaderMasks.samplerMask; - + const uint32_t texturesToGen = m_activeTexturesToGen & usedSamplerMask; if (unlikely(texturesToGen != 0)) GenerateTextureMips(texturesToGen); @@ -5938,8 +5926,9 @@ namespace dxvk { if (m_flags.test(D3D9DeviceFlag::DirtyViewportScissor)) BindViewportAndScissor(); - if (m_dirtySamplerStates) - UndirtySamplers(); + const uint32_t activeDirtySamplers = m_dirtySamplerStates & usedSamplerMask; + if (activeDirtySamplers) + UndirtySamplers(activeDirtySamplers); if (m_dirtyTextures) UndirtyTextures(); @@ -6030,6 +6019,10 @@ namespace dxvk { UpdateFixedFunctionPS(); } + const uint32_t depthTextureMask = m_depthTextures & usedSamplerMask; + if (depthTextureMask != m_lastSamplerDepthMode) + UpdateSamplerDepthModeSpecConstant(depthTextureMask); + if (m_flags.test(D3D9DeviceFlag::DirtySharedPixelShaderData)) { m_flags.clr(D3D9DeviceFlag::DirtySharedPixelShaderData); @@ -6720,6 +6713,15 @@ namespace dxvk { } + void D3D9DeviceEx::UpdateSamplerDepthModeSpecConstant(uint32_t value) { + EmitCs([cBitfield = value](DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::SamplerDepthMode, cBitfield); + }); + + m_lastSamplerDepthMode = value; + } + + void D3D9DeviceEx::ApplyPrimitiveType( DxvkContext* pContext, D3DPRIMITIVETYPE PrimType) { @@ -7036,24 +7038,21 @@ namespace dxvk { for (uint32_t i = 0; i < caps::MaxStreams; i++) m_state.streamFreq[i] = 1; - for (uint32_t i = 0; i < m_state.textures.size(); i++) { + for (uint32_t i = 0; i < m_state.textures.size(); i++) TextureChangePrivate(m_state.textures[i], nullptr); - DWORD sampler = i; - auto samplerInfo = RemapStateSamplerShader(sampler); - uint32_t colorSlot = computeResourceSlotId(samplerInfo.first, DxsoBindingType::ColorImage, uint32_t(samplerInfo.second)); - uint32_t depthSlot = computeResourceSlotId(samplerInfo.first, DxsoBindingType::DepthImage, uint32_t(samplerInfo.second)); - - EmitCs([ - cColorSlot = colorSlot, - cDepthSlot = depthSlot - ](DxvkContext* ctx) { - ctx->bindResourceView(cColorSlot, nullptr, nullptr); - ctx->bindResourceView(cDepthSlot, nullptr, nullptr); - }); - } + EmitCs([ + cSize = m_state.textures.size() + ](DxvkContext* ctx) { + for (uint32_t i = 0; i < cSize; i++) { + auto samplerInfo = RemapStateSamplerShader(DWORD(i)); + uint32_t slot = computeResourceSlotId(samplerInfo.first, DxsoBindingType::Image, uint32_t(samplerInfo.second)); + ctx->bindResourceView(slot, nullptr, nullptr); + } + }); m_dirtyTextures = 0; + m_depthTextures = 0; auto& ss = m_state.samplerStates; for (uint32_t i = 0; i < ss.size(); i++) { @@ -7088,6 +7087,7 @@ namespace dxvk { UpdateSamplerSpecConsant(0u); UpdateBoolSpecConstantVertex(0u); UpdateBoolSpecConstantPixel(0u); + UpdateSamplerDepthModeSpecConstant(0u); return D3D_OK; } diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h index 3d5a741e..7dc5a386 100644 --- a/src/d3d9/d3d9_device.h +++ b/src/d3d9/d3d9_device.h @@ -82,11 +82,6 @@ namespace dxvk { uint32_t instanceCount; }; - struct D3D9SamplerPair { - Rc color; - Rc depth; - }; - struct D3D9BufferSlice { DxvkBufferSlice slice = {}; void* mapPtr = nullptr; @@ -840,7 +835,7 @@ namespace dxvk { void BindTexture(DWORD SamplerSampler); - void UndirtySamplers(); + void UndirtySamplers(uint32_t mask); void UndirtyTextures(); @@ -926,6 +921,9 @@ namespace dxvk { D3D9DeviceFlags m_flags; uint32_t m_dirtySamplerStates = 0; uint32_t m_dirtyTextures = 0; + // Last state of depth textures. Doesn't update when NULL is bound. + // & with m_activeTextures to normalize. + uint32_t m_depthTextures = 0; D3D9Adapter* m_adapter; Rc m_dxvkDevice; @@ -1024,7 +1022,7 @@ namespace dxvk { std::unordered_map< D3D9SamplerKey, - D3D9SamplerPair, + Rc, D3D9SamplerKeyHash, D3D9SamplerKeyEq> m_samplers; @@ -1063,6 +1061,8 @@ namespace dxvk { uint32_t m_activeHazardsDS = 0; uint32_t m_lastHazardsDS = 0; + uint32_t m_lastSamplerDepthMode = 0; + D3D9ShaderMasks m_vsShaderMasks = D3D9ShaderMasks(); D3D9ShaderMasks m_psShaderMasks = FixedFunctionMask; @@ -1241,6 +1241,8 @@ namespace dxvk { void UpdateFetch4SpecConstant(uint32_t value); + void UpdateSamplerDepthModeSpecConstant(uint32_t value); + }; } diff --git a/src/d3d9/d3d9_fixed_function.cpp b/src/d3d9/d3d9_fixed_function.cpp index be71b9c6..e6cd68f3 100644 --- a/src/d3d9/d3d9_fixed_function.cpp +++ b/src/d3d9/d3d9_fixed_function.cpp @@ -2092,7 +2092,7 @@ namespace dxvk { m_module.setDebugName(sampler.varId, name.c_str()); const uint32_t bindingId = computeResourceSlotId(DxsoProgramType::PixelShader, - DxsoBindingType::ColorImage, i); + DxsoBindingType::Image, i); sampler.bound = m_module.specConstBool(true); m_module.decorateSpecId(sampler.bound, bindingId); diff --git a/src/d3d9/d3d9_sampler.cpp b/src/d3d9/d3d9_sampler.cpp index cc16ed46..6a68f220 100644 --- a/src/d3d9/d3d9_sampler.cpp +++ b/src/d3d9/d3d9_sampler.cpp @@ -9,6 +9,7 @@ namespace dxvk { std::hash tahash; std::hash tfhash; std::hash fhash; + std::hash bhash; state.add(tahash(key.AddressU)); state.add(tahash(key.AddressV)); @@ -20,6 +21,7 @@ namespace dxvk { state.add(fhash (key.MipmapLodBias)); state.add(dhash (key.MaxMipLevel)); state.add(dhash (key.BorderColor)); + state.add(bhash (key.Depth)); return state; } @@ -35,7 +37,8 @@ namespace dxvk { && a.MaxAnisotropy == b.MaxAnisotropy && a.MipmapLodBias == b.MipmapLodBias && a.MaxMipLevel == b.MaxMipLevel - && a.BorderColor == b.BorderColor; + && a.BorderColor == b.BorderColor + && a.Depth == b.Depth; } } \ No newline at end of file diff --git a/src/d3d9/d3d9_sampler.h b/src/d3d9/d3d9_sampler.h index a6d0a4a6..44471094 100644 --- a/src/d3d9/d3d9_sampler.h +++ b/src/d3d9/d3d9_sampler.h @@ -21,6 +21,7 @@ namespace dxvk { float MipmapLodBias; DWORD MaxMipLevel; D3DCOLOR BorderColor; + bool Depth; }; struct D3D9SamplerKeyHash { diff --git a/src/d3d9/d3d9_spec_constants.h b/src/d3d9/d3d9_spec_constants.h index 106b78f7..7a8a33d5 100644 --- a/src/d3d9/d3d9_spec_constants.h +++ b/src/d3d9/d3d9_spec_constants.h @@ -16,7 +16,9 @@ namespace dxvk { VertexShaderBools = 7, PixelShaderBools = 8, - Fetch4 = 9 + Fetch4 = 9, + + SamplerDepthMode = 10, }; } \ No newline at end of file diff --git a/src/dxso/dxso_compiler.cpp b/src/dxso/dxso_compiler.cpp index 758a5f7a..f656ce6e 100644 --- a/src/dxso/dxso_compiler.cpp +++ b/src/dxso/dxso_compiler.cpp @@ -362,6 +362,10 @@ namespace dxvk { ? D3D9SpecConstantId::VertexShaderBools : D3D9SpecConstantId::PixelShaderBools)); m_module.setDebugName(m_boolSpecConstant, "boolConstants"); + + m_depthSpecConstant = m_module.specConst32(m_module.defIntType(32, 0), 0); + m_module.decorateSpecId(m_depthSpecConstant, getSpecId(D3D9SpecConstantId::SamplerDepthMode)); + m_module.setDebugName(m_depthSpecConstant, "depthSamplers"); } @@ -683,8 +687,11 @@ namespace dxvk { DxsoTextureType type) { m_usedSamplers |= (1u << idx); - auto DclSampler = [this]( + VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + + auto DclSampler = [this, &viewType]( uint32_t idx, + uint32_t bindingId, DxsoSamplerType type, bool depth, bool implicit) { @@ -694,7 +701,6 @@ namespace dxvk { : m_samplers[idx].depth[type]; spv::Dim dimensionality; - VkImageViewType viewType; const char* suffix = "_2d"; @@ -736,31 +742,25 @@ namespace dxvk { std::string name = str::format("s", idx, suffix, depth ? "_shadow" : ""); m_module.setDebugName(sampler.varId, name.c_str()); - const uint32_t bindingId = computeResourceSlotId(m_programInfo.type(), - !depth ? DxsoBindingType::ColorImage : DxsoBindingType::DepthImage, - idx); - m_module.decorateDescriptorSet(sampler.varId, 0); m_module.decorateBinding (sampler.varId, bindingId); - - // Store descriptor info for the shader interface - DxvkResourceSlot resource; - resource.slot = bindingId; - resource.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - resource.view = implicit ? VK_IMAGE_VIEW_TYPE_MAX_ENUM : viewType; - resource.access = VK_ACCESS_SHADER_READ_BIT; - m_resourceSlots.push_back(resource); }; - if (m_programInfo.majorVersion() >= 2 && !m_moduleInfo.options.forceSamplerTypeSpecConstants) { + const uint32_t binding = computeResourceSlotId(m_programInfo.type(), + DxsoBindingType::Image, + idx); + + const bool implicit = m_programInfo.majorVersion() < 2 || m_moduleInfo.options.forceSamplerTypeSpecConstants; + + if (!implicit) { DxsoSamplerType samplerType = SamplerTypeFromTextureType(type); - DclSampler(idx, samplerType, false, false); + DclSampler(idx, binding, samplerType, false, implicit); if (samplerType != SamplerTypeTexture3D) { // We could also be depth compared! - DclSampler(idx, samplerType, true, false); + DclSampler(idx, binding, samplerType, true, implicit); } } else { @@ -769,33 +769,27 @@ namespace dxvk { for (uint32_t i = 0; i < SamplerTypeCount; i++) { auto samplerType = static_cast(i); - DclSampler(idx, samplerType, false, true); + DclSampler(idx, binding, samplerType, false, implicit); if (samplerType != SamplerTypeTexture3D) - DclSampler(idx, samplerType, true, true); + DclSampler(idx, binding, samplerType, true, implicit); } } - - - // Declare a specialization constant which will - // store whether or not the depth/color views are bound. - const uint32_t colorBinding = computeResourceSlotId(m_programInfo.type(), - DxsoBindingType::ColorImage, idx); - - const uint32_t depthBinding = computeResourceSlotId(m_programInfo.type(), - DxsoBindingType::DepthImage, idx); DxsoSampler& sampler = m_samplers[idx]; - - sampler.colorSpecConst = m_module.specConstBool(true); - sampler.depthSpecConst = m_module.specConstBool(true); + sampler.boundConst = m_module.specConstBool(true); sampler.type = type; - m_module.decorateSpecId(sampler.colorSpecConst, colorBinding); - m_module.decorateSpecId(sampler.depthSpecConst, depthBinding); - m_module.setDebugName(sampler.colorSpecConst, - str::format("s", idx, "_useColor").c_str()); - m_module.setDebugName(sampler.depthSpecConst, - str::format("s", idx, "_useShadow").c_str()); + m_module.decorateSpecId(sampler.boundConst, binding); + m_module.setDebugName(sampler.boundConst, + str::format("s", idx, "_bound").c_str()); + + // Store descriptor info for the shader interface + DxvkResourceSlot resource; + resource.slot = binding; + resource.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + resource.view = implicit ? VK_IMAGE_VIEW_TYPE_MAX_ENUM : viewType; + resource.access = VK_ACCESS_SHADER_READ_BIT; + m_resourceSlots.push_back(resource); } @@ -2882,21 +2876,28 @@ void DxsoCompiler::emitControlFlowGenericLoop( uint32_t depthLabel = m_module.allocateId(); uint32_t endLabel = m_module.allocateId(); + uint32_t typeId = m_module.defIntType(32, 0); + uint32_t offset = m_module.consti32(m_programInfo.type() == DxsoProgramTypes::VertexShader ? samplerIdx + 17 : samplerIdx); + uint32_t bitCnt = m_module.consti32(1); + uint32_t isDepth = m_module.opBitFieldUExtract(typeId, m_depthSpecConstant, offset, bitCnt); + isDepth = m_module.opIEqual(m_module.defBoolType(), isDepth, m_module.constu32(1)); + m_module.opSelectionMerge(endLabel, spv::SelectionControlMaskNone); - m_module.opBranchConditional(sampler.depthSpecConst, depthLabel, colorLabel); + m_module.opBranchConditional(isDepth, depthLabel, colorLabel); m_module.opLabel(colorLabel); - SampleImage(texcoordVar, sampler.color[samplerType], false, samplerType, sampler.colorSpecConst); + SampleImage(texcoordVar, sampler.color[samplerType], false, samplerType, sampler.boundConst); m_module.opBranch(endLabel); m_module.opLabel(depthLabel); - SampleImage(texcoordVar, sampler.depth[samplerType], true, samplerType, 0); // already specc'ed + // No spec constant as if we are unbound we always fall down the color path. + SampleImage(texcoordVar, sampler.depth[samplerType], true, samplerType, 0); m_module.opBranch(endLabel); m_module.opLabel(endLabel); } else - SampleImage(texcoordVar, sampler.color[samplerType], false, samplerType, sampler.colorSpecConst); + SampleImage(texcoordVar, sampler.color[samplerType], false, samplerType, sampler.boundConst); }; if (m_programInfo.majorVersion() >= 2 && !m_moduleInfo.options.forceSamplerTypeSpecConstants) { diff --git a/src/dxso/dxso_compiler.h b/src/dxso/dxso_compiler.h index 27b722c1..193f248e 100644 --- a/src/dxso/dxso_compiler.h +++ b/src/dxso/dxso_compiler.h @@ -128,8 +128,7 @@ namespace dxvk { DxsoSamplerInfo color[SamplerTypeCount]; DxsoSamplerInfo depth[SamplerTypeCount]; - uint32_t colorSpecConst; - uint32_t depthSpecConst; + uint32_t boundConst; DxsoTextureType type; }; @@ -270,6 +269,7 @@ namespace dxvk { SpirvModule m_module; uint32_t m_boolSpecConstant; + uint32_t m_depthSpecConstant; /////////////////////////////////////////////////////// // Resource slot description for the shader. This will diff --git a/src/dxso/dxso_util.cpp b/src/dxso/dxso_util.cpp index eeeaed01..16a75082 100644 --- a/src/dxso/dxso_util.cpp +++ b/src/dxso/dxso_util.cpp @@ -4,39 +4,6 @@ namespace dxvk { - uint32_t computeResourceSlotId( - DxsoProgramType shaderStage, - DxsoBindingType bindingType, - uint32_t bindingIndex) { - const uint32_t stageOffset = 12 * uint32_t(shaderStage); - - if (shaderStage == DxsoProgramTypes::VertexShader) { - switch (bindingType) { - case DxsoBindingType::ConstantBuffer: return bindingIndex + stageOffset + 0; // 0 + 4 = 4 - case DxsoBindingType::ColorImage: return bindingIndex + stageOffset + 4; // 4 + 4 = 8 - case DxsoBindingType::DepthImage: return bindingIndex + stageOffset + 8; // 8 + 4 = 12 - default: Logger::err("computeResourceSlotId: Invalid resource type"); - } - } - else { // Pixel Shader - switch (bindingType) { - case DxsoBindingType::ConstantBuffer: return bindingIndex + stageOffset + 0; // 0 + 3 = 3 - // The extra sampler here is being reserved for DMAP stuff later on. - case DxsoBindingType::ColorImage: return bindingIndex + stageOffset + 3; // 3 + 17 = 20 - case DxsoBindingType::DepthImage: return bindingIndex + stageOffset + 20; // 20 + 17 = 27 - default: Logger::err("computeResourceSlotId: Invalid resource type"); - } - } - - return 0; - } - - // TODO: Intergrate into compute resource slot ID/refactor all of this? - uint32_t getSWVPBufferSlot() { - return 39; - } - - dxvk::mutex g_linkerSlotMutex; uint32_t g_linkerSlotCount = 0; std::array g_linkerSlots; diff --git a/src/dxso/dxso_util.h b/src/dxso/dxso_util.h index 307a28d9..fac03d73 100644 --- a/src/dxso/dxso_util.h +++ b/src/dxso/dxso_util.h @@ -9,8 +9,7 @@ namespace dxvk { enum class DxsoBindingType : uint32_t { ConstantBuffer, - ColorImage, - DepthImage // <-- We use whatever one is bound to determine whether an image should be 'shadow' sampled or not. + Image, }; enum DxsoConstantBuffers : uint32_t { @@ -26,12 +25,22 @@ namespace dxvk { PSCount }; - uint32_t computeResourceSlotId( - DxsoProgramType shaderStage, - DxsoBindingType bindingType, - uint32_t bindingIndex); + constexpr uint32_t computeResourceSlotId( + DxsoProgramType shaderStage, + DxsoBindingType bindingType, + uint32_t bindingIndex) { + const uint32_t stageOffset = 8 * uint32_t(shaderStage); - uint32_t getSWVPBufferSlot(); + if (bindingType == DxsoBindingType::ConstantBuffer) + return bindingIndex + stageOffset; + else // if (bindingType == DxsoBindingType::Image) + return bindingIndex + stageOffset + (shaderStage == DxsoProgramType::PixelShader ? PSCount : VSCount); + } + + // TODO: Intergrate into compute resource slot ID/refactor all of this? + constexpr uint32_t getSWVPBufferSlot() { + return 27; // From last pixel shader slot, above. + } uint32_t RegisterLinkerSlot(DxsoSemantic semantic);