From e5a06d3f4a103a54cd4eb51970fedee405d1d698 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 28 Jan 2019 21:14:17 +0100 Subject: [PATCH] [dxbc] Only load requested components from constant buffers Results in better performance compared to loading the entire vector on RADV. Suggested by Samuel Pitoiset. --- src/dxbc/dxbc_compiler.cpp | 57 ++++++++++++++++++++++++++++++++++++-- src/dxbc/dxbc_compiler.h | 4 +++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 6417641c6..bd3f4a3c8 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -5187,14 +5187,65 @@ namespace dxvk { m_module.opStore(ptr.id, tmp.id); } } - - + + DxbcRegisterValue DxbcCompiler::emitRegisterLoadRaw( const DxbcRegister& reg) { return emitValueLoad(emitGetOperandPtr(reg)); } + DxbcRegisterValue DxbcCompiler::emitConstantBufferLoad( + const DxbcRegister& reg, + DxbcRegMask writeMask) { + DxbcRegisterPointer ptr = emitGetOperandPtr(reg); + + std::array ccomps = { 0, 0, 0, 0 }; + std::array scomps = { 0, 0, 0, 0 }; + uint32_t scount = 0; + + for (uint32_t i = 0; i < 4; i++) { + uint32_t sindex = reg.swizzle[i]; + + if (!writeMask[i] || ccomps[sindex]) + continue; + + uint32_t componentId = m_module.constu32(sindex); + uint32_t componentPtr = m_module.opAccessChain( + m_module.defPointerType( + getScalarTypeId(DxbcScalarType::Float32), + spv::StorageClassUniformConstant), + ptr.id, 1, &componentId); + + ccomps[sindex] = m_module.opLoad( + getScalarTypeId(DxbcScalarType::Float32), + componentPtr); + } + + for (uint32_t i = 0; i < 4; i++) { + uint32_t sindex = reg.swizzle[i]; + + if (writeMask[i]) + scomps[scount++] = ccomps[sindex]; + } + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Float32; + result.type.ccount = scount; + result.id = scomps[0]; + + if (scount > 1) { + result.id = m_module.opCompositeConstruct( + getVectorTypeId(result.type), + scount, scomps.data()); + } + + result = emitRegisterBitcast(result, reg.dataType); + result = emitSrcOperandModifiers(result, reg.modifiers); + return result; + } + + DxbcRegisterValue DxbcCompiler::emitRegisterLoad( const DxbcRegister& reg, DxbcRegMask writeMask) { @@ -5236,6 +5287,8 @@ namespace dxvk { // Cast constants to the requested type return emitRegisterBitcast(result, reg.dataType); + } else if (reg.type == DxbcOperandType::ConstantBuffer) { + return emitConstantBufferLoad(reg, writeMask); } else { // Load operand from the operand pointer DxbcRegisterValue result = emitRegisterLoadRaw(reg); diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 28ac3d03c..3b717169d 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -972,6 +972,10 @@ namespace dxvk { DxbcRegisterValue emitRegisterLoadRaw( const DxbcRegister& reg); + DxbcRegisterValue emitConstantBufferLoad( + const DxbcRegister& reg, + DxbcRegMask writeMask); + DxbcRegisterValue emitRegisterLoad( const DxbcRegister& reg, DxbcRegMask writeMask);