Path: blob/main_old/src/tests/compiler_tests/BufferVariables_test.cpp
1693 views
//1// Copyright 2017 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// BufferVariables_test.cpp:6// Tests for buffer variables in GLSL ES 3.10 section 4.3.7.7//89#include "gtest/gtest.h"1011#include "GLSLANG/ShaderLang.h"12#include "angle_gl.h"13#include "gtest/gtest.h"14#include "tests/test_utils/ShaderCompileTreeTest.h"15#include "tests/test_utils/compiler_test.h"1617using namespace sh;1819class BufferVariablesTest : public ShaderCompileTreeTest20{21public:22BufferVariablesTest() {}2324protected:25::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }26ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }27void initResources(ShBuiltInResources *resources) override28{29resources->MaxShaderStorageBufferBindings = 8;30}31};3233class BufferVariablesMatchTest : public MatchOutputCodeTest34{35public:36BufferVariablesMatchTest() : MatchOutputCodeTest(GL_VERTEX_SHADER, 0, SH_ESSL_OUTPUT)37{38getResources()->MaxShaderStorageBufferBindings = 8;39}40};4142// Test that the buffer qualifier described in GLSL ES 3.10 section 4.3.7 can be successfully43// compiled.44TEST_F(BufferVariablesTest, BasicShaderStorageBlockDeclaration)45{46const std::string &source =47"#version 310 es\n"48"layout(binding = 3) buffer buf {\n"49" int b1;\n"50" buffer int b2;\n"51"};\n"52"void main()\n"53"{\n"54"}\n";55if (!compile(source))56{57FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;58}59}6061// Test that shader storage block layout qualifiers can be declared for global scope.62TEST_F(BufferVariablesTest, LayoutQualifiersDeclaredInGlobal)63{64const std::string &source =65"#version 310 es\n"66"layout(shared, column_major) buffer;\n"67"void main()\n"68"{\n"69"}\n";70if (!compile(source))71{72FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;73}74}7576// Test that shader storage block can be used with one or more memory qualifiers.77TEST_F(BufferVariablesTest, ShaderStorageBlockWithMemoryQualifier)78{79const std::string &source =80"#version 310 es\n"81"layout(binding = 3) writeonly buffer buf {\n"82" int b1;\n"83" buffer int b2;\n"84"};\n"85"void main()\n"86"{\n"87"}\n";88if (!compile(source))89{90FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;91}92}9394// Test that buffer variables can be used with one or more memory qualifiers.95TEST_F(BufferVariablesTest, BufferVariablesWithMemoryQualifier)96{97const std::string &source =98"#version 310 es\n"99"layout(binding = 3) buffer buf {\n"100" writeonly int b1;\n"101" writeonly buffer int b2;\n"102"};\n"103"void main()\n"104"{\n"105"}\n";106if (!compile(source))107{108FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;109}110}111112// Test that it is a compile-time error to declare buffer variables at global scope (outside a113// block).114TEST_F(BufferVariablesTest, DeclareBufferVariableAtGlobal)115{116const std::string &source =117"#version 310 es\n"118"layout(binding = 3) buffer int a;\n"119"void main()\n"120"{\n"121"}\n";122if (compile(source))123{124FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;125}126}127128// Test that the buffer variable can't be opaque type.129TEST_F(BufferVariablesTest, BufferVariableWithOpaqueType)130{131const std::string &source =132"#version 310 es\n"133"layout(binding = 3) buffer buf {\n"134" int b1;\n"135" atomic_uint b2;\n"136"};\n"137"void main()\n"138"{\n"139"}\n";140if (compile(source))141{142FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;143}144}145146// Test that the uniform variable can't be in shader storage block.147TEST_F(BufferVariablesTest, UniformVariableInShaderStorageBlock)148{149const std::string &source =150"#version 310 es\n"151"layout(binding = 3) buffer buf {\n"152" uniform int a;\n"153"};\n"154"void main()\n"155"{\n"156"}\n";157if (compile(source))158{159FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;160}161}162163// Test that buffer qualifier is not supported in verson lower than GLSL ES 3.10.164TEST_F(BufferVariablesTest, BufferQualifierInESSL3)165{166const std::string &source =167"#version 300 es\n"168"layout(binding = 3) buffer buf {\n"169" int b1;\n"170" buffer int b2;\n"171"};\n"172"void main()\n"173"{\n"174"}\n";175if (compile(source))176{177FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;178}179}180181// Test that can't assign to a readonly buffer variable.182TEST_F(BufferVariablesTest, AssignToReadonlyBufferVariable)183{184const std::string &source =185"#version 310 es\n"186"layout(binding = 3) buffer buf {\n"187" readonly int b1;\n"188"};\n"189"void main()\n"190"{\n"191" b1 = 5;\n"192"}\n";193if (compile(source))194{195FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;196}197}198199// Test that can't assign to a buffer variable declared within shader storage block with readonly.200TEST_F(BufferVariablesTest, AssignToBufferVariableWithinReadonlyBlock)201{202const std::string &source =203"#version 310 es\n"204"layout(binding = 3) readonly buffer buf {\n"205" int b1;\n"206"};\n"207"void main()\n"208"{\n"209" b1 = 5;\n"210"}\n";211if (compile(source))212{213FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;214}215}216217// Test that can't assign to a readonly buffer variable through an instance name.218TEST_F(BufferVariablesTest, AssignToReadonlyBufferVariableByInstanceName)219{220const std::string &source =221R"(#version 310 es222layout(binding = 3) buffer buf {223readonly float f;224} instanceBuffer;225void main()226{227instanceBuffer.f += 0.2;228})";229if (compile(source))230{231FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;232}233}234235// Test that can't assign to a readonly struct buffer variable.236TEST_F(BufferVariablesTest, AssignToReadonlyStructBufferVariable)237{238const std::string &source =239R"(#version 310 es240struct S {241float f;242};243layout(binding = 3) buffer buf {244readonly S s;245};246void main()247{248s.f += 0.2;249})";250if (compile(source))251{252FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;253}254}255256// Test that can't assign to a readonly struct buffer variable through an instance name.257TEST_F(BufferVariablesTest, AssignToReadonlyStructBufferVariableByInstanceName)258{259const std::string &source =260R"(#version 310 es261struct S {262float f;263};264layout(binding = 3) buffer buf {265readonly S s;266} instanceBuffer;267void main()268{269instanceBuffer.s.f += 0.2;270})";271if (compile(source))272{273FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;274}275}276277// Test that a readonly and writeonly buffer variable should neither read or write.278TEST_F(BufferVariablesTest, AccessReadonlyWriteonlyBufferVariable)279{280const std::string &source =281"#version 310 es\n"282"layout(binding = 3) buffer buf {\n"283" readonly writeonly int b1;\n"284"};\n"285"void main()\n"286"{\n"287" b1 = 5;\n"288" int test = b1;\n"289"}\n";290if (compile(source))291{292FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;293}294}295296// Test that accessing a writeonly buffer variable should be error.297TEST_F(BufferVariablesTest, AccessWriteonlyBufferVariable)298{299const std::string &source =300"#version 310 es\n"301"layout(binding = 3) buffer buf {\n"302" writeonly int b1;\n"303"};\n"304"void main()\n"305"{\n"306" int test = b1;\n"307"}\n";308if (compile(source))309{310FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;311}312}313314// Test that accessing a buffer variable through an instance name is ok.315TEST_F(BufferVariablesTest, AccessReadonlyBufferVariableByInstanceName)316{317const std::string &source =318"#version 310 es\n"319"layout(binding = 3) buffer buf {\n"320" readonly float f;\n"321"} instanceBuffer;\n"322"void main()\n"323"{\n"324" gl_Position.x = instanceBuffer.f;\n"325"}\n";326if (!compile(source))327{328FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;329}330}331332// Test that accessing a buffer variable through an instance name inherits the writeonly qualifier333// and generates errors.334TEST_F(BufferVariablesTest, AccessWriteonlyBufferVariableByInstanceName)335{336const std::string &source =337"#version 310 es\n"338"layout(binding = 3) writeonly buffer buf {\n"339" float f;\n"340"} instanceBuffer;\n"341"void main()\n"342"{\n"343" float test = instanceBuffer.f;\n"344"}\n";345if (compile(source))346{347FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;348}349}350351// Test that writeonly buffer variable as the argument of a unary operator should be error.352TEST_F(BufferVariablesTest, UnaryOperatorWithWriteonlyBufferVariable)353{354const std::string &source =355"#version 310 es\n"356"layout(binding = 3) buffer buf {\n"357" writeonly int b1;\n"358"};\n"359"void main()\n"360"{\n"361" ++b1;\n"362"}\n";363if (compile(source))364{365FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;366}367}368369// Test that writeonly buffer variable on the left-hand side of compound assignment should be error.370TEST_F(BufferVariablesTest, CompoundAssignmentToWriteonlyBufferVariable)371{372const std::string &source =373"#version 310 es\n"374"layout(binding = 3) buffer buf {\n"375" writeonly int b1;\n"376"};\n"377"void main()\n"378"{\n"379" b1 += 5;\n"380"}\n";381if (compile(source))382{383FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;384}385}386387// Test that writeonly buffer variable as ternary op argument should be error.388TEST_F(BufferVariablesTest, TernarySelectionWithWriteonlyBufferVariable)389{390const std::string &source =391"#version 310 es\n"392"layout(binding = 3) buffer buf {\n"393" writeonly bool b1;\n"394"};\n"395"void main()\n"396"{\n"397" int test = b1 ? 1 : 0;\n"398"}\n";399if (compile(source))400{401FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;402}403}404405// Test that writeonly buffer variable as array constructor argument should be error.406TEST_F(BufferVariablesTest, ArrayConstructorWithWriteonlyBufferVariable)407{408const std::string &source =409"#version 310 es\n"410"layout(binding = 3) buffer buf {\n"411" writeonly float f;\n"412"};\n"413"void main()\n"414"{\n"415" float a[3] = float[3](f, f, f);\n"416"}\n";417if (compile(source))418{419FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;420}421}422423// Test that writeonly buffer variable as structure constructor argument should be error.424TEST_F(BufferVariablesTest, StructureConstructorWithWriteonlyBufferVariable)425{426const std::string &source =427"#version 310 es\n"428"struct S {\n"429" int a;\n"430"};\n"431"struct T {\n"432" S b;\n"433"};\n"434"layout(binding = 3) buffer buf {\n"435" writeonly S c;\n"436"};\n"437"void main()\n"438"{\n"439" T t = T(c);\n"440"}\n";441if (compile(source))442{443FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;444}445}446447// Test that writeonly buffer variable as built-in function argument should be error.448TEST_F(BufferVariablesTest, BuildInFunctionWithWriteonlyBufferVariable)449{450const std::string &source =451"#version 310 es\n"452"layout(binding = 3) buffer buf {\n"453" writeonly int a;\n"454"};\n"455"void main()\n"456"{\n"457" int test = min(a, 1);\n"458"}\n";459if (compile(source))460{461FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;462}463}464465// Test that readonly buffer variable as user-defined function in argument should be ok.466TEST_F(BufferVariablesTest, UserDefinedFunctionWithReadonlyBufferVariableInArgument)467{468const std::string &source =469"#version 310 es\n"470"layout(binding = 3) buffer buf {\n"471" readonly float f;\n"472"};\n"473"void foo(float a) {}\n"474"void main()\n"475"{\n"476" foo(f);\n"477"}\n";478if (!compile(source))479{480FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;481}482}483484// Test that writeonly buffer variable as user-defined function in argument should be error.485TEST_F(BufferVariablesTest, UserDefinedFunctionWithWriteonlyBufferVariableInArgument)486{487const std::string &source =488"#version 310 es\n"489"layout(binding = 3) buffer buf {\n"490" writeonly float f;\n"491"};\n"492"void foo(float a) {}\n"493"void main()\n"494"{\n"495" foo(f);\n"496"}\n";497if (compile(source))498{499FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;500}501}502503// Test that writeonly buffer variable as user-defined function out argument should be ok.504TEST_F(BufferVariablesTest, UserDefinedFunctionWithWriteonlyBufferVariableOutArgument)505{506const std::string &source =507"#version 310 es\n"508"layout(binding = 3) buffer buf {\n"509" writeonly float f;\n"510"};\n"511"void foo(out float a) {}\n"512"void main()\n"513"{\n"514" foo(f);\n"515"}\n";516if (!compile(source))517{518FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;519}520}521522// Test that readonly buffer variable as user-defined function out argument should be error.523TEST_F(BufferVariablesTest, UserDefinedFunctionWithReadonlyBufferVariableOutArgument)524{525const std::string &source =526"#version 310 es\n"527"layout(binding = 3) buffer buf {\n"528" readonly float f;\n"529"};\n"530"void foo(out float a) {}\n"531"void main()\n"532"{\n"533" foo(f);\n"534"}\n";535if (compile(source))536{537FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;538}539}540541// Test that buffer qualifier can't modify a function parameter.542TEST_F(BufferVariablesTest, BufferQualifierOnFunctionParameter)543{544const std::string &source =545"#version 310 es\n"546"void foo(buffer float a) {}\n"547"void main()\n"548"{\n"549"}\n";550if (compile(source))551{552FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;553}554}555556// Test that std430 qualifier is supported for shader storage blocks.557TEST_F(BufferVariablesTest, ShaderStorageBlockWithStd430)558{559const std::string &source =560"#version 310 es\n"561"layout(std430) buffer buf {\n"562" int b1;\n"563" int b2;\n"564"};\n"565"void main()\n"566"{\n"567"}\n";568if (!compile(source))569{570FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;571}572}573574// Test that using std430 qualifier on a uniform block will fail to compile.575TEST_F(BufferVariablesTest, UniformBlockWithStd430)576{577const std::string &source =578"#version 310 es\n"579"layout(std430) uniform buf {\n"580" int b1;\n"581" int b2;\n"582"};\n"583"void main()\n"584"{\n"585"}\n";586if (compile(source))587{588FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;589}590}591592// Test that indexing a runtime-sized array with a positive index compiles.593TEST_F(BufferVariablesTest, IndexRuntimeSizedArray)594{595const std::string &source =596R"(#version 310 es597598layout(std430) buffer buf599{600int arr[];601};602603void main()604{605arr[100];606})";607if (!compile(source))608{609FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;610}611}612613// Test that indexing a runtime-sized array with a negative constant index does not compile.614TEST_F(BufferVariablesTest, IndexRuntimeSizedArrayWithNegativeIndex)615{616const std::string &source =617R"(#version 310 es618619layout(std430) buffer buf620{621int arr[];622};623624void main()625{626arr[-1];627})";628if (compile(source))629{630FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;631}632}633634// Test that only the last member of a buffer can be runtime-sized.635TEST_F(BufferVariablesTest, RuntimeSizedVariableInNotLastInBuffer)636{637const std::string &source =638R"(#version 310 es639640layout(std430) buffer buf641{642int arr[];643int i;644};645646void main()647{648})";649if (compile(source))650{651FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;652}653}654655// Test that memory qualifiers are output.656TEST_F(BufferVariablesMatchTest, MemoryQualifiers)657{658const std::string &source =659R"(#version 310 es660661layout(std430) coherent buffer buf662{663int defaultCoherent;664coherent ivec2 specifiedCoherent;665volatile ivec3 specifiedVolatile;666restrict ivec4 specifiedRestrict;667readonly float specifiedReadOnly;668writeonly vec2 specifiedWriteOnly;669volatile readonly vec3 specifiedMultiple;670};671672void main()673{674})";675compile(source);676ASSERT_TRUE(foundInESSLCode("coherent highp int"));677ASSERT_TRUE(foundInESSLCode("coherent highp ivec2"));678ASSERT_TRUE(foundInESSLCode("coherent volatile highp ivec3"));679ASSERT_TRUE(foundInESSLCode("coherent restrict highp ivec4"));680ASSERT_TRUE(foundInESSLCode("readonly coherent highp float"));681ASSERT_TRUE(foundInESSLCode("writeonly coherent highp vec2"));682ASSERT_TRUE(foundInESSLCode("readonly coherent volatile highp vec3"));683}684685686