mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-27 13:50:07 +00:00
61d8c0384b
Creates a pass that will remove instructions that are invalid for the current shader stage. For the instruction to be considered for replacement 1) The opcode must be valid for a shader modules. 2) The opcode must be invalid for the current shader stage. 3) All entry points to the module must be for the same shader stage. 4) The function containing the instruction must be reachable from an entry point. Fixes #1247.
591 lines
24 KiB
C++
591 lines
24 KiB
C++
// Copyright (c) 2017 Google Inc.
|
|
//
|
|
// 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 "assembly_builder.h"
|
|
#include "gmock/gmock.h"
|
|
#include "pass_fixture.h"
|
|
|
|
#include <cstdarg>
|
|
|
|
namespace {
|
|
|
|
using namespace spvtools;
|
|
|
|
using ReplaceInvalidOpcodeTest = PassTest<::testing::Test>;
|
|
|
|
#ifdef SPIRV_EFFCEE
|
|
TEST_F(ReplaceInvalidOpcodeTest, ReplaceInstruction) {
|
|
const std::string text = R"(
|
|
; CHECK: [[special_const:%\w+]] = OpConstant %float -6.25985e+18
|
|
; CHECK: [[constant:%\w+]] = OpConstantComposite %v4float [[special_const]] [[special_const]] [[special_const]] [[special_const]]
|
|
; CHECK-NOT: OpImageSampleImplicitLod
|
|
; CHECK: OpStore [[:%\w+]] [[constant]]
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
|
|
OpSource GLSL 400
|
|
OpSourceExtension "GL_ARB_separate_shader_objects"
|
|
OpSourceExtension "GL_ARB_shading_language_420pack"
|
|
OpName %main "main"
|
|
OpDecorate %3 Location 0
|
|
OpDecorate %gl_VertexIndex BuiltIn VertexIndex
|
|
OpMemberDecorate %_struct_6 0 BuiltIn Position
|
|
OpDecorate %_struct_6 Block
|
|
%void = OpTypeVoid
|
|
%8 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
|
%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
|
|
%12 = OpTypeSampler
|
|
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
|
|
%14 = OpTypeSampledImage %10
|
|
%v4float = OpTypeVector %float 4
|
|
%v2float = OpTypeVector %float 2
|
|
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
|
%3 = OpVariable %_ptr_Output_v4float Output
|
|
%int = OpTypeInt 32 1
|
|
%_ptr_Input_int = OpTypePointer Input %int
|
|
%gl_VertexIndex = OpVariable %_ptr_Input_int Input
|
|
%_struct_6 = OpTypeStruct %v4float
|
|
%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
|
|
%5 = OpVariable %_ptr_Output__struct_6 Output
|
|
%int_0 = OpConstant %int 0
|
|
%float_0 = OpConstant %float 0
|
|
%23 = OpConstantComposite %v2float %float_0 %float_0
|
|
%24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
|
|
%25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
|
%main = OpFunction %void None %8
|
|
%26 = OpLabel
|
|
%27 = OpLoad %12 %25
|
|
%28 = OpLoad %10 %24
|
|
%29 = OpSampledImage %14 %28 %27
|
|
%30 = OpImageSampleImplicitLod %v4float %29 %23
|
|
%31 = OpAccessChain %_ptr_Output_v4float %5 %int_0
|
|
OpStore %31 %30
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
SinglePassRunAndMatch<opt::ReplaceInvalidOpcodePass>(text, false);
|
|
}
|
|
|
|
TEST_F(ReplaceInvalidOpcodeTest, ReplaceInstructionInNonEntryPoint) {
|
|
const std::string text = R"(
|
|
; CHECK: [[special_const:%\w+]] = OpConstant %float -6.25985e+18
|
|
; CHECK: [[constant:%\w+]] = OpConstantComposite %v4float [[special_const]] [[special_const]] [[special_const]] [[special_const]]
|
|
; CHECK-NOT: OpImageSampleImplicitLod
|
|
; CHECK: OpStore [[:%\w+]] [[constant]]
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
|
|
OpSource GLSL 400
|
|
OpSourceExtension "GL_ARB_separate_shader_objects"
|
|
OpSourceExtension "GL_ARB_shading_language_420pack"
|
|
OpName %main "main"
|
|
OpDecorate %3 Location 0
|
|
OpDecorate %gl_VertexIndex BuiltIn VertexIndex
|
|
OpMemberDecorate %_struct_6 0 BuiltIn Position
|
|
OpDecorate %_struct_6 Block
|
|
%void = OpTypeVoid
|
|
%8 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
|
%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
|
|
%12 = OpTypeSampler
|
|
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
|
|
%14 = OpTypeSampledImage %10
|
|
%v4float = OpTypeVector %float 4
|
|
%v2float = OpTypeVector %float 2
|
|
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
|
%3 = OpVariable %_ptr_Output_v4float Output
|
|
%int = OpTypeInt 32 1
|
|
%_ptr_Input_int = OpTypePointer Input %int
|
|
%gl_VertexIndex = OpVariable %_ptr_Input_int Input
|
|
%_struct_6 = OpTypeStruct %v4float
|
|
%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
|
|
%5 = OpVariable %_ptr_Output__struct_6 Output
|
|
%int_0 = OpConstant %int 0
|
|
%float_0 = OpConstant %float 0
|
|
%23 = OpConstantComposite %v2float %float_0 %float_0
|
|
%24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
|
|
%25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
|
%main = OpFunction %void None %8
|
|
%26 = OpLabel
|
|
%27 = OpFunctionCall %void %28
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%28 = OpFunction %void None %8
|
|
%29 = OpLabel
|
|
%30 = OpLoad %12 %25
|
|
%31 = OpLoad %10 %24
|
|
%32 = OpSampledImage %14 %31 %30
|
|
%33 = OpImageSampleImplicitLod %v4float %32 %23
|
|
%34 = OpAccessChain %_ptr_Output_v4float %5 %int_0
|
|
OpStore %34 %33
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
SinglePassRunAndMatch<opt::ReplaceInvalidOpcodePass>(text, false);
|
|
}
|
|
|
|
TEST_F(ReplaceInvalidOpcodeTest, ReplaceInstructionMultipleEntryPoints) {
|
|
const std::string text = R"(
|
|
; CHECK: [[special_const:%\w+]] = OpConstant %float -6.25985e+18
|
|
; CHECK: [[constant:%\w+]] = OpConstantComposite %v4float [[special_const]] [[special_const]] [[special_const]] [[special_const]]
|
|
; CHECK-NOT: OpImageSampleImplicitLod
|
|
; CHECK: OpStore [[:%\w+]] [[constant]]
|
|
; CHECK-NOT: OpImageSampleImplicitLod
|
|
; CHECK: OpStore [[:%\w+]] [[constant]]
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
|
|
OpEntryPoint Vertex %main2 "main2" %3 %gl_VertexIndex %5
|
|
OpSource GLSL 400
|
|
OpSourceExtension "GL_ARB_separate_shader_objects"
|
|
OpSourceExtension "GL_ARB_shading_language_420pack"
|
|
OpName %main "main"
|
|
OpName %main2 "main2"
|
|
OpDecorate %3 Location 0
|
|
OpDecorate %gl_VertexIndex BuiltIn VertexIndex
|
|
OpMemberDecorate %_struct_6 0 BuiltIn Position
|
|
OpDecorate %_struct_6 Block
|
|
%void = OpTypeVoid
|
|
%8 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
|
%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
|
|
%12 = OpTypeSampler
|
|
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
|
|
%14 = OpTypeSampledImage %10
|
|
%v4float = OpTypeVector %float 4
|
|
%v2float = OpTypeVector %float 2
|
|
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
|
%3 = OpVariable %_ptr_Output_v4float Output
|
|
%int = OpTypeInt 32 1
|
|
%_ptr_Input_int = OpTypePointer Input %int
|
|
%gl_VertexIndex = OpVariable %_ptr_Input_int Input
|
|
%_struct_6 = OpTypeStruct %v4float
|
|
%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
|
|
%5 = OpVariable %_ptr_Output__struct_6 Output
|
|
%int_0 = OpConstant %int 0
|
|
%float_0 = OpConstant %float 0
|
|
%23 = OpConstantComposite %v2float %float_0 %float_0
|
|
%24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
|
|
%25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
|
%main = OpFunction %void None %8
|
|
%26 = OpLabel
|
|
%27 = OpLoad %12 %25
|
|
%28 = OpLoad %10 %24
|
|
%29 = OpSampledImage %14 %28 %27
|
|
%30 = OpImageSampleImplicitLod %v4float %29 %23
|
|
%31 = OpAccessChain %_ptr_Output_v4float %5 %int_0
|
|
OpStore %31 %30
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%main2 = OpFunction %void None %8
|
|
%46 = OpLabel
|
|
%47 = OpLoad %12 %25
|
|
%48 = OpLoad %10 %24
|
|
%49 = OpSampledImage %14 %48 %47
|
|
%50 = OpImageSampleImplicitLod %v4float %49 %23
|
|
%51 = OpAccessChain %_ptr_Output_v4float %5 %int_0
|
|
OpStore %51 %50
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
SinglePassRunAndMatch<opt::ReplaceInvalidOpcodePass>(text, false);
|
|
}
|
|
TEST_F(ReplaceInvalidOpcodeTest, DontReplaceInstruction) {
|
|
const std::string text = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %main "main" %3 %gl_VertexIndex %5
|
|
OpSource GLSL 400
|
|
OpSourceExtension "GL_ARB_separate_shader_objects"
|
|
OpSourceExtension "GL_ARB_shading_language_420pack"
|
|
OpName %main "main"
|
|
OpDecorate %3 Location 0
|
|
OpDecorate %gl_VertexIndex BuiltIn VertexIndex
|
|
OpMemberDecorate %_struct_6 0 BuiltIn Position
|
|
OpDecorate %_struct_6 Block
|
|
%void = OpTypeVoid
|
|
%8 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
|
%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
|
|
%12 = OpTypeSampler
|
|
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
|
|
%14 = OpTypeSampledImage %10
|
|
%v4float = OpTypeVector %float 4
|
|
%v2float = OpTypeVector %float 2
|
|
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
|
%3 = OpVariable %_ptr_Output_v4float Output
|
|
%int = OpTypeInt 32 1
|
|
%_ptr_Input_int = OpTypePointer Input %int
|
|
%gl_VertexIndex = OpVariable %_ptr_Input_int Input
|
|
%_struct_6 = OpTypeStruct %v4float
|
|
%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
|
|
%5 = OpVariable %_ptr_Output__struct_6 Output
|
|
%int_0 = OpConstant %int 0
|
|
%float_0 = OpConstant %float 0
|
|
%23 = OpConstantComposite %v2float %float_0 %float_0
|
|
%24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
|
|
%25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
|
%main = OpFunction %void None %8
|
|
%26 = OpLabel
|
|
%27 = OpLoad %12 %25
|
|
%28 = OpLoad %10 %24
|
|
%29 = OpSampledImage %14 %28 %27
|
|
%30 = OpImageSampleImplicitLod %v4float %29 %23
|
|
%31 = OpAccessChain %_ptr_Output_v4float %5 %int_0
|
|
OpStore %31 %30
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
auto result = SinglePassRunAndDisassemble<opt::ReplaceInvalidOpcodePass>(
|
|
text, /* skip_nop = */ true, /* do_validation = */ false);
|
|
EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
|
|
}
|
|
|
|
TEST_F(ReplaceInvalidOpcodeTest, MultipleEntryPointsDifferentStage) {
|
|
const std::string text = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
|
|
OpEntryPoint Fragment %main2 "main2" %3 %gl_VertexIndex %5
|
|
OpSource GLSL 400
|
|
OpSourceExtension "GL_ARB_separate_shader_objects"
|
|
OpSourceExtension "GL_ARB_shading_language_420pack"
|
|
OpName %main "main"
|
|
OpName %main2 "main2"
|
|
OpDecorate %3 Location 0
|
|
OpDecorate %gl_VertexIndex BuiltIn VertexIndex
|
|
OpMemberDecorate %_struct_6 0 BuiltIn Position
|
|
OpDecorate %_struct_6 Block
|
|
%void = OpTypeVoid
|
|
%8 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
|
%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
|
|
%12 = OpTypeSampler
|
|
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
|
|
%14 = OpTypeSampledImage %10
|
|
%v4float = OpTypeVector %float 4
|
|
%v2float = OpTypeVector %float 2
|
|
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
|
%3 = OpVariable %_ptr_Output_v4float Output
|
|
%int = OpTypeInt 32 1
|
|
%_ptr_Input_int = OpTypePointer Input %int
|
|
%gl_VertexIndex = OpVariable %_ptr_Input_int Input
|
|
%_struct_6 = OpTypeStruct %v4float
|
|
%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
|
|
%5 = OpVariable %_ptr_Output__struct_6 Output
|
|
%int_0 = OpConstant %int 0
|
|
%float_0 = OpConstant %float 0
|
|
%23 = OpConstantComposite %v2float %float_0 %float_0
|
|
%24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
|
|
%25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
|
%main = OpFunction %void None %8
|
|
%26 = OpLabel
|
|
%27 = OpLoad %12 %25
|
|
%28 = OpLoad %10 %24
|
|
%29 = OpSampledImage %14 %28 %27
|
|
%30 = OpImageSampleImplicitLod %v4float %29 %23
|
|
%31 = OpAccessChain %_ptr_Output_v4float %5 %int_0
|
|
OpStore %31 %30
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%main2 = OpFunction %void None %8
|
|
%46 = OpLabel
|
|
%47 = OpLoad %12 %25
|
|
%48 = OpLoad %10 %24
|
|
%49 = OpSampledImage %14 %48 %47
|
|
%50 = OpImageSampleImplicitLod %v4float %49 %23
|
|
%51 = OpAccessChain %_ptr_Output_v4float %5 %int_0
|
|
OpStore %51 %50
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
auto result = SinglePassRunAndDisassemble<opt::ReplaceInvalidOpcodePass>(
|
|
text, /* skip_nop = */ true, /* do_validation = */ false);
|
|
EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
|
|
}
|
|
|
|
TEST_F(ReplaceInvalidOpcodeTest, DontReplaceLinkage) {
|
|
const std::string text = R"(
|
|
OpCapability Shader
|
|
OpCapability Linkage
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
|
|
OpSource GLSL 400
|
|
OpSourceExtension "GL_ARB_separate_shader_objects"
|
|
OpSourceExtension "GL_ARB_shading_language_420pack"
|
|
OpName %main "main"
|
|
OpDecorate %3 Location 0
|
|
OpDecorate %gl_VertexIndex BuiltIn VertexIndex
|
|
OpMemberDecorate %_struct_6 0 BuiltIn Position
|
|
OpDecorate %_struct_6 Block
|
|
%void = OpTypeVoid
|
|
%8 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
|
%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
|
|
%12 = OpTypeSampler
|
|
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
|
|
%14 = OpTypeSampledImage %10
|
|
%v4float = OpTypeVector %float 4
|
|
%v2float = OpTypeVector %float 2
|
|
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
|
%3 = OpVariable %_ptr_Output_v4float Output
|
|
%int = OpTypeInt 32 1
|
|
%_ptr_Input_int = OpTypePointer Input %int
|
|
%gl_VertexIndex = OpVariable %_ptr_Input_int Input
|
|
%_struct_6 = OpTypeStruct %v4float
|
|
%_ptr_Output__struct_6 = OpTypePointer Output %_struct_6
|
|
%5 = OpVariable %_ptr_Output__struct_6 Output
|
|
%int_0 = OpConstant %int 0
|
|
%float_0 = OpConstant %float 0
|
|
%23 = OpConstantComposite %v2float %float_0 %float_0
|
|
%24 = OpVariable %_ptr_UniformConstant_10 UniformConstant
|
|
%25 = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
|
%main = OpFunction %void None %8
|
|
%26 = OpLabel
|
|
%27 = OpLoad %12 %25
|
|
%28 = OpLoad %10 %24
|
|
%29 = OpSampledImage %14 %28 %27
|
|
%30 = OpImageSampleImplicitLod %v4float %29 %23
|
|
%31 = OpAccessChain %_ptr_Output_v4float %5 %int_0
|
|
OpStore %31 %30
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
auto result = SinglePassRunAndDisassemble<opt::ReplaceInvalidOpcodePass>(
|
|
text, /* skip_nop = */ true, /* do_validation = */ false);
|
|
EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
|
|
}
|
|
|
|
TEST_F(ReplaceInvalidOpcodeTest, BarrierDontReplace) {
|
|
const std::string text = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpSource GLSL 450
|
|
OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
|
|
OpSourceExtension "GL_GOOGLE_include_directive"
|
|
OpName %main "main"
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%uint = OpTypeInt 32 0
|
|
%uint_2 = OpConstant %uint 2
|
|
%uint_264 = OpConstant %uint 264
|
|
%main = OpFunction %void None %3
|
|
%5 = OpLabel
|
|
OpControlBarrier %uint_2 %uint_2 %uint_264
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
auto result = SinglePassRunAndDisassemble<opt::ReplaceInvalidOpcodePass>(
|
|
text, /* skip_nop = */ true, /* do_validation = */ false);
|
|
EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
|
|
}
|
|
|
|
TEST_F(ReplaceInvalidOpcodeTest, BarrierReplace) {
|
|
const std::string text = R"(
|
|
; CHECK-NOT: OpControlBarrier
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main"
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpSource GLSL 450
|
|
OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
|
|
OpSourceExtension "GL_GOOGLE_include_directive"
|
|
OpName %main "main"
|
|
%void = OpTypeVoid
|
|
%3 = OpTypeFunction %void
|
|
%uint = OpTypeInt 32 0
|
|
%uint_2 = OpConstant %uint 2
|
|
%uint_264 = OpConstant %uint 264
|
|
%main = OpFunction %void None %3
|
|
%5 = OpLabel
|
|
OpControlBarrier %uint_2 %uint_2 %uint_264
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
SinglePassRunAndMatch<opt::ReplaceInvalidOpcodePass>(text, false);
|
|
}
|
|
|
|
struct Message {
|
|
spv_message_level_t level;
|
|
const char* source_file;
|
|
uint32_t line_number;
|
|
uint32_t column_number;
|
|
const char* message;
|
|
};
|
|
|
|
MessageConsumer GetTestMessageConsumer(
|
|
std::vector<Message>& expected_messages) {
|
|
return [&expected_messages](spv_message_level_t level, const char* source,
|
|
const spv_position_t& position,
|
|
const char* message) {
|
|
EXPECT_TRUE(!expected_messages.empty());
|
|
if (expected_messages.empty()) {
|
|
return;
|
|
}
|
|
|
|
EXPECT_EQ(expected_messages[0].level, level);
|
|
EXPECT_EQ(expected_messages[0].line_number, position.line);
|
|
EXPECT_EQ(expected_messages[0].column_number, position.column);
|
|
EXPECT_STREQ(expected_messages[0].source_file, source);
|
|
EXPECT_STREQ(expected_messages[0].message, message);
|
|
|
|
expected_messages.erase(expected_messages.begin());
|
|
};
|
|
}
|
|
|
|
TEST_F(ReplaceInvalidOpcodeTest, MessageTest) {
|
|
const std::string text = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
|
|
OpSource GLSL 400
|
|
%6 = OpString "test.hlsl"
|
|
OpSourceExtension "GL_ARB_separate_shader_objects"
|
|
OpSourceExtension "GL_ARB_shading_language_420pack"
|
|
OpName %main "main"
|
|
OpDecorate %3 Location 0
|
|
OpDecorate %gl_VertexIndex BuiltIn VertexIndex
|
|
OpMemberDecorate %_struct_7 0 BuiltIn Position
|
|
OpDecorate %_struct_7 Block
|
|
%void = OpTypeVoid
|
|
%9 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%11 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
|
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
|
|
%13 = OpTypeSampler
|
|
%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
|
|
%15 = OpTypeSampledImage %11
|
|
%v4float = OpTypeVector %float 4
|
|
%v2float = OpTypeVector %float 2
|
|
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
|
%3 = OpVariable %_ptr_Output_v4float Output
|
|
%int = OpTypeInt 32 1
|
|
%_ptr_Input_int = OpTypePointer Input %int
|
|
%gl_VertexIndex = OpVariable %_ptr_Input_int Input
|
|
%_struct_7 = OpTypeStruct %v4float
|
|
%_ptr_Output__struct_7 = OpTypePointer Output %_struct_7
|
|
%5 = OpVariable %_ptr_Output__struct_7 Output
|
|
%int_0 = OpConstant %int 0
|
|
%float_0 = OpConstant %float 0
|
|
%24 = OpConstantComposite %v2float %float_0 %float_0
|
|
%25 = OpVariable %_ptr_UniformConstant_11 UniformConstant
|
|
%26 = OpVariable %_ptr_UniformConstant_13 UniformConstant
|
|
%main = OpFunction %void None %9
|
|
%27 = OpLabel
|
|
OpLine %6 2 4
|
|
%28 = OpLoad %13 %26
|
|
%29 = OpLoad %11 %25
|
|
%30 = OpSampledImage %15 %29 %28
|
|
%31 = OpImageSampleImplicitLod %v4float %30 %24
|
|
%32 = OpAccessChain %_ptr_Output_v4float %5 %int_0
|
|
OpStore %32 %31
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
std::vector<Message> messages = {
|
|
{SPV_MSG_WARNING, "test.hlsl", 2, 4,
|
|
"Removing ImageSampleImplicitLod instruction because of incompatible "
|
|
"execution model."}};
|
|
SetMessageConsumer(GetTestMessageConsumer(messages));
|
|
auto result = SinglePassRunAndDisassemble<opt::ReplaceInvalidOpcodePass>(
|
|
text, /* skip_nop = */ true, /* do_validation = */ false);
|
|
EXPECT_EQ(opt::Pass::Status::SuccessWithChange, std::get<1>(result));
|
|
}
|
|
|
|
TEST_F(ReplaceInvalidOpcodeTest, MultipleMessageTest) {
|
|
const std::string text = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Vertex %main "main" %3 %gl_VertexIndex %5
|
|
OpSource GLSL 400
|
|
%6 = OpString "test.hlsl"
|
|
OpSourceExtension "GL_ARB_separate_shader_objects"
|
|
OpSourceExtension "GL_ARB_shading_language_420pack"
|
|
OpName %main "main"
|
|
OpDecorate %3 Location 0
|
|
OpDecorate %gl_VertexIndex BuiltIn VertexIndex
|
|
OpMemberDecorate %_struct_7 0 BuiltIn Position
|
|
OpDecorate %_struct_7 Block
|
|
%void = OpTypeVoid
|
|
%9 = OpTypeFunction %void
|
|
%float = OpTypeFloat 32
|
|
%11 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
|
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
|
|
%13 = OpTypeSampler
|
|
%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
|
|
%15 = OpTypeSampledImage %11
|
|
%v4float = OpTypeVector %float 4
|
|
%v2float = OpTypeVector %float 2
|
|
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
|
%3 = OpVariable %_ptr_Output_v4float Output
|
|
%int = OpTypeInt 32 1
|
|
%_ptr_Input_int = OpTypePointer Input %int
|
|
%gl_VertexIndex = OpVariable %_ptr_Input_int Input
|
|
%_struct_7 = OpTypeStruct %v4float
|
|
%_ptr_Output__struct_7 = OpTypePointer Output %_struct_7
|
|
%5 = OpVariable %_ptr_Output__struct_7 Output
|
|
%int_0 = OpConstant %int 0
|
|
%float_0 = OpConstant %float 0
|
|
%24 = OpConstantComposite %v2float %float_0 %float_0
|
|
%25 = OpVariable %_ptr_UniformConstant_11 UniformConstant
|
|
%26 = OpVariable %_ptr_UniformConstant_13 UniformConstant
|
|
%main = OpFunction %void None %9
|
|
%27 = OpLabel
|
|
OpLine %6 2 4
|
|
%28 = OpLoad %13 %26
|
|
%29 = OpLoad %11 %25
|
|
%30 = OpSampledImage %15 %29 %28
|
|
%31 = OpImageSampleImplicitLod %v4float %30 %24
|
|
OpLine %6 12 4
|
|
%41 = OpImageSampleProjImplicitLod %v4float %30 %24
|
|
%32 = OpAccessChain %_ptr_Output_v4float %5 %int_0
|
|
OpStore %32 %31
|
|
OpReturn
|
|
OpFunctionEnd)";
|
|
|
|
std::vector<Message> messages = {
|
|
{SPV_MSG_WARNING, "test.hlsl", 2, 4,
|
|
"Removing ImageSampleImplicitLod instruction because of incompatible "
|
|
"execution model."},
|
|
{SPV_MSG_WARNING, "test.hlsl", 12, 4,
|
|
"Removing ImageSampleProjImplicitLod instruction because of "
|
|
"incompatible "
|
|
"execution model."}};
|
|
SetMessageConsumer(GetTestMessageConsumer(messages));
|
|
auto result = SinglePassRunAndDisassemble<opt::ReplaceInvalidOpcodePass>(
|
|
text, /* skip_nop = */ true, /* do_validation = */ false);
|
|
EXPECT_EQ(opt::Pass::Status::SuccessWithChange, std::get<1>(result));
|
|
}
|
|
#endif
|
|
} // anonymous namespace
|