diff --git a/Test/310.frag b/Test/310.frag index 3de390a908085c010b60285127c28d137f1c283f..116a0a733c4b061a5a6b7e6205bd96d6957fea33 100644 --- a/Test/310.frag +++ b/Test/310.frag @@ -397,3 +397,33 @@ void interp() res4 = interpolateAtSample(outp, 0); // ERROR, not interpolant } +layout(blend_support_softlight) out; // ERROR, need extension + +#ifdef GL_KHR_blend_equation_advanced +#extension GL_KHR_blend_equation_advanced : enable +#endif + +layout(blend_support_multiply) out; +layout(blend_support_screen) out; +layout(blend_support_overlay) out; +layout(blend_support_darken, blend_support_lighten) out; +layout(blend_support_colordodge) layout(blend_support_colorburn) out; +layout(blend_support_hardlight) out; +layout(blend_support_softlight) out; +layout(blend_support_difference) out; +layout(blend_support_exclusion) out; +layout(blend_support_hsl_hue) out; +layout(blend_support_hsl_saturation) out; +layout(blend_support_hsl_color) out; +layout(blend_support_hsl_luminosity) out; +layout(blend_support_all_equations) out; + +layout(blend_support_hsl_luminosity) out; // okay to repeat + +layout(blend_support_hsl_luminosity) in; // ERROR, only on "out" +layout(blend_support_hsl_luminosity) out vec4; // ERROR, only on standalone +layout(blend_support_hsl_luminosity) out vec4 badout; // ERROR, only on standalone +layout(blend_support_hsl_luminosity) struct badS {int i;}; // ERROR, only on standalone +layout(blend_support_hsl_luminosity) void blendFoo() { } // ERROR, only on standalone +void blendFoo(layout(blend_support_hsl_luminosity) vec3 v) { } // ERROR, only on standalone +layout(blend_support_flizbit) out; // ERROR, no flizbit diff --git a/Test/baseResults/310.frag.out b/Test/baseResults/310.frag.out index 40e0e2d48c176d10903e55e145118cda82a06141..910cd9c5558b8d0e4f4b0131872d1ec1d051791f 100644 --- a/Test/baseResults/310.frag.out +++ b/Test/baseResults/310.frag.out @@ -121,12 +121,21 @@ ERROR: 0:391: 'interpolateAtOffset' : first argument must be an interpolant, or ERROR: 0:392: 'interpolateAtOffset' : first argument must be an interpolant, or interpolant-array element ERROR: 0:396: 'interpolateAtCentroid' : first argument must be an interpolant, or interpolant-array element ERROR: 0:397: 'interpolateAtSample' : first argument must be an interpolant, or interpolant-array element -ERROR: 113 compilation errors. No code generated. +ERROR: 0:400: 'blend equation' : required extension not requested: GL_KHR_blend_equation_advanced +ERROR: 0:423: 'blend equation' : can only apply to 'out' +ERROR: 0:424: 'blend equation' : can only apply to a standalone qualifier +ERROR: 0:425: 'blend equation' : can only apply to a standalone qualifier +ERROR: 0:426: 'blend equation' : can only apply to a standalone qualifier +ERROR: 0:427: 'blend equation' : can only apply to a standalone qualifier +ERROR: 0:428: 'blend equation' : can only apply to a standalone qualifier +ERROR: 0:429: 'blend_support' : unknown blend equation +ERROR: 121 compilation errors. No code generated. Shader version: 310 Requested GL_EXT_shader_io_blocks Requested GL_EXT_texture_cube_map_array +Requested GL_KHR_blend_equation_advanced Requested GL_OES_geometry_shader Requested GL_OES_gpu_shader5 Requested GL_OES_sample_variables @@ -137,6 +146,7 @@ gl_FragCoord pixel center is integer gl_FragCoord origin is upper left using early_fragment_tests using depth_any +using blend_support_multiply blend_support_screen blend_support_overlay blend_support_darken blend_support_lighten blend_support_colordodge blend_support_colorburn blend_support_hardlight blend_support_softlight blend_support_difference blend_support_exclusion blend_support_hsl_hue blend_support_hsl_saturation blend_support_hsl_color blend_support_hsl_luminosity blend_support_all_equations ERROR: node is still EOpNull! 0:21 Function Definition: main( (global void) 0:21 Function Parameters: @@ -897,6 +907,11 @@ ERROR: node is still EOpNull! 0:397 'outp' (out mediump 4-component vector of float) 0:397 Constant: 0:397 0 (const int) +0:427 Function Definition: blendFoo( (temp void) +0:427 Function Parameters: +0:428 Function Definition: blendFoo(vf3; (global void) +0:428 Function Parameters: +0:428 'v' (in mediump 3-component vector of float) 0:? Linker Objects 0:? 'gl_FragCoord' (smooth in mediump 4-component vector of float) 0:? 'v3' (layout(location=2 ) smooth in mediump 3-component vector of float) @@ -990,6 +1005,7 @@ ERROR: node is still EOpNull! 0:? 'colorSampleBad' (sample out mediump 4-component vector of float) 0:? 'colorfsi' (flat sample in mediump 4-component vector of float) 0:? 'sampInArray' (smooth sample in 4-element array of mediump 3-component vector of float) +0:? 'badout' (out mediump 4-component vector of float) Linked fragment stage: @@ -999,6 +1015,7 @@ ERROR: Linking fragment stage: when more than one fragment shader output, all mu Shader version: 310 Requested GL_EXT_shader_io_blocks Requested GL_EXT_texture_cube_map_array +Requested GL_KHR_blend_equation_advanced Requested GL_OES_geometry_shader Requested GL_OES_gpu_shader5 Requested GL_OES_sample_variables @@ -1009,6 +1026,7 @@ gl_FragCoord pixel center is integer gl_FragCoord origin is upper left using early_fragment_tests using depth_any +using blend_support_multiply blend_support_screen blend_support_overlay blend_support_darken blend_support_lighten blend_support_colordodge blend_support_colorburn blend_support_hardlight blend_support_softlight blend_support_difference blend_support_exclusion blend_support_hsl_hue blend_support_hsl_saturation blend_support_hsl_color blend_support_hsl_luminosity blend_support_all_equations ERROR: node is still EOpNull! 0:21 Function Definition: main( (global void) 0:21 Function Parameters: @@ -1769,6 +1787,11 @@ ERROR: node is still EOpNull! 0:397 'outp' (out mediump 4-component vector of float) 0:397 Constant: 0:397 0 (const int) +0:427 Function Definition: blendFoo( (temp void) +0:427 Function Parameters: +0:428 Function Definition: blendFoo(vf3; (global void) +0:428 Function Parameters: +0:428 'v' (in mediump 3-component vector of float) 0:? Linker Objects 0:? 'gl_FragCoord' (smooth in mediump 4-component vector of float) 0:? 'v3' (layout(location=2 ) smooth in mediump 3-component vector of float) @@ -1862,4 +1885,5 @@ ERROR: node is still EOpNull! 0:? 'colorSampleBad' (sample out mediump 4-component vector of float) 0:? 'colorfsi' (flat sample in mediump 4-component vector of float) 0:? 'sampInArray' (smooth sample in 4-element array of mediump 3-component vector of float) +0:? 'badout' (out mediump 4-component vector of float) diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 8900b5b433c3104752d2c45cde6ebfea53df6089..c765d44375eb057de0a1ae69349e0994b3f4bdc7 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -294,6 +294,30 @@ enum TLayoutDepth { EldCount }; +enum TBlendEquationShift { + // No 'EBlendNone': + // These are used as bit-shift amounts. A mask of such shifts will have type 'int', + // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set. + EBlendMultiply, + EBlendScreen, + EBlendOverlay, + EBlendDarken, + EBlendLighten, + EBlendColordodge, + EBlendColorburn, + EBlendHardlight, + EBlendSoftlight, + EBlendDifference, + EBlendExclusion, + EBlendHslHue, + EBlendHslSaturation, + EBlendHslColor, + EBlendHslLuminosity, + EBlendAllEquations, + + EBlendCount +}; + class TQualifier { public: void clear() @@ -669,6 +693,28 @@ public: default: return "none"; } } + static const char* getBlendEquationString(TBlendEquationShift e) + { + switch (e) { + case EBlendMultiply: return "blend_support_multiply"; + case EBlendScreen: return "blend_support_screen"; + case EBlendOverlay: return "blend_support_overlay"; + case EBlendDarken: return "blend_support_darken"; + case EBlendLighten: return "blend_support_lighten"; + case EBlendColordodge: return "blend_support_colordodge"; + case EBlendColorburn: return "blend_support_colorburn"; + case EBlendHardlight: return "blend_support_hardlight"; + case EBlendSoftlight: return "blend_support_softlight"; + case EBlendDifference: return "blend_support_difference"; + case EBlendExclusion: return "blend_support_exclusion"; + case EBlendHslHue: return "blend_support_hsl_hue"; + case EBlendHslSaturation: return "blend_support_hsl_saturation"; + case EBlendHslColor: return "blend_support_hsl_color"; + case EBlendHslLuminosity: return "blend_support_hsl_luminosity"; + case EBlendAllEquations: return "blend_support_all_equations"; + default: return "unknown"; + } + } static const char* getGeometryString(TLayoutGeometry geometry) { switch (geometry) { @@ -728,6 +774,7 @@ struct TShaderQualifiers { int localSize[3]; // compute shader bool earlyFragmentTests; // fragment input TLayoutDepth layoutDepth; + bool blendEquation; // true if any blend equation was specified void init() { @@ -744,6 +791,7 @@ struct TShaderQualifiers { localSize[2] = 1; earlyFragmentTests = false; layoutDepth = EldNone; + blendEquation = false; } // Merge in characteristics from the 'src' qualifier. They can override when @@ -774,6 +822,8 @@ struct TShaderQualifiers { earlyFragmentTests = true; if (src.layoutDepth) layoutDepth = src.layoutDepth; + if (src.blendEquation) + blendEquation = src.blendEquation; } }; diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index f983313f1317ac4e255516b4bb331477cedffc60..b52e63e8f79a5ed5122573648d097a8a1542425d 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -2379,6 +2379,9 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut) return; + if (publicType.shaderQualifiers.blendEquation) + error(loc, "can only be applied to a standalone 'out'", "blend equation", ""); + // now, knowing it is a shader in/out, do all the in/out semantic checks if (publicType.basicType == EbtBool) { @@ -3694,6 +3697,21 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi return; } } + if (id.compare(0, 13, "blend_support") == 0) { + bool found = false; + for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) { + if (id == TQualifier::getBlendEquationString(be)) { + requireExtensions(loc, 1, &E_GL_KHR_blend_equation_advanced, "blend equation"); + intermediate.addBlendEquation(be); + publicType.shaderQualifiers.blendEquation = true; + found = true; + break; + } + } + if (! found) + error(loc, "unknown blend equation", "blend_support", ""); + return; + } } error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), ""); } @@ -4232,6 +4250,9 @@ void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQua if (shaderQualifiers.localSize[i] > 1) error(loc, message, "local_size", ""); } + if (shaderQualifiers.blendEquation) + error(loc, message, "blend equation", ""); + // TBD: correctness: are any of these missing? pixelCenterInteger, originUpperLeft, spacing, order, pointmode, earlyfragment, depth } // Correct and/or advance an object's offset layout qualifier. @@ -5480,6 +5501,10 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con else error(loc, "can only apply to 'in'", "early_fragment_tests", ""); } + if (publicType.shaderQualifiers.blendEquation) { + if (publicType.qualifier.storage != EvqVaryingOut) + error(loc, "can only apply to 'out'", "blend equation", ""); + } const TQualifier& qualifier = publicType.qualifier; diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index a269ea3d2d0ea007b1df243a5d0f2270e1ec4219..28f81061049d041d3ab26da0d4dc660d6cb4040c 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -179,8 +179,8 @@ void TParseContext::initializeExtensionBehavior() extensionBehavior[E_GL_GOOGLE_include_directive] = EBhDisable; // AEP - extensionBehavior[E_GL_ANDROID_extension_pack_es31a] = EBhDisablePartial; - extensionBehavior[E_GL_KHR_blend_equation_advanced] = EBhDisablePartial; + extensionBehavior[E_GL_ANDROID_extension_pack_es31a] = EBhDisable; + extensionBehavior[E_GL_KHR_blend_equation_advanced] = EBhDisable; extensionBehavior[E_GL_OES_sample_variables] = EBhDisable; extensionBehavior[E_GL_OES_shader_image_atomic] = EBhDisable; extensionBehavior[E_GL_OES_shader_multisample_interpolation] = EBhDisable; diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index 7edae3884397316c946b6bbae3cc20de16c6d2e4..015f91e67002e1531cff86b50e2ac186e30e3162 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -740,6 +740,15 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree) infoSink.debug << "using early_fragment_tests\n"; if (depthLayout != EldNone) infoSink.debug << "using " << TQualifier::getLayoutDepthString(depthLayout) << "\n"; + if (blendEquations != 0) { + infoSink.debug << "using"; + // blendEquations is a mask, decode it + for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) { + if (blendEquations & (1 << be)) + infoSink.debug << " " << TQualifier::getBlendEquationString(be); + } + infoSink.debug << "\n"; + } break; case EShLangCompute: diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index 643c8883d441803b9d1ccbe2de2b3a8d8b451f34..19edae46f2692714ba98c9a4384dd1784892f464 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -88,6 +88,8 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) else if (depthLayout != unit.depthLayout) error(infoSink, "Contradictory depth layouts"); + blendEquations |= unit.blendEquations; + if (inputPrimitive == ElgNone) inputPrimitive = unit.inputPrimitive; else if (inputPrimitive != unit.inputPrimitive) diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 627f503b361610adc471d88b5ae8eeda9add58ff..dedf1e68a34d255292d65f6aafa4b06db22ce828 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -127,7 +127,7 @@ public: explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v), numMains(0), numErrors(0), recursive(false), invocations(0), vertices(0), inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false), - vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), depthLayout(EldNone), xfbMode(false) + vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), depthLayout(EldNone), blendEquations(0), xfbMode(false) { localSize[0] = 1; localSize[1] = 1; @@ -277,6 +277,9 @@ public: } TLayoutDepth getDepth() const { return depthLayout; } + void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } + unsigned int getBlendEquations() const { return blendEquations; } + void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); void merge(TInfoSink&, TIntermediate&); void finalCheck(TInfoSink&); @@ -332,6 +335,7 @@ protected: int localSize[3]; bool earlyFragmentTests; TLayoutDepth depthLayout; + int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift bool xfbMode; typedef std::list<TCall> TGraph;