1
0
Fork 0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-06 20:58:37 +01:00

[dxbc] Implement gather operations with sparse feedback

This commit is contained in:
Philip Rebohle 2022-08-22 03:38:12 +02:00
parent 614024873d
commit d5b68b3642
2 changed files with 94 additions and 18 deletions

View file

@ -3386,6 +3386,7 @@ namespace dxvk {
void DxbcCompiler::emitTextureGather(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitTextureGather(const DxbcShaderInstruction& ins) {
// Gather4 takes the following operands: // Gather4 takes the following operands:
// (dst0) The destination register // (dst0) The destination register
// (dst1) The residency code for sparse ops
// (src0) Texture coordinates // (src0) Texture coordinates
// (src1) The texture itself // (src1) The texture itself
// (src2) The sampler, with a component selector // (src2) The sampler, with a component selector
@ -3396,7 +3397,9 @@ namespace dxvk {
// TODO reduce code duplication by moving some common code // TODO reduce code duplication by moving some common code
// in both sample() and gather() into separate methods // in both sample() and gather() into separate methods
const bool isExtendedGather = ins.op == DxbcOpcode::Gather4Po const bool isExtendedGather = ins.op == DxbcOpcode::Gather4Po
|| ins.op == DxbcOpcode::Gather4PoC; || ins.op == DxbcOpcode::Gather4PoC
|| ins.op == DxbcOpcode::Gather4PoS
|| ins.op == DxbcOpcode::Gather4PoCS;
const DxbcRegister& texCoordReg = ins.src[0]; const DxbcRegister& texCoordReg = ins.src[0];
const DxbcRegister& textureReg = ins.src[1 + isExtendedGather]; const DxbcRegister& textureReg = ins.src[1 + isExtendedGather];
@ -3415,8 +3418,10 @@ namespace dxvk {
// Load reference value for depth-compare operations // Load reference value for depth-compare operations
const bool isDepthCompare = ins.op == DxbcOpcode::Gather4C const bool isDepthCompare = ins.op == DxbcOpcode::Gather4C
|| ins.op == DxbcOpcode::Gather4PoC; || ins.op == DxbcOpcode::Gather4PoC
|| ins.op == DxbcOpcode::Gather4CS
|| ins.op == DxbcOpcode::Gather4PoCS;
const DxbcRegisterValue referenceValue = isDepthCompare const DxbcRegisterValue referenceValue = isDepthCompare
? emitRegisterLoad(ins.src[3 + isExtendedGather], ? emitRegisterLoad(ins.src[3 + isExtendedGather],
DxbcRegMask(true, false, false, false)) DxbcRegMask(true, false, false, false))
@ -3424,7 +3429,8 @@ namespace dxvk {
// Accumulate additional image operands. // Accumulate additional image operands.
SpirvImageOperands imageOperands; SpirvImageOperands imageOperands;
imageOperands.sparse = ins.dstCount == 2;
if (isExtendedGather) { if (isExtendedGather) {
m_module.enableCapability(spv::CapabilityImageGatherExtended); m_module.enableCapability(spv::CapabilityImageGatherExtended);
@ -3445,30 +3451,41 @@ namespace dxvk {
getVectorTypeId({ DxbcScalarType::Sint32, imageLayerDim }), getVectorTypeId({ DxbcScalarType::Sint32, imageLayerDim }),
imageLayerDim, offsetIds.data()); imageLayerDim, offsetIds.data());
} }
// Gathering texels always returns a four-component // Gathering texels always returns a four-component
// vector, even for the depth-compare variants. // vector, even for the depth-compare variants.
uint32_t sampledImageId = emitLoadSampledImage(texture, sampler, isDepthCompare); uint32_t sampledImageId = emitLoadSampledImage(texture, sampler, isDepthCompare);
DxbcRegisterValue result; DxbcVectorType texelType;
result.type.ctype = texture.sampledType; texelType.ctype = texture.sampledType;
result.type.ccount = 4; texelType.ccount = 4;
uint32_t texelTypeId = getVectorTypeId(texelType);
uint32_t resultTypeId = texelTypeId;
uint32_t resultId = 0;
if (imageOperands.sparse)
resultTypeId = getSparseResultTypeId(texelTypeId);
switch (ins.op) { switch (ins.op) {
// Simple image gather operation // Simple image gather operation
case DxbcOpcode::Gather4: case DxbcOpcode::Gather4:
case DxbcOpcode::Gather4Po: { case DxbcOpcode::Gather4S:
result.id = m_module.opImageGather( case DxbcOpcode::Gather4Po:
getVectorTypeId(result.type), sampledImageId, coord.id, case DxbcOpcode::Gather4PoS: {
resultId = m_module.opImageGather(
resultTypeId, sampledImageId, coord.id,
m_module.consti32(samplerReg.swizzle[0]), m_module.consti32(samplerReg.swizzle[0]),
imageOperands); imageOperands);
} break; } break;
// Depth-compare operation // Depth-compare operation
case DxbcOpcode::Gather4C: case DxbcOpcode::Gather4C:
case DxbcOpcode::Gather4PoC: { case DxbcOpcode::Gather4CS:
result.id = m_module.opImageDrefGather( case DxbcOpcode::Gather4PoC:
getVectorTypeId(result.type), sampledImageId, coord.id, case DxbcOpcode::Gather4PoCS: {
resultId = m_module.opImageDrefGather(
resultTypeId, sampledImageId, coord.id,
referenceValue.id, imageOperands); referenceValue.id, imageOperands);
} break; } break;
@ -3478,13 +3495,23 @@ namespace dxvk {
ins.op)); ins.op));
return; return;
} }
// If necessary, deal with the sparse result
DxbcRegisterValue result;
result.type = texelType;
result.id = imageOperands.sparse
? emitExtractSparseTexel(texelTypeId, resultId)
: resultId;
// Swizzle components using the texture swizzle // Swizzle components using the texture swizzle
// and the destination operand's write mask // and the destination operand's write mask
result = emitRegisterSwizzle(result, result = emitRegisterSwizzle(result,
textureReg.swizzle, ins.dst[0].mask); textureReg.swizzle, ins.dst[0].mask);
emitRegisterStore(ins.dst[0], result); emitRegisterStore(ins.dst[0], result);
if (imageOperands.sparse)
emitStoreSparseFeedback(ins.dst[1], resultId);
} }
@ -4549,6 +4576,33 @@ namespace dxvk {
} }
uint32_t DxbcCompiler::emitExtractSparseTexel(
uint32_t texelTypeId,
uint32_t resultId) {
uint32_t index = 1;
return m_module.opCompositeExtract(
texelTypeId, resultId, 1, &index);
}
void DxbcCompiler::emitStoreSparseFeedback(
const DxbcRegister& feedbackRegister,
uint32_t resultId) {
if (feedbackRegister.type != DxbcOperandType::Null) {
uint32_t index = 0;
DxbcRegisterValue result;
result.type = { DxbcScalarType::Uint32, 1 };
result.id = m_module.opCompositeExtract(
getScalarTypeId(DxbcScalarType::Uint32),
resultId, 1, &index);
emitRegisterStore(feedbackRegister, result);
}
}
DxbcRegisterValue DxbcCompiler::emitDstOperandModifiers( DxbcRegisterValue DxbcCompiler::emitDstOperandModifiers(
DxbcRegisterValue value, DxbcRegisterValue value,
DxbcOpModifiers modifiers) { DxbcOpModifiers modifiers) {
@ -7592,6 +7646,15 @@ namespace dxvk {
} }
uint32_t DxbcCompiler::getSparseResultTypeId(uint32_t baseType) {
m_module.enableCapability(spv::CapabilitySparseResidency);
uint32_t uintType = getScalarTypeId(DxbcScalarType::Uint32);
std::array<uint32_t, 2> typeIds = { uintType, baseType };
return m_module.defStructType(typeIds.size(), typeIds.data());
}
uint32_t DxbcCompiler::getPerVertexBlockId() { uint32_t DxbcCompiler::getPerVertexBlockId() {
uint32_t t_f32 = m_module.defFloatType(32); uint32_t t_f32 = m_module.defFloatType(32);
uint32_t t_f32_v4 = m_module.defVectorType(t_f32, 4); uint32_t t_f32_v4 = m_module.defVectorType(t_f32, 4);

View file

@ -882,6 +882,16 @@ namespace dxvk {
DxbcRegisterValue value, DxbcRegisterValue value,
DxbcOpModifiers modifiers); DxbcOpModifiers modifiers);
///////////////////////////
// Sparse feedback methods
uint32_t emitExtractSparseTexel(
uint32_t texelTypeId,
uint32_t resultId);
void emitStoreSparseFeedback(
const DxbcRegister& feedbackRegister,
uint32_t resultId);
//////////////////////////////// ////////////////////////////////
// Pointer manipulation methods // Pointer manipulation methods
DxbcRegisterPointer emitArrayAccess( DxbcRegisterPointer emitArrayAccess(
@ -1149,7 +1159,7 @@ namespace dxvk {
uint32_t emitSamplePosArray(); uint32_t emitSamplePosArray();
void emitFloatControl(); void emitFloatControl();
/////////////////////////////// ///////////////////////////////
// Variable definition methods // Variable definition methods
uint32_t emitNewVariable( uint32_t emitNewVariable(
@ -1223,7 +1233,10 @@ namespace dxvk {
uint32_t getPointerTypeId( uint32_t getPointerTypeId(
const DxbcRegisterInfo& type); const DxbcRegisterInfo& type);
uint32_t getSparseResultTypeId(
uint32_t baseType);
uint32_t getPerVertexBlockId(); uint32_t getPerVertexBlockId();
uint32_t getFunctionId( uint32_t getFunctionId(