[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) {
// 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:

View File

@ -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();

View File

@ -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);
}
}
}

View File

@ -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);
};
}