diff --git a/src/d3d9/d3d9_constant_layout.h b/src/d3d9/d3d9_constant_layout.h index ddee0f3b..df4120bc 100644 --- a/src/d3d9/d3d9_constant_layout.h +++ b/src/d3d9/d3d9_constant_layout.h @@ -14,7 +14,12 @@ namespace dxvk { uint32_t floatSize() const { return floatCount * 4 * sizeof(float); } uint32_t intSize() const { return intCount * 4 * sizeof(int); } - uint32_t bitmaskSize() const { return bitmaskCount * 1 * sizeof(uint32_t); } + uint32_t bitmaskSize() const { + // Account for SWVP (non SWVP uses a spec constant) + return bitmaskCount != 1 + ? bitmaskCount * 1 * sizeof(uint32_t) + : 0; + } uint32_t floatOffset() const { return 0; } uint32_t intOffset() const { return floatOffset() + floatSize(); } diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index e03881af..7c8a7e80 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -4438,8 +4438,6 @@ namespace dxvk { std::memcpy(dst->fConsts, Src.fConsts, constSet.meta->maxConstIndexF * sizeof(Vector4)); if (constSet.meta->maxConstIndexI) std::memcpy(dst->iConsts, Src.iConsts, constSet.meta->maxConstIndexI * sizeof(Vector4i)); - if (constSet.meta->maxConstIndexB) - dst->bConsts[0] = Src.bConsts[0]; } @@ -5422,9 +5420,18 @@ namespace dxvk { GetVertexShaderPermutation()); } UploadConstants(); + + if (likely(!CanSWVP())) { + UpdateBoolSpecConstantVertex( + m_state.vsConsts.bConsts[0] & + GetCommonShader(m_state.vertexShader)->GetMeta().boolConstantMask); + } else + UpdateBoolSpecConstantVertex(0); } - else + else { + UpdateBoolSpecConstantVertex(0); UpdateFixedFunctionVS(); + } if (m_flags.test(D3D9DeviceFlag::DirtyInputLayout)) BindInputLayout(); @@ -5444,8 +5451,13 @@ namespace dxvk { UpdateSamplerTypes(m_d3d9Options.forceSamplerTypeSpecConstants ? m_samplerTypeBitfield : 0u, 0u); else UpdateSamplerTypes(m_samplerTypeBitfield, m_projectionBitfield); // For implicit samplers... + + UpdateBoolSpecConstantPixel( + m_state.psConsts.bConsts[0] & + GetCommonShader(m_state.pixelShader)->GetMeta().boolConstantMask); } else { + UpdateBoolSpecConstantPixel(0); UpdateSamplerTypes(0u, 0u); UpdateFixedFunctionPS(); @@ -5764,7 +5776,8 @@ namespace dxvk { ? DetermineMaxCount(m_state.vertexShader) : DetermineMaxCount(m_state.pixelShader); - m_consts[ProgramType].dirty |= StartRegister < maxCount; + if constexpr (ConstantType != D3D9ConstantType::Bool) + m_consts[ProgramType].dirty |= StartRegister < maxCount; UpdateStateConstants( &m_state, @@ -6104,6 +6117,30 @@ namespace dxvk { } + void D3D9DeviceEx::UpdateBoolSpecConstantVertex(uint32_t value) { + if (value == m_lastBoolSpecConstantVertex) + return; + + EmitCs([cBitfield = value](DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::VertexShaderBools, cBitfield); + }); + + m_lastBoolSpecConstantVertex = value; + } + + + void D3D9DeviceEx::UpdateBoolSpecConstantPixel(uint32_t value) { + if (value == m_lastBoolSpecConstantPixel) + return; + + EmitCs([cBitfield = value](DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::PixelShaderBools, cBitfield); + }); + + m_lastBoolSpecConstantPixel = value; + } + + void D3D9DeviceEx::UpdateSamplerSpecConsant(uint32_t value) { EmitCs([cBitfield = value](DxvkContext* ctx) { ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::SamplerType, cBitfield); @@ -6484,6 +6521,8 @@ namespace dxvk { m_flags.set(D3D9DeviceFlag::DirtyInputLayout); UpdateSamplerSpecConsant(0u); + UpdateBoolSpecConstantVertex(0u); + UpdateBoolSpecConstantPixel(0u); return D3D_OK; } diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h index d8968657..6c919311 100644 --- a/src/d3d9/d3d9_device.h +++ b/src/d3d9/d3d9_device.h @@ -1014,6 +1014,9 @@ namespace dxvk { uint32_t m_lastProjectionBitfield = 0; uint32_t m_projectionBitfield = 0; + uint32_t m_lastBoolSpecConstantVertex = 0; + uint32_t m_lastBoolSpecConstantPixel = 0; + uint32_t m_lastPointMode = 0; uint32_t m_activeRTs = 0; @@ -1162,6 +1165,10 @@ namespace dxvk { bool UseProgrammablePS(); + void UpdateBoolSpecConstantVertex(uint32_t value); + + void UpdateBoolSpecConstantPixel(uint32_t value); + void UpdateSamplerSpecConsant(uint32_t value); void UpdateProjectionSpecConstant(uint32_t value); diff --git a/src/d3d9/d3d9_spec_constants.h b/src/d3d9/d3d9_spec_constants.h index cdd04a63..5d1bd3c0 100644 --- a/src/d3d9/d3d9_spec_constants.h +++ b/src/d3d9/d3d9_spec_constants.h @@ -14,6 +14,9 @@ namespace dxvk { PointMode = 6, ProjectionType = 7, + + VertexShaderBools = 8, + PixelShaderBools = 9, }; } \ No newline at end of file diff --git a/src/dxso/dxso_compiler.cpp b/src/dxso/dxso_compiler.cpp index 4acc3b63..306e9a38 100644 --- a/src/dxso/dxso_compiler.cpp +++ b/src/dxso/dxso_compiler.cpp @@ -294,10 +294,9 @@ namespace dxvk { m_module.decorateArrayStride(members[0], 16); m_module.decorateArrayStride(members[1], 16); - if (m_layout->bitmaskCount == 1) { - members[2] = getScalarTypeId(DxsoScalarType::Uint32); - } - else { + const bool swvp = m_layout->bitmaskCount != 1; + + if (swvp) { // Must be a multiple of 4 otherwise. members[2] = m_module.defArrayTypeUnique( getVectorTypeId({ DxsoScalarType::Uint32, 4 }), @@ -307,18 +306,22 @@ namespace dxvk { } const uint32_t structType = - m_module.defStructType(members.size(), members.data()); + m_module.defStructType(swvp ? 3 : 2, members.data()); m_module.decorateBlock(structType); m_module.memberDecorateOffset(structType, 0, m_layout->floatOffset()); m_module.memberDecorateOffset(structType, 1, m_layout->intOffset()); - m_module.memberDecorateOffset(structType, 2, m_layout->bitmaskOffset()); + + if (swvp) + m_module.memberDecorateOffset(structType, 2, m_layout->bitmaskOffset()); m_module.setDebugName(structType, "cbuffer_t"); m_module.setDebugMemberName(structType, 0, "f"); m_module.setDebugMemberName(structType, 1, "i"); - m_module.setDebugMemberName(structType, 2, "b"); + + if (swvp) + m_module.setDebugMemberName(structType, 2, "b"); m_cBuffer = m_module.newVar( m_module.defPointerType(structType, spv::StorageClassUniform), @@ -339,6 +342,13 @@ namespace dxvk { resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; resource.access = VK_ACCESS_UNIFORM_READ_BIT; m_resourceSlots.push_back(resource); + + m_boolSpecConstant = m_module.specConst32(m_module.defIntType(32, 0), 0); + m_module.decorateSpecId(m_boolSpecConstant, getSpecId( + m_programInfo.type() == DxsoProgramType::VertexShader + ? D3D9SpecConstantId::VertexShaderBools + : D3D9SpecConstantId::PixelShaderBools)); + m_module.setDebugName(m_boolSpecConstant, "boolConstants"); } @@ -897,6 +907,7 @@ namespace dxvk { case DxsoRegisterType::ConstBool: m_meta.maxConstIndexB = std::max(m_meta.maxConstIndexB, reg.id.num + 1); m_meta.maxConstIndexB = std::min(m_meta.maxConstIndexB, m_layout->boolCount); + m_meta.boolConstantMask |= 1 << reg.id.num; break; default: break; @@ -939,18 +950,25 @@ namespace dxvk { uint32_t uintType = getScalarTypeId(DxsoScalarType::Uint32); uint32_t uvec4Type = getVectorTypeId({ DxsoScalarType::Uint32, 4 }); - std::array indices = { m_module.constu32(2), m_module.constu32(reg.id.num / 128) }; + // If not SWVP, spec const this + uint32_t bitfield; + if (m_layout->bitmaskCount != 1) { + std::array indices = { m_module.constu32(2), m_module.constu32(reg.id.num / 128) }; - uint32_t indexCount = m_layout->bitmaskCount == 1 ? 1 : 2; - uint32_t accessType = m_layout->bitmaskCount == 1 ? uintType : uvec4Type; + uint32_t indexCount = m_layout->bitmaskCount == 1 ? 1 : 2; + uint32_t accessType = m_layout->bitmaskCount == 1 ? uintType : uvec4Type; - uint32_t ptrId = m_module.opAccessChain( - m_module.defPointerType(accessType, spv::StorageClassUniform), - m_cBuffer, indexCount, indices.data()); + uint32_t ptrId = m_module.opAccessChain( + m_module.defPointerType(accessType, spv::StorageClassUniform), + m_cBuffer, indexCount, indices.data()); + + bitfield = m_module.opLoad(accessType, ptrId); + } + else + bitfield = m_boolSpecConstant; uint32_t bitIdx = m_module.consti32(reg.id.num % 32); - uint32_t bitfield = m_module.opLoad(accessType, ptrId); if (m_layout->bitmaskCount != 1) { uint32_t index = (reg.id.num % 128) / 32; bitfield = m_module.opCompositeExtract(uintType, bitfield, 1, &index); diff --git a/src/dxso/dxso_compiler.h b/src/dxso/dxso_compiler.h index 4185f335..b46ff682 100644 --- a/src/dxso/dxso_compiler.h +++ b/src/dxso/dxso_compiler.h @@ -266,6 +266,8 @@ namespace dxvk { SpirvModule m_module; + uint32_t m_boolSpecConstant; + /////////////////////////////////////////////////////// // Resource slot description for the shader. This will // be used to map D3D9 bindings to DXVK bindings. diff --git a/src/dxso/dxso_isgn.h b/src/dxso/dxso_isgn.h index 168c8d8e..2faa04ef 100644 --- a/src/dxso/dxso_isgn.h +++ b/src/dxso/dxso_isgn.h @@ -34,6 +34,8 @@ namespace dxvk { uint32_t maxConstIndexF = 0; uint32_t maxConstIndexI = 0; uint32_t maxConstIndexB = 0; + + uint32_t boolConstantMask = 0; }; } \ No newline at end of file