HLSL: split textures used for both shadow and non-shadow modes

A single texture can statically appear in code mixed with a shadow sampler
and a non-shadow sampler.  This would be create invalid SPIR-V, unless
one of them is provably dead.

The previous detection of this happened before DCE, so some shaders would
trigger the error even though they wouldn't after DCE.  To handle that
case, this PR splits the texture into two: one with each mode.  It sets
"needsLegalization" (if that happens for any texture) to warn that this shader
will need post-compilation legalization.

If the texture is only used with one of the two modes, behavior is as it
was before.
This commit is contained in:
LoopDawg
2017-10-05 16:25:52 -06:00
parent 263986eb6e
commit 73c57bbe50
6 changed files with 260 additions and 34 deletions

View File

@@ -457,10 +457,29 @@ 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;
// A texture object may be used with shadow and non-shadow samplers, but both may not be
// alive post-DCE in the same shader. We do not know at compilation time which are alive: that's
// only known post-DCE. If a texture is used both ways, we create two textures, and
// leave the elimiation of one to the optimizer. This maps the shader variant to
// the shadow variant.
//
// This can be removed if and when the texture shadow code in
// HlslParseContext::handleSamplerTextureCombine is removed.
struct tShadowTextureSymbols {
tShadowTextureSymbols() { symId.fill(-1); }
void set(bool shadow, int id) { symId[int(shadow)] = id; }
int get(bool shadow) const { return symId[int(shadow)]; }
// True if this texture has been seen with both shadow and non-shadow modes
bool overloaded() const { return symId[0] != -1 && symId[1] != -1; }
bool isShadowId(int id) const { return symId[1] == id; }
private:
std::array<int, 2> symId;
};
TMap<int, tShadowTextureSymbols*> textureShadowVariant;
};
// This is the prefix we use for built-in methods to avoid namespace collisions with