Commit ca2b6e1f by Mohan Maiya Committed by Commit Bot

Vulkan: Implement EXT_shader_non_constant_global_initializers

Enables the translator to handle non-constant global initializers in all essl versions iff the shader enables the extension to do so. Bug: angleproject:4468 Test: angle_end2end_tests --gtest_filter=ShaderNonConstGlobalInitializerTest.* Change-Id: I8f138c12fc83d2f38ff8f45ca9133222b01e4087 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2102959Reviewed-by: 's avatarTobin Ehlis <tobine@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Mohan Maiya <m.maiya@samsung.com>
parent 13ea5b7f
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 225 #define ANGLE_SH_VERSION 226
enum ShShaderSpec enum ShShaderSpec
{ {
...@@ -387,6 +387,7 @@ struct ShBuiltInResources ...@@ -387,6 +387,7 @@ struct ShBuiltInResources
int EXT_YUV_target; int EXT_YUV_target;
int EXT_geometry_shader; int EXT_geometry_shader;
int EXT_gpu_shader5; int EXT_gpu_shader5;
int EXT_shader_non_constant_global_initializers;
int OES_texture_storage_multisample_2d_array; int OES_texture_storage_multisample_2d_array;
int OES_texture_3D; int OES_texture_3D;
int ANGLE_texture_multisample; int ANGLE_texture_multisample;
......
...@@ -557,6 +557,21 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, ...@@ -557,6 +557,21 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
return false; return false;
} }
// We need to generate globals early if we have non constant initializers enabled
bool initializeLocalsAndGlobals =
(compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
bool highPrecisionSupported = mShaderVersion > 100 || mShaderType != GL_FRAGMENT_SHADER ||
mResources.FragmentPrecisionHigh == 1;
bool enableNonConstantInitializers = IsExtensionEnabled(
mExtensionBehavior, TExtension::EXT_shader_non_constant_global_initializers);
if (enableNonConstantInitializers &&
!DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
highPrecisionSupported, &mSymbolTable))
{
return false;
}
// Create the function DAG and check there is no recursion // Create the function DAG and check there is no recursion
if (!initCallDag(root)) if (!initCallDag(root))
{ {
...@@ -765,8 +780,6 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, ...@@ -765,8 +780,6 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
GetGlobalPoolAllocator()->unlock(); GetGlobalPoolAllocator()->unlock();
mBuiltInFunctionEmulator.markBuiltInFunctionsForEmulation(root); mBuiltInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
bool highPrecisionSupported = mShaderVersion > 100 || mShaderType != GL_FRAGMENT_SHADER ||
mResources.FragmentPrecisionHigh == 1;
if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS) if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
{ {
if (!ScalarizeVecAndMatConstructorArgs(this, root, mShaderType, highPrecisionSupported, if (!ScalarizeVecAndMatConstructorArgs(this, root, mShaderType, highPrecisionSupported,
...@@ -839,10 +852,11 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, ...@@ -839,10 +852,11 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
// statements from expressions. But it's fine to run DeferGlobalInitializers after the above // statements from expressions. But it's fine to run DeferGlobalInitializers after the above
// SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
// on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00. // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
bool initializeLocalsAndGlobals = // Exception: if EXT_shader_non_constant_global_initializers is enabled, we must generate global
(compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType()); // initializers before we generate the DAG, since initializers may call functions which must not
bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES); // be optimized out
if (!DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize, if (!enableNonConstantInitializers &&
!DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
highPrecisionSupported, &mSymbolTable)) highPrecisionSupported, &mSymbolTable))
{ {
return false; return false;
......
...@@ -12,29 +12,30 @@ ...@@ -12,29 +12,30 @@
#include <string.h> #include <string.h>
#define LIST_EXTENSIONS(OP) \ #define LIST_EXTENSIONS(OP) \
OP(ARB_texture_rectangle) \ OP(ARB_texture_rectangle) \
OP(ANGLE_texture_multisample) \ OP(ANGLE_texture_multisample) \
OP(ARM_shader_framebuffer_fetch) \ OP(ARM_shader_framebuffer_fetch) \
OP(EXT_blend_func_extended) \ OP(EXT_blend_func_extended) \
OP(EXT_draw_buffers) \ OP(EXT_draw_buffers) \
OP(EXT_frag_depth) \ OP(EXT_frag_depth) \
OP(EXT_geometry_shader) \ OP(EXT_geometry_shader) \
OP(EXT_gpu_shader5) \ OP(EXT_gpu_shader5) \
OP(EXT_shader_framebuffer_fetch) \ OP(EXT_shader_framebuffer_fetch) \
OP(EXT_shader_texture_lod) \ OP(EXT_shader_texture_lod) \
OP(EXT_YUV_target) \ OP(EXT_YUV_target) \
OP(NV_EGL_stream_consumer_external) \ OP(EXT_shader_non_constant_global_initializers) \
OP(NV_shader_framebuffer_fetch) \ OP(NV_EGL_stream_consumer_external) \
OP(OES_EGL_image_external) \ OP(NV_shader_framebuffer_fetch) \
OP(OES_EGL_image_external_essl3) \ OP(OES_EGL_image_external) \
OP(OES_standard_derivatives) \ OP(OES_EGL_image_external_essl3) \
OP(OES_texture_storage_multisample_2d_array) \ OP(OES_standard_derivatives) \
OP(OES_texture_3D) \ OP(OES_texture_storage_multisample_2d_array) \
OP(OVR_multiview) \ OP(OES_texture_3D) \
OP(OVR_multiview2) \ OP(OVR_multiview) \
OP(ANGLE_multi_draw) \ OP(OVR_multiview2) \
OP(ANGLE_base_vertex_base_instance) \ OP(ANGLE_multi_draw) \
OP(ANGLE_base_vertex_base_instance) \
OP(WEBGL_video_texture) OP(WEBGL_video_texture)
namespace sh namespace sh
......
...@@ -29,6 +29,7 @@ enum class TExtension ...@@ -29,6 +29,7 @@ enum class TExtension
EXT_shader_framebuffer_fetch, EXT_shader_framebuffer_fetch,
EXT_shader_texture_lod, EXT_shader_texture_lod,
EXT_YUV_target, EXT_YUV_target,
EXT_shader_non_constant_global_initializers,
NV_EGL_stream_consumer_external, NV_EGL_stream_consumer_external,
NV_shader_framebuffer_fetch, NV_shader_framebuffer_fetch,
OES_EGL_image_external, OES_EGL_image_external,
......
...@@ -81,6 +81,10 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi ...@@ -81,6 +81,10 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi
{ {
extBehavior[TExtension::EXT_gpu_shader5] = EBhUndefined; extBehavior[TExtension::EXT_gpu_shader5] = EBhUndefined;
} }
if (resources.EXT_shader_non_constant_global_initializers)
{
extBehavior[TExtension::EXT_shader_non_constant_global_initializers] = EBhUndefined;
}
if (resources.OES_texture_storage_multisample_2d_array) if (resources.OES_texture_storage_multisample_2d_array)
{ {
extBehavior[TExtension::OES_texture_storage_multisample_2d_array] = EBhUndefined; extBehavior[TExtension::OES_texture_storage_multisample_2d_array] = EBhUndefined;
......
...@@ -2038,10 +2038,13 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, ...@@ -2038,10 +2038,13 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
return false; return false;
} }
bool nonConstGlobalInitializers =
IsExtensionEnabled(mDirectiveHandler.extensionBehavior(),
TExtension::EXT_shader_non_constant_global_initializers);
bool globalInitWarning = false; bool globalInitWarning = false;
if (symbolTable.atGlobalLevel() && if (symbolTable.atGlobalLevel() &&
!ValidateGlobalInitializer(initializer, mShaderVersion, sh::IsWebGLBasedSpec(mShaderSpec), !ValidateGlobalInitializer(initializer, mShaderVersion, sh::IsWebGLBasedSpec(mShaderSpec),
&globalInitWarning)) nonConstGlobalInitializers, &globalInitWarning))
{ {
// Error message does not completely match behavior with ESSL 1.00, but // Error message does not completely match behavior with ESSL 1.00, but
// we want to steer developers towards only using constant expressions. // we want to steer developers towards only using constant expressions.
......
...@@ -149,30 +149,31 @@ void InitBuiltInResources(ShBuiltInResources *resources) ...@@ -149,30 +149,31 @@ void InitBuiltInResources(ShBuiltInResources *resources)
resources->MaxDrawBuffers = 1; resources->MaxDrawBuffers = 1;
// Extensions. // Extensions.
resources->OES_standard_derivatives = 0; resources->OES_standard_derivatives = 0;
resources->OES_EGL_image_external = 0; resources->OES_EGL_image_external = 0;
resources->OES_EGL_image_external_essl3 = 0; resources->OES_EGL_image_external_essl3 = 0;
resources->NV_EGL_stream_consumer_external = 0; resources->NV_EGL_stream_consumer_external = 0;
resources->ARB_texture_rectangle = 0; resources->ARB_texture_rectangle = 0;
resources->EXT_blend_func_extended = 0; resources->EXT_blend_func_extended = 0;
resources->EXT_draw_buffers = 0; resources->EXT_draw_buffers = 0;
resources->EXT_frag_depth = 0; resources->EXT_frag_depth = 0;
resources->EXT_shader_texture_lod = 0; resources->EXT_shader_texture_lod = 0;
resources->WEBGL_debug_shader_precision = 0; resources->WEBGL_debug_shader_precision = 0;
resources->EXT_shader_framebuffer_fetch = 0; resources->EXT_shader_framebuffer_fetch = 0;
resources->NV_shader_framebuffer_fetch = 0; resources->NV_shader_framebuffer_fetch = 0;
resources->ARM_shader_framebuffer_fetch = 0; resources->ARM_shader_framebuffer_fetch = 0;
resources->OVR_multiview = 0; resources->OVR_multiview = 0;
resources->OVR_multiview2 = 0; resources->OVR_multiview2 = 0;
resources->EXT_YUV_target = 0; resources->EXT_YUV_target = 0;
resources->EXT_geometry_shader = 0; resources->EXT_geometry_shader = 0;
resources->EXT_gpu_shader5 = 0; resources->EXT_gpu_shader5 = 0;
resources->OES_texture_storage_multisample_2d_array = 0; resources->EXT_shader_non_constant_global_initializers = 0;
resources->OES_texture_3D = 0; resources->OES_texture_storage_multisample_2d_array = 0;
resources->ANGLE_texture_multisample = 0; resources->OES_texture_3D = 0;
resources->ANGLE_multi_draw = 0; resources->ANGLE_texture_multisample = 0;
resources->ANGLE_base_vertex_base_instance = 0; resources->ANGLE_multi_draw = 0;
resources->WEBGL_video_texture = 0; resources->ANGLE_base_vertex_base_instance = 0;
resources->WEBGL_video_texture = 0;
resources->NV_draw_buffers = 0; resources->NV_draw_buffers = 0;
......
...@@ -19,7 +19,9 @@ const int kMaxAllowedTraversalDepth = 256; ...@@ -19,7 +19,9 @@ const int kMaxAllowedTraversalDepth = 256;
class ValidateGlobalInitializerTraverser : public TIntermTraverser class ValidateGlobalInitializerTraverser : public TIntermTraverser
{ {
public: public:
ValidateGlobalInitializerTraverser(int shaderVersion, bool isWebGL); ValidateGlobalInitializerTraverser(int shaderVersion,
bool isWebGL,
bool hasExtNonConstGlobalInitializers);
void visitSymbol(TIntermSymbol *node) override; void visitSymbol(TIntermSymbol *node) override;
void visitConstantUnion(TIntermConstantUnion *node) override; void visitConstantUnion(TIntermConstantUnion *node) override;
...@@ -31,8 +33,24 @@ class ValidateGlobalInitializerTraverser : public TIntermTraverser ...@@ -31,8 +33,24 @@ class ValidateGlobalInitializerTraverser : public TIntermTraverser
bool issueWarning() const { return mIssueWarning; } bool issueWarning() const { return mIssueWarning; }
private: private:
ANGLE_INLINE void onNonConstInitializerVisit(bool accept)
{
if (accept)
{
if (!mExtNonConstGlobalInitializers)
{
mIssueWarning = true;
}
}
else
{
mIsValid = false;
}
}
int mShaderVersion; int mShaderVersion;
bool mIsWebGL; bool mIsWebGL;
bool mExtNonConstGlobalInitializers;
bool mIsValid; bool mIsValid;
bool mIssueWarning; bool mIssueWarning;
}; };
...@@ -51,14 +69,8 @@ void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node) ...@@ -51,14 +69,8 @@ void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node)
// We allow these cases to be compatible with legacy ESSL 1.00 content. // We allow these cases to be compatible with legacy ESSL 1.00 content.
// Implement stricter rules for ESSL 3.00 since there's no legacy content to deal // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal
// with. // with.
if ((mShaderVersion >= 300) || !mIsWebGL) onNonConstInitializerVisit(mExtNonConstGlobalInitializers ||
{ ((mShaderVersion < 300) && mIsWebGL));
mIsValid = false;
}
else
{
mIssueWarning = true;
}
break; break;
default: default:
mIsValid = false; mIsValid = false;
...@@ -74,14 +86,8 @@ void ValidateGlobalInitializerTraverser::visitConstantUnion(TIntermConstantUnion ...@@ -74,14 +86,8 @@ void ValidateGlobalInitializerTraverser::visitConstantUnion(TIntermConstantUnion
case EvqConst: case EvqConst:
break; break;
case EvqTemporary: case EvqTemporary:
if ((mShaderVersion >= 300) || !mIsWebGL) onNonConstInitializerVisit(mExtNonConstGlobalInitializers ||
{ ((mShaderVersion < 300) && mIsWebGL));
mIsValid = false;
}
else
{
mIssueWarning = true;
}
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -96,7 +102,7 @@ bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggr ...@@ -96,7 +102,7 @@ bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggr
// the function call ops. // the function call ops.
if (node->isFunctionCall()) if (node->isFunctionCall())
{ {
mIsValid = false; onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
} }
return true; return true;
} }
...@@ -105,7 +111,7 @@ bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary ...@@ -105,7 +111,7 @@ bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary
{ {
if (node->isAssignment()) if (node->isAssignment())
{ {
mIsValid = false; onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
} }
return true; return true;
} }
...@@ -114,16 +120,19 @@ bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *n ...@@ -114,16 +120,19 @@ bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *n
{ {
if (node->isAssignment()) if (node->isAssignment())
{ {
mIsValid = false; onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
} }
return true; return true;
} }
ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(int shaderVersion, ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(
bool isWebGL) int shaderVersion,
bool isWebGL,
bool hasExtNonConstGlobalInitializers)
: TIntermTraverser(true, false, false, nullptr), : TIntermTraverser(true, false, false, nullptr),
mShaderVersion(shaderVersion), mShaderVersion(shaderVersion),
mIsWebGL(isWebGL), mIsWebGL(isWebGL),
mExtNonConstGlobalInitializers(hasExtNonConstGlobalInitializers),
mIsValid(true), mIsValid(true),
mIssueWarning(false) mIssueWarning(false)
{ {
...@@ -135,9 +144,11 @@ ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(int shade ...@@ -135,9 +144,11 @@ ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(int shade
bool ValidateGlobalInitializer(TIntermTyped *initializer, bool ValidateGlobalInitializer(TIntermTyped *initializer,
int shaderVersion, int shaderVersion,
bool isWebGL, bool isWebGL,
bool hasExtNonConstGlobalInitializers,
bool *warning) bool *warning)
{ {
ValidateGlobalInitializerTraverser validate(shaderVersion, isWebGL); ValidateGlobalInitializerTraverser validate(shaderVersion, isWebGL,
hasExtNonConstGlobalInitializers);
initializer->traverse(&validate); initializer->traverse(&validate);
ASSERT(warning != nullptr); ASSERT(warning != nullptr);
*warning = validate.issueWarning(); *warning = validate.issueWarning();
......
...@@ -16,6 +16,7 @@ class TIntermTyped; ...@@ -16,6 +16,7 @@ class TIntermTyped;
bool ValidateGlobalInitializer(TIntermTyped *initializer, bool ValidateGlobalInitializer(TIntermTyped *initializer,
int shaderVersion, int shaderVersion,
bool isWebGL, bool isWebGL,
bool hasExtNonConstGlobalInitializers,
bool *warning); bool *warning);
} // namespace sh } // namespace sh
......
...@@ -992,6 +992,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -992,6 +992,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_OES_point_sprite"] = enableableExtension(&Extensions::pointSpriteOES); map["GL_OES_point_sprite"] = enableableExtension(&Extensions::pointSpriteOES);
map["GL_OES_draw_texture"] = enableableExtension(&Extensions::drawTextureOES); map["GL_OES_draw_texture"] = enableableExtension(&Extensions::drawTextureOES);
map["GL_ANGLE_memory_size"] = enableableExtension(&Extensions::memorySize); map["GL_ANGLE_memory_size"] = enableableExtension(&Extensions::memorySize);
map["GL_EXT_shader_non_constant_global_initializers"] = enableableExtension(&Extensions::shaderNonConstGlobalInitializersEXT);
map["GL_WEBGL_video_texture"] = enableableExtension(&Extensions::webglVideoTexture); map["GL_WEBGL_video_texture"] = enableableExtension(&Extensions::webglVideoTexture);
// clang-format on // clang-format on
......
...@@ -595,6 +595,9 @@ struct Extensions ...@@ -595,6 +595,9 @@ struct Extensions
return (drawElementsBaseVertexOES || drawElementsBaseVertexEXT); return (drawElementsBaseVertexOES || drawElementsBaseVertexEXT);
} }
// GL_EXT_shader_non_constant_global_initializers
bool shaderNonConstGlobalInitializersEXT = false;
// GL_EXT_gpu_shader5 // GL_EXT_gpu_shader5
bool gpuShader5EXT = false; bool gpuShader5EXT = false;
// WEBGL_video_texture // WEBGL_video_texture
......
...@@ -90,8 +90,10 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state) ...@@ -90,8 +90,10 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state)
mResources.OES_standard_derivatives = extensions.standardDerivativesOES; mResources.OES_standard_derivatives = extensions.standardDerivativesOES;
mResources.EXT_draw_buffers = extensions.drawBuffers; mResources.EXT_draw_buffers = extensions.drawBuffers;
mResources.EXT_shader_texture_lod = extensions.shaderTextureLOD; mResources.EXT_shader_texture_lod = extensions.shaderTextureLOD;
mResources.OES_EGL_image_external = extensions.eglImageExternalOES; mResources.EXT_shader_non_constant_global_initializers =
mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3OES; extensions.shaderNonConstGlobalInitializersEXT;
mResources.OES_EGL_image_external = extensions.eglImageExternalOES;
mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3OES;
mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternalNV; mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternalNV;
mResources.ARB_texture_rectangle = extensions.textureRectangle; mResources.ARB_texture_rectangle = extensions.textureRectangle;
mResources.EXT_gpu_shader5 = extensions.gpuShader5EXT; mResources.EXT_gpu_shader5 = extensions.gpuShader5EXT;
......
...@@ -162,6 +162,9 @@ void RendererVk::ensureCapsInitialized() const ...@@ -162,6 +162,9 @@ void RendererVk::ensureCapsInitialized() const
// We support getting image data for Textures and Renderbuffers. // We support getting image data for Textures and Renderbuffers.
mNativeExtensions.getImageANGLE = true; mNativeExtensions.getImageANGLE = true;
// Implemented in the translator
mNativeExtensions.shaderNonConstGlobalInitializersEXT = true;
// Vulkan has no restrictions of the format of cubemaps, so if the proper formats are supported, // Vulkan has no restrictions of the format of cubemaps, so if the proper formats are supported,
// creating a cube of any of these formats should be implicitly supported. // creating a cube of any of these formats should be implicitly supported.
mNativeExtensions.depthTextureCubeMapOES = mNativeExtensions.depthTextureCubeMapOES =
......
...@@ -106,6 +106,7 @@ angle_end2end_tests_sources = [ ...@@ -106,6 +106,7 @@ angle_end2end_tests_sources = [
"gl_tests/SRGBTextureTest.cpp", "gl_tests/SRGBTextureTest.cpp",
"gl_tests/SamplersTest.cpp", "gl_tests/SamplersTest.cpp",
"gl_tests/SemaphoreTest.cpp", "gl_tests/SemaphoreTest.cpp",
"gl_tests/ShaderNonConstGlobalInitializerTest.cpp",
"gl_tests/ShaderStorageBufferTest.cpp", "gl_tests/ShaderStorageBufferTest.cpp",
"gl_tests/SimpleOperationTest.cpp", "gl_tests/SimpleOperationTest.cpp",
"gl_tests/SixteenBppTextureTest.cpp", "gl_tests/SixteenBppTextureTest.cpp",
......
//
// Copyright 2020 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.
//
// Tests for GL_EXT_shader_non_constant_global_initializers
//
#include "common/mathutil.h"
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
using namespace angle;
class ShaderNonConstGlobalInitializerTest : public ANGLETest
{
protected:
ShaderNonConstGlobalInitializerTest() : ANGLETest()
{
setWindowWidth(128);
setWindowHeight(128);
}
void draw(GLuint program)
{
std::array<Vector4, 3> vertices;
vertices[0] = {-1.0, -1.0, 0.0, 1.0};
vertices[1] = {1.0, -1.0, 0.0, 1.0};
vertices[2] = {0.0, 1.0, 0.0, 2.0};
GLint positionLocation = glGetAttribLocation(program, "a_position");
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, vertices.data());
glEnableVertexAttribArray(positionLocation);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
};
// Tests that the extension is disabled if not explicitly enabled- non constant initializers should
// be forbidden in all cases unless this extension is explicitly requested
TEST_P(ShaderNonConstGlobalInitializerTest, Disabled)
{
const char *fragSrc = R"(#version 100
precision lowp float;
uniform float nondeterministic_uniform;
float nonConstInitializer();
float nonConstGlobal = nonConstInitializer();
float sideEffectGlobal = 0.0;
float nonConstInitializer() {
sideEffectGlobal = 1.0;
return nondeterministic_uniform;
}
void main()
{
gl_FragColor = vec4(nondeterministic_uniform, nonConstGlobal, sideEffectGlobal, 1.0);
}
)";
GLShader badFragment(GL_FRAGMENT_SHADER);
glShaderSource(badFragment, 1, &fragSrc, nullptr);
glCompileShader(badFragment);
GLint compileResult;
glGetShaderiv(badFragment, GL_COMPILE_STATUS, &compileResult);
EXPECT_EQ(compileResult, 0);
EXPECT_GL_NO_ERROR();
}
// Test that non constant initializers are evaluated correctly in ESSL 100
TEST_P(ShaderNonConstGlobalInitializerTest, v100)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
const char *fragSrc = R"(#version 100
#extension GL_EXT_shader_non_constant_global_initializers : require
precision lowp float;
#ifndef GL_EXT_shader_non_constant_global_initializers
#error GL_EXT_shader_non_constant_global_initializers is not defined
#endif
uniform float nondeterministic_uniform;
float nonConstInitializer();
float nonConstGlobal = nonConstInitializer();
float sideEffectGlobal = 0.0;
float nonConstInitializer() {
sideEffectGlobal = 1.0;
return nondeterministic_uniform;
}
void main()
{
gl_FragColor = vec4(nondeterministic_uniform, nonConstGlobal, sideEffectGlobal, 1.0);
}
)";
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragSrc);
EXPECT_GL_NO_ERROR();
glUseProgram(program);
glUniform1f(glGetUniformLocation(program, "nondeterministic_uniform"), 1.0f);
ASSERT_GL_NO_ERROR();
draw(program);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::white);
}
// Test that non constant initializers are evaluated correctly in ESSL 300
TEST_P(ShaderNonConstGlobalInitializerTest, v300es)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
const char *fragSrc = R"(#version 300 es
#extension GL_EXT_shader_non_constant_global_initializers : require
precision highp float;
out vec4 fragColor;
#ifndef GL_EXT_shader_non_constant_global_initializers
#error GL_EXT_shader_non_constant_global_initializers is not defined
#endif
uniform float nondeterministic_uniform;
float nonConstInitializer();
float nonConstGlobal = nonConstInitializer();
float sideEffectGlobal = 0.0;
float nonConstInitializer() {
sideEffectGlobal = 1.0;
return nondeterministic_uniform;
}
void main()
{
fragColor = vec4(nondeterministic_uniform, nonConstGlobal, sideEffectGlobal, 1.0);
}
)";
ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragSrc);
EXPECT_GL_NO_ERROR();
glUseProgram(program);
glUniform1f(glGetUniformLocation(program, "nondeterministic_uniform"), 1.0f);
ASSERT_GL_NO_ERROR();
draw(program);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::white);
}
ANGLE_INSTANTIATE_TEST_ES3(ShaderNonConstGlobalInitializerTest);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment