| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659 |
- // Copyright (c) 2019 Google LLC
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include <sstream>
- #include <string>
- #include <vector>
- #include "pass_fixture.h"
- #include "pass_utils.h"
- #include "source/opt/graphics_robust_access_pass.h"
- namespace {
- using namespace spvtools;
- using opt::GraphicsRobustAccessPass;
- using GraphicsRobustAccessTest = opt::PassTest<::testing::Test>;
- // Test incompatible module, determined at module-level.
- TEST_F(GraphicsRobustAccessTest, FailNotShader) {
- const std::string text = R"(
- ; CHECK: Can only process Shader modules
- OpCapability Kernel
- )";
- SinglePassRunAndFail<GraphicsRobustAccessPass>(text);
- }
- TEST_F(GraphicsRobustAccessTest, FailCantProcessVariablePointers) {
- const std::string text = R"(
- ; CHECK: Can't process modules with VariablePointers capability
- OpCapability VariablePointers
- )";
- SinglePassRunAndFail<GraphicsRobustAccessPass>(text);
- }
- TEST_F(GraphicsRobustAccessTest, FailCantProcessVariablePointersStorageBuffer) {
- const std::string text = R"(
- ; CHECK: Can't process modules with VariablePointersStorageBuffer capability
- OpCapability VariablePointersStorageBuffer
- )";
- SinglePassRunAndFail<GraphicsRobustAccessPass>(text);
- }
- TEST_F(GraphicsRobustAccessTest, FailCantProcessRuntimeDescriptorArrayEXT) {
- const std::string text = R"(
- ; CHECK: Can't process modules with RuntimeDescriptorArrayEXT capability
- OpCapability RuntimeDescriptorArrayEXT
- )";
- SinglePassRunAndFail<GraphicsRobustAccessPass>(text);
- }
- TEST_F(GraphicsRobustAccessTest, FailCantProcessPhysical32AddressingModel) {
- const std::string text = R"(
- ; CHECK: Addressing model must be Logical. Found OpMemoryModel Physical32 OpenCL
- OpCapability Shader
- OpMemoryModel Physical32 OpenCL
- )";
- SinglePassRunAndFail<GraphicsRobustAccessPass>(text);
- }
- TEST_F(GraphicsRobustAccessTest, FailCantProcessPhysical64AddressingModel) {
- const std::string text = R"(
- ; CHECK: Addressing model must be Logical. Found OpMemoryModel Physical64 OpenCL
- OpCapability Shader
- OpMemoryModel Physical64 OpenCL
- )";
- SinglePassRunAndFail<GraphicsRobustAccessPass>(text);
- }
- TEST_F(GraphicsRobustAccessTest,
- FailCantProcessPhysicalStorageBuffer64EXTAddressingModel) {
- const std::string text = R"(
- ; CHECK: Addressing model must be Logical. Found OpMemoryModel PhysicalStorageBuffer64 GLSL450
- OpCapability Shader
- OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
- )";
- SinglePassRunAndFail<GraphicsRobustAccessPass>(text);
- }
- // Test access chains
- // Returns the names of access chain instructions handled by the pass.
- // For the purposes of this pass, regular and in-bounds access chains are the
- // same.)
- std::vector<const char*> AccessChains() {
- return {"OpAccessChain", "OpInBoundsAccessChain"};
- }
- std::string ShaderPreamble() {
- return R"(
- OpCapability Shader
- OpMemoryModel Logical Simple
- OpEntryPoint GLCompute %main "main"
- )";
- }
- std::string ShaderPreamble(const std::vector<std::string>& names) {
- std::ostringstream os;
- os << ShaderPreamble();
- for (auto& name : names) {
- os << " OpName %" << name << " \"" << name << "\"\n";
- }
- return os.str();
- }
- std::string ShaderPreambleAC() {
- return ShaderPreamble({"ac", "ptr_ty", "var"});
- }
- std::string ShaderPreambleAC(const std::vector<std::string>& names) {
- auto names2 = names;
- names2.push_back("ac");
- names2.push_back("ptr_ty");
- names2.push_back("var");
- return ShaderPreamble(names2);
- }
- std::string DecoSSBO() {
- return R"(
- OpDecorate %ssbo_s BufferBlock
- OpMemberDecorate %ssbo_s 0 Offset 0
- OpMemberDecorate %ssbo_s 1 Offset 4
- OpMemberDecorate %ssbo_s 2 Offset 16
- OpDecorate %var DescriptorSet 0
- OpDecorate %var Binding 0
- )";
- }
- std::string TypesVoid() {
- return R"(
- %void = OpTypeVoid
- %void_fn = OpTypeFunction %void
- )";
- }
- std::string TypesInt() {
- return R"(
- %uint = OpTypeInt 32 0
- %int = OpTypeInt 32 1
- )";
- }
- std::string TypesFloat() {
- return R"(
- %float = OpTypeFloat 32
- )";
- }
- std::string TypesShort() {
- return R"(
- %ushort = OpTypeInt 16 0
- %short = OpTypeInt 16 1
- )";
- }
- std::string TypesLong() {
- return R"(
- %ulong = OpTypeInt 64 0
- %long = OpTypeInt 64 1
- )";
- }
- std::string MainPrefix() {
- return R"(
- %main = OpFunction %void None %void_fn
- %entry = OpLabel
- )";
- }
- std::string MainSuffix() {
- return R"(
- OpReturn
- OpFunctionEnd
- )";
- }
- std::string ACCheck(const std::string& access_chain_inst,
- const std::string& original,
- const std::string& transformed) {
- return "\n ; CHECK: %ac = " + access_chain_inst + " %ptr_ty %var" +
- (transformed.empty() ? "" : " ") + transformed +
- "\n ; CHECK-NOT: " + access_chain_inst +
- "\n ; CHECK-NEXT: OpReturn"
- "\n %ac = " +
- access_chain_inst + " %ptr_ty %var " + (original.empty() ? "" : " ") +
- original + "\n";
- }
- std::string ACCheckFail(const std::string& access_chain_inst,
- const std::string& original,
- const std::string& transformed) {
- return "\n ; CHECK: %ac = " + access_chain_inst + " %ptr_ty %var" +
- (transformed.empty() ? "" : " ") + transformed +
- "\n ; CHECK-NOT: " + access_chain_inst +
- "\n ; CHECK-NOT: OpReturn"
- "\n %ac = " +
- access_chain_inst + " %ptr_ty %var " + (original.empty() ? "" : " ") +
- original + "\n";
- }
- // Access chain into:
- // Vector
- // Vector sizes 2, 3, 4
- // Matrix
- // Matrix columns 2, 4
- // Component is vector 2, 4
- // Array
- // Struct
- // TODO(dneto): RuntimeArray
- TEST_F(GraphicsRobustAccessTest, ACVectorLeastInboundConstantUntouched) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() << R"(
- %uvec2 = OpTypeVector %uint 2
- %var_ty = OpTypePointer Function %uvec2
- %ptr_ty = OpTypePointer Function %uint
- %uint_0 = OpConstant %uint 0
- )"
- << MainPrefix() << R"(
- %var = OpVariable %var_ty Function)" << ACCheck(ac, "%uint_0", "%uint_0")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACVectorMostInboundConstantUntouched) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() << R"(
- %v4uint = OpTypeVector %uint 4
- %var_ty = OpTypePointer Function %v4uint
- %ptr_ty = OpTypePointer Function %uint
- %uint_3 = OpConstant %uint 3
- )"
- << MainPrefix() << R"(
- %var = OpVariable %var_ty Function)" << ACCheck(ac, "%uint_3", "%uint_3")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACVectorExcessConstantClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() << R"(
- %v4uint = OpTypeVector %uint 4
- %var_ty = OpTypePointer Function %v4uint
- %ptr_ty = OpTypePointer Function %uint
- %uint_4 = OpConstant %uint 4
- )"
- << MainPrefix() << R"(
- %var = OpVariable %var_ty Function)" << ACCheck(ac, "%uint_4", "%int_3")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACVectorNegativeConstantClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() << R"(
- %v4uint = OpTypeVector %uint 4
- %var_ty = OpTypePointer Function %v4uint
- %ptr_ty = OpTypePointer Function %uint
- %int_n1 = OpConstant %int -1
- )"
- << MainPrefix() << R"(
- ; CHECK: %int_0 = OpConstant %int 0
- %var = OpVariable %var_ty Function)" << ACCheck(ac, "%int_n1", "%int_0")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- // Like the previous test, but ensures the pass knows how to modify an index
- // which does not come first in the access chain.
- TEST_F(GraphicsRobustAccessTest, ACVectorInArrayNegativeConstantClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt() << R"(
- %v4uint = OpTypeVector %uint 4
- %uint_1 = OpConstant %uint 1
- %uint_2 = OpConstant %uint 2
- %arr = OpTypeArray %v4uint %uint_2
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %uint
- %int_n1 = OpConstant %int -1
- )"
- << MainPrefix() << R"(
- ; CHECK: %int_0 = OpConstant %int 0
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%uint_1 %int_n1", "%uint_1 %int_0") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACVectorGeneralClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt() << R"(
- %v4uint = OpTypeVector %uint 4
- %var_ty = OpTypePointer Function %v4uint
- %ptr_ty = OpTypePointer Function %uint
- %i = OpUndef %int)"
- << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %int_3 = OpConstant %int 3
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_3
- %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACVectorGeneralShortClamped) {
- // Show that signed 16 bit integers are clamped as well.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int16\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesShort() <<
- R"(
- %v4short = OpTypeVector %short 4
- %var_ty = OpTypePointer Function %v4short
- %ptr_ty = OpTypePointer Function %short
- %i = OpUndef %short)"
- << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-NOT: = OpTypeInt 32
- ; CHECK-DAG: %short_0 = OpConstant %short 0
- ; CHECK-DAG: %short_3 = OpConstant %short 3
- ; CHECK-NOT: = OpTypeInt 32
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %short %[[GLSLSTD450]] SClamp %i %short_0 %short_3
- %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACVectorGeneralUShortClamped) {
- // Show that unsigned 16 bit integers are clamped as well.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int16\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesShort() <<
- R"(
- %v4ushort = OpTypeVector %ushort 4
- %var_ty = OpTypePointer Function %v4ushort
- %ptr_ty = OpTypePointer Function %ushort
- %i = OpUndef %ushort)"
- << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-NOT: = OpTypeInt 32
- ; CHECK-DAG: %short_0 = OpConstant %short 0
- ; CHECK-DAG: %short_3 = OpConstant %short 3
- ; CHECK-NOT: = OpTypeInt 32
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %ushort %[[GLSLSTD450]] SClamp %i %short_0 %short_3
- %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACVectorGeneralLongClamped) {
- // Show that signed 64 bit integers are clamped as well.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int64\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesLong() <<
- R"(
- %v4long = OpTypeVector %long 4
- %var_ty = OpTypePointer Function %v4long
- %ptr_ty = OpTypePointer Function %long
- %i = OpUndef %long)"
- << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-NOT: = OpTypeInt 32
- ; CHECK-DAG: %long_0 = OpConstant %long 0
- ; CHECK-DAG: %long_3 = OpConstant %long 3
- ; CHECK-NOT: = OpTypeInt 32
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %long %[[GLSLSTD450]] SClamp %i %long_0 %long_3
- %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACVectorGeneralULongClamped) {
- // Show that unsigned 64 bit integers are clamped as well.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int64\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesLong() <<
- R"(
- %v4ulong = OpTypeVector %ulong 4
- %var_ty = OpTypePointer Function %v4ulong
- %ptr_ty = OpTypePointer Function %ulong
- %i = OpUndef %ulong)"
- << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-NOT: = OpTypeInt 32
- ; CHECK-DAG: %long_0 = OpConstant %long 0
- ; CHECK-DAG: %long_3 = OpConstant %long 3
- ; CHECK-NOT: = OpTypeInt 32
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %ulong %[[GLSLSTD450]] SClamp %i %long_0 %long_3
- %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACMatrixLeastInboundConstantUntouched) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %v2float = OpTypeVector %float 2
- %mat4v2float = OpTypeMatrix %v2float 4
- %var_ty = OpTypePointer Function %mat4v2float
- %ptr_ty = OpTypePointer Function %float
- %uint_0 = OpConstant %uint 0
- %uint_1 = OpConstant %uint 1
- )" << MainPrefix() << R"(
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%uint_0 %uint_1", "%uint_0 %uint_1")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACMatrixMostInboundConstantUntouched) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %v2float = OpTypeVector %float 2
- %mat4v2float = OpTypeMatrix %v2float 4
- %var_ty = OpTypePointer Function %mat4v2float
- %ptr_ty = OpTypePointer Function %float
- %uint_1 = OpConstant %uint 1
- %uint_3 = OpConstant %uint 3
- )" << MainPrefix() << R"(
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%uint_3 %uint_1", "%uint_3 %uint_1")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACMatrixExcessConstantClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %v2float = OpTypeVector %float 2
- %mat4v2float = OpTypeMatrix %v2float 4
- %var_ty = OpTypePointer Function %mat4v2float
- %ptr_ty = OpTypePointer Function %float
- %uint_1 = OpConstant %uint 1
- %uint_4 = OpConstant %uint 4
- )" << MainPrefix() << R"(
- ; CHECK: %int_3 = OpConstant %int 3
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%uint_4 %uint_1", "%int_3 %uint_1") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACMatrixNegativeConstantClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %v2float = OpTypeVector %float 2
- %mat4v2float = OpTypeMatrix %v2float 4
- %var_ty = OpTypePointer Function %mat4v2float
- %ptr_ty = OpTypePointer Function %float
- %uint_1 = OpConstant %uint 1
- %int_n1 = OpConstant %int -1
- )" << MainPrefix() << R"(
- ; CHECK: %int_0 = OpConstant %int 0
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%int_n1 %uint_1", "%int_0 %uint_1") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACMatrixGeneralClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %v2float = OpTypeVector %float 2
- %mat4v2float = OpTypeMatrix %v2float 4
- %var_ty = OpTypePointer Function %mat4v2float
- %ptr_ty = OpTypePointer Function %float
- %uint_1 = OpConstant %uint 1
- %i = OpUndef %int
- )" << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %int_3 = OpConstant %int 3
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_3
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%i %uint_1", "%[[clamp]] %uint_1") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACArrayLeastInboundConstantUntouched) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %uint_200 = OpConstant %uint 200
- %arr = OpTypeArray %float %uint_200
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %int_0 = OpConstant %int 0
- )" << MainPrefix() << R"(
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%int_0", "%int_0") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACArrayMostInboundConstantUntouched) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %uint_200 = OpConstant %uint 200
- %arr = OpTypeArray %float %uint_200
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %int_199 = OpConstant %int 199
- )" << MainPrefix() << R"(
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%int_199", "%int_199") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACArrayGeneralClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %uint_200 = OpConstant %uint 200
- %arr = OpTypeArray %float %uint_200
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %i = OpUndef %int
- )" << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %int_199 = OpConstant %int 199
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_199
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACArrayGeneralShortIndexUIntBoundsClamped) {
- // Index is signed short, array bounds overflows the index type.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int16\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt()
- << TypesShort() << TypesFloat() << R"(
- %uint_70000 = OpConstant %uint 70000 ; overflows 16bits
- %arr = OpTypeArray %float %uint_70000
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %i = OpUndef %short
- )" << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %int_69999 = OpConstant %int 69999
- ; CHECK: OpLabel
- ; CHECK: %[[i_ext:\w+]] = OpSConvert %uint %i
- ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %[[i_ext]] %int_0 %int_69999
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACArrayGeneralUShortIndexIntBoundsClamped) {
- // Index is unsigned short, array bounds overflows the index type.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int16\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt()
- << TypesShort() << TypesFloat() << R"(
- %int_70000 = OpConstant %int 70000 ; overflows 16bits
- %arr = OpTypeArray %float %int_70000
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %i = OpUndef %ushort
- )" << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %int_69999 = OpConstant %int 69999
- ; CHECK: OpLabel
- ; CHECK: %[[i_ext:\w+]] = OpUConvert %uint %i
- ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %[[i_ext]] %int_0 %int_69999
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACArrayGeneralUIntIndexShortBoundsClamped) {
- // Signed int index i is wider than the array bounds type.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int16\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt()
- << TypesShort() << TypesFloat() << R"(
- %short_200 = OpConstant %short 200
- %arr = OpTypeArray %float %short_200
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %i = OpUndef %uint
- )" << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %int_199 = OpConstant %int 199
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %i %int_0 %int_199
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACArrayGeneralIntIndexUShortBoundsClamped) {
- // Unsigned int index i is wider than the array bounds type.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int16\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt()
- << TypesShort() << TypesFloat() << R"(
- %ushort_200 = OpConstant %ushort 200
- %arr = OpTypeArray %float %ushort_200
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %i = OpUndef %int
- )" << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %int_199 = OpConstant %int 199
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_199
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACArrayGeneralLongIndexUIntBoundsClamped) {
- // Signed long index i is wider than the array bounds type.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int64\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt()
- << TypesLong() << TypesFloat() << R"(
- %uint_200 = OpConstant %uint 200
- %arr = OpTypeArray %float %uint_200
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %i = OpUndef %long
- )" << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %long_0 = OpConstant %long 0
- ; CHECK-DAG: %long_199 = OpConstant %long 199
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %long %[[GLSLSTD450]] SClamp %i %long_0 %long_199
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACArrayGeneralULongIndexIntBoundsClamped) {
- // Unsigned long index i is wider than the array bounds type.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int64\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt()
- << TypesLong() << TypesFloat() << R"(
- %int_200 = OpConstant %int 200
- %arr = OpTypeArray %float %int_200
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %i = OpUndef %ulong
- )" << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %long_0 = OpConstant %long 0
- ; CHECK-DAG: %long_199 = OpConstant %long 199
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %ulong %[[GLSLSTD450]] SClamp %i %long_0 %long_199
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest,
- ACArrayGeneralShortIndeArrayBiggerThanShortMaxClipsToShortIntMax) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int16\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesShort()
- << TypesInt() << TypesFloat() << R"(
- %uint_50000 = OpConstant %uint 50000
- %arr = OpTypeArray %float %uint_50000
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %i = OpUndef %ushort
- )" << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %short_0 = OpConstant %short 0
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %short 32767
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %ushort %[[GLSLSTD450]] SClamp %i %short_0 %[[intmax]]
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest,
- ACArrayGeneralIntIndexArrayBiggerThanIntMaxClipsToSignedIntMax) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %uint_3000000000 = OpConstant %uint 3000000000
- %arr = OpTypeArray %float %uint_3000000000
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %i = OpUndef %uint
- )" << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %i %int_0 %[[intmax]]
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%i", "%[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest,
- ACArrayGeneralLongIndexArrayBiggerThanLongMaxClipsToSignedLongMax) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int64\n"
- << ShaderPreambleAC({"i"}) << TypesVoid() << TypesInt()
- << TypesLong()
- << TypesFloat()
- // 2^63 == 9,223,372,036,854,775,807
- << R"(
- %ulong_9223372036854775999 = OpConstant %ulong 9223372036854775999
- %arr = OpTypeArray %float %ulong_9223372036854775999
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %i = OpUndef %ulong
- )"
- << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %long_0 = OpConstant %long 0
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %long 9223372036854775807
- ; CHECK: OpLabel
- ; CHECK: %[[clamp:\w+]] = OpExtInst %ulong %[[GLSLSTD450]] SClamp %i %long_0 %[[intmax]]
- %var = OpVariable %var_ty Function)" << ACCheck(ac, "%i", "%[[clamp]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACArraySpecIdSizedAlwaysClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"spec200"}) << R"(
- OpDecorate %spec200 SpecId 0 )" << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %spec200 = OpSpecConstant %int 200
- %arr = OpTypeArray %float %spec200
- %var_ty = OpTypePointer Function %arr
- %ptr_ty = OpTypePointer Function %float
- %uint_5 = OpConstant %uint 5
- )" << MainPrefix() << R"(
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %uint_0 = OpConstant %uint 0
- ; CHECK-DAG: %uint_1 = OpConstant %uint 1
- ; CHECK-DAG: %[[uint_intmax:\w+]] = OpConstant %uint 2147483647
- ; CHECK: OpLabel
- ; CHECK: %[[max:\w+]] = OpISub %uint %spec200 %uint_1
- ; CHECK: %[[smin:\w+]] = OpExtInst %uint %[[GLSLSTD450]] UMin %[[max]] %[[uint_intmax]]
- ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %uint_5 %uint_0 %[[smin]]
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%uint_5", "%[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACStructLeastUntouched) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %struct = OpTypeStruct %float %float %float
- %var_ty = OpTypePointer Function %struct
- %ptr_ty = OpTypePointer Function %float
- %int_0 = OpConstant %int 0
- )" << MainPrefix() << R"(
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%int_0", "%int_0") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACStructMostUntouched) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %struct = OpTypeStruct %float %float %float
- %var_ty = OpTypePointer Function %struct
- %ptr_ty = OpTypePointer Function %float
- %int_2 = OpConstant %int 2
- )" << MainPrefix() << R"(
- %var = OpVariable %var_ty Function)"
- << ACCheck(ac, "%int_2", "%int_2") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACStructSpecConstantFail) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"struct", "spec200"})
- << "OpDecorate %spec200 SpecId 0\n"
- <<
- TypesVoid() << TypesInt() << TypesFloat() << R"(
- %spec200 = OpSpecConstant %int 200
- %struct = OpTypeStruct %float %float %float
- %var_ty = OpTypePointer Function %struct
- %ptr_ty = OpTypePointer Function %float
- )" << MainPrefix() << R"(
- %var = OpVariable %var_ty Function
- ; CHECK: Member index into struct is not a constant integer
- ; CHECK-SAME: %spec200 = OpSpecConstant %int 200
- )"
- << ACCheckFail(ac, "%spec200", "%spec200") << MainSuffix();
- SinglePassRunAndFail<GraphicsRobustAccessPass>(shaders.str());
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACStructFloatConstantFail) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"struct"}) <<
- TypesVoid() << TypesInt() << TypesFloat() << R"(
- %float_2 = OpConstant %float 2
- %struct = OpTypeStruct %float %float %float
- %var_ty = OpTypePointer Function %struct
- %ptr_ty = OpTypePointer Function %float
- )" << MainPrefix() << R"(
- %var = OpVariable %var_ty Function
- ; CHECK: Member index into struct is not a constant integer
- ; CHECK-SAME: %float_2 = OpConstant %float 2
- )"
- << ACCheckFail(ac, "%float_2", "%float_2") << MainSuffix();
- SinglePassRunAndFail<GraphicsRobustAccessPass>(shaders.str());
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACStructNonConstantFail) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"struct", "i"}) <<
- TypesVoid() << TypesInt() << TypesFloat() << R"(
- %float_2 = OpConstant %float 2
- %struct = OpTypeStruct %float %float %float
- %var_ty = OpTypePointer Function %struct
- %ptr_ty = OpTypePointer Function %float
- %i = OpUndef %int
- )" << MainPrefix() << R"(
- %var = OpVariable %var_ty Function
- ; CHECK: Member index into struct is not a constant integer
- ; CHECK-SAME: %i = OpUndef %int
- )"
- << ACCheckFail(ac, "%i", "%i") << MainSuffix();
- SinglePassRunAndFail<GraphicsRobustAccessPass>(shaders.str());
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACStructExcessFail) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"struct", "i"}) << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %struct = OpTypeStruct %float %float %float
- %var_ty = OpTypePointer Function %struct
- %ptr_ty = OpTypePointer Function %float
- %i = OpConstant %int 4
- )" << MainPrefix() << R"(
- %var = OpVariable %var_ty Function
- ; CHECK: Member index 4 is out of bounds for struct type:
- ; CHECK-SAME: %struct = OpTypeStruct %float %float %float
- )"
- << ACCheckFail(ac, "%i", "%i") << MainSuffix();
- SinglePassRunAndFail<GraphicsRobustAccessPass>(shaders.str());
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACStructNegativeFail) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"struct", "i"}) << TypesVoid() << TypesInt()
- << TypesFloat() << R"(
- %struct = OpTypeStruct %float %float %float
- %var_ty = OpTypePointer Function %struct
- %ptr_ty = OpTypePointer Function %float
- %i = OpConstant %int -1
- )" << MainPrefix() << R"(
- %var = OpVariable %var_ty Function
- ; CHECK: Member index -1 is out of bounds for struct type:
- ; CHECK-SAME: %struct = OpTypeStruct %float %float %float
- )"
- << ACCheckFail(ac, "%i", "%i") << MainSuffix();
- SinglePassRunAndFail<GraphicsRobustAccessPass>(shaders.str());
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACRTArrayLeastInboundClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC() << "OpDecorate %rtarr ArrayStride 4 "
- << DecoSSBO() << TypesVoid() << TypesInt() << TypesFloat() << R"(
- %rtarr = OpTypeRuntimeArray %float
- %ssbo_s = OpTypeStruct %uint %uint %rtarr
- %var_ty = OpTypePointer Uniform %ssbo_s
- %ptr_ty = OpTypePointer Uniform %float
- %var = OpVariable %var_ty Uniform
- %int_0 = OpConstant %int 0
- %int_2 = OpConstant %int 2
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_1 = OpConstant %int 1
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647
- ; CHECK: OpLabel
- ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2
- ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1
- ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]]
- ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %int_0 %int_0 %[[smin]]
- )"
- << MainPrefix() << ACCheck(ac, "%int_2 %int_0", "%int_2 %[[clamp]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralShortIndexClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int16\n"
- << ShaderPreambleAC({"i"}) << "OpDecorate %rtarr ArrayStride 4 "
- << DecoSSBO() << TypesVoid() << TypesShort() << TypesFloat() << R"(
- %rtarr = OpTypeRuntimeArray %float
- %ssbo_s = OpTypeStruct %short %short %rtarr
- %var_ty = OpTypePointer Uniform %ssbo_s
- %ptr_ty = OpTypePointer Uniform %float
- %var = OpVariable %var_ty Uniform
- %short_2 = OpConstant %short 2
- %i = OpUndef %short
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK: %uint = OpTypeInt 32 0
- ; CHECK-DAG: %uint_1 = OpConstant %uint 1
- ; CHECK-DAG: %uint_0 = OpConstant %uint 0
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %uint 2147483647
- ; CHECK: OpLabel
- ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2
- ; CHECK-DAG: %[[max:\w+]] = OpISub %uint %[[arrlen]] %uint_1
- ; CHECK-DAG: %[[i_ext:\w+]] = OpSConvert %uint %i
- ; CHECK: %[[smin:\w+]] = OpExtInst %uint %[[GLSLSTD450]] UMin %[[max]] %[[intmax]]
- ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %[[i_ext]] %uint_0 %[[smin]]
- )"
- << MainPrefix() << ACCheck(ac, "%short_2 %i", "%short_2 %[[clamp]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralUShortIndexClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int16\n"
- << ShaderPreambleAC({"i"}) << "OpDecorate %rtarr ArrayStride 4 "
- << DecoSSBO() << TypesVoid() << TypesShort() << TypesFloat() << R"(
- %rtarr = OpTypeRuntimeArray %float
- %ssbo_s = OpTypeStruct %short %short %rtarr
- %var_ty = OpTypePointer Uniform %ssbo_s
- %ptr_ty = OpTypePointer Uniform %float
- %var = OpVariable %var_ty Uniform
- %short_2 = OpConstant %short 2
- %i = OpUndef %ushort
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK: %uint = OpTypeInt 32 0
- ; CHECK-DAG: %uint_1 = OpConstant %uint 1
- ; CHECK-DAG: %uint_0 = OpConstant %uint 0
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %uint 2147483647
- ; CHECK: OpLabel
- ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2
- ; CHECK-DAG: %[[max:\w+]] = OpISub %uint %[[arrlen]] %uint_1
- ; CHECK-DAG: %[[i_ext:\w+]] = OpSConvert %uint %i
- ; CHECK: %[[smin:\w+]] = OpExtInst %uint %[[GLSLSTD450]] UMin %[[max]] %[[intmax]]
- ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %[[i_ext]] %uint_0 %[[smin]]
- )"
- << MainPrefix() << ACCheck(ac, "%short_2 %i", "%short_2 %[[clamp]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralIntIndexClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"i"}) << "OpDecorate %rtarr ArrayStride 4 "
- << DecoSSBO() << TypesVoid() << TypesInt() << TypesFloat() << R"(
- %rtarr = OpTypeRuntimeArray %float
- %ssbo_s = OpTypeStruct %int %int %rtarr
- %var_ty = OpTypePointer Uniform %ssbo_s
- %ptr_ty = OpTypePointer Uniform %float
- %var = OpVariable %var_ty Uniform
- %int_2 = OpConstant %int 2
- %i = OpUndef %int
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_1 = OpConstant %int 1
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647
- ; CHECK: OpLabel
- ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2
- ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1
- ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]]
- ; CHECK: %[[clamp:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %[[smin]]
- )"
- << MainPrefix() << ACCheck(ac, "%int_2 %i", "%int_2 %[[clamp]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralUIntIndexClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"i"}) << "OpDecorate %rtarr ArrayStride 4 "
- << DecoSSBO() << TypesVoid() << TypesInt() << TypesFloat() << R"(
- %rtarr = OpTypeRuntimeArray %float
- %ssbo_s = OpTypeStruct %int %int %rtarr
- %var_ty = OpTypePointer Uniform %ssbo_s
- %ptr_ty = OpTypePointer Uniform %float
- %var = OpVariable %var_ty Uniform
- %int_2 = OpConstant %int 2
- %i = OpUndef %uint
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %uint_1 = OpConstant %uint 1
- ; CHECK-DAG: %uint_0 = OpConstant %uint 0
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %uint 2147483647
- ; CHECK: OpLabel
- ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2
- ; CHECK: %[[max:\w+]] = OpISub %uint %[[arrlen]] %uint_1
- ; CHECK: %[[smin:\w+]] = OpExtInst %uint %[[GLSLSTD450]] UMin %[[max]] %[[intmax]]
- ; CHECK: %[[clamp:\w+]] = OpExtInst %uint %[[GLSLSTD450]] SClamp %i %uint_0 %[[smin]]
- )"
- << MainPrefix() << ACCheck(ac, "%int_2 %i", "%int_2 %[[clamp]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralLongIndexClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int64" << ShaderPreambleAC({"i"})
- << "OpDecorate %rtarr ArrayStride 4 " << DecoSSBO() << TypesVoid()
- << TypesInt() << TypesLong() << TypesFloat() << R"(
- %rtarr = OpTypeRuntimeArray %float
- %ssbo_s = OpTypeStruct %int %int %rtarr
- %var_ty = OpTypePointer Uniform %ssbo_s
- %ptr_ty = OpTypePointer Uniform %float
- %var = OpVariable %var_ty Uniform
- %int_2 = OpConstant %int 2
- %i = OpUndef %long
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %long_0 = OpConstant %long 0
- ; CHECK-DAG: %long_1 = OpConstant %long 1
- ; CHECK-DAG: %[[longmax:\w+]] = OpConstant %long 9223372036854775807
- ; CHECK: OpLabel
- ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2
- ; CHECK: %[[arrlen_ext:\w+]] = OpUConvert %ulong %[[arrlen]]
- ; CHECK: %[[max:\w+]] = OpISub %long %[[arrlen_ext]] %long_1
- ; CHECK: %[[smin:\w+]] = OpExtInst %long %[[GLSLSTD450]] UMin %[[max]] %[[longmax]]
- ; CHECK: %[[clamp:\w+]] = OpExtInst %long %[[GLSLSTD450]] SClamp %i %long_0 %[[smin]]
- )" << MainPrefix()
- << ACCheck(ac, "%int_2 %i", "%int_2 %[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACRTArrayGeneralULongIndexClamped) {
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << "OpCapability Int64" << ShaderPreambleAC({"i"})
- << "OpDecorate %rtarr ArrayStride 4 " << DecoSSBO() << TypesVoid()
- << TypesInt() << TypesLong() << TypesFloat() << R"(
- %rtarr = OpTypeRuntimeArray %float
- %ssbo_s = OpTypeStruct %int %int %rtarr
- %var_ty = OpTypePointer Uniform %ssbo_s
- %ptr_ty = OpTypePointer Uniform %float
- %var = OpVariable %var_ty Uniform
- %int_2 = OpConstant %int 2
- %i = OpUndef %ulong
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %ulong_0 = OpConstant %ulong 0
- ; CHECK-DAG: %ulong_1 = OpConstant %ulong 1
- ; CHECK-DAG: %[[longmax:\w+]] = OpConstant %ulong 9223372036854775807
- ; CHECK: OpLabel
- ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2
- ; CHECK: %[[arrlen_ext:\w+]] = OpUConvert %ulong %[[arrlen]]
- ; CHECK: %[[max:\w+]] = OpISub %ulong %[[arrlen_ext]] %ulong_1
- ; CHECK: %[[smin:\w+]] = OpExtInst %ulong %[[GLSLSTD450]] UMin %[[max]] %[[longmax]]
- ; CHECK: %[[clamp:\w+]] = OpExtInst %ulong %[[GLSLSTD450]] SClamp %i %ulong_0 %[[smin]]
- )" << MainPrefix()
- << ACCheck(ac, "%int_2 %i", "%int_2 %[[clamp]]") << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACRTArrayStructVectorElem) {
- // The point of this test is that the access chain can have indices past the
- // index into the runtime array. For good measure, the index into the final
- // struct is out of bounds. We have to clamp that index too.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"i", "j"})
- << "OpDecorate %rtarr ArrayStride 32\n"
- << DecoSSBO() << "OpMemberDecorate %rtelem 0 Offset 0\n"
- << "OpMemberDecorate %rtelem 1 Offset 16\n"
- << TypesVoid() << TypesInt() << TypesFloat() << R"(
- %v4float = OpTypeVector %float 4
- %rtelem = OpTypeStruct %v4float %v4float
- %rtarr = OpTypeRuntimeArray %rtelem
- %ssbo_s = OpTypeStruct %int %int %rtarr
- %var_ty = OpTypePointer Uniform %ssbo_s
- %ptr_ty = OpTypePointer Uniform %float
- %var = OpVariable %var_ty Uniform
- %int_1 = OpConstant %int 1
- %int_2 = OpConstant %int 2
- %i = OpUndef %int
- %j = OpUndef %int
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %int_3 = OpConstant %int 3
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647
- ; CHECK: OpLabel
- ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %var 2
- ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1
- ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]]
- ; CHECK: %[[clamp_i:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %[[smin]]
- ; CHECK: %[[clamp_j:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %j %int_0 %int_3
- )" << MainPrefix()
- << ACCheck(ac, "%int_2 %i %int_1 %j",
- "%int_2 %[[clamp_i]] %int_1 %[[clamp_j]]")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACArrayRTArrayStructVectorElem) {
- // Now add an additional level of arrays around the Block-decorated struct.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"i", "ssbo_s"})
- << "OpDecorate %rtarr ArrayStride 32\n"
- << DecoSSBO() << "OpMemberDecorate %rtelem 0 Offset 0\n"
- << "OpMemberDecorate %rtelem 1 Offset 16\n"
- << TypesVoid() << TypesInt() << TypesFloat() << R"(
- %v4float = OpTypeVector %float 4
- %rtelem = OpTypeStruct %v4float %v4float
- %rtarr = OpTypeRuntimeArray %rtelem
- %ssbo_s = OpTypeStruct %int %int %rtarr
- %arr_size = OpConstant %int 10
- %arr_ssbo = OpTypeArray %ssbo_s %arr_size
- %var_ty = OpTypePointer Uniform %arr_ssbo
- %ptr_ty = OpTypePointer Uniform %float
- %var = OpVariable %var_ty Uniform
- %int_1 = OpConstant %int 1
- %int_2 = OpConstant %int 2
- %int_17 = OpConstant %int 17
- %i = OpUndef %int
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %[[ssbo_p:\w+]] = OpTypePointer Uniform %ssbo_s
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %int_9 = OpConstant %int 9
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647
- ; CHECK: OpLabel
- ; This access chain is manufactured only so we can compute the array length.
- ; Note that the %int_9 is already clamped
- ; CHECK: %[[ssbo_base:\w+]] = )" << ac
- << R"( %[[ssbo_p]] %var %int_9
- ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %[[ssbo_base]] 2
- ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1
- ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]]
- ; CHECK: %[[clamp_i:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %[[smin]]
- )" << MainPrefix()
- << ACCheck(ac, "%int_17 %int_2 %i %int_1 %int_2",
- "%int_9 %int_2 %[[clamp_i]] %int_1 %int_2")
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, ACSplitACArrayRTArrayStructVectorElem) {
- // Split the address calculation across two access chains. Force
- // the transform to walk up the access chains to find the base variable.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"i", "j", "k", "ssbo_s", "ssbo_pty",
- "rtarr_pty", "ac_ssbo", "ac_rtarr"})
- << "OpDecorate %rtarr ArrayStride 32\n"
- << DecoSSBO() << "OpMemberDecorate %rtelem 0 Offset 0\n"
- << "OpMemberDecorate %rtelem 1 Offset 16\n"
- << TypesVoid() << TypesInt() << TypesFloat() << R"(
- %v4float = OpTypeVector %float 4
- %rtelem = OpTypeStruct %v4float %v4float
- %rtarr = OpTypeRuntimeArray %rtelem
- %ssbo_s = OpTypeStruct %int %int %rtarr
- %arr_size = OpConstant %int 10
- %arr_ssbo = OpTypeArray %ssbo_s %arr_size
- %var_ty = OpTypePointer Uniform %arr_ssbo
- %ssbo_pty = OpTypePointer Uniform %ssbo_s
- %rtarr_pty = OpTypePointer Uniform %rtarr
- %ptr_ty = OpTypePointer Uniform %float
- %var = OpVariable %var_ty Uniform
- %int_1 = OpConstant %int 1
- %int_2 = OpConstant %int 2
- %i = OpUndef %int
- %j = OpUndef %int
- %k = OpUndef %int
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %int_9 = OpConstant %int 9
- ; CHECK-DAG: %int_3 = OpConstant %int 3
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647
- ; CHECK: OpLabel
- ; CHECK: %[[clamp_i:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_9
- ; CHECK: %ac_ssbo = )" << ac
- << R"( %ssbo_pty %var %[[clamp_i]]
- ; CHECK: %ac_rtarr = )"
- << ac << R"( %rtarr_pty %ac_ssbo %int_2
- ; This is the interesting bit. This array length is needed for an OpAccessChain
- ; computing %ac, but the algorithm had to track back through %ac_rtarr's
- ; definition to find the base pointer %ac_ssbo.
- ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %ac_ssbo 2
- ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1
- ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]]
- ; CHECK: %[[clamp_j:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %j %int_0 %[[smin]]
- ; CHECK: %[[clamp_k:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %k %int_0 %int_3
- ; CHECK: %ac = )" << ac
- << R"( %ptr_ty %ac_rtarr %[[clamp_j]] %int_1 %[[clamp_k]]
- ; CHECK-NOT: AccessChain
- )" << MainPrefix()
- << "%ac_ssbo = " << ac << " %ssbo_pty %var %i\n"
- << "%ac_rtarr = " << ac << " %rtarr_pty %ac_ssbo %int_2\n"
- << "%ac = " << ac << " %ptr_ty %ac_rtarr %j %int_1 %k\n"
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest,
- ACSplitACArrayRTArrayStructVectorElemAcrossBasicBlocks) {
- // Split the address calculation across two access chains. Force
- // the transform to walk up the access chains to find the base variable.
- // This time, put the different access chains in different basic blocks.
- // This is an integrity check to ensure that we keep the instruction-to-block
- // mapping consistent.
- for (auto* ac : AccessChains()) {
- std::ostringstream shaders;
- shaders << ShaderPreambleAC({"i", "j", "k", "bb1", "bb2", "ssbo_s",
- "ssbo_pty", "rtarr_pty", "ac_ssbo",
- "ac_rtarr"})
- << "OpDecorate %rtarr ArrayStride 32\n"
- << DecoSSBO() << "OpMemberDecorate %rtelem 0 Offset 0\n"
- << "OpMemberDecorate %rtelem 1 Offset 16\n"
- << TypesVoid() << TypesInt() << TypesFloat() << R"(
- %v4float = OpTypeVector %float 4
- %rtelem = OpTypeStruct %v4float %v4float
- %rtarr = OpTypeRuntimeArray %rtelem
- %ssbo_s = OpTypeStruct %int %int %rtarr
- %arr_size = OpConstant %int 10
- %arr_ssbo = OpTypeArray %ssbo_s %arr_size
- %var_ty = OpTypePointer Uniform %arr_ssbo
- %ssbo_pty = OpTypePointer Uniform %ssbo_s
- %rtarr_pty = OpTypePointer Uniform %rtarr
- %ptr_ty = OpTypePointer Uniform %float
- %var = OpVariable %var_ty Uniform
- %int_1 = OpConstant %int 1
- %int_2 = OpConstant %int 2
- %i = OpUndef %int
- %j = OpUndef %int
- %k = OpUndef %int
- ; CHECK: %[[GLSLSTD450:\w+]] = OpExtInstImport "GLSL.std.450"
- ; CHECK-DAG: %int_0 = OpConstant %int 0
- ; CHECK-DAG: %int_9 = OpConstant %int 9
- ; CHECK-DAG: %int_3 = OpConstant %int 3
- ; CHECK-DAG: %[[intmax:\w+]] = OpConstant %int 2147483647
- ; CHECK: OpLabel
- ; CHECK: %[[clamp_i:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %i %int_0 %int_9
- ; CHECK: %ac_ssbo = )" << ac
- << R"( %ssbo_pty %var %[[clamp_i]]
- ; CHECK: %bb1 = OpLabel
- ; CHECK: %ac_rtarr = )"
- << ac << R"( %rtarr_pty %ac_ssbo %int_2
- ; CHECK: %bb2 = OpLabel
- ; This is the interesting bit. This array length is needed for an OpAccessChain
- ; computing %ac, but the algorithm had to track back through %ac_rtarr's
- ; definition to find the base pointer %ac_ssbo.
- ; CHECK: %[[arrlen:\w+]] = OpArrayLength %uint %ac_ssbo 2
- ; CHECK: %[[max:\w+]] = OpISub %int %[[arrlen]] %int_1
- ; CHECK: %[[smin:\w+]] = OpExtInst %int %[[GLSLSTD450]] UMin %[[max]] %[[intmax]]
- ; CHECK: %[[clamp_j:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %j %int_0 %[[smin]]
- ; CHECK: %[[clamp_k:\w+]] = OpExtInst %int %[[GLSLSTD450]] SClamp %k %int_0 %int_3
- ; CHECK: %ac = )" << ac
- << R"( %ptr_ty %ac_rtarr %[[clamp_j]] %int_1 %[[clamp_k]]
- ; CHECK-NOT: AccessChain
- )" << MainPrefix()
- << "%ac_ssbo = " << ac << " %ssbo_pty %var %i\n"
- << "OpBranch %bb1\n%bb1 = OpLabel\n"
- << "%ac_rtarr = " << ac << " %rtarr_pty %ac_ssbo %int_2\n"
- << "OpBranch %bb2\n%bb2 = OpLabel\n"
- << "%ac = " << ac << " %ptr_ty %ac_rtarr %j %int_1 %k\n"
- << MainSuffix();
- SinglePassRunAndMatch<GraphicsRobustAccessPass>(shaders.str(), true);
- }
- }
- TEST_F(GraphicsRobustAccessTest, bug3813) {
- // This shader comes from Dawn's
- // TextureViewSamplingTest.TextureCubeMapOnWholeTexture, converted from GLSL
- // by glslang.
- // The pass was inserting a signed 32-bit int type, but not correctly marking
- // the shader as changed.
- std::string shader = R"(
- ; SPIR-V
- ; Version: 1.0
- ; Generator: Google Shaderc over Glslang; 10
- ; Bound: 46
- ; Schema: 0
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main" %12 %29
- OpExecutionMode %4 OriginUpperLeft
- OpSource GLSL 450
- OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
- OpSourceExtension "GL_GOOGLE_include_directive"
- OpName %4 "main"
- OpName %8 "sc"
- OpName %12 "texCoord"
- OpName %21 "tc"
- OpName %29 "fragColor"
- OpName %32 "texture0"
- OpName %36 "sampler0"
- OpDecorate %12 Location 0
- OpDecorate %29 Location 0
- OpDecorate %32 DescriptorSet 0
- OpDecorate %32 Binding 1
- OpDecorate %36 DescriptorSet 0
- OpDecorate %36 Binding 0
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %7 = OpTypePointer Function %6
- %9 = OpConstant %6 2
- %10 = OpTypeVector %6 2
- %11 = OpTypePointer Input %10
- %12 = OpVariable %11 Input
- %13 = OpTypeInt 32 0
- %14 = OpConstant %13 0
- %15 = OpTypePointer Input %6
- %19 = OpConstant %6 1
- %22 = OpConstant %13 1
- %27 = OpTypeVector %6 4
- %28 = OpTypePointer Output %27
- %29 = OpVariable %28 Output
- %30 = OpTypeImage %6 Cube 0 0 0 1 Unknown
- %31 = OpTypePointer UniformConstant %30
- %32 = OpVariable %31 UniformConstant
- %34 = OpTypeSampler
- %35 = OpTypePointer UniformConstant %34
- %36 = OpVariable %35 UniformConstant
- %38 = OpTypeSampledImage %30
- %43 = OpTypeVector %6 3
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- %8 = OpVariable %7 Function
- %21 = OpVariable %7 Function
- %16 = OpAccessChain %15 %12 %14
- %17 = OpLoad %6 %16
- %18 = OpFMul %6 %9 %17
- %20 = OpFSub %6 %18 %19
- OpStore %8 %20
- %23 = OpAccessChain %15 %12 %22
- %24 = OpLoad %6 %23
- %25 = OpFMul %6 %9 %24
- %26 = OpFSub %6 %25 %19
- OpStore %21 %26
- %33 = OpLoad %30 %32
- %37 = OpLoad %34 %36
- %39 = OpSampledImage %38 %33 %37
- %40 = OpLoad %6 %21
- %41 = OpLoad %6 %8
- %42 = OpFNegate %6 %41
- %44 = OpCompositeConstruct %43 %19 %40 %42
- %45 = OpImageSampleImplicitLod %27 %39 %44
- OpStore %29 %45
- OpReturn
- OpFunctionEnd
- )";
- std::string expected = R"(OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %main "main" %texCoord %fragColor
- OpExecutionMode %main OriginUpperLeft
- OpSource GLSL 450
- OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
- OpSourceExtension "GL_GOOGLE_include_directive"
- OpName %main "main"
- OpName %sc "sc"
- OpName %texCoord "texCoord"
- OpName %tc "tc"
- OpName %fragColor "fragColor"
- OpName %texture0 "texture0"
- OpName %sampler0 "sampler0"
- OpDecorate %texCoord Location 0
- OpDecorate %fragColor Location 0
- OpDecorate %texture0 DescriptorSet 0
- OpDecorate %texture0 Binding 1
- OpDecorate %sampler0 DescriptorSet 0
- OpDecorate %sampler0 Binding 0
- %void = OpTypeVoid
- %10 = OpTypeFunction %void
- %float = OpTypeFloat 32
- %_ptr_Function_float = OpTypePointer Function %float
- %float_2 = OpConstant %float 2
- %v2float = OpTypeVector %float 2
- %_ptr_Input_v2float = OpTypePointer Input %v2float
- %texCoord = OpVariable %_ptr_Input_v2float Input
- %uint = OpTypeInt 32 0
- %uint_0 = OpConstant %uint 0
- %_ptr_Input_float = OpTypePointer Input %float
- %float_1 = OpConstant %float 1
- %uint_1 = OpConstant %uint 1
- %v4float = OpTypeVector %float 4
- %_ptr_Output_v4float = OpTypePointer Output %v4float
- %fragColor = OpVariable %_ptr_Output_v4float Output
- %23 = OpTypeImage %float Cube 0 0 0 1 Unknown
- %_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23
- %texture0 = OpVariable %_ptr_UniformConstant_23 UniformConstant
- %25 = OpTypeSampler
- %_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25
- %sampler0 = OpVariable %_ptr_UniformConstant_25 UniformConstant
- %27 = OpTypeSampledImage %23
- %v3float = OpTypeVector %float 3
- %int = OpTypeInt 32 1
- %main = OpFunction %void None %10
- %29 = OpLabel
- %sc = OpVariable %_ptr_Function_float Function
- %tc = OpVariable %_ptr_Function_float Function
- %30 = OpAccessChain %_ptr_Input_float %texCoord %uint_0
- %31 = OpLoad %float %30
- %32 = OpFMul %float %float_2 %31
- %33 = OpFSub %float %32 %float_1
- OpStore %sc %33
- %34 = OpAccessChain %_ptr_Input_float %texCoord %uint_1
- %35 = OpLoad %float %34
- %36 = OpFMul %float %float_2 %35
- %37 = OpFSub %float %36 %float_1
- OpStore %tc %37
- %38 = OpLoad %23 %texture0
- %39 = OpLoad %25 %sampler0
- %40 = OpSampledImage %27 %38 %39
- %41 = OpLoad %float %tc
- %42 = OpLoad %float %sc
- %43 = OpFNegate %float %42
- %44 = OpCompositeConstruct %v3float %float_1 %41 %43
- %45 = OpImageSampleImplicitLod %v4float %40 %44
- OpStore %fragColor %45
- OpReturn
- OpFunctionEnd
- )";
- SinglePassRunAndCheck<GraphicsRobustAccessPass>(shader, expected, false,
- true);
- }
- TEST_F(GraphicsRobustAccessTest, ReplaceIndexReportsChanged) {
- // A ClusterFuzz generated shader that triggered a
- // "Binary size unexpectedly changed despite the optimizer saying there was no
- // change" assertion.
- // See https://github.com/KhronosGroup/SPIRV-Tools/issues/4166.
- std::string shader = R"(
- ; SPIR-V
- ; Version: 1.0
- ; Generator: Google Shaderc over Glslang; 245
- ; Bound: 41
- ; Schema: 0
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint GLCompute %main "else" %gl_GlobalInvocationID
- OpExecutionMode %main LocalSize 1 1 3338665985
- OpSource GLSL 450
- OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
- OpSourceExtension "GL_GOOGLE_include_directive"
- OpName %main "main"
- OpName %index "index"
- OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
- OpName %S "S"
- OpMemberName %_struct_24 0 ""
- OpMemberName %_struct_24 1 ""
- OpName %Dst "Dst"
- OpMemberName %Dst 0 "s"
- OpName %dst "dst"
- OpName %Src "Src"
- OpMemberName %Src 0 "s"
- OpName %src "src"
- OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
- OpMemberDecorate %_struct_24 0 Offset 64
- OpMemberDecorate %_struct_24 1 Offset 8
- OpDecorate %_arr__struct_24_uint_1 ArrayStride 16
- OpMemberDecorate %Dst 0 Offset 0
- OpDecorate %Dst BufferBlock
- OpDecorate %dst DescriptorSet 0
- OpDecorate %dst Binding 1
- OpDecorate %_arr__struct_24_uint_1_0 ArrayStride 16
- OpMemberDecorate %Src 0 Offset 0
- OpDecorate %Src Block
- OpDecorate %src DescriptorSet 0
- OpDecorate %src Binding 0
- %void = OpTypeVoid
- %3 = OpTypeFunction %void
- %uint = OpTypeInt 32 0
- %_ptr_Function_uint = OpTypePointer Function %uint
- %v3uint = OpTypeVector %uint 3
- %_ptr_Input_v3uint = OpTypePointer Input %v3uint
- %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
- %uint_4864 = OpConstant %uint 4864
- %_ptr_Input_uint = OpTypePointer Input %uint
- %uint_1 = OpConstant %uint 1
- %bool = OpTypeBool
- %v2uint = OpTypeVector %uint 2
- %_struct_24 = OpTypeStruct %_ptr_Input_uint %v2uint
- %_arr__struct_24_uint_1 = OpTypeArray %_struct_24 %uint_1
- %Dst = OpTypeStruct %_arr__struct_24_uint_1
- %_ptr_Uniform_Dst = OpTypePointer Uniform %Dst
- %dst = OpVariable %_ptr_Uniform_Dst Uniform
- %int = OpTypeInt 32 1
- %int_0 = OpConstant %int 0
- %_arr__struct_24_uint_1_0 = OpTypeArray %_struct_24 %uint_1
- %Src = OpTypeStruct %_arr__struct_24_uint_1_0
- %_ptr_Uniform_Src = OpTypePointer Uniform %Src
- %src = OpVariable %_ptr_Uniform_Src Uniform
- %_ptr_Uniform__struct_24 = OpTypePointer Uniform %_struct_24
- %main = OpFunction %void None %3
- %5 = OpLabel
- %index = OpVariable %_ptr_Function_uint Function
- %14 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_4864
- %15 = OpLoad %uint %14
- OpStore %index %15
- %16 = OpLoad %uint %index
- %S = OpUGreaterThanEqual %bool %16 %uint_1
- OpSelectionMerge %21 None
- OpBranchConditional %S %20 %21
- %20 = OpLabel
- OpReturn
- %21 = OpLabel
- %31 = OpLoad %uint %index
- %36 = OpLoad %uint %index
- %38 = OpAccessChain %_ptr_Uniform__struct_24 %src %int_0 %36
- %39 = OpLoad %_struct_24 %38
- %40 = OpAccessChain %_ptr_Uniform__struct_24 %dst %int_0 %31
- OpStore %40 %39
- OpReturn
- OpFunctionEnd
- )";
- std::vector<uint32_t> optimized_bin;
- auto status = spvtools::opt::Pass::Status::Failure;
- std::tie(optimized_bin, status) =
- SinglePassRunToBinary<GraphicsRobustAccessPass>(shader, false);
- // Check whether the pass returns the correct modification indication.
- EXPECT_EQ(status, spvtools::opt::Pass::Status::SuccessWithChange);
- }
- // TODO(dneto): Test access chain index wider than 64 bits?
- // TODO(dneto): Test struct access chain index wider than 64 bits?
- // TODO(dneto): OpImageTexelPointer
- // - all Dim types: 1D 2D Cube 3D Rect Buffer
- // - all Dim types that can be arrayed: 1D 2D 3D
- // - sample index: set to 0 if not multisampled
- // - Dim (2D, Cube Rect} with multisampling
- // -1 0 max excess
- // TODO(dneto): Test OpImageTexelPointer with coordinate component index other
- // than 32 bits.
- } // namespace
|