From 41d660f220dd907333402b57442b7023382429de Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 20 Dec 2017 20:21:44 +0100 Subject: [PATCH] [spirv] Added image operand structure for more flexible sample ops --- src/dxbc/dxbc_compiler.cpp | 26 ++++++++---- src/dxgi/dxgi_presenter.cpp | 3 +- src/spirv/spirv_module.cpp | 83 ++++++++++++++++++++++++++++++++----- src/spirv/spirv_module.h | 29 +++++++++++-- 4 files changed, 116 insertions(+), 25 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 1e79b9b6..03021c11 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -1193,7 +1193,6 @@ namespace dxvk { void DxbcCompiler::emitSample(const DxbcShaderInstruction& ins) { - // TODO support address offset // TODO support more sample ops // All sample instructions have at least these operands: @@ -1240,6 +1239,11 @@ namespace dxvk { m_samplers.at(samplerId).typeId, m_samplers.at(samplerId).varId)); + // Accumulate additional image operands. These are + // not part of the actual operand token in SPIR-V. + SpirvImageOperands imageOperands; + // TODO implement sample controls + // Sampling an image always returns a four-component // vector, whereas depth-compare ops return a scalar. DxbcRegisterValue result; @@ -1247,25 +1251,29 @@ namespace dxvk { result.type.ccount = isDepthCompare ? 1 : 4; switch (ins.op) { + // Simple image sample operation case DxbcOpcode::Sample: { result.id = m_module.opImageSampleImplicitLod( getVectorTypeId(result.type), - sampledImageId, coord.id); + sampledImageId, coord.id, + imageOperands); } break; + // Depth-compare operation case DxbcOpcode::SampleC: { result.id = m_module.opImageSampleDrefImplicitLod( - getVectorTypeId(result.type), - sampledImageId, coord.id, - referenceValue.id); + getVectorTypeId(result.type), sampledImageId, coord.id, + referenceValue.id, imageOperands); } break; + // Depth-compare operation on mip level zero case DxbcOpcode::SampleClz: { + imageOperands.flags |= spv::ImageOperandsLodMask; + imageOperands.sLod = m_module.constf32(0.0f); + result.id = m_module.opImageSampleDrefExplicitLod( - getVectorTypeId(result.type), - sampledImageId, coord.id, - referenceValue.id, - m_module.constf32(0.0f)); + getVectorTypeId(result.type), sampledImageId, coord.id, + referenceValue.id, imageOperands); } break; default: diff --git a/src/dxgi/dxgi_presenter.cpp b/src/dxgi/dxgi_presenter.cpp index 8cadfeaa..493f8821 100644 --- a/src/dxgi/dxgi_presenter.cpp +++ b/src/dxgi/dxgi_presenter.cpp @@ -472,7 +472,8 @@ namespace dxvk { typeSampledTex, module.opLoad(typeTexture, rcTexture), module.opLoad(typeSampler, rcSampler)), - module.opLoad(typeVec2, inTexCoord))); + module.opLoad(typeVec2, inTexCoord), + SpirvImageOperands())); module.opReturn(); module.functionEnd(); diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index 4e11c226..737b7c9c 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -1521,14 +1521,18 @@ namespace dxvk { uint32_t SpirvModule::opImageSampleImplicitLod( uint32_t resultType, uint32_t sampledImage, - uint32_t coordinates) { + uint32_t coordinates, + const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); - m_code.putIns (spv::OpImageSampleImplicitLod, 5); + m_code.putIns(spv::OpImageSampleImplicitLod, + 5 + getImageOperandWordCount(operands)); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(sampledImage); m_code.putWord(coordinates); + + putImageOperands(operands); return resultId; } @@ -1537,16 +1541,18 @@ namespace dxvk { uint32_t resultType, uint32_t sampledImage, uint32_t coordinates, - uint32_t lod) { + const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); - m_code.putIns (spv::OpImageSampleExplicitLod, 7); + m_code.putIns(spv::OpImageSampleExplicitLod, + 5 + getImageOperandWordCount(operands)); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(sampledImage); m_code.putWord(coordinates); m_code.putWord(spv::ImageOperandsLodMask); - m_code.putWord(lod); + + putImageOperands(operands); return resultId; } @@ -1555,15 +1561,19 @@ namespace dxvk { uint32_t resultType, uint32_t sampledImage, uint32_t coordinates, - uint32_t reference) { + uint32_t reference, + const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); - m_code.putIns (spv::OpImageSampleDrefImplicitLod, 6); + m_code.putIns(spv::OpImageSampleDrefImplicitLod, + 6 + getImageOperandWordCount(operands)); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(sampledImage); m_code.putWord(coordinates); m_code.putWord(reference); + + putImageOperands(operands); return resultId; } @@ -1573,17 +1583,18 @@ namespace dxvk { uint32_t sampledImage, uint32_t coordinates, uint32_t reference, - uint32_t lod) { + const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); - m_code.putIns (spv::OpImageSampleDrefExplicitLod, 8); + m_code.putIns(spv::OpImageSampleDrefExplicitLod, + 6 + getImageOperandWordCount(operands)); 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); + + putImageOperands(operands); return resultId; } @@ -1683,4 +1694,54 @@ namespace dxvk { m_instExt.putStr (name); } + + uint32_t SpirvModule::getImageOperandWordCount(const SpirvImageOperands& op) const { + // Each flag may add one or more operands + const uint32_t result + = ((op.flags & spv::ImageOperandsBiasMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsLodMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsConstOffsetMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsGradMask) ? 2 : 0) + + ((op.flags & spv::ImageOperandsOffsetMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsConstOffsetsMask)? 1 : 0) + + ((op.flags & spv::ImageOperandsSampleMask) ? 1 : 0) + + ((op.flags & spv::ImageOperandsMinLodMask) ? 1 : 0); + + // Add a DWORD for the operand mask if it is non-zero + return result != 0 ? result + 1 : 0; + } + + + void SpirvModule::putImageOperands(const SpirvImageOperands& op) { + if (op.flags != 0) { + m_code.putWord(op.flags); + + if (op.flags & spv::ImageOperandsBiasMask) + m_code.putWord(op.sLodBias); + + if (op.flags & spv::ImageOperandsLodMask) + m_code.putWord(op.sLod); + + if (op.flags & spv::ImageOperandsConstOffsetMask) + m_code.putWord(op.sConstOffset); + + if (op.flags & spv::ImageOperandsGradMask) { + m_code.putWord(op.sGradX); + m_code.putWord(op.sGradY); + } + + if (op.flags & spv::ImageOperandsOffsetMask) + m_code.putWord(op.gOffset); + + if (op.flags & spv::ImageOperandsConstOffsetsMask) + m_code.putWord(op.gConstOffsets); + + if (op.flags & spv::ImageOperandsSampleMask) + m_code.putWord(op.sSampleId); + + if (op.flags & spv::ImageOperandsMinLodMask) + m_code.putWord(op.sMinLod); + } + } + } \ No newline at end of file diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index 414f4e0d..1717972f 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -4,6 +4,19 @@ namespace dxvk { + struct SpirvImageOperands { + uint32_t flags = 0; + uint32_t sLodBias = 0; + uint32_t sLod = 0; + uint32_t sConstOffset = 0; + uint32_t sGradX = 0; + uint32_t sGradY = 0; + uint32_t gOffset = 0; + uint32_t gConstOffsets = 0; + uint32_t sSampleId = 0; + uint32_t sMinLod = 0; + }; + /** * \brief SPIR-V module * @@ -518,26 +531,28 @@ namespace dxvk { uint32_t opImageSampleImplicitLod( uint32_t resultType, uint32_t sampledImage, - uint32_t coordinates); + uint32_t coordinates, + const SpirvImageOperands& operands); uint32_t opImageSampleExplicitLod( uint32_t resultType, uint32_t sampledImage, uint32_t coordinates, - uint32_t lod); + const SpirvImageOperands& operands); uint32_t opImageSampleDrefImplicitLod( uint32_t resultType, uint32_t sampledImage, uint32_t coordinates, - uint32_t reference); + uint32_t reference, + const SpirvImageOperands& operands); uint32_t opImageSampleDrefExplicitLod( uint32_t resultType, uint32_t sampledImage, uint32_t coordinates, uint32_t reference, - uint32_t lod); + const SpirvImageOperands& operands); void opLoopMerge( uint32_t mergeBlock, @@ -587,6 +602,12 @@ namespace dxvk { void instImportGlsl450(); + uint32_t getImageOperandWordCount( + const SpirvImageOperands& op) const; + + void putImageOperands( + const SpirvImageOperands& op); + }; } \ No newline at end of file