Parser & SPV: Implement two extensions regarding GLSL sparse texture.

Implement extension "GL_ARB_sparse_texture2".
Implement extension "GL_ARB_sparse_texture_clamp".
This commit is contained in:
Rex Xu
2015-12-31 16:11:41 +08:00
parent e23c9849c2
commit 48edadfd24
12 changed files with 1621 additions and 151 deletions

View File

@@ -1884,6 +1884,14 @@ void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate
void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments)
{
const glslang::TIntermSequence& glslangArguments = node.getSequence();
glslang::TSampler sampler = {};
bool cubeCompare = false;
if (node.isTexture()) {
sampler = glslangArguments[0]->getAsTyped()->getType().getSampler();
cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
}
for (int i = 0; i < (int)glslangArguments.size(); ++i) {
builder.clearAccessChain();
glslangArguments[i]->traverse(this);
@@ -1902,6 +1910,51 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate&
if (i == 0)
lvalue = true;
break;
case glslang::EOpSparseTexture:
if ((cubeCompare && i == 3) || (! cubeCompare && i == 2))
lvalue = true;
break;
case glslang::EOpSparseTextureClamp:
if ((cubeCompare && i == 4) || (! cubeCompare && i == 3))
lvalue = true;
break;
case glslang::EOpSparseTextureLod:
case glslang::EOpSparseTextureOffset:
if (i == 3)
lvalue = true;
break;
case glslang::EOpSparseTextureFetch:
if ((sampler.dim != glslang::EsdRect && i == 3) || (sampler.dim == glslang::EsdRect && i == 2))
lvalue = true;
break;
case glslang::EOpSparseTextureFetchOffset:
if ((sampler.dim != glslang::EsdRect && i == 4) || (sampler.dim == glslang::EsdRect && i == 3))
lvalue = true;
break;
case glslang::EOpSparseTextureLodOffset:
case glslang::EOpSparseTextureGrad:
case glslang::EOpSparseTextureOffsetClamp:
if (i == 4)
lvalue = true;
break;
case glslang::EOpSparseTextureGradOffset:
case glslang::EOpSparseTextureGradClamp:
if (i == 5)
lvalue = true;
break;
case glslang::EOpSparseTextureGradOffsetClamp:
if (i == 6)
lvalue = true;
break;
case glslang::EOpSparseTextureGather:
if ((sampler.shadow && i == 3) || (! sampler.shadow && i == 2))
lvalue = true;
break;
case glslang::EOpSparseTextureGatherOffset:
case glslang::EOpSparseTextureGatherOffsets:
if ((sampler.shadow && i == 4) || (! sampler.shadow && i == 3))
lvalue = true;
break;
default:
break;
}
@@ -1963,6 +2016,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
return builder.createTextureQueryCall(spv::OpImageQueryLod, params);
case glslang::EOpTextureQueryLevels:
return builder.createTextureQueryCall(spv::OpImageQueryLevels, params);
case glslang::EOpSparseTexelsResident:
return builder.createUnaryOp(spv::OpImageSparseTexelsResident, builder.makeBoolType(), arguments[0]);
default:
assert(0);
break;
@@ -1990,7 +2045,11 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
operands.push_back(*opIt);
builder.createNoResultOp(spv::OpImageWrite, operands);
return spv::NoResult;
} else {
} else if (node->isSparseImage()) {
spv::MissingFunctionality("sparse image functions");
return spv::NoResult;
}
else {
// Process image atomic operations
// GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer,
@@ -2010,7 +2069,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
}
// Check for texture functions other than queries
bool sparse = node->isSparseTexture();
bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
// check for bias argument
@@ -2021,6 +2080,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
++nonBiasArgCount;
if (cracked.grad)
nonBiasArgCount += 2;
if (cracked.lodClamp)
++nonBiasArgCount;
if (sparse)
++nonBiasArgCount;
if ((int)arguments.size() > nonBiasArgCount)
bias = true;
@@ -2032,9 +2095,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
int extraArgs = 0;
// sort out where Dref is coming from
if (sampler.shadow && sampler.dim == glslang::EsdCube && sampler.arrayed)
if (cubeCompare) {
params.Dref = arguments[2];
else if (sampler.shadow && cracked.gather) {
++extraArgs;
} else if (sampler.shadow && cracked.gather) {
params.Dref = arguments[2];
++extraArgs;
} else if (sampler.shadow) {
@@ -2066,6 +2130,14 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
params.offsets = arguments[2 + extraArgs];
++extraArgs;
}
if (cracked.lodClamp) {
params.lodClamp = arguments[2 + extraArgs];
++extraArgs;
}
if (sparse) {
params.texelOut = arguments[2 + extraArgs];
++extraArgs;
}
if (bias) {
params.bias = arguments[2 + extraArgs];
++extraArgs;
@@ -2080,7 +2152,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
}
}
return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), cracked.fetch, cracked.proj, cracked.gather, params);
return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), sparse, cracked.fetch, cracked.proj, cracked.gather, params);
}
spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node)

View File

@@ -1222,7 +1222,7 @@ Id Builder::createBuiltinCall(Decoration /*precision*/, Id resultType, Id builti
// Accept all parameters needed to create a texture instruction.
// Create the correct instruction based on the inputs, and make the call.
Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, bool gather, const TextureParameters& parameters)
Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, const TextureParameters& parameters)
{
static const int maxTextureArgs = 10;
Id texArgs[maxTextureArgs] = {};
@@ -1275,6 +1275,10 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, b
mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask);
texArgs[numArgs++] = parameters.sample;
}
if (parameters.lodClamp) {
mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask);
texArgs[numArgs++] = parameters.lodClamp;
}
if (mask == ImageOperandsMaskNone)
--numArgs; // undo speculative reservation for the mask argument
else
@@ -1286,35 +1290,68 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, b
Op opCode;
opCode = OpImageSampleImplicitLod;
if (fetch) {
opCode = OpImageFetch;
if (sparse)
opCode = OpImageSparseFetch;
else
opCode = OpImageFetch;
} else if (gather) {
if (parameters.Dref)
opCode = OpImageDrefGather;
if (sparse)
opCode = OpImageSparseDrefGather;
else
opCode = OpImageDrefGather;
else
opCode = OpImageGather;
if (sparse)
opCode = OpImageSparseGather;
else
opCode = OpImageGather;
} else if (xplicit) {
if (parameters.Dref) {
if (proj)
opCode = OpImageSampleProjDrefExplicitLod;
if (sparse)
opCode = OpImageSparseSampleProjDrefExplicitLod;
else
opCode = OpImageSampleProjDrefExplicitLod;
else
opCode = OpImageSampleDrefExplicitLod;
if (sparse)
opCode = OpImageSparseSampleDrefExplicitLod;
else
opCode = OpImageSampleDrefExplicitLod;
} else {
if (proj)
opCode = OpImageSampleProjExplicitLod;
if (sparse)
opCode = OpImageSparseSampleProjExplicitLod;
else
opCode = OpImageSampleProjExplicitLod;
else
opCode = OpImageSampleExplicitLod;
if (sparse)
opCode = OpImageSparseSampleExplicitLod;
else
opCode = OpImageSampleExplicitLod;
}
} else {
if (parameters.Dref) {
if (proj)
opCode = OpImageSampleProjDrefImplicitLod;
if (sparse)
opCode = OpImageSparseSampleProjDrefImplicitLod;
else
opCode = OpImageSampleProjDrefImplicitLod;
else
opCode = OpImageSampleDrefImplicitLod;
if (sparse)
opCode = OpImageSparseSampleDrefImplicitLod;
else
opCode = OpImageSampleDrefImplicitLod;
} else {
if (proj)
opCode = OpImageSampleProjImplicitLod;
if (sparse)
opCode = OpImageSparseSampleProjImplicitLod;
else
opCode = OpImageSampleProjImplicitLod;
else
opCode = OpImageSampleImplicitLod;
if (sparse)
opCode = OpImageSparseSampleImplicitLod;
else
opCode = OpImageSampleImplicitLod;
}
}
@@ -1335,6 +1372,15 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, b
}
}
Id typeId0 = 0;
Id typeId1 = 0;
if (sparse) {
typeId0 = resultType;
typeId1 = getDerefTypeId(parameters.texelOut);
resultType = makeStructResultType(typeId0, typeId1);
}
// Build the SPIR-V instruction
Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode);
for (int op = 0; op < optArgNum; ++op)
@@ -1348,10 +1394,16 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, b
Id resultId = textureInst->getResultId();
// When a smear is needed, do it, as per what was computed
// above when resultType was changed to a scalar type.
if (resultType != smearedType)
resultId = smearScalar(precision, resultId, smearedType);
if (sparse) {
// Decode the return type that was a special structure
createStore(createCompositeExtract(resultId, typeId1, 1), parameters.texelOut);
resultId = createCompositeExtract(resultId, typeId0, 0);
} else {
// When a smear is needed, do it, as per what was computed
// above when resultType was changed to a scalar type.
if (resultType != smearedType)
resultId = smearScalar(precision, resultId, smearedType);
}
return resultId;
}

View File

@@ -310,10 +310,12 @@ public:
Id gradY;
Id sample;
Id comp;
Id texelOut;
Id lodClamp;
};
// Select the correct texture operation based on all inputs, and emit the correct instruction
Id createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, bool gather, const TextureParameters&);
Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, const TextureParameters&);
// Emit the OpTextureQuery* instruction that was passed in.
// Figure out the right return value and type, and return it.