Pure Texture to Sampled Texture Transform

Adds a transformation step to the post processing step.
Two modes are available:
1) keep
- Keeps samplers, textures and sampled textures as is
2) transform pure texture into sampled texture and remove pure samplers
- removes all pure samplers
- transforms all pure textures into its sampled counter part

Change-Id: If54972e8052961db66c23f4b7e719d363cf6edbd
This commit is contained in:
t.jung 2017-04-25 23:31:03 +02:00
parent d6af18f621
commit baf570efa5
9 changed files with 159 additions and 2 deletions

View File

@ -0,0 +1,38 @@
spv.texture.sampler.transform.frag
Warning, version 440 is not yet complete; most version-specific features are present, but some are missing.
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 19
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 9 16
ExecutionMode 4 OriginUpperLeft
Source GLSL 440
Name 4 "main"
Name 9 "color"
Name 12 "tex"
Name 16 "coord"
Decorate 12(tex) DescriptorSet 0
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
8: TypePointer Output 7(fvec4)
9(color): 8(ptr) Variable Output
10: TypeImage 6(float) 2D sampled format:Unknown
11: TypePointer UniformConstant 10
12(tex): 11(ptr) Variable UniformConstant
14: TypeVector 6(float) 2
15: TypePointer Input 14(fvec2)
16(coord): 15(ptr) Variable Input
4(main): 2 Function None 3
5: Label
13: 10 Load 12(tex)
17: 14(fvec2) Load 16(coord)
18: 7(fvec4) ImageSampleImplicitLod 13 17
Store 9(color) 18
Return
FunctionEnd

View File

@ -0,0 +1,13 @@
#version 440
uniform sampler smp;
uniform texture2D tex;
in vec2 coord;
out vec4 color;
void main()
{
color = texture(sampler2D(tex, smp), coord);
}

View File

@ -1310,6 +1310,7 @@ public:
virtual TBasicType getBasicType() const { return basicType; }
virtual const TSampler& getSampler() const { return sampler; }
virtual TSampler& getSampler() { return sampler; }
virtual TQualifier& getQualifier() { return qualifier; }
virtual const TQualifier& getQualifier() const { return qualifier; }

View File

@ -1776,6 +1776,14 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
// Propagate 'noContraction' label in backward from 'precise' variables.
glslang::PropagateNoContraction(*this);
switch (textureSamplerTransformMode) {
case EShTexSampTransKeep:
break;
case EShTexSampTransUpgradeTextureRemoveSampler:
performTextureUpgradeAndSamplerRemovalTransformation(root);
break;
}
return true;
}
@ -2943,4 +2951,41 @@ bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TInt
(node2.getType().getQualifier().isSpecConstant() && node1.getType().getQualifier().isConstant());
}
struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser {
bool visitAggregate(TVisit, TIntermAggregate* ag) override {
using namespace std;
TIntermSequence& seq = ag->getSequence();
// remove pure sampler variables
TIntermSequence::iterator newEnd = remove_if(seq.begin(), seq.end(), [](TIntermNode* node) {
TIntermSymbol* symbol = node->getAsSymbolNode();
if (!symbol)
return false;
return (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isPureSampler());
});
seq.erase(newEnd, seq.end());
// replace constructors with sampler/textures
// update textures into sampled textures
for_each(seq.begin(), seq.end(), [](TIntermNode*& node) {
TIntermSymbol* symbol = node->getAsSymbolNode();
if (!symbol) {
TIntermAggregate *constructor = node->getAsAggregate();
if (constructor && constructor->getOp() == EOpConstructTextureSampler) {
if (!constructor->getSequence().empty())
node = constructor->getSequence()[0];
}
} else if (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isTexture()) {
symbol->getWritableType().getSampler().combined = true;
}
});
return true;
}
};
void TIntermediate::performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root)
{
TextureUpgradeAndSamplerRemovalTransform transform;
root->traverse(&transform);
}
} // end namespace glslang

View File

@ -1578,6 +1578,7 @@ void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslI
void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); }
void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); }
void TShader::setResourceSetBinding(const std::vector<std::string>& base) { intermediate->setResourceSetBinding(base); }
void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
//
// Turn the shader strings into a parse tree in the TIntermediate.

View File

@ -182,7 +182,8 @@ public:
useUnknownFormat(false),
hlslOffsets(false),
useStorageBuffer(false),
hlslIoMapping(false)
hlslIoMapping(false),
textureSamplerTransformMode(EShTexSampTransKeep)
{
localSize[0] = 1;
localSize[1] = 1;
@ -233,6 +234,7 @@ public:
bool usingStorageBuffer() const { return useStorageBuffer; }
void setHlslIoMapping(bool b) { hlslIoMapping = b; }
bool usingHlslIoMapping() { return hlslIoMapping; }
void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
void setVersion(int v) { version = v; }
int getVersion() const { return version; }
@ -472,6 +474,7 @@ protected:
void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&);
void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
const EShLanguage language; // stage, known at construction time
EShSource source; // source language, known a bit later
@ -536,6 +539,8 @@ protected:
std::unordered_set<int> usedConstantId; // specialization constant ids used
std::set<TString> semanticNameSet;
EShTextureSamplerTransformMode textureSamplerTransformMode;
private:
void operator=(TIntermediate&); // prevent assignments
};

View File

@ -134,6 +134,14 @@ typedef enum {
EShOptFull, // Optimizations that will take more time
} EShOptimizationLevel;
//
// Texture and Sampler transformation mode.
//
typedef enum {
EShTexSampTransKeep, // keep textures and samplers as is (default)
EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers
} EShTextureSamplerTransformMode;
//
// Message choices for what errors and warnings are given.
//
@ -313,6 +321,7 @@ public:
void setHlslIoMapping(bool hlslIoMap);
void setFlattenUniformArrays(bool flatten);
void setNoStorageFormat(bool useUnknownFormat);
void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
// Interface to #include handlers.
//

View File

@ -75,6 +75,7 @@ using CompileVulkanToSpirvTestAMD = GlslangTest<::testing::TestWithParam<std::st
#ifdef NV_EXTENSIONS
using CompileVulkanToSpirvTestNV = GlslangTest<::testing::TestWithParam<std::string>>;
#endif
using CompileUpgradeTextureToSampledTextureAndDropSamplersTest = GlslangTest<::testing::TestWithParam<std::string>>;
// Compiling GLSL to SPIR-V under Vulkan semantics. Expected to successfully
// generate SPIR-V.
@ -172,6 +173,15 @@ TEST_P(CompileVulkanToSpirvTestNV, FromFile)
}
#endif
TEST_P(CompileUpgradeTextureToSampledTextureAndDropSamplersTest, FromFile)
{
loadCompileUpgradeTextureToSampledTextureAndDropSamplersAndCheck(GlobalTestSettings.testRoot,
GetParam(),
Source::GLSL,
Semantics::Vulkan,
Target::Spv);
}
// clang-format off
INSTANTIATE_TEST_CASE_P(
Glsl, CompileVulkanToSpirvTest,
@ -407,6 +417,14 @@ INSTANTIATE_TEST_CASE_P(
FileNameAsCustomTestSuffix
);
#endif
INSTANTIATE_TEST_CASE_P(
Glsl, CompileUpgradeTextureToSampledTextureAndDropSamplersTest,
::testing::ValuesIn(std::vector<std::string>({
"spv.texture.sampler.transform.frag",
})),
FileNameAsCustomTestSuffix
);
// clang-format on
} // anonymous namespace

View File

@ -197,12 +197,14 @@ public:
GlslangResult compileAndLink(
const std::string shaderName, const std::string& code,
const std::string& entryPointName, EShMessages controls,
bool flattenUniformArrays = false)
bool flattenUniformArrays = false,
EShTextureSamplerTransformMode texSampTransMode = EShTexSampTransKeep)
{
const EShLanguage kind = GetShaderStage(GetSuffix(shaderName));
glslang::TShader shader(kind);
shader.setAutoMapLocations(true);
shader.setTextureSamplerTransformMode(texSampTransMode);
shader.setFlattenUniformArrays(flattenUniformArrays);
bool success = compile(&shader, code, entryPointName, controls);
@ -570,6 +572,31 @@ public:
expectedErrorFname);
}
void loadCompileUpgradeTextureToSampledTextureAndDropSamplersAndCheck(const std::string& testDir,
const std::string& testName,
Source source,
Semantics semantics,
Target target,
const std::string& entryPointName = "")
{
const std::string inputFname = testDir + "/" + testName;
const std::string expectedOutputFname = testDir + "/baseResults/" + testName + ".out";
std::string input, expectedOutput;
tryLoadFile(inputFname, "input", &input);
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
const EShMessages controls = DeriveOptions(source, semantics, target);
GlslangResult result = compileAndLink(testName, input, entryPointName, controls, false, EShTexSampTransUpgradeTextureRemoveSampler);
// Generate the hybrid output in the way of glslangValidator.
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(),
expectedOutputFname);
}
private:
const int defaultVersion;
const EProfile defaultProfile;