From 21a8770f92f463176e61122df36e3a4950fb5204 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Mon, 21 Oct 2013 19:25:59 +0000 Subject: [PATCH] Add texture gather functions (and extension check) for GLSL 400 and GL_ARB_texture_gather. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23631 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- Test/130.frag | 14 +++ Test/400.frag | 13 ++- Test/baseResults/130.frag.out | 30 ++++- Test/baseResults/400.frag.out | 125 +++++++++++++++++---- Todo.txt | 12 +- glslang/MachineIndependent/Initialize.cpp | 99 +++++++++++++++- glslang/MachineIndependent/Initialize.h | 1 + glslang/MachineIndependent/ParseHelper.cpp | 36 +++++- glslang/MachineIndependent/ParseHelper.h | 1 + glslang/MachineIndependent/Versions.cpp | 5 +- glslang/MachineIndependent/Versions.h | 1 + 11 files changed, 301 insertions(+), 36 deletions(-) diff --git a/Test/130.frag b/Test/130.frag index 57de4489..c65cd0ef 100644 --- a/Test/130.frag +++ b/Test/130.frag @@ -17,3 +17,17 @@ void main() { float clip = gl_ClipDistance[3]; } + +uniform samplerCube sampC; + +void foo() +{ + vec4 s = textureGather(sampC, vec3(0.2)); +} + +#extension GL_ARB_texture_gather : enable + +void bar() +{ + vec4 s = textureGather(sampC, vec3(0.2)); +} diff --git a/Test/400.frag b/Test/400.frag index c57ca065..f1e48c00 100644 --- a/Test/400.frag +++ b/Test/400.frag @@ -1,13 +1,24 @@ -#version 330 core +#version 400 core in vec2 c2D; flat in int i; out vec4 outp; uniform sampler2D arrayedSampler[5]; +uniform usampler2DRect samp2dr; +uniform isampler2DArray isamp2DA; void main() { vec4 v; v = texture(arrayedSampler[i], c2D); outp.x = gl_ClipDistance[1]; + + ivec2 offsets[4]; + uvec4 uv4 = textureGatherOffsets(samp2dr, c2D, offsets, 2); + vec4 v4 = textureGather(arrayedSampler[0], c2D); + ivec4 iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 3); + iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), i); // ERROR, last argument not const + iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 4); // ERROR, last argument out of range + iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 1+2); + iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(i)); } diff --git a/Test/baseResults/130.frag.out b/Test/baseResults/130.frag.out index 9abb24ff..56965232 100644 --- a/Test/baseResults/130.frag.out +++ b/Test/baseResults/130.frag.out @@ -1,5 +1,8 @@ Warning, version 130 is not yet complete; most features are present, but a few are missing. -0:? Sequence +ERROR: 0:25: 'texture gather function' : not supported for this version or the enabled extensions +ERROR: 1 compilation errors. No code generated. + +ERROR: node is still EOpNull! 0:16 Function Definition: main( (void) 0:16 Function Parameters: 0:18 Sequence @@ -10,6 +13,30 @@ Warning, version 130 is not yet complete; most features are present, but a few a 0:18 'gl_ClipDistance' (smooth in unsized array of float) 0:18 Constant: 0:18 3 (const int) +0:23 Function Definition: foo( (void) +0:23 Function Parameters: +0:25 Sequence +0:25 Sequence +0:25 move second child to first child (4-component vector of float) +0:25 's' (4-component vector of float) +0:25 Function Call: textureGather(sC1;vf3; (4-component vector of float) +0:25 'sampC' (uniform samplerCube) +0:25 Constant: +0:25 0.200000 +0:25 0.200000 +0:25 0.200000 +0:30 Function Definition: bar( (void) +0:30 Function Parameters: +0:32 Sequence +0:32 Sequence +0:32 move second child to first child (4-component vector of float) +0:32 's' (4-component vector of float) +0:32 Function Call: textureGather(sC1;vf3; (4-component vector of float) +0:32 'sampC' (uniform samplerCube) +0:32 Constant: +0:32 0.200000 +0:32 0.200000 +0:32 0.200000 0:? Linker Objects 0:? 'a' (3-component vector of float) 0:? 'b' (float) @@ -19,4 +46,5 @@ Warning, version 130 is not yet complete; most features are present, but a few a 0:? 'fflat' (flat in float) 0:? 'fsmooth' (smooth in float) 0:? 'fnop' (noperspective in float) +0:? 'sampC' (uniform samplerCube) diff --git a/Test/baseResults/400.frag.out b/Test/baseResults/400.frag.out index 75c4842d..8a605764 100644 --- a/Test/baseResults/400.frag.out +++ b/Test/baseResults/400.frag.out @@ -1,30 +1,113 @@ -Warning, version 330 is not yet complete; some version-specific features are present, but many are missing. -ERROR: 0:11: 'variable indexing sampler array' : not supported for this version or the enabled extensions -ERROR: 1 compilation errors. No code generated. +Warning, version 400 is not yet complete; some version-specific features are present, but many are missing. +ERROR: 0:20: 'texture gather component' : must be a constant +ERROR: 0:21: 'texture gather component' : must be 0, 1, 2, or 3 +ERROR: 2 compilation errors. No code generated. ERROR: node is still EOpNull! -0:8 Function Definition: main( (void) -0:8 Function Parameters: +0:10 Function Definition: main( (void) +0:10 Function Parameters: 0:? Sequence -0:11 move second child to first child (4-component vector of float) -0:11 'v' (4-component vector of float) -0:11 Function Call: texture(s21;vf2; (4-component vector of float) -0:11 indirect index (uniform sampler2D) -0:11 'arrayedSampler' (uniform 5-element array of sampler2D) -0:11 'i' (flat in int) -0:11 'c2D' (smooth in 2-component vector of float) -0:12 move second child to first child (float) -0:12 direct index (float) -0:12 'outp' (out 4-component vector of float) -0:12 Constant: -0:12 0 (const int) -0:12 direct index (smooth in float) -0:12 'gl_ClipDistance' (smooth in unsized array of float) -0:12 Constant: -0:12 1 (const int) +0:13 move second child to first child (4-component vector of float) +0:13 'v' (4-component vector of float) +0:13 Function Call: texture(s21;vf2; (4-component vector of float) +0:13 indirect index (uniform sampler2D) +0:13 'arrayedSampler' (uniform 5-element array of sampler2D) +0:13 'i' (flat in int) +0:13 'c2D' (smooth in 2-component vector of float) +0:14 move second child to first child (float) +0:14 direct index (float) +0:14 'outp' (out 4-component vector of float) +0:14 Constant: +0:14 0 (const int) +0:14 direct index (smooth in float) +0:14 'gl_ClipDistance' (smooth in unsized array of float) +0:14 Constant: +0:14 1 (const int) +0:17 Sequence +0:17 move second child to first child (4-component vector of uint) +0:17 'uv4' (4-component vector of uint) +0:17 Function Call: textureGatherOffsets(usR21;vf2;vi2[4];i1; (4-component vector of uint) +0:17 'samp2dr' (uniform usampler2DRect) +0:17 'c2D' (smooth in 2-component vector of float) +0:17 'offsets' (4-element array of 2-component vector of int) +0:17 Constant: +0:17 2 (const int) +0:18 Sequence +0:18 move second child to first child (4-component vector of float) +0:18 'v4' (4-component vector of float) +0:18 Function Call: textureGather(s21;vf2; (4-component vector of float) +0:18 direct index (uniform sampler2D) +0:18 'arrayedSampler' (uniform 5-element array of sampler2D) +0:18 Constant: +0:18 0 (const int) +0:18 'c2D' (smooth in 2-component vector of float) +0:19 Sequence +0:19 move second child to first child (4-component vector of int) +0:19 'iv4' (4-component vector of int) +0:19 Function Call: textureGatherOffset(isA21;vf3;vi2;i1; (4-component vector of int) +0:19 'isamp2DA' (uniform isampler2DArray) +0:19 Constant: +0:19 0.100000 +0:19 0.100000 +0:19 0.100000 +0:19 Constant: +0:19 1 (const int) +0:19 1 (const int) +0:19 Constant: +0:19 3 (const int) +0:20 move second child to first child (4-component vector of int) +0:20 'iv4' (4-component vector of int) +0:20 Function Call: textureGatherOffset(isA21;vf3;vi2;i1; (4-component vector of int) +0:20 'isamp2DA' (uniform isampler2DArray) +0:20 Constant: +0:20 0.100000 +0:20 0.100000 +0:20 0.100000 +0:20 Constant: +0:20 1 (const int) +0:20 1 (const int) +0:20 'i' (flat in int) +0:21 move second child to first child (4-component vector of int) +0:21 'iv4' (4-component vector of int) +0:21 Function Call: textureGatherOffset(isA21;vf3;vi2;i1; (4-component vector of int) +0:21 'isamp2DA' (uniform isampler2DArray) +0:21 Constant: +0:21 0.100000 +0:21 0.100000 +0:21 0.100000 +0:21 Constant: +0:21 1 (const int) +0:21 1 (const int) +0:21 Constant: +0:21 4 (const int) +0:22 move second child to first child (4-component vector of int) +0:22 'iv4' (4-component vector of int) +0:22 Function Call: textureGatherOffset(isA21;vf3;vi2;i1; (4-component vector of int) +0:22 'isamp2DA' (uniform isampler2DArray) +0:22 Constant: +0:22 0.100000 +0:22 0.100000 +0:22 0.100000 +0:22 Constant: +0:22 1 (const int) +0:22 1 (const int) +0:22 Constant: +0:22 3 (const int) +0:23 move second child to first child (4-component vector of int) +0:23 'iv4' (4-component vector of int) +0:23 Function Call: textureGatherOffset(isA21;vf3;vi2; (4-component vector of int) +0:23 'isamp2DA' (uniform isampler2DArray) +0:23 Constant: +0:23 0.100000 +0:23 0.100000 +0:23 0.100000 +0:23 Construct ivec2 (2-component vector of int) +0:23 'i' (flat in int) 0:? Linker Objects 0:? 'c2D' (smooth in 2-component vector of float) 0:? 'i' (flat in int) 0:? 'outp' (out 4-component vector of float) 0:? 'arrayedSampler' (uniform 5-element array of sampler2D) +0:? 'samp2dr' (uniform usampler2DRect) +0:? 'isamp2DA' (uniform isampler2DArray) diff --git a/Todo.txt b/Todo.txt index a82851d6..2b5d3421 100644 --- a/Todo.txt +++ b/Todo.txt @@ -115,10 +115,10 @@ Shader Functionality to Implement/Finish - bitCount(),findLSB(), andfindMSB() - New built-in to query LOD, textureQueryLod(). - New overloaded function matching algorithm, handling selection from many valid multiple choices. - - Texture gather functions that return four texels with a single call. - - textureGather() - - textureGatherOffset() - - textureGatherOffsets() + + Texture gather functions that return four texels with a single call. + + textureGather() + + textureGatherOffset() + + textureGatherOffsets() + Add streams out from geometry shader. Output can be directed to streams through + EmitStreamVertex() and EndStreamPrimitive(). GLSL 4.1 @@ -168,8 +168,8 @@ Shader Functionality to Implement/Finish - Make GLSL consistent with the API regarding user clipping, by no longer referring to gl_Position when gl_ClipVertex is not written. Rather, user clipping becomes undefined. - Clarified that a comma sequence-operator expression cannot be a constant expression. E.g., “(2,3)” is not allowed, semantically, as a valid constant expression 3, even though it is an expression that will evaluate to 3. - - Use vec2 instead of vec3 for coordinate in textureGather*(sampler2DRect,...). - - Clarify that textureGatherOffset() can take non-constants for the offsets. + + Use vec2 instead of vec3 for coordinate in textureGather*(sampler2DRect,...). + + Clarify that textureGatherOffset() can take non-constants for the offsets. GLSL 4.3 - Add shader storage buffer objects, as per the ARB_shader_storage_buffer_object extension. This includes - allowing the last member of a storage buffer block to be an array that does not know its size until render time diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index 00689a18..53ffd6cd 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -1397,6 +1397,11 @@ void TBuiltIns::initialize(int version, EProfile profile) // void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile) { + // + // In this function proper, enumerate the types, then calls the next set of functions + // to enumerate all the uses for that type. + // + TBasicType bTypes[3] = { EbtFloat, EbtInt, EbtUint }; // enumerate all the types @@ -1455,8 +1460,11 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile) if (image) addImageFunctions(sampler, typeName, version, profile); - else + else { addSamplingFunctions(sampler, typeName, version, profile); + if (version >= 130) + addGatherFunctions(sampler, typeName, version, profile); + } } } } @@ -1469,6 +1477,8 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile) // Helper function for add2ndGenerationSamplingImaging(), // when adding context-independent built-in functions. // +// Add all the query functions for the given type. +// void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int version, EProfile profile) { // @@ -1502,6 +1512,8 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int versi // Helper function for add2ndGenerationSamplingImaging(), // when adding context-independent built-in functions. // +// Add all the image access functions for the given type. +// void TBuiltIns::addImageFunctions(TSampler sampler, TString& typeName, int version, EProfile profile) { // TODO: 4.2 Functionality: imaging functions @@ -1511,6 +1523,8 @@ void TBuiltIns::addImageFunctions(TSampler sampler, TString& typeName, int versi // Helper function for add2ndGenerationSamplingImaging(), // when adding context-independent built-in functions. // +// Add all the texture lookup functions for the given type. +// void TBuiltIns::addSamplingFunctions(TSampler sampler, TString& typeName, int version, EProfile profile) { // make one string per stage to contain all functions of the passed-in type for that stage @@ -1690,6 +1704,89 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, TString& typeName, int ve } } + +// +// Helper function for add2ndGenerationSamplingImaging(), +// when adding context-independent built-in functions. +// +// Add all the texture gather functions for the given type. +// +void TBuiltIns::addGatherFunctions(TSampler sampler, TString& typeName, int version, EProfile profile) +{ + switch (sampler.dim) { + case Esd2D: + case EsdRect: + case EsdCube: + break; + default: + return; + } + + if (sampler.ms) + return; + + // make one string per stage to contain all functions of the passed-in type for that stage + TString functions[EShLangCount]; + + for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name: none, Offset, and Offsets + + for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument + + if (comp > 0 && sampler.shadow) + continue; + + if (offset > 0 && sampler.dim == EsdCube) + continue; + + TString s; + + // return type + s.append(prefixes[sampler.type]); + s.append("vec4 "); + + // name + s.append("textureGather"); + switch (offset) { + case 1: + s.append("Offset"); + break; + case 2: + s.append("Offsets"); + default: + break; + } + s.append("("); + + // sampler type argument + s.append(typeName); + + // P coordinate argument + s.append(",vec"); + int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0); + s.append(postfixes[totalDims]); + + // refZ argument + if (sampler.shadow) + s.append(",float"); + + // offset argument + if (offset > 0) { + s.append(",ivec2"); + if (offset == 2) + s.append("[4]"); + } + + // comp argument + if (comp) + s.append(",int"); + + s.append(");\n"); + commonBuiltins.append(s); + //printf("%s", s.c_str()); + } + } +} + // // Add context-dependent built-in functions and variables that are present // for the given version and profile. Share common ones across stages, otherwise diff --git a/glslang/MachineIndependent/Initialize.h b/glslang/MachineIndependent/Initialize.h index 2b0c6b03..a45f4259 100644 --- a/glslang/MachineIndependent/Initialize.h +++ b/glslang/MachineIndependent/Initialize.h @@ -69,6 +69,7 @@ protected: void addQueryFunctions(TSampler, TString& typeName, int version, EProfile profile); void addImageFunctions(TSampler, TString& typeName, int version, EProfile profile); void addSamplingFunctions(TSampler, TString& typeName, int version, EProfile profile); + void addGatherFunctions(TSampler, TString& typeName, int version, EProfile profile); TString commonBuiltins; TString stageBuiltins[EShLangCount]; diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index de9c859d..c16c35d4 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -867,10 +867,8 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal qualifierList.push_back(qual); } - // built-in texturing functions get their return value precision from the precision of the sampler - if (builtIn && fnCandidate->getType().getQualifier().precision == EpqNone && - fnCandidate->getParamCount() > 0 && (*fnCandidate)[0].type->getBasicType() == EbtSampler) - result->getQualifier().precision = result->getAsAggregate()->getSequence()[0]->getAsTyped()->getQualifier().precision; + if (builtIn) + nonOpBuiltInCheck(loc, *fnCandidate, result->getAsAggregate()); } } else { // error message was put out by PaFindFunction() @@ -892,6 +890,36 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal return result; } +// +// Do additional checking of built-in function calls that were not mapped +// to built-in operations (e.g., texturing functions). +// +// Assumes there has been a semantically correct match to a built-in function. +// +void TParseContext::nonOpBuiltInCheck(TSourceLoc loc, const TFunction& fnCandidate, TIntermAggregate* callNode) +{ + // built-in texturing functions get their return value precision from the precision of the sampler + if (fnCandidate.getType().getQualifier().precision == EpqNone && + fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler) + callNode->getQualifier().precision = callNode->getAsAggregate()->getSequence()[0]->getAsTyped()->getQualifier().precision; + + if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) { + const char* feature = "texture gather function"; + requireProfile(loc, ~EEsProfile, feature); + profileRequires(loc, ~EEsProfile, 400, GL_ARB_texture_gather, feature); + int lastArgIndex = fnCandidate.getParamCount() - 1; + if (fnCandidate[lastArgIndex].type->getBasicType() == EbtInt && fnCandidate[lastArgIndex].type->isScalar()) { + // the last integral argument to a texture gather must be a constant int between 0 and 3 + if (callNode->getSequence()[lastArgIndex]->getAsConstantUnion()) { + int value = callNode->getSequence()[lastArgIndex]->getAsConstantUnion()->getConstArray()[0].getIConst(); + if (value < 0 || value > 3) + error(loc, "must be 0, 1, 2, or 3", "texture gather component", ""); + } else + error(loc, "must be a constant", "texture gather component", ""); + } + } +} + // // Handle seeing a built-in-type constructor call in the grammar. // diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index cc637846..3e7e1c1d 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -82,6 +82,7 @@ public: TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function); TIntermAggregate* handleFunctionPrototype(TSourceLoc, TFunction&); TIntermTyped* handleFunctionCall(TSourceLoc, TFunction*, TIntermNode*, TIntermAggregate*); + void nonOpBuiltInCheck(TSourceLoc, const TFunction&, TIntermAggregate*); TFunction* handleConstructorCall(TSourceLoc, TPublicType&); bool parseVectorFields(TSourceLoc, const TString&, int vecSize, TVectorFields&); diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index aa6fc526..7e0b493d 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -138,9 +138,10 @@ namespace glslang { // void TParseContext::initializeExtensionBehavior() { - extensionBehavior[GL_ARB_texture_rectangle] = EBhDisable; - extensionBehavior[GL_3DL_array_objects] = EBhDisable; + extensionBehavior[GL_ARB_texture_rectangle] = EBhDisable; + extensionBehavior[GL_3DL_array_objects] = EBhDisable; extensionBehavior[GL_ARB_shading_language_420pack] = EBhDisable; + extensionBehavior[GL_ARB_texture_gather] = EBhDisable; } // diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h index 94fd6445..44e81f38 100644 --- a/glslang/MachineIndependent/Versions.h +++ b/glslang/MachineIndependent/Versions.h @@ -74,6 +74,7 @@ typedef enum { const char* const GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle"; const char* const GL_3DL_array_objects = "GL_3DL_array_objects"; const char* const GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack"; +const char* const GL_ARB_texture_gather = "GL_ARB_texture_gather"; } // end namespace glslang