From c8b2e36f52e86aaa028e7cc762936fd4a6944f6b Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Sun, 30 Aug 2015 05:43:51 -0600 Subject: [PATCH] Implement GL_KHR_blend_equation_advanced. --- Test/310.frag | 30 +++++++++++ Test/baseResults/310.frag.out | 26 +++++++++- glslang/Include/Types.h | 50 +++++++++++++++++++ glslang/MachineIndependent/ParseHelper.cpp | 25 ++++++++++ glslang/MachineIndependent/Versions.cpp | 4 +- glslang/MachineIndependent/intermOut.cpp | 9 ++++ glslang/MachineIndependent/linkValidate.cpp | 2 + .../MachineIndependent/localintermediate.h | 6 ++- 8 files changed, 148 insertions(+), 4 deletions(-) diff --git a/Test/310.frag b/Test/310.frag index 3de390a90..116a0a733 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 40e0e2d48..910cd9c55 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 8900b5b43..c765d4437 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 f983313f1..b52e63e8f 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 a269ea3d2..28f810610 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 7edae3884..015f91e67 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 643c8883d..19edae46f 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 627f503b3..dedf1e68a 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; -- GitLab