1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 10:54:16 +01:00

[spirv] Added image operand structure for more flexible sample ops

This commit is contained in:
Philip Rebohle 2017-12-20 20:21:44 +01:00
parent 84190369ab
commit 41d660f220
4 changed files with 116 additions and 25 deletions

View File

@ -1193,7 +1193,6 @@ namespace dxvk {
void DxbcCompiler::emitSample(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitSample(const DxbcShaderInstruction& ins) {
// TODO support address offset
// TODO support more sample ops // TODO support more sample ops
// All sample instructions have at least these operands: // All sample instructions have at least these operands:
@ -1240,6 +1239,11 @@ namespace dxvk {
m_samplers.at(samplerId).typeId, m_samplers.at(samplerId).typeId,
m_samplers.at(samplerId).varId)); 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 // Sampling an image always returns a four-component
// vector, whereas depth-compare ops return a scalar. // vector, whereas depth-compare ops return a scalar.
DxbcRegisterValue result; DxbcRegisterValue result;
@ -1247,25 +1251,29 @@ namespace dxvk {
result.type.ccount = isDepthCompare ? 1 : 4; result.type.ccount = isDepthCompare ? 1 : 4;
switch (ins.op) { switch (ins.op) {
// Simple image sample operation
case DxbcOpcode::Sample: { case DxbcOpcode::Sample: {
result.id = m_module.opImageSampleImplicitLod( result.id = m_module.opImageSampleImplicitLod(
getVectorTypeId(result.type), getVectorTypeId(result.type),
sampledImageId, coord.id); sampledImageId, coord.id,
imageOperands);
} break; } break;
// Depth-compare operation
case DxbcOpcode::SampleC: { case DxbcOpcode::SampleC: {
result.id = m_module.opImageSampleDrefImplicitLod( result.id = m_module.opImageSampleDrefImplicitLod(
getVectorTypeId(result.type), getVectorTypeId(result.type), sampledImageId, coord.id,
sampledImageId, coord.id, referenceValue.id, imageOperands);
referenceValue.id);
} break; } break;
// Depth-compare operation on mip level zero
case DxbcOpcode::SampleClz: { case DxbcOpcode::SampleClz: {
imageOperands.flags |= spv::ImageOperandsLodMask;
imageOperands.sLod = m_module.constf32(0.0f);
result.id = m_module.opImageSampleDrefExplicitLod( result.id = m_module.opImageSampleDrefExplicitLod(
getVectorTypeId(result.type), getVectorTypeId(result.type), sampledImageId, coord.id,
sampledImageId, coord.id, referenceValue.id, imageOperands);
referenceValue.id,
m_module.constf32(0.0f));
} break; } break;
default: default:

View File

@ -472,7 +472,8 @@ namespace dxvk {
typeSampledTex, typeSampledTex,
module.opLoad(typeTexture, rcTexture), module.opLoad(typeTexture, rcTexture),
module.opLoad(typeSampler, rcSampler)), module.opLoad(typeSampler, rcSampler)),
module.opLoad(typeVec2, inTexCoord))); module.opLoad(typeVec2, inTexCoord),
SpirvImageOperands()));
module.opReturn(); module.opReturn();
module.functionEnd(); module.functionEnd();

View File

@ -1521,14 +1521,18 @@ namespace dxvk {
uint32_t SpirvModule::opImageSampleImplicitLod( uint32_t SpirvModule::opImageSampleImplicitLod(
uint32_t resultType, uint32_t resultType,
uint32_t sampledImage, uint32_t sampledImage,
uint32_t coordinates) { uint32_t coordinates,
const SpirvImageOperands& operands) {
uint32_t resultId = this->allocateId(); 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(resultType);
m_code.putWord(resultId); m_code.putWord(resultId);
m_code.putWord(sampledImage); m_code.putWord(sampledImage);
m_code.putWord(coordinates); m_code.putWord(coordinates);
putImageOperands(operands);
return resultId; return resultId;
} }
@ -1537,16 +1541,18 @@ namespace dxvk {
uint32_t resultType, uint32_t resultType,
uint32_t sampledImage, uint32_t sampledImage,
uint32_t coordinates, uint32_t coordinates,
uint32_t lod) { const SpirvImageOperands& operands) {
uint32_t resultId = this->allocateId(); 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(resultType);
m_code.putWord(resultId); m_code.putWord(resultId);
m_code.putWord(sampledImage); m_code.putWord(sampledImage);
m_code.putWord(coordinates); m_code.putWord(coordinates);
m_code.putWord(spv::ImageOperandsLodMask); m_code.putWord(spv::ImageOperandsLodMask);
m_code.putWord(lod);
putImageOperands(operands);
return resultId; return resultId;
} }
@ -1555,15 +1561,19 @@ namespace dxvk {
uint32_t resultType, uint32_t resultType,
uint32_t sampledImage, uint32_t sampledImage,
uint32_t coordinates, uint32_t coordinates,
uint32_t reference) { uint32_t reference,
const SpirvImageOperands& operands) {
uint32_t resultId = this->allocateId(); 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(resultType);
m_code.putWord(resultId); m_code.putWord(resultId);
m_code.putWord(sampledImage); m_code.putWord(sampledImage);
m_code.putWord(coordinates); m_code.putWord(coordinates);
m_code.putWord(reference); m_code.putWord(reference);
putImageOperands(operands);
return resultId; return resultId;
} }
@ -1573,17 +1583,18 @@ namespace dxvk {
uint32_t sampledImage, uint32_t sampledImage,
uint32_t coordinates, uint32_t coordinates,
uint32_t reference, uint32_t reference,
uint32_t lod) { const SpirvImageOperands& operands) {
uint32_t resultId = this->allocateId(); 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(resultType);
m_code.putWord(resultId); m_code.putWord(resultId);
m_code.putWord(sampledImage); m_code.putWord(sampledImage);
m_code.putWord(coordinates); m_code.putWord(coordinates);
m_code.putWord(reference); m_code.putWord(reference);
m_code.putWord(spv::ImageOperandsLodMask);
m_code.putWord(lod); putImageOperands(operands);
return resultId; return resultId;
} }
@ -1683,4 +1694,54 @@ namespace dxvk {
m_instExt.putStr (name); 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);
}
}
} }

View File

@ -4,6 +4,19 @@
namespace dxvk { 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 * \brief SPIR-V module
* *
@ -518,26 +531,28 @@ namespace dxvk {
uint32_t opImageSampleImplicitLod( uint32_t opImageSampleImplicitLod(
uint32_t resultType, uint32_t resultType,
uint32_t sampledImage, uint32_t sampledImage,
uint32_t coordinates); uint32_t coordinates,
const SpirvImageOperands& operands);
uint32_t opImageSampleExplicitLod( uint32_t opImageSampleExplicitLod(
uint32_t resultType, uint32_t resultType,
uint32_t sampledImage, uint32_t sampledImage,
uint32_t coordinates, uint32_t coordinates,
uint32_t lod); const SpirvImageOperands& operands);
uint32_t opImageSampleDrefImplicitLod( uint32_t opImageSampleDrefImplicitLod(
uint32_t resultType, uint32_t resultType,
uint32_t sampledImage, uint32_t sampledImage,
uint32_t coordinates, uint32_t coordinates,
uint32_t reference); uint32_t reference,
const SpirvImageOperands& operands);
uint32_t opImageSampleDrefExplicitLod( uint32_t opImageSampleDrefExplicitLod(
uint32_t resultType, uint32_t resultType,
uint32_t sampledImage, uint32_t sampledImage,
uint32_t coordinates, uint32_t coordinates,
uint32_t reference, uint32_t reference,
uint32_t lod); const SpirvImageOperands& operands);
void opLoopMerge( void opLoopMerge(
uint32_t mergeBlock, uint32_t mergeBlock,
@ -587,6 +602,12 @@ namespace dxvk {
void instImportGlsl450(); void instImportGlsl450();
uint32_t getImageOperandWordCount(
const SpirvImageOperands& op) const;
void putImageOperands(
const SpirvImageOperands& op);
}; };
} }