mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-07 06:09:57 +03:00
Vulkan: Shader support for KHR_blend_equation_advanced
Translator can accept the layout qualifiers for the advanced blend equation. No emulation code is currently generated, and ANGLE will initially rely on the corresponding Vulkan extension. Based on change by Brandon Schade <b.schade@samsung.com> Bug: angleproject:3586 Test: angle_unittests --gtest_filter=*KHRBlendEquationAdvanced* Change-Id: I3b728c5f144386d7030bbbb301ddb07daa1492b9 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3481309 Reviewed-by: Brandon Schade <b.schade@samsung.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
committed by
Angle LUCI CQ
parent
b69349bc62
commit
1e773db907
@@ -26,7 +26,7 @@
|
||||
|
||||
// Version number for shader translation API.
|
||||
// It is incremented every time the API changes.
|
||||
#define ANGLE_SH_VERSION 270
|
||||
#define ANGLE_SH_VERSION 271
|
||||
|
||||
enum ShShaderSpec
|
||||
{
|
||||
@@ -418,6 +418,7 @@ struct ShBuiltInResources
|
||||
int OES_primitive_bounding_box;
|
||||
int ANGLE_base_vertex_base_instance_shader_builtin;
|
||||
int ANDROID_extension_pack_es31a;
|
||||
int KHR_blend_equation_advanced;
|
||||
|
||||
// Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
|
||||
// with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate
|
||||
@@ -794,6 +795,10 @@ GLenum GetTessGenSpacing(const ShHandle handle);
|
||||
GLenum GetTessGenVertexOrder(const ShHandle handle);
|
||||
GLenum GetTessGenPointMode(const ShHandle handle);
|
||||
|
||||
// Returns the blend equation list supported in the fragment shader. This is a bitset of
|
||||
// gl::BlendEquationType, and can only include bits from KHR_blend_equation_advanced.
|
||||
uint32_t GetAdvancedBlendEquations(const ShHandle handle);
|
||||
|
||||
//
|
||||
// Helper function to identify specs that are based on the WebGL spec.
|
||||
//
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// This type is defined here to simplify ANGLE's integration with glslang for SPIRv.
|
||||
// This type is defined here to simplify ANGLE's integration with glslang for SPIR-V.
|
||||
using ShCompileOptions = uint64_t;
|
||||
|
||||
namespace sh
|
||||
@@ -219,7 +219,7 @@ struct ShaderVariable
|
||||
bool readonly;
|
||||
bool writeonly;
|
||||
|
||||
// From EXT_shader_framebuffer_fetch
|
||||
// From EXT_shader_framebuffer_fetch / KHR_blend_equation_advanced
|
||||
bool isFragmentInOut;
|
||||
|
||||
// OutputVariable
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
"src/compiler/translator/generate_parser.py":
|
||||
"ad919972a040d9b3b4aa5dc547fadc75",
|
||||
"src/compiler/translator/glslang.l":
|
||||
"921021111f9906b6b4869375b152499b",
|
||||
"9b5ed85f6601eb6b13a9476916e448e0",
|
||||
"src/compiler/translator/glslang.y":
|
||||
"bbc109b19c5a4724d0e2f9191ac52603",
|
||||
"src/compiler/translator/glslang_lex_autogen.cpp":
|
||||
"18f56a5303e6b7e061d8aadef69faf9b",
|
||||
"9ad7d62cfd81e36db3c97390c8f8ad26",
|
||||
"src/compiler/translator/glslang_tab_autogen.cpp":
|
||||
"d2408828dd4449860b1bd06ea97707a5",
|
||||
"src/compiler/translator/glslang_tab_autogen.h":
|
||||
|
||||
@@ -347,6 +347,51 @@ std::ostream &operator<<(std::ostream &os, BlendEquationType value)
|
||||
case BlendEquationType::ReverseSubtract:
|
||||
os << "GL_FUNC_REVERSE_SUBTRACT";
|
||||
break;
|
||||
case BlendEquationType::Multiply:
|
||||
os << "GL_MULTIPLY_KHR";
|
||||
break;
|
||||
case BlendEquationType::Screen:
|
||||
os << "GL_SCREEN_KHR";
|
||||
break;
|
||||
case BlendEquationType::Overlay:
|
||||
os << "GL_OVERLAY_KHR";
|
||||
break;
|
||||
case BlendEquationType::Darken:
|
||||
os << "GL_DARKEN_KHR";
|
||||
break;
|
||||
case BlendEquationType::Lighten:
|
||||
os << "GL_LIGHTEN_KHR";
|
||||
break;
|
||||
case BlendEquationType::Colordodge:
|
||||
os << "GL_COLORDODGE_KHR";
|
||||
break;
|
||||
case BlendEquationType::Colorburn:
|
||||
os << "GL_COLORBURN_KHR";
|
||||
break;
|
||||
case BlendEquationType::Hardlight:
|
||||
os << "GL_HARDLIGHT_KHR";
|
||||
break;
|
||||
case BlendEquationType::Softlight:
|
||||
os << "GL_SOFTLIGHT_KHR";
|
||||
break;
|
||||
case BlendEquationType::Difference:
|
||||
os << "GL_DIFFERENCE_KHR";
|
||||
break;
|
||||
case BlendEquationType::Exclusion:
|
||||
os << "GL_EXCLUSION_KHR";
|
||||
break;
|
||||
case BlendEquationType::HslHue:
|
||||
os << "GL_HSL_HUE_KHR";
|
||||
break;
|
||||
case BlendEquationType::HslSaturation:
|
||||
os << "GL_HSL_SATURATION_KHR";
|
||||
break;
|
||||
case BlendEquationType::HslColor:
|
||||
os << "GL_HSL_COLOR_KHR";
|
||||
break;
|
||||
case BlendEquationType::HslLuminosity:
|
||||
os << "GL_HSL_LUMINOSITY_KHR";
|
||||
break;
|
||||
default:
|
||||
os << "GL_INVALID_ENUM";
|
||||
break;
|
||||
|
||||
@@ -341,23 +341,72 @@ enum class BlendEquationType
|
||||
Unused = 3,
|
||||
Subtract = 4, // GLenum == 0x800A
|
||||
ReverseSubtract = 5, // GLenum == 0x800B
|
||||
InvalidEnum = 6,
|
||||
EnumCount = 6
|
||||
|
||||
Multiply = 6, // GLenum == 0x9294
|
||||
Screen = 7, // GLenum == 0x9295
|
||||
Overlay = 8, // GLenum == 0x9296
|
||||
Darken = 9, // GLenum == 0x9297
|
||||
Lighten = 10, // GLenum == 0x9298
|
||||
Colordodge = 11, // GLenum == 0x9299
|
||||
Colorburn = 12, // GLenum == 0x929A
|
||||
Hardlight = 13, // GLenum == 0x929B
|
||||
Softlight = 14, // GLenum == 0x929C
|
||||
Unused2 = 15,
|
||||
Difference = 16, // GLenum == 0x929E
|
||||
Unused3 = 17,
|
||||
Exclusion = 18, // GLenum == 0x92A0
|
||||
|
||||
HslHue = 19, // GLenum == 0x92AD
|
||||
HslSaturation = 20, // GLenum == 0x92AE
|
||||
HslColor = 21, // GLenum == 0x92AF
|
||||
HslLuminosity = 22, // GLenum == 0x92B0
|
||||
|
||||
InvalidEnum = 23,
|
||||
EnumCount = InvalidEnum
|
||||
};
|
||||
|
||||
using BlendEquationBitSet = angle::PackedEnumBitSet<gl::BlendEquationType>;
|
||||
|
||||
template <>
|
||||
constexpr BlendEquationType FromGLenum<BlendEquationType>(GLenum from)
|
||||
{
|
||||
const GLenum scaled = (from - GL_FUNC_ADD);
|
||||
return (scaled == static_cast<GLenum>(BlendEquationType::Unused) ||
|
||||
scaled >= static_cast<GLenum>(BlendEquationType::EnumCount))
|
||||
? BlendEquationType::InvalidEnum
|
||||
: static_cast<BlendEquationType>(scaled);
|
||||
if (from <= GL_FUNC_REVERSE_SUBTRACT)
|
||||
{
|
||||
const GLenum scaled = (from - GL_FUNC_ADD);
|
||||
return (scaled == static_cast<GLenum>(BlendEquationType::Unused))
|
||||
? BlendEquationType::InvalidEnum
|
||||
: static_cast<BlendEquationType>(scaled);
|
||||
}
|
||||
if (from <= GL_EXCLUSION_KHR)
|
||||
{
|
||||
const GLenum scaled =
|
||||
(from - GL_MULTIPLY_KHR + static_cast<uint32_t>(BlendEquationType::Multiply));
|
||||
return (scaled == static_cast<GLenum>(BlendEquationType::Unused2) ||
|
||||
scaled == static_cast<GLenum>(BlendEquationType::Unused3))
|
||||
? BlendEquationType::InvalidEnum
|
||||
: static_cast<BlendEquationType>(scaled);
|
||||
}
|
||||
if (from <= GL_HSL_LUMINOSITY_KHR)
|
||||
{
|
||||
return static_cast<BlendEquationType>(from - GL_HSL_HUE_KHR +
|
||||
static_cast<uint32_t>(BlendEquationType::HslHue));
|
||||
}
|
||||
return BlendEquationType::InvalidEnum;
|
||||
}
|
||||
|
||||
constexpr GLenum ToGLenum(BlendEquationType from)
|
||||
{
|
||||
return static_cast<GLenum>(from) + GL_FUNC_ADD;
|
||||
if (from <= BlendEquationType::ReverseSubtract)
|
||||
{
|
||||
return static_cast<GLenum>(from) + GL_FUNC_ADD;
|
||||
}
|
||||
if (from <= BlendEquationType::Exclusion)
|
||||
{
|
||||
return static_cast<GLenum>(from) - static_cast<GLenum>(BlendEquationType::Multiply) +
|
||||
GL_MULTIPLY_KHR;
|
||||
}
|
||||
return static_cast<GLenum>(from) - static_cast<GLenum>(BlendEquationType::HslHue) +
|
||||
GL_HSL_HUE_KHR;
|
||||
}
|
||||
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Add, GL_FUNC_ADD);
|
||||
@@ -365,6 +414,21 @@ ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Min, GL_MIN);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Max, GL_MAX);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Subtract, GL_FUNC_SUBTRACT);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, ReverseSubtract, GL_FUNC_REVERSE_SUBTRACT);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Multiply, GL_MULTIPLY_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Screen, GL_SCREEN_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Overlay, GL_OVERLAY_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Darken, GL_DARKEN_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Lighten, GL_LIGHTEN_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Colordodge, GL_COLORDODGE_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Colorburn, GL_COLORBURN_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Hardlight, GL_HARDLIGHT_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Softlight, GL_SOFTLIGHT_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Difference, GL_DIFFERENCE_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Exclusion, GL_EXCLUSION_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslHue, GL_HSL_HUE_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslSaturation, GL_HSL_SATURATION_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslColor, GL_HSL_COLOR_KHR);
|
||||
ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, HslLuminosity, GL_HSL_LUMINOSITY_KHR);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, BlendEquationType value);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ angle_translator_sources = [
|
||||
"include/GLES3/gl3platform.h",
|
||||
"include/KHR/khrplatform.h",
|
||||
"include/angle_gl.h",
|
||||
"src/compiler/translator/BaseTypes.cpp",
|
||||
"src/compiler/translator/BaseTypes.h",
|
||||
"src/compiler/translator/BuiltInFunctionEmulator.cpp",
|
||||
"src/compiler/translator/BuiltInFunctionEmulator.h",
|
||||
|
||||
64
src/compiler/translator/BaseTypes.cpp
Normal file
64
src/compiler/translator/BaseTypes.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// Copyright 2022 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
#include "BaseTypes.h"
|
||||
|
||||
#include "common/PackedEnums.h"
|
||||
|
||||
namespace sh
|
||||
{
|
||||
namespace
|
||||
{
|
||||
constexpr gl::BlendEquationBitSet kAdvancedBlendBits{
|
||||
gl::BlendEquationType::Multiply, gl::BlendEquationType::Screen,
|
||||
gl::BlendEquationType::Overlay, gl::BlendEquationType::Darken,
|
||||
gl::BlendEquationType::Lighten, gl::BlendEquationType::Colordodge,
|
||||
gl::BlendEquationType::Colorburn, gl::BlendEquationType::Hardlight,
|
||||
gl::BlendEquationType::Softlight, gl::BlendEquationType::Difference,
|
||||
gl::BlendEquationType::Exclusion, gl::BlendEquationType::HslHue,
|
||||
gl::BlendEquationType::HslSaturation, gl::BlendEquationType::HslColor,
|
||||
gl::BlendEquationType::HslLuminosity,
|
||||
};
|
||||
|
||||
constexpr gl::BlendEquationBitSet kAdvancedBlendHslBits{
|
||||
gl::BlendEquationType::HslHue,
|
||||
gl::BlendEquationType::HslSaturation,
|
||||
gl::BlendEquationType::HslColor,
|
||||
gl::BlendEquationType::HslLuminosity,
|
||||
};
|
||||
|
||||
bool IsValidAdvancedBlendBitSet(uint32_t enabledEquations)
|
||||
{
|
||||
return (gl::BlendEquationBitSet(enabledEquations) & ~kAdvancedBlendBits).none();
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
bool AdvancedBlendEquations::any() const
|
||||
{
|
||||
ASSERT(IsValidAdvancedBlendBitSet(mEnabledBlendEquations));
|
||||
return mEnabledBlendEquations != 0;
|
||||
}
|
||||
|
||||
bool AdvancedBlendEquations::anyHsl() const
|
||||
{
|
||||
ASSERT(IsValidAdvancedBlendBitSet(mEnabledBlendEquations));
|
||||
return (gl::BlendEquationBitSet(mEnabledBlendEquations) & kAdvancedBlendHslBits).any();
|
||||
}
|
||||
|
||||
void AdvancedBlendEquations::setAll()
|
||||
{
|
||||
ASSERT(IsValidAdvancedBlendBitSet(mEnabledBlendEquations));
|
||||
mEnabledBlendEquations = kAdvancedBlendBits.bits();
|
||||
}
|
||||
|
||||
void AdvancedBlendEquations::set(uint32_t blendEquation)
|
||||
{
|
||||
gl::BlendEquationType eq = static_cast<gl::BlendEquationType>(blendEquation);
|
||||
mEnabledBlendEquations = gl::BlendEquationBitSet(mEnabledBlendEquations).set(eq).bits();
|
||||
ASSERT(IsValidAdvancedBlendBitSet(mEnabledBlendEquations));
|
||||
}
|
||||
|
||||
} // namespace sh
|
||||
@@ -1304,6 +1304,36 @@ enum TLayoutTessEvaluationType
|
||||
EtetPointMode
|
||||
};
|
||||
|
||||
class AdvancedBlendEquations
|
||||
{
|
||||
public:
|
||||
// Must have a trivial default constructor since it is used in YYSTYPE.
|
||||
AdvancedBlendEquations() = default;
|
||||
explicit constexpr AdvancedBlendEquations(uint32_t initialState)
|
||||
: mEnabledBlendEquations(initialState)
|
||||
{}
|
||||
|
||||
bool any() const;
|
||||
bool anyHsl() const;
|
||||
|
||||
void setAll();
|
||||
void reset() { mEnabledBlendEquations = 0; }
|
||||
|
||||
// Parameter is gl::BlendEquationType, but PackedEnums.h include is not possible here.
|
||||
void set(uint32_t blendEquation);
|
||||
|
||||
uint32_t bits() const { return mEnabledBlendEquations; }
|
||||
|
||||
AdvancedBlendEquations operator|=(AdvancedBlendEquations other)
|
||||
{
|
||||
mEnabledBlendEquations |= other.mEnabledBlendEquations;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t mEnabledBlendEquations;
|
||||
};
|
||||
|
||||
struct TLayoutQualifier
|
||||
{
|
||||
// Must have a trivial default constructor since it is used in YYSTYPE.
|
||||
@@ -1320,7 +1350,7 @@ struct TLayoutQualifier
|
||||
invocations == 0 && maxVertices == -1 && vertices == 0 &&
|
||||
tesPrimitiveType == EtetUndefined && tesVertexSpacingType == EtetUndefined &&
|
||||
tesOrderingType == EtetUndefined && tesPointType == EtetUndefined && index == -1 &&
|
||||
inputAttachmentIndex == -1 && noncoherent == false;
|
||||
inputAttachmentIndex == -1 && noncoherent == false && !advancedBlendEquations.any();
|
||||
}
|
||||
|
||||
bool isCombinationValid() const
|
||||
@@ -1333,6 +1363,7 @@ struct TLayoutQualifier
|
||||
bool otherLayoutQualifiersSpecified =
|
||||
(location != -1 || binding != -1 || index != -1 || matrixPacking != EmpUnspecified ||
|
||||
blockStorage != EbsUnspecified || imageInternalFormat != EiifUnspecified);
|
||||
bool blendEquationSpecified = advancedBlendEquations.any();
|
||||
|
||||
// we can have either the work group size specified, or number of views,
|
||||
// or yuv layout qualifier, or early_fragment_tests layout qualifier, or the other layout
|
||||
@@ -1340,7 +1371,7 @@ struct TLayoutQualifier
|
||||
return (workGroupSizeSpecified ? 1 : 0) + (numViewsSet ? 1 : 0) + (yuv ? 1 : 0) +
|
||||
(earlyFragmentTests ? 1 : 0) + (otherLayoutQualifiersSpecified ? 1 : 0) +
|
||||
(geometryShaderSpecified ? 1 : 0) + (subpassInputSpecified ? 1 : 0) +
|
||||
(noncoherent ? 1 : 0) <=
|
||||
(noncoherent ? 1 : 0) + (blendEquationSpecified ? 1 : 0) <=
|
||||
1;
|
||||
}
|
||||
|
||||
@@ -1391,6 +1422,9 @@ struct TLayoutQualifier
|
||||
int inputAttachmentIndex;
|
||||
bool noncoherent;
|
||||
|
||||
// KHR_blend_equation_advanced layout qualifiers.
|
||||
AdvancedBlendEquations advancedBlendEquations;
|
||||
|
||||
private:
|
||||
explicit constexpr TLayoutQualifier(int /*placeholder*/)
|
||||
: location(-1),
|
||||
@@ -1414,7 +1448,8 @@ struct TLayoutQualifier
|
||||
tesPointType(EtetUndefined),
|
||||
index(-1),
|
||||
inputAttachmentIndex(-1),
|
||||
noncoherent(false)
|
||||
noncoherent(false),
|
||||
advancedBlendEquations(0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -346,6 +346,7 @@ TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
|
||||
mTessEvaluationShaderInputOrderingType(EtetUndefined),
|
||||
mTessEvaluationShaderInputPointType(EtetUndefined),
|
||||
mHasAnyPreciseType(false),
|
||||
mAdvancedBlendEquations(0),
|
||||
mCompileOptions(0)
|
||||
{}
|
||||
|
||||
@@ -560,6 +561,10 @@ void TCompiler::setASTMetadata(const TParseContext &parseContext)
|
||||
|
||||
mHasAnyPreciseType = parseContext.hasAnyPreciseType();
|
||||
|
||||
if (mShaderType == GL_FRAGMENT_SHADER)
|
||||
{
|
||||
mAdvancedBlendEquations = parseContext.getAdvancedBlendEquations();
|
||||
}
|
||||
if (mShaderType == GL_GEOMETRY_SHADER_EXT)
|
||||
{
|
||||
mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType();
|
||||
|
||||
@@ -184,6 +184,8 @@ class TCompiler : public TShHandleBase
|
||||
|
||||
bool hasAnyPreciseType() const { return mHasAnyPreciseType; }
|
||||
|
||||
AdvancedBlendEquations getAdvancedBlendEquations() const { return mAdvancedBlendEquations; }
|
||||
|
||||
unsigned int getSharedMemorySize() const;
|
||||
|
||||
sh::GLenum getShaderType() const { return mShaderType; }
|
||||
@@ -339,6 +341,9 @@ class TCompiler : public TShHandleBase
|
||||
|
||||
bool mHasAnyPreciseType;
|
||||
|
||||
// advanced blend equation parameters
|
||||
AdvancedBlendEquations mAdvancedBlendEquations;
|
||||
|
||||
// name hashing.
|
||||
NameMap mNameMap;
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
OP(EXT_texture_buffer) \
|
||||
OP(EXT_texture_cube_map_array) \
|
||||
OP(EXT_YUV_target) \
|
||||
OP(KHR_blend_equation_advanced) \
|
||||
OP(NV_EGL_stream_consumer_external) \
|
||||
OP(NV_shader_framebuffer_fetch) \
|
||||
OP(NV_shader_noperspective_interpolation) \
|
||||
|
||||
@@ -46,6 +46,7 @@ enum class TExtension : uint8_t
|
||||
EXT_texture_buffer,
|
||||
EXT_texture_cube_map_array,
|
||||
EXT_YUV_target,
|
||||
KHR_blend_equation_advanced,
|
||||
NV_EGL_stream_consumer_external,
|
||||
NV_shader_framebuffer_fetch,
|
||||
NV_shader_noperspective_interpolation,
|
||||
|
||||
@@ -185,6 +185,10 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi
|
||||
{
|
||||
extBehavior[TExtension::ANDROID_extension_pack_es31a] = EBhUndefined;
|
||||
}
|
||||
if (resources.KHR_blend_equation_advanced)
|
||||
{
|
||||
extBehavior[TExtension::KHR_blend_equation_advanced] = EBhUndefined;
|
||||
}
|
||||
}
|
||||
|
||||
void ResetExtensionBehavior(const ShBuiltInResources &resources,
|
||||
|
||||
@@ -148,6 +148,10 @@ TIntermTyped *FindLValueBase(TIntermTyped *node)
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void AddAdvancedBlendEquation(gl::BlendEquationType eq, TLayoutQualifier *qualifier)
|
||||
{
|
||||
qualifier->advancedBlendEquations.set(static_cast<uint32_t>(eq));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// This tracks each binding point's current default offset for inheritance of subsequent
|
||||
@@ -244,6 +248,7 @@ TParseContext::TParseContext(TSymbolTable &symt,
|
||||
mTessEvaluationShaderInputOrderingType(EtetUndefined),
|
||||
mTessEvaluationShaderInputPointType(EtetUndefined),
|
||||
mHasAnyPreciseType(false),
|
||||
mAdvancedBlendEquations(0),
|
||||
mFunctionBodyNewScope(false),
|
||||
mOutputType(outputType)
|
||||
{}
|
||||
@@ -1836,9 +1841,10 @@ void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, co
|
||||
|
||||
void TParseContext::checkCanUseLayoutQualifier(const TSourceLoc &location)
|
||||
{
|
||||
constexpr std::array<TExtension, 2u> extensions{
|
||||
constexpr std::array<TExtension, 3u> extensions{
|
||||
{TExtension::EXT_shader_framebuffer_fetch,
|
||||
TExtension::EXT_shader_framebuffer_fetch_non_coherent}};
|
||||
TExtension::EXT_shader_framebuffer_fetch_non_coherent,
|
||||
TExtension::KHR_blend_equation_advanced}};
|
||||
if (getShaderVersion() < 300 && !checkCanUseOneOfExtensions(location, extensions))
|
||||
{
|
||||
error(location, "qualifier supported in GLSL ES 3.00 and above only", "layout");
|
||||
@@ -2120,6 +2126,20 @@ void TParseContext::checkInvariantVariableQualifier(bool invariant,
|
||||
}
|
||||
}
|
||||
|
||||
void TParseContext::checkAdvancedBlendEquationsNotSpecified(
|
||||
const TSourceLoc &location,
|
||||
const AdvancedBlendEquations &advancedBlendEquations,
|
||||
const TQualifier &qualifier)
|
||||
{
|
||||
if (advancedBlendEquations.any() && qualifier != EvqFragmentOut)
|
||||
{
|
||||
error(location,
|
||||
"invalid layout qualifier: blending equation qualifiers are only permitted on the "
|
||||
"fragment 'out' qualifier ",
|
||||
"blend_support_qualifier");
|
||||
}
|
||||
}
|
||||
|
||||
bool TParseContext::isExtensionEnabled(TExtension extension) const
|
||||
{
|
||||
return IsExtensionEnabled(extensionBehavior(), extension);
|
||||
@@ -3626,6 +3646,9 @@ void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &type
|
||||
checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage,
|
||||
typeQualifier.qualifier);
|
||||
|
||||
checkAdvancedBlendEquationsNotSpecified(
|
||||
typeQualifier.line, layoutQualifier.advancedBlendEquations, typeQualifier.qualifier);
|
||||
|
||||
if (typeQualifier.qualifier != EvqFragmentIn)
|
||||
{
|
||||
checkEarlyFragmentTestsIsNotSpecified(typeQualifier.line,
|
||||
@@ -3757,6 +3780,28 @@ void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &type
|
||||
|
||||
mEarlyFragmentTestsSpecified = true;
|
||||
}
|
||||
else if (typeQualifier.qualifier == EvqFragmentOut)
|
||||
{
|
||||
if (mShaderVersion < 320 && !isExtensionEnabled(TExtension::KHR_blend_equation_advanced))
|
||||
{
|
||||
error(typeQualifier.line,
|
||||
"out type qualifier without variable declaration is supported in GLSL ES 3.20,"
|
||||
" or if GL_KHR_blend_equation_advanced is enabled",
|
||||
"layout");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!layoutQualifier.advancedBlendEquations.any())
|
||||
{
|
||||
error(typeQualifier.line,
|
||||
"only blend equations are allowed as layout qualifier when not declaring a "
|
||||
"variable",
|
||||
"layout");
|
||||
return;
|
||||
}
|
||||
|
||||
mAdvancedBlendEquations |= layoutQualifier.advancedBlendEquations;
|
||||
}
|
||||
else if (typeQualifier.qualifier == EvqTessControlOut)
|
||||
{
|
||||
if (mShaderVersion < 310)
|
||||
@@ -5281,15 +5326,95 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qual
|
||||
error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
|
||||
}
|
||||
}
|
||||
else if (qualifierType == "noncoherent" && mShaderType == GL_FRAGMENT_SHADER)
|
||||
else if (mShaderType == GL_FRAGMENT_SHADER)
|
||||
{
|
||||
if (checkCanUseOneOfExtensions(
|
||||
qualifierTypeLine, std::array<TExtension, 2u>{
|
||||
{TExtension::EXT_shader_framebuffer_fetch,
|
||||
TExtension::EXT_shader_framebuffer_fetch_non_coherent}}))
|
||||
if (qualifierType == "noncoherent")
|
||||
{
|
||||
checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 100);
|
||||
qualifier.noncoherent = true;
|
||||
if (checkCanUseOneOfExtensions(
|
||||
qualifierTypeLine,
|
||||
std::array<TExtension, 2u>{
|
||||
{TExtension::EXT_shader_framebuffer_fetch,
|
||||
TExtension::EXT_shader_framebuffer_fetch_non_coherent}}))
|
||||
{
|
||||
checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 100);
|
||||
qualifier.noncoherent = true;
|
||||
}
|
||||
}
|
||||
else if (qualifierType == "blend_support_multiply")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::Multiply, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_screen")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::Screen, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_overlay")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::Overlay, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_darken")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::Darken, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_lighten")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::Lighten, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_colordodge")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::Colordodge, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_colorburn")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::Colorburn, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_hardlight")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::Hardlight, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_softlight")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::Softlight, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_difference")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::Difference, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_exclusion")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::Exclusion, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_hsl_hue")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::HslHue, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_hsl_saturation")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::HslSaturation, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_hsl_color")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::HslColor, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_hsl_luminosity")
|
||||
{
|
||||
AddAdvancedBlendEquation(gl::BlendEquationType::HslLuminosity, &qualifier);
|
||||
}
|
||||
else if (qualifierType == "blend_support_all_equations")
|
||||
{
|
||||
qualifier.advancedBlendEquations.setAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
|
||||
}
|
||||
|
||||
if (qualifier.advancedBlendEquations.any() && mShaderVersion < 320)
|
||||
{
|
||||
if (!checkCanUseExtension(qualifierTypeLine, TExtension::KHR_blend_equation_advanced))
|
||||
{
|
||||
qualifier.advancedBlendEquations.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -192,6 +192,12 @@ class TParseContext : angle::NonCopyable
|
||||
const TSourceLoc &qualifierLocation);
|
||||
void checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier);
|
||||
void checkTCSOutVarIndexIsValid(TIntermBinary *binaryExpression, const TSourceLoc &location);
|
||||
|
||||
void checkAdvancedBlendEquationsNotSpecified(
|
||||
const TSourceLoc &location,
|
||||
const AdvancedBlendEquations &advancedBlendEquations,
|
||||
const TQualifier &qualifier);
|
||||
|
||||
const TPragma &pragma() const { return mDirectiveHandler.pragma(); }
|
||||
const TExtensionBehavior &extensionBehavior() const
|
||||
{
|
||||
@@ -495,6 +501,7 @@ class TParseContext : angle::NonCopyable
|
||||
|
||||
void markShaderHasPrecise() { mHasAnyPreciseType = true; }
|
||||
bool hasAnyPreciseType() const { return mHasAnyPreciseType; }
|
||||
AdvancedBlendEquations getAdvancedBlendEquations() const { return mAdvancedBlendEquations; }
|
||||
|
||||
ShShaderOutput getOutputType() const { return mOutputType; }
|
||||
|
||||
@@ -735,6 +742,8 @@ class TParseContext : angle::NonCopyable
|
||||
// Whether the |precise| keyword has been seen in the shader.
|
||||
bool mHasAnyPreciseType;
|
||||
|
||||
AdvancedBlendEquations mAdvancedBlendEquations;
|
||||
|
||||
// Track when we add new scope for func body in ESSL 1.00 spec
|
||||
bool mFunctionBodyNewScope;
|
||||
|
||||
|
||||
@@ -853,6 +853,11 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
|
||||
joinedQualifier.index = rightQualifier.index;
|
||||
}
|
||||
|
||||
if (rightQualifier.advancedBlendEquations.any())
|
||||
{
|
||||
joinedQualifier.advancedBlendEquations |= rightQualifier.advancedBlendEquations;
|
||||
}
|
||||
|
||||
return joinedQualifier;
|
||||
}
|
||||
|
||||
|
||||
@@ -233,6 +233,7 @@ void InitBuiltInResources(ShBuiltInResources *resources)
|
||||
resources->EXT_texture_buffer = 0;
|
||||
resources->OES_sample_variables = 0;
|
||||
resources->EXT_clip_cull_distance = 0;
|
||||
resources->KHR_blend_equation_advanced = 0;
|
||||
|
||||
resources->MaxClipDistances = 8;
|
||||
resources->MaxCullDistances = 8;
|
||||
@@ -925,6 +926,14 @@ unsigned int GetShaderSharedMemorySize(const ShHandle handle)
|
||||
return sharedMemorySize;
|
||||
}
|
||||
|
||||
uint32_t GetAdvancedBlendEquations(const ShHandle handle)
|
||||
{
|
||||
TCompiler *compiler = GetCompilerFromHandle(handle);
|
||||
ASSERT(compiler);
|
||||
|
||||
return compiler->getAdvancedBlendEquations().bits();
|
||||
}
|
||||
|
||||
void InitializeGlslang()
|
||||
{
|
||||
if (initializeGlslangRefCount == 0)
|
||||
|
||||
@@ -96,7 +96,7 @@ static bool is_extension_enabled_or_is_core(TParseContext *context,
|
||||
// which means in version V1, the symbol is reserved, and remains reserved until V3. From versions
|
||||
// V2 until V3, it's a keyword if the extension is enabled. From version V3 on, it's a keyword in
|
||||
// the spec itself. Prior to V1, the symbol can be used as identifier.
|
||||
static int ES2_extension_2_ES3_keyword(TParseContext *context, TExtension extension1, TExtension extension2, int token);
|
||||
static int ES2_extensions_ES3_keyword(TParseContext *context, TExtension extension1, TExtension extension2, TExtension extension3, int token);
|
||||
static int ES2_reserved_ES3_keyword(TParseContext *context, int token);
|
||||
static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
|
||||
static int ES3_keyword(TParseContext *context, int token);
|
||||
@@ -247,7 +247,7 @@ O [0-7]
|
||||
"samplerVideoWEBGL" { return WEBGL_video_texture_extension(context, SAMPLERVIDEOWEBGL); }
|
||||
"struct" { return STRUCT; }
|
||||
|
||||
"layout" { return ES2_extension_2_ES3_keyword(context, TExtension::EXT_shader_framebuffer_fetch, TExtension::EXT_shader_framebuffer_fetch_non_coherent, LAYOUT); }
|
||||
"layout" { return ES2_extensions_ES3_keyword(context, TExtension::EXT_shader_framebuffer_fetch, TExtension::EXT_shader_framebuffer_fetch_non_coherent, TExtension::KHR_blend_equation_advanced, LAYOUT); }
|
||||
|
||||
"yuvCscStandardEXT" { return ES3_extension(context, TExtension::EXT_YUV_target, YUVCSCSTANDARDEXT); }
|
||||
"itu_601" { return yuvcscstandardext_constant(context); }
|
||||
@@ -612,7 +612,7 @@ int WEBGL_video_texture_extension(TParseContext *context, int token)
|
||||
return check_type(yyscanner);
|
||||
}
|
||||
|
||||
int ES2_extension_2_ES3_keyword(TParseContext *context, TExtension extension1, TExtension extension2, int token)
|
||||
int ES2_extensions_ES3_keyword(TParseContext *context, TExtension extension1, TExtension extension2, TExtension extension3, int token)
|
||||
{
|
||||
struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
|
||||
yyscan_t yyscanner = (yyscan_t) context->getScanner();
|
||||
@@ -626,6 +626,10 @@ int ES2_extension_2_ES3_keyword(TParseContext *context, TExtension extension1, T
|
||||
{
|
||||
return token;
|
||||
}
|
||||
else if (is_extension_enabled_or_is_core(context, 100, extension3, 300))
|
||||
{
|
||||
return token;
|
||||
}
|
||||
|
||||
// not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name
|
||||
yylval->lex.string = AllocatePoolCharArray(yytext, yyleng);
|
||||
|
||||
@@ -918,10 +918,11 @@ static bool is_extension_enabled_or_is_core(TParseContext *context,
|
||||
// which means in version V1, the symbol is reserved, and remains reserved until V3. From versions
|
||||
// V2 until V3, it's a keyword if the extension is enabled. From version V3 on, it's a keyword in
|
||||
// the spec itself. Prior to V1, the symbol can be used as identifier.
|
||||
static int ES2_extension_2_ES3_keyword(TParseContext *context,
|
||||
TExtension extension1,
|
||||
TExtension extension2,
|
||||
int token);
|
||||
static int ES2_extensions_ES3_keyword(TParseContext *context,
|
||||
TExtension extension1,
|
||||
TExtension extension2,
|
||||
TExtension extension3,
|
||||
int token);
|
||||
static int ES2_reserved_ES3_keyword(TParseContext *context, int token);
|
||||
static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
|
||||
static int ES3_keyword(TParseContext *context, int token);
|
||||
@@ -1689,9 +1690,10 @@ YY_DECL
|
||||
case 97:
|
||||
YY_RULE_SETUP
|
||||
{
|
||||
return ES2_extension_2_ES3_keyword(
|
||||
return ES2_extensions_ES3_keyword(
|
||||
context, TExtension::EXT_shader_framebuffer_fetch,
|
||||
TExtension::EXT_shader_framebuffer_fetch_non_coherent, LAYOUT);
|
||||
TExtension::EXT_shader_framebuffer_fetch_non_coherent,
|
||||
TExtension::KHR_blend_equation_advanced, LAYOUT);
|
||||
}
|
||||
YY_BREAK
|
||||
case 98:
|
||||
@@ -3458,10 +3460,11 @@ int WEBGL_video_texture_extension(TParseContext *context, int token)
|
||||
return check_type(yyscanner);
|
||||
}
|
||||
|
||||
int ES2_extension_2_ES3_keyword(TParseContext *context,
|
||||
TExtension extension1,
|
||||
TExtension extension2,
|
||||
int token)
|
||||
int ES2_extensions_ES3_keyword(TParseContext *context,
|
||||
TExtension extension1,
|
||||
TExtension extension2,
|
||||
TExtension extension3,
|
||||
int token)
|
||||
{
|
||||
struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner();
|
||||
yyscan_t yyscanner = (yyscan_t)context->getScanner();
|
||||
@@ -3475,6 +3478,10 @@ int ES2_extension_2_ES3_keyword(TParseContext *context,
|
||||
{
|
||||
return token;
|
||||
}
|
||||
else if (is_extension_enabled_or_is_core(context, 100, extension3, 300))
|
||||
{
|
||||
return token;
|
||||
}
|
||||
|
||||
// not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name
|
||||
yylval->lex.string = AllocatePoolCharArray(yytext, yyleng);
|
||||
|
||||
@@ -50,7 +50,7 @@ TEST(BlendStateExt, Init)
|
||||
ASSERT_EQ(blendStateExt.mMaxDrawBuffers, 1u);
|
||||
ASSERT_EQ(blendStateExt.mMaxEnabledMask.to_ulong(), 1u);
|
||||
ASSERT_EQ(blendStateExt.mMaxColorMask, is64Bit ? 0xFFu : 0xFu);
|
||||
ASSERT_EQ(blendStateExt.mMaxEquationMask, is64Bit ? 0xFFu : 0xFu);
|
||||
ASSERT_EQ(blendStateExt.mMaxEquationMask, 0xFFu);
|
||||
ASSERT_EQ(blendStateExt.mMaxFactorMask, 0xFFu);
|
||||
checkInitState(blendStateExt);
|
||||
}
|
||||
@@ -60,7 +60,7 @@ TEST(BlendStateExt, Init)
|
||||
ASSERT_EQ(blendStateExt.mMaxDrawBuffers, 4u);
|
||||
ASSERT_EQ(blendStateExt.mMaxEnabledMask.to_ulong(), 0xFu);
|
||||
ASSERT_EQ(blendStateExt.mMaxColorMask, is64Bit ? 0xFFFFFFFFu : 0xFFFFu);
|
||||
ASSERT_EQ(blendStateExt.mMaxEquationMask, is64Bit ? 0xFFFFFFFFu : 0xFFFFu);
|
||||
ASSERT_EQ(blendStateExt.mMaxEquationMask, 0xFFFFFFFFu);
|
||||
ASSERT_EQ(blendStateExt.mMaxFactorMask, 0xFFFFFFFFu);
|
||||
checkInitState(blendStateExt);
|
||||
}
|
||||
@@ -70,7 +70,7 @@ TEST(BlendStateExt, Init)
|
||||
ASSERT_EQ(blendStateExt.mMaxDrawBuffers, 8u);
|
||||
ASSERT_EQ(blendStateExt.mMaxEnabledMask.to_ulong(), 0xFFu);
|
||||
ASSERT_EQ(blendStateExt.mMaxColorMask, is64Bit ? 0xFFFFFFFFFFFFFFFFu : 0xFFFFFFFFu);
|
||||
ASSERT_EQ(blendStateExt.mMaxEquationMask, is64Bit ? 0xFFFFFFFFFFFFFFFFu : 0xFFFFFFFFu);
|
||||
ASSERT_EQ(blendStateExt.mMaxEquationMask, 0xFFFFFFFFFFFFFFFFu);
|
||||
ASSERT_EQ(blendStateExt.mMaxFactorMask, 0xFFFFFFFFFFFFFFFFu);
|
||||
checkInitState(blendStateExt);
|
||||
}
|
||||
@@ -126,13 +126,13 @@ TEST(BlendStateExt, BlendEquations)
|
||||
gl::BlendStateExt blendStateExt = gl::BlendStateExt(7);
|
||||
|
||||
blendStateExt.setEquations(GL_MIN, GL_FUNC_SUBTRACT);
|
||||
ASSERT_EQ(blendStateExt.mEquationColor, is64Bit ? 0x01010101010101u : 0x1111111u);
|
||||
ASSERT_EQ(blendStateExt.mEquationAlpha, is64Bit ? 0x04040404040404u : 0x4444444u);
|
||||
ASSERT_EQ(blendStateExt.mEquationColor, 0x01010101010101u);
|
||||
ASSERT_EQ(blendStateExt.mEquationAlpha, 0x04040404040404u);
|
||||
|
||||
blendStateExt.setEquationsIndexed(3, GL_MAX, GL_FUNC_SUBTRACT);
|
||||
blendStateExt.setEquationsIndexed(5, GL_MIN, GL_FUNC_ADD);
|
||||
ASSERT_EQ(blendStateExt.mEquationColor, is64Bit ? 0x01010102010101u : 0x1112111u);
|
||||
ASSERT_EQ(blendStateExt.mEquationAlpha, is64Bit ? 0x04000404040404u : 0x4044444u);
|
||||
ASSERT_EQ(blendStateExt.mEquationColor, 0x01010102010101u);
|
||||
ASSERT_EQ(blendStateExt.mEquationAlpha, 0x04000404040404u);
|
||||
ASSERT_EQ(blendStateExt.getEquationColorIndexed(3), static_cast<GLenum>(GL_MAX));
|
||||
ASSERT_EQ(blendStateExt.getEquationAlphaIndexed(5), static_cast<GLenum>(GL_FUNC_ADD));
|
||||
|
||||
@@ -141,8 +141,8 @@ TEST(BlendStateExt, BlendEquations)
|
||||
gl::BlendStateExt::EquationStorage::Type otherEquationAlpha =
|
||||
blendStateExt.expandEquationAlphaIndexed(0);
|
||||
|
||||
ASSERT_EQ(otherEquationColor, is64Bit ? 0x01010101010101u : 0x1111111u);
|
||||
ASSERT_EQ(otherEquationAlpha, is64Bit ? 0x04040404040404u : 0x4444444u);
|
||||
ASSERT_EQ(otherEquationColor, 0x01010101010101u);
|
||||
ASSERT_EQ(otherEquationAlpha, 0x04040404040404u);
|
||||
|
||||
const gl::DrawBufferMask diff =
|
||||
blendStateExt.compareEquations(otherEquationColor, otherEquationAlpha);
|
||||
|
||||
@@ -108,6 +108,7 @@ angle_unittests_compiler_tests_sources = [
|
||||
"compiler_tests/ImmutableString_test.cpp",
|
||||
"compiler_tests/InitOutputVariables_test.cpp",
|
||||
"compiler_tests/IntermNode_test.cpp",
|
||||
"compiler_tests/KHR_blend_equation_advanced_test.cpp",
|
||||
"compiler_tests/NV_draw_buffers_test.cpp",
|
||||
"compiler_tests/OES_sample_variables_test.cpp",
|
||||
"compiler_tests/OES_standard_derivatives_test.cpp",
|
||||
|
||||
322
src/tests/compiler_tests/KHR_blend_equation_advanced_test.cpp
Normal file
322
src/tests/compiler_tests/KHR_blend_equation_advanced_test.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
//
|
||||
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// KHR_blend_equation_advanced_test.cpp:
|
||||
// Test for KHR_blend_equation_advanced and KHR_blend_equation_advanced_coherent
|
||||
//
|
||||
|
||||
#include "tests/test_utils/ShaderExtensionTest.h"
|
||||
|
||||
#include "common/PackedEnums.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
const char EXTPragma[] =
|
||||
"#extension GL_KHR_blend_equation_advanced : require\n"
|
||||
"#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n";
|
||||
|
||||
// Use the multiply equation for blending
|
||||
const char ESSL310_Simple[] =
|
||||
R"(
|
||||
precision highp float;
|
||||
|
||||
layout (blend_support_multiply) out;
|
||||
layout (location = 0) out vec4 oCol;
|
||||
|
||||
uniform vec4 uSrcCol;
|
||||
|
||||
void main (void)
|
||||
{
|
||||
oCol = uSrcCol;
|
||||
})";
|
||||
|
||||
const char ESSL310_DeclaredMultiplyScreenSeparately[] =
|
||||
R"(
|
||||
precision highp float;
|
||||
|
||||
layout (blend_support_multiply) out;
|
||||
layout (blend_support_screen) out;
|
||||
layout (location = 0) out vec4 oCol;
|
||||
|
||||
uniform vec4 uSrcCol;
|
||||
|
||||
void main (void)
|
||||
{
|
||||
oCol = uSrcCol;
|
||||
})";
|
||||
|
||||
const char ESSL310_DeclaredMultiplyScreenSuccessively[] =
|
||||
R"(
|
||||
precision highp float;
|
||||
|
||||
layout (blend_support_multiply, blend_support_screen) out;
|
||||
layout (location = 0) out vec4 oCol;
|
||||
|
||||
uniform vec4 uSrcCol;
|
||||
|
||||
void main (void)
|
||||
{
|
||||
oCol = uSrcCol;
|
||||
})";
|
||||
|
||||
const char ESSL310_With_FramebufferFetch[] =
|
||||
R"(
|
||||
precision highp float;
|
||||
|
||||
layout (blend_support_multiply) out;
|
||||
layout (location = 0, noncoherent) inout vec4 oCol;
|
||||
|
||||
uniform vec4 uSrcCol;
|
||||
|
||||
void main (void)
|
||||
{
|
||||
oCol = mix(oCol, uSrcCol, 0.5f);
|
||||
})";
|
||||
|
||||
class KHRBlendEquationAdvancedTest : public sh::ShaderExtensionTest
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
std::map<ShShaderOutput, std::string> shaderOutputList = {
|
||||
{SH_GLSL_450_CORE_OUTPUT, "SH_GLSL_450_CORE_OUTPUT"},
|
||||
#if defined(ANGLE_ENABLE_VULKAN)
|
||||
{SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}
|
||||
#endif
|
||||
};
|
||||
|
||||
Initialize(shaderOutputList);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
for (auto shaderOutputType : mShaderOutputList)
|
||||
{
|
||||
DestroyCompiler(shaderOutputType.first);
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize(std::map<ShShaderOutput, std::string> &shaderOutputList)
|
||||
{
|
||||
mShaderOutputList = std::move(shaderOutputList);
|
||||
|
||||
for (auto shaderOutputType : mShaderOutputList)
|
||||
{
|
||||
sh::InitBuiltInResources(&mResourceList[shaderOutputType.first]);
|
||||
mCompilerList[shaderOutputType.first] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyCompiler(ShShaderOutput shaderOutputType)
|
||||
{
|
||||
if (mCompilerList[shaderOutputType])
|
||||
{
|
||||
sh::Destruct(mCompilerList[shaderOutputType]);
|
||||
mCompilerList[shaderOutputType] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeCompiler()
|
||||
{
|
||||
for (auto shaderOutputType : mShaderOutputList)
|
||||
{
|
||||
InitializeCompiler(shaderOutputType.first);
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeCompiler(ShShaderOutput shaderOutputType)
|
||||
{
|
||||
DestroyCompiler(shaderOutputType);
|
||||
|
||||
mCompilerList[shaderOutputType] =
|
||||
sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()), shaderOutputType,
|
||||
&mResourceList[shaderOutputType]);
|
||||
ASSERT_TRUE(mCompilerList[shaderOutputType] != nullptr)
|
||||
<< "Compiler for " << mShaderOutputList[shaderOutputType]
|
||||
<< " could not be constructed.";
|
||||
}
|
||||
|
||||
testing::AssertionResult TestShaderCompile(ShShaderOutput shaderOutputType, const char *pragma)
|
||||
{
|
||||
const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma,
|
||||
testing::get<2>(GetParam())};
|
||||
|
||||
bool success = sh::Compile(mCompilerList[shaderOutputType], shaderStrings, 3,
|
||||
SH_VARIABLES | SH_OBJECT_CODE);
|
||||
if (success)
|
||||
{
|
||||
return ::testing::AssertionSuccess()
|
||||
<< "Compilation success(" << mShaderOutputList[shaderOutputType] << ")";
|
||||
}
|
||||
return ::testing::AssertionFailure() << sh::GetInfoLog(mCompilerList[shaderOutputType]);
|
||||
}
|
||||
|
||||
void TestShaderCompile(bool expectation, const char *pragma)
|
||||
{
|
||||
for (auto shaderOutputType : mShaderOutputList)
|
||||
{
|
||||
if (expectation)
|
||||
{
|
||||
EXPECT_TRUE(TestShaderCompile(shaderOutputType.first, pragma));
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_FALSE(TestShaderCompile(shaderOutputType.first, pragma));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetExtensionEnable(bool enable)
|
||||
{
|
||||
for (auto shaderOutputType : mShaderOutputList)
|
||||
{
|
||||
mResourceList[shaderOutputType.first].KHR_blend_equation_advanced = enable;
|
||||
mResourceList[shaderOutputType.first].EXT_shader_framebuffer_fetch_non_coherent =
|
||||
enable;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
std::map<ShShaderOutput, std::string> mShaderOutputList;
|
||||
std::map<ShShaderOutput, ShHandle> mCompilerList;
|
||||
std::map<ShShaderOutput, ShBuiltInResources> mResourceList;
|
||||
};
|
||||
|
||||
class KHRBlendEquationAdvancedES310Test : public KHRBlendEquationAdvancedTest
|
||||
{};
|
||||
|
||||
// Extension flag is required to compile properly. Expect failure when it is
|
||||
// not present.
|
||||
TEST_P(KHRBlendEquationAdvancedES310Test, CompileFailsWithoutExtension)
|
||||
{
|
||||
SetExtensionEnable(false);
|
||||
InitializeCompiler();
|
||||
TestShaderCompile(false, EXTPragma);
|
||||
}
|
||||
|
||||
// Extension directive is required to compile properly. Expect failure when
|
||||
// it is not present.
|
||||
TEST_P(KHRBlendEquationAdvancedES310Test, CompileFailsWithExtensionWithoutPragma)
|
||||
{
|
||||
SetExtensionEnable(true);
|
||||
InitializeCompiler();
|
||||
TestShaderCompile(false, "");
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
|
||||
KHRBlendEquationAdvancedES310Test,
|
||||
Combine(Values(SH_GLES3_1_SPEC),
|
||||
Values(sh::ESSLVersion310),
|
||||
Values(ESSL310_Simple,
|
||||
ESSL310_With_FramebufferFetch,
|
||||
ESSL310_DeclaredMultiplyScreenSeparately,
|
||||
ESSL310_DeclaredMultiplyScreenSuccessively)));
|
||||
|
||||
#if defined(ANGLE_ENABLE_VULKAN)
|
||||
|
||||
class KHRBlendEquationAdvancedSuccessTest : public KHRBlendEquationAdvancedTest
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
std::map<ShShaderOutput, std::string> shaderOutputList = {
|
||||
{SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}};
|
||||
|
||||
Initialize(shaderOutputList);
|
||||
}
|
||||
};
|
||||
|
||||
class KHRBlendEquationAdvancedES310SuccessTest : public KHRBlendEquationAdvancedSuccessTest
|
||||
{};
|
||||
|
||||
// With extension flag and extension directive, compiling succeeds.
|
||||
// Also test that the extension directive state is reset correctly.
|
||||
TEST_P(KHRBlendEquationAdvancedES310SuccessTest, CompileSucceedsWithExtensionAndPragma)
|
||||
{
|
||||
SetExtensionEnable(true);
|
||||
InitializeCompiler();
|
||||
TestShaderCompile(true, EXTPragma);
|
||||
// Test reset functionality.
|
||||
TestShaderCompile(false, "");
|
||||
TestShaderCompile(true, EXTPragma);
|
||||
}
|
||||
|
||||
// The SL #version 100 shaders that are correct work similarly
|
||||
// in both GL2 and GL3, with and without the version string.
|
||||
INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
|
||||
KHRBlendEquationAdvancedES310SuccessTest,
|
||||
Combine(Values(SH_GLES3_1_SPEC),
|
||||
Values(sh::ESSLVersion310),
|
||||
Values(ESSL310_Simple,
|
||||
ESSL310_With_FramebufferFetch,
|
||||
ESSL310_DeclaredMultiplyScreenSeparately,
|
||||
ESSL310_DeclaredMultiplyScreenSuccessively)));
|
||||
|
||||
class KHRBlendEquationAdvancedEnabledListCheckTest : public KHRBlendEquationAdvancedTest
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
std::map<ShShaderOutput, std::string> shaderOutputList = {
|
||||
{SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}};
|
||||
|
||||
Initialize(shaderOutputList);
|
||||
}
|
||||
|
||||
const ShHandle &GetCompilerHandle(const ShShaderOutput outputType) const
|
||||
{
|
||||
return mCompilerList.at(outputType);
|
||||
}
|
||||
};
|
||||
|
||||
class KHRBlendEquationAdvancedEnabledSeparatelyTest
|
||||
: public KHRBlendEquationAdvancedEnabledListCheckTest
|
||||
{};
|
||||
|
||||
// Test for declaring different blend equations in separate layout declarations
|
||||
TEST_P(KHRBlendEquationAdvancedEnabledSeparatelyTest, DeclaredEquationSeparately)
|
||||
{
|
||||
SetExtensionEnable(true);
|
||||
InitializeCompiler();
|
||||
TestShaderCompile(true, EXTPragma);
|
||||
|
||||
const ShHandle compilerHandle = GetCompilerHandle(SH_SPIRV_VULKAN_OUTPUT);
|
||||
gl::BlendEquationBitSet enabledBlendEquation(sh::GetAdvancedBlendEquations(compilerHandle));
|
||||
EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Multiply));
|
||||
EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Screen));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
|
||||
KHRBlendEquationAdvancedEnabledSeparatelyTest,
|
||||
Combine(Values(SH_GLES3_1_SPEC),
|
||||
Values(sh::ESSLVersion310),
|
||||
Values(ESSL310_DeclaredMultiplyScreenSeparately)));
|
||||
|
||||
class KHRBlendEquationAdvancedEnabledSuccessivelyTest
|
||||
: public KHRBlendEquationAdvancedEnabledListCheckTest
|
||||
{};
|
||||
|
||||
// Test for declaring different blend equations in the same layout declaration
|
||||
TEST_P(KHRBlendEquationAdvancedEnabledSuccessivelyTest, DeclaredEquationSuccessively)
|
||||
{
|
||||
SetExtensionEnable(true);
|
||||
InitializeCompiler();
|
||||
TestShaderCompile(true, EXTPragma);
|
||||
|
||||
const ShHandle compilerHandle = GetCompilerHandle(SH_SPIRV_VULKAN_OUTPUT);
|
||||
gl::BlendEquationBitSet enabledBlendEquation(sh::GetAdvancedBlendEquations(compilerHandle));
|
||||
EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Multiply));
|
||||
EXPECT_TRUE(enabledBlendEquation.test(gl::BlendEquationType::Screen));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(CorrectESSL310Shaders,
|
||||
KHRBlendEquationAdvancedEnabledSuccessivelyTest,
|
||||
Combine(Values(SH_GLES3_1_SPEC),
|
||||
Values(sh::ESSLVersion310),
|
||||
Values(ESSL310_DeclaredMultiplyScreenSuccessively)));
|
||||
|
||||
#endif
|
||||
|
||||
} // anonymous namespace
|
||||
0
src/tests/gl_tests/ProgramPipelineTest.cpp
Executable file → Normal file
0
src/tests/gl_tests/ProgramPipelineTest.cpp
Executable file → Normal file
Reference in New Issue
Block a user