diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 99e45e85..aac78c27 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -1209,7 +1209,7 @@ namespace dxvk { // TODO support address offset // TODO support more sample ops - // sample has four operands: + // All sample instructions have at least these operands: // (dst0) The destination register // (src0) Texture coordinates // (src1) The texture itself @@ -1227,6 +1227,12 @@ namespace dxvk { const DxbcRegisterValue coord = emitRegisterLoad( texCoordReg, DxbcRegMask(true, true, true, true)); + // Load reference value for depth-compare operations + DxbcRegisterValue referenceValue; + + if (ins.op == DxbcOpcode::SampleC || ins.op == DxbcOpcode::SampleClz) + referenceValue = emitRegisterLoad(ins.src[3], DxbcRegMask(true, false, false, false)); + // Combine the texture and the sampler into a sampled image const uint32_t sampledImageType = m_module.defSampledImageType( m_textures.at(textureId).textureTypeId); @@ -1242,18 +1248,41 @@ namespace dxvk { // Sampling an image in SPIR-V always returns a four-component // vector, so we need to declare the corresponding type here - // TODO infer sampled type properly + // TODO infer sampled types properly DxbcRegisterValue result; - result.type.ctype = DxbcScalarType::Float32; - result.type.ccount = 4; - result.id = m_module.opImageSampleImplicitLod( - getVectorTypeId(result.type), - sampledImageId, coord.id); + + switch (ins.op) { + case DxbcOpcode::Sample: { + result.type.ctype = DxbcScalarType::Float32; + result.type.ccount = 4; + result.id = m_module.opImageSampleImplicitLod( + getVectorTypeId(result.type), + sampledImageId, coord.id); + } break; + + case DxbcOpcode::SampleClz: { + result.type.ctype = DxbcScalarType::Float32; + result.type.ccount = 1; + result.id = m_module.opImageSampleDrefExplicitLod( + getVectorTypeId(result.type), + sampledImageId, coord.id, + referenceValue.id, + m_module.constf32(0.0f)); + } break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + return; + } // Swizzle components using the texture swizzle // and the destination operand's write mask - result = emitRegisterSwizzle(result, - textureReg.swizzle, ins.dst[0].mask); + if (result.type.ccount != 1) { + result = emitRegisterSwizzle(result, + textureReg.swizzle, ins.dst[0].mask); + } emitRegisterStore(ins.dst[0], result); } diff --git a/src/dxbc/dxbc_defs.cpp b/src/dxbc/dxbc_defs.cpp index 0109f7e6..49d00cf1 100644 --- a/src/dxbc/dxbc_defs.cpp +++ b/src/dxbc/dxbc_defs.cpp @@ -169,10 +169,10 @@ namespace dxvk { } }, /* IMul */ { 4, DxbcInstClass::VectorImul, { - { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, - { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, - { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, - { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, } }, /* INe */ { 3, DxbcInstClass::VectorCmp, { @@ -300,9 +300,21 @@ namespace dxvk { { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, } }, /* SampleC */ - { }, + { 5, DxbcInstClass::TextureSample, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, /* SampleClz */ - { }, + { 5, DxbcInstClass::TextureSample, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, /* SampleL */ { }, /* SampleD */ @@ -335,10 +347,10 @@ namespace dxvk { { }, /* UMul */ { 4, DxbcInstClass::VectorImul, { - { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, - { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, - { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, - { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, } }, /* UMad */ { }, diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index c1fdcbbe..b29c9926 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -1533,6 +1533,26 @@ namespace dxvk { } + uint32_t SpirvModule::opImageSampleDrefExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + uint32_t lod) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpImageSampleDrefExplicitLod, 8); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(sampledImage); + m_code.putWord(coordinates); + m_code.putWord(reference); + m_code.putWord(spv::ImageOperandsLodMask); + m_code.putWord(lod); + return resultId; + } + + void SpirvModule::opLoopMerge( uint32_t mergeBlock, uint32_t continueTarget, diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index 87bbb2c0..6a816a17 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -520,6 +520,13 @@ namespace dxvk { uint32_t sampledImage, uint32_t coordinates); + uint32_t opImageSampleDrefExplicitLod( + uint32_t resultType, + uint32_t sampledImage, + uint32_t coordinates, + uint32_t reference, + uint32_t lod); + void opLoopMerge( uint32_t mergeBlock, uint32_t continueTarget,