Commit 195f584e by LoopDawg

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.
parent f21c173a
hlsl.samplecmp.negative.frag hlsl.samplecmp.negative.frag
ERROR: 0:9: '' : expected: SamplerComparisonState ERROR: 0:10: '' : expected: SamplerComparisonState
ERROR: 1 compilation errors. No code generated. ERROR: 1 compilation errors. No code generated.
Shader version: 500 Shader version: 500
gl_FragCoord origin is upper left gl_FragCoord origin is upper left
ERROR: node is still EOpNull! ERROR: node is still EOpNull!
0:7 Function Definition: @main( ( temp 4-component vector of float) 0:8 Function Definition: @main( ( temp 4-component vector of float)
0:7 Function Parameters: 0:8 Function Parameters:
0:? Sequence 0:? Sequence
0:8 texture ( temp float) 0:9 texture ( temp float)
0:8 Construct combined texture-sampler ( temp sampler2DShadow) 0:9 Construct combined texture-sampler ( temp sampler2DShadow)
0:8 'g_shadowTex' ( uniform texture2D) 0:9 'g_shadowTex' ( uniform texture2DShadow)
0:8 'g_shadowSamplerComp' ( uniform sampler) 0:9 'g_shadowSamplerComp' ( uniform sampler)
0:8 Construct vec3 ( temp 3-component vector of float) 0:9 Construct vec3 ( temp 3-component vector of float)
0:? Constant: 0:? Constant:
0:? 0.000000 0:? 0.000000
0:? 0.000000 0:? 0.000000
0:8 Constant: 0:9 Constant:
0:8 0.000000 0:9 0.000000
0:9 ERROR: Bad aggregation op 0:10 ERROR: Bad aggregation op
( temp float) ( temp float)
0:9 'g_shadowTex' ( uniform texture2D) 0:10 'g_nonShadowTex' ( uniform texture2D)
0:9 'g_shadowSampler' ( uniform sampler) 0:10 'g_shadowSampler' ( uniform sampler)
0:? Constant: 0:? Constant:
0:? 0.000000 0:? 0.000000
0:? 0.000000 0:? 0.000000
0:9 Constant: 0:10 Constant:
0:9 0.000000 0:10 0.000000
0:11 Branch: Return with expression 0:12 Branch: Return with expression
0:11 Constant: 0:12 Constant:
0:11 0.000000 0:12 0.000000
0:11 0.000000 0:12 0.000000
0:11 0.000000 0:12 0.000000
0:11 0.000000 0:12 0.000000
0:7 Function Definition: main( ( temp void) 0:8 Function Definition: main( ( temp void)
0:7 Function Parameters: 0:8 Function Parameters:
0:? Sequence 0:? Sequence
0:7 move second child to first child ( temp 4-component vector of float) 0:8 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) 0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:7 Function Call: @main( ( temp 4-component vector of float) 0:8 Function Call: @main( ( temp 4-component vector of float)
0:? Linker Objects 0:? Linker Objects
0:? 'g_shadowTex' ( uniform texture2D) 0:? 'g_nonShadowTex' ( uniform texture2D)
0:? 'g_shadowTex' ( uniform texture2DShadow)
0:? 'g_shadowSampler' ( uniform sampler) 0:? 'g_shadowSampler' ( uniform sampler)
0:? 'g_shadowSamplerComp' ( uniform sampler) 0:? 'g_shadowSamplerComp' ( uniform sampler)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) 0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
...@@ -53,42 +54,43 @@ Linked fragment stage: ...@@ -53,42 +54,43 @@ Linked fragment stage:
Shader version: 500 Shader version: 500
gl_FragCoord origin is upper left gl_FragCoord origin is upper left
ERROR: node is still EOpNull! ERROR: node is still EOpNull!
0:7 Function Definition: @main( ( temp 4-component vector of float) 0:8 Function Definition: @main( ( temp 4-component vector of float)
0:7 Function Parameters: 0:8 Function Parameters:
0:? Sequence 0:? Sequence
0:8 texture ( temp float) 0:9 texture ( temp float)
0:8 Construct combined texture-sampler ( temp sampler2DShadow) 0:9 Construct combined texture-sampler ( temp sampler2DShadow)
0:8 'g_shadowTex' ( uniform texture2D) 0:9 'g_shadowTex' ( uniform texture2DShadow)
0:8 'g_shadowSamplerComp' ( uniform sampler) 0:9 'g_shadowSamplerComp' ( uniform sampler)
0:8 Construct vec3 ( temp 3-component vector of float) 0:9 Construct vec3 ( temp 3-component vector of float)
0:? Constant: 0:? Constant:
0:? 0.000000 0:? 0.000000
0:? 0.000000 0:? 0.000000
0:8 Constant: 0:9 Constant:
0:8 0.000000 0:9 0.000000
0:9 ERROR: Bad aggregation op 0:10 ERROR: Bad aggregation op
( temp float) ( temp float)
0:9 'g_shadowTex' ( uniform texture2D) 0:10 'g_nonShadowTex' ( uniform texture2D)
0:9 'g_shadowSampler' ( uniform sampler) 0:10 'g_shadowSampler' ( uniform sampler)
0:? Constant: 0:? Constant:
0:? 0.000000 0:? 0.000000
0:? 0.000000 0:? 0.000000
0:9 Constant: 0:10 Constant:
0:9 0.000000 0:10 0.000000
0:11 Branch: Return with expression 0:12 Branch: Return with expression
0:11 Constant: 0:12 Constant:
0:11 0.000000 0:12 0.000000
0:11 0.000000 0:12 0.000000
0:11 0.000000 0:12 0.000000
0:11 0.000000 0:12 0.000000
0:7 Function Definition: main( ( temp void) 0:8 Function Definition: main( ( temp void)
0:7 Function Parameters: 0:8 Function Parameters:
0:? Sequence 0:? Sequence
0:7 move second child to first child ( temp 4-component vector of float) 0:8 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) 0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:7 Function Call: @main( ( temp 4-component vector of float) 0:8 Function Call: @main( ( temp 4-component vector of float)
0:? Linker Objects 0:? Linker Objects
0:? 'g_shadowTex' ( uniform texture2D) 0:? 'g_nonShadowTex' ( uniform texture2D)
0:? 'g_shadowTex' ( uniform texture2DShadow)
0:? 'g_shadowSampler' ( uniform sampler) 0:? 'g_shadowSampler' ( uniform sampler)
0:? 'g_shadowSamplerComp' ( uniform sampler) 0:? 'g_shadowSamplerComp' ( uniform sampler)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) 0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
......
Texture2D g_nonShadowTex;
Texture2D g_shadowTex; Texture2D g_shadowTex;
SamplerState g_shadowSampler; SamplerState g_shadowSampler;
SamplerComparisonState g_shadowSamplerComp; SamplerComparisonState g_shadowSamplerComp;
...@@ -6,7 +7,7 @@ SamplerComparisonState g_shadowSamplerComp; ...@@ -6,7 +7,7 @@ SamplerComparisonState g_shadowSamplerComp;
float4 main() : SV_Target0 float4 main() : SV_Target0
{ {
g_shadowTex.SampleCmp(g_shadowSamplerComp, float2(0,0), 0); // OK g_shadowTex.SampleCmp(g_shadowSamplerComp, float2(0,0), 0); // OK
g_shadowTex.SampleCmp(g_shadowSampler, float2(0,0), 0); // ERROR (should be comparison sampler) g_nonShadowTex.SampleCmp(g_shadowSampler, float2(0,0), 0); // ERROR (should be comparison sampler)
return 0; return 0;
} }
...@@ -2946,6 +2946,36 @@ TIntermAggregate* HlslParseContext::handleSamplerTextureCombine(const TSourceLoc ...@@ -2946,6 +2946,36 @@ TIntermAggregate* HlslParseContext::handleSamplerTextureCombine(const TSourceLoc
samplerType.combined = true; samplerType.combined = true;
samplerType.shadow = argSampler->getType().getSampler().shadow; 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->setType(TType(samplerType, EvqTemporary));
txcombine->setLoc(loc); txcombine->setLoc(loc);
...@@ -9463,6 +9493,21 @@ void HlslParseContext::removeUnusedStructBufferCounters() ...@@ -9463,6 +9493,21 @@ void HlslParseContext::removeUnusedStructBufferCounters()
linkageSymbols.erase(endIt, linkageSymbols.end()); 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 // post-processing
void HlslParseContext::finish() void HlslParseContext::finish()
{ {
...@@ -9474,6 +9519,7 @@ void HlslParseContext::finish() ...@@ -9474,6 +9519,7 @@ void HlslParseContext::finish()
removeUnusedStructBufferCounters(); removeUnusedStructBufferCounters();
addPatchConstantInvocation(); addPatchConstantInvocation();
fixTextureShadowModes();
TParseContextBase::finish(); TParseContextBase::finish();
} }
......
...@@ -262,6 +262,7 @@ protected: ...@@ -262,6 +262,7 @@ protected:
bool wasSplit(int id) const { return splitNonIoVars.find(id) != splitNonIoVars.end(); } bool wasSplit(int id) const { return splitNonIoVars.find(id) != splitNonIoVars.end(); }
TVariable* getSplitNonIoVar(int id) const; TVariable* getSplitNonIoVar(int id) const;
void addPatchConstantInvocation(); void addPatchConstantInvocation();
void fixTextureShadowModes();
TIntermTyped* makeIntegerIndex(TIntermTyped*); TIntermTyped* makeIntegerIndex(TIntermTyped*);
void fixBuiltInIoType(TType&); void fixBuiltInIoType(TType&);
...@@ -455,6 +456,11 @@ protected: ...@@ -455,6 +456,11 @@ protected:
}; };
TVector<tMipsOperatorData> mipsOperatorMipArg; 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 // This is the prefix we use for built-in methods to avoid namespace collisions with
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment