Skip to content

Commit

Permalink
Merge pull request #856 from TiemoJung/texture_upgrade
Browse files Browse the repository at this point in the history
Pure Texture to Sampled Texture Transform
  • Loading branch information
johnkslang authored May 29, 2017
2 parents d6af18f + baf570e commit 136b1e2
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 2 deletions.
38 changes: 38 additions & 0 deletions Test/baseResults/spv.texture.sampler.transform.frag.out
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions Test/spv.texture.sampler.transform.frag
Original file line number Diff line number Diff line change
@@ -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);
}
1 change: 1 addition & 0 deletions glslang/Include/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,7 @@ class TType {

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; }
Expand Down
45 changes: 45 additions & 0 deletions glslang/MachineIndependent/Intermediate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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
1 change: 1 addition & 0 deletions glslang/MachineIndependent/ShaderLang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 6 additions & 1 deletion glslang/MachineIndependent/localintermediate.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ class TIntermediate {
useUnknownFormat(false),
hlslOffsets(false),
useStorageBuffer(false),
hlslIoMapping(false)
hlslIoMapping(false),
textureSamplerTransformMode(EShTexSampTransKeep)
{
localSize[0] = 1;
localSize[1] = 1;
Expand Down Expand Up @@ -233,6 +234,7 @@ class TIntermediate {
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; }
Expand Down Expand Up @@ -472,6 +474,7 @@ class TIntermediate {
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
Expand Down Expand Up @@ -536,6 +539,8 @@ class TIntermediate {
std::unordered_set<int> usedConstantId; // specialization constant ids used
std::set<TString> semanticNameSet;

EShTextureSamplerTransformMode textureSamplerTransformMode;

private:
void operator=(TIntermediate&); // prevent assignments
};
Expand Down
9 changes: 9 additions & 0 deletions glslang/Public/ShaderLang.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//
Expand Down Expand Up @@ -313,6 +321,7 @@ class TShader {
void setHlslIoMapping(bool hlslIoMap);
void setFlattenUniformArrays(bool flatten);
void setNoStorageFormat(bool useUnknownFormat);
void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);

// Interface to #include handlers.
//
Expand Down
18 changes: 18 additions & 0 deletions gtests/Spv.FromFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
29 changes: 28 additions & 1 deletion gtests/TestFixture.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,14 @@ class GlslangTest : public GT {
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);
Expand Down Expand Up @@ -570,6 +572,31 @@ class GlslangTest : public GT {
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;
Expand Down

0 comments on commit 136b1e2

Please sign in to comment.