HLSL: force textures to shadow modes from combined samplers
Texture shadow mode must match the state of the sampler they are combined with. This change does that, both for the AST and the symbol table. Note that the texture cannot easily be *created* the right way, because this may not be known at that time. Instead, the texture is subsequently patched. This cannot work if a single texture is used with both a shadow and non-shadow sampler, so that case is detected and generates an error. This is permitted by the HLSL language, however. See #1073 discussion. Fixed one test source that was using a texture with both shadow and non-shadow samplers.
This commit is contained in:
@@ -2946,6 +2946,36 @@ TIntermAggregate* HlslParseContext::handleSamplerTextureCombine(const TSourceLoc
|
||||
samplerType.combined = true;
|
||||
samplerType.shadow = argSampler->getType().getSampler().shadow;
|
||||
|
||||
{
|
||||
// ** TODO: **
|
||||
// This forces the texture's shadow state to be the sampler's
|
||||
// shadow state. This can't work if a single texture is used with
|
||||
// both comparison and non-comparison samplers, so an error is
|
||||
// reported if the shader does that.
|
||||
//
|
||||
// If this code is ever removed (possibly due to a relaxation in the
|
||||
// SPIR-V rules), also remove the textureShadowMode member variable.
|
||||
TIntermSymbol* texSymbol = argTex->getAsSymbolNode();
|
||||
|
||||
if (texSymbol == nullptr)
|
||||
texSymbol = argTex->getAsBinaryNode()->getLeft()->getAsSymbolNode();
|
||||
|
||||
if (texSymbol != nullptr) {
|
||||
const auto textureShadowModeEntry = textureShadowMode.find(texSymbol->getId());
|
||||
|
||||
// Check to see if this texture has been given a different shadow mode already.
|
||||
if (textureShadowModeEntry != textureShadowMode.end() &&
|
||||
textureShadowModeEntry->second != samplerType.shadow) {
|
||||
error(loc, "all uses of texture must use the same shadow mode", "", "");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
argTex->getWritableType().getSampler().shadow = samplerType.shadow;
|
||||
textureShadowMode[texSymbol->getId()] = samplerType.shadow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
txcombine->setType(TType(samplerType, EvqTemporary));
|
||||
txcombine->setLoc(loc);
|
||||
|
||||
@@ -9463,6 +9493,21 @@ void HlslParseContext::removeUnusedStructBufferCounters()
|
||||
linkageSymbols.erase(endIt, linkageSymbols.end());
|
||||
}
|
||||
|
||||
// Finalization step: patch texture shadow modes to match samplers they were combined with
|
||||
void HlslParseContext::fixTextureShadowModes()
|
||||
{
|
||||
for (auto symbol = linkageSymbols.begin(); symbol != linkageSymbols.end(); ++symbol) {
|
||||
TSampler& sampler = (*symbol)->getWritableType().getSampler();
|
||||
|
||||
if (sampler.isTexture()) {
|
||||
const auto shadowMode = textureShadowMode.find((*symbol)->getUniqueId());
|
||||
if (shadowMode != textureShadowMode.end())
|
||||
sampler.shadow = shadowMode->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// post-processing
|
||||
void HlslParseContext::finish()
|
||||
{
|
||||
@@ -9474,6 +9519,7 @@ void HlslParseContext::finish()
|
||||
|
||||
removeUnusedStructBufferCounters();
|
||||
addPatchConstantInvocation();
|
||||
fixTextureShadowModes();
|
||||
|
||||
TParseContextBase::finish();
|
||||
}
|
||||
|
||||
@@ -262,6 +262,7 @@ protected:
|
||||
bool wasSplit(int id) const { return splitNonIoVars.find(id) != splitNonIoVars.end(); }
|
||||
TVariable* getSplitNonIoVar(int id) const;
|
||||
void addPatchConstantInvocation();
|
||||
void fixTextureShadowModes();
|
||||
TIntermTyped* makeIntegerIndex(TIntermTyped*);
|
||||
|
||||
void fixBuiltInIoType(TType&);
|
||||
@@ -455,6 +456,11 @@ protected:
|
||||
};
|
||||
|
||||
TVector<tMipsOperatorData> mipsOperatorMipArg;
|
||||
|
||||
// This can be removed if and when the texture shadow workarounnd in
|
||||
// HlslParseContext::handleSamplerTextureCombine is removed. It maps
|
||||
// texture symbol IDs to the shadow modes of samplers they were combined with.
|
||||
TMap<int, bool> textureShadowMode;
|
||||
};
|
||||
|
||||
// This is the prefix we use for built-in methods to avoid namespace collisions with
|
||||
|
||||
Reference in New Issue
Block a user