blob: c41098cd2423b4e3a77fb730b1f548c3c03d4ac1 [file]
// Copyright (c) 2026 The Khronos Group 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.
// Tests displaying ShaderDebugInfo in validation error messages
#include <string>
#include "gmock/gmock.h"
#include "test/val/val_fixtures.h"
namespace spvtools {
namespace val {
namespace {
using ::testing::HasSubstr;
using ValidateShaderDebugInfo = spvtest::ValidateBase<bool>;
TEST_F(ValidateShaderDebugInfo, DebugLineSingleLine) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%19 = OpString "#version 450
layout(set = 0, binding = 1, std430) buffer SSBO {
vec4 data;
};
void main() {
data = vec4(0.0);
}"
OpDecorate %SSBO Block
OpMemberDecorate %SSBO 0 Offset 0
OpDecorate %_ Binding 1
OpDecorate %_ DescriptorSet 0
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_0 = OpConstant %uint 0
%18 = OpExtInst %void %1 DebugSource %2 %19
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%SSBO = OpTypeStruct %v4float
%_ptr_StorageBuffer_SSBO = OpTypePointer StorageBuffer %SSBO
%uint_12 = OpConstant %uint 12
%_ = OpVariable %_ptr_StorageBuffer_SSBO StorageBuffer
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%float_0 = OpConstant %float 0
%50 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
%uint_7 = OpConstant %uint 7
%main = OpFunction %void None %5
%15 = OpLabel
%54 = OpExtInst %void %1 DebugLine %18 %uint_7 %uint_7 %uint_0 %uint_0
;; invalid here
%53 = OpAccessChain %_ptr_StorageBuffer_v4float %_ %int_0 %int_0 %int_0
OpStore %53 %50
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"( --> a.comp:7:0
|
7 | data = vec4(0.0);
|)"));
}
TEST_F(ValidateShaderDebugInfo, DebugNoLine) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%19 = OpString "#version 450
layout(set = 0, binding = 1, std430) buffer SSBO {
vec4 data;
};
void main() {
data = vec4(0.0);
}"
OpDecorate %SSBO Block
OpMemberDecorate %SSBO 0 Offset 0
OpDecorate %_ Binding 1
OpDecorate %_ DescriptorSet 0
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_0 = OpConstant %uint 0
%18 = OpExtInst %void %1 DebugSource %2 %19
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%SSBO = OpTypeStruct %v4float
%_ptr_StorageBuffer_SSBO = OpTypePointer StorageBuffer %SSBO
%uint_12 = OpConstant %uint 12
%_ = OpVariable %_ptr_StorageBuffer_SSBO StorageBuffer
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%float_0 = OpConstant %float 0
%50 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
%uint_7 = OpConstant %uint 7
%main = OpFunction %void None %5
%15 = OpLabel
%54 = OpExtInst %void %1 DebugLine %18 %uint_7 %uint_7 %uint_0 %uint_0
%55 = OpExtInst %void %1 DebugNoLine
%53 = OpAccessChain %_ptr_StorageBuffer_v4float %_ %int_0 %int_0 %int_0
%56 = OpExtInst %void %1 DebugLine %18 %uint_7 %uint_7 %uint_0 %uint_0
OpStore %53 %50
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(), Not(HasSubstr("a.comp")));
}
TEST_F(ValidateShaderDebugInfo, DebugLineMultieLine) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%19 = OpString "#version 450
layout(set = 0, binding = 1, std430) buffer SSBO {
vec4 data;
};
void main() {
data = vec4(0.0);
}"
OpDecorate %SSBO Block
OpMemberDecorate %SSBO 0 Offset 0
OpDecorate %_ Binding 1
OpDecorate %_ DescriptorSet 0
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_0 = OpConstant %uint 0
%18 = OpExtInst %void %1 DebugSource %2 %19
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%SSBO = OpTypeStruct %v4float
%_ptr_StorageBuffer_SSBO = OpTypePointer StorageBuffer %SSBO
%uint_12 = OpConstant %uint 12
%_ = OpVariable %_ptr_StorageBuffer_SSBO StorageBuffer
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%float_0 = OpConstant %float 0
%50 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
%uint_6 = OpConstant %uint 6
%uint_8 = OpConstant %uint 8
%main = OpFunction %void None %5
%15 = OpLabel
%54 = OpExtInst %void %1 DebugLine %18 %uint_6 %uint_8 %uint_0 %uint_0
;; invalid here
%53 = OpAccessChain %_ptr_StorageBuffer_v4float %_ %int_0 %int_0 %int_0
OpStore %53 %50
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"( --> a.comp:6:0
|
6 | void main() {
7 | data = vec4(0.0);
8 | }
|)"));
}
TEST_F(ValidateShaderDebugInfo, DebugSourceContinued) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%text = OpString "#version 450
layout(set = 0, binding = 1, std430) buffer SSBO {
vec4 data;
};
"
%text1 = OpString "void main() {"
%text2 = OpString "
data = vec4"
%text3 = OpString "(0.0);
}"
OpDecorate %SSBO Block
OpMemberDecorate %SSBO 0 Offset 0
OpDecorate %_ Binding 1
OpDecorate %_ DescriptorSet 0
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_0 = OpConstant %uint 0
%d_source = OpExtInst %void %1 DebugSource %2 %text
%d1 = OpExtInst %void %1 DebugSourceContinued %text1
%d2 = OpExtInst %void %1 DebugSourceContinued %text2
%d3 = OpExtInst %void %1 DebugSourceContinued %text3
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%SSBO = OpTypeStruct %v4float
%_ptr_StorageBuffer_SSBO = OpTypePointer StorageBuffer %SSBO
%uint_12 = OpConstant %uint 12
%_ = OpVariable %_ptr_StorageBuffer_SSBO StorageBuffer
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%float_0 = OpConstant %float 0
%50 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
%uint_6 = OpConstant %uint 6
%uint_8 = OpConstant %uint 8
%main = OpFunction %void None %5
%15 = OpLabel
%54 = OpExtInst %void %1 DebugLine %d_source %uint_6 %uint_8 %uint_0 %uint_0
;; invalid here
%53 = OpAccessChain %_ptr_StorageBuffer_v4float %_ %int_0 %int_0 %int_0
OpStore %53 %50
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"( --> a.comp:6:0
|
6 | void main() {
7 | data = vec4(0.0);
8 | }
|)"));
}
// Make sure we can handle various instructions where there DebugInfo is unused
TEST_F(ValidateShaderDebugInfo, UnusedOpFunction) {
const std::string str = R"(
OpCapability Shader
OpCapability Linkage
OpExtension "SPV_KHR_non_semantic_info"
%d = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
%1 = OpTypeVoid
%2 = OpTypeInt 32 0
%4 = OpFunction %1 None %2
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str.c_str());
EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"OpFunction Function Type <id> '3[%uint]' is not a function type."));
}
TEST_F(ValidateShaderDebugInfo, VariableBasic) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %x
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%8 = OpString "uint"
%16 = OpString "main"
%19 = OpString "#version 450
layout(set = 0, binding = 1, std430) buffer SSBO {
vec4 data;
} x;
void main() {
x.data = vec4(0.0);
}"
%25 = OpString "float"
%31 = OpString "data"
%34 = OpString "SSBO"
%40 = OpString "x"
%46 = OpString "int"
OpDecorate %SSBO Block
OpMemberDecorate %SSBO 0 Offset 0
OpDecorate %x Binding 1
OpDecorate %x DescriptorSet 0
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%18 = OpExtInst %void %1 DebugSource %2 %19
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%uint_2 = OpConstant %uint 2
%20 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %18 %uint_2
%17 = OpExtInst %void %1 DebugFunction %16 %6 %18 %uint_6 %uint_0 %20 %16 %uint_3 %uint_6
%float = OpTypeFloat 32
%26 = OpExtInst %void %1 DebugTypeBasic %25 %uint_32 %uint_3 %uint_0
%v4float = OpTypeVector %float 4
%28 = OpExtInst %void %1 DebugTypeVector %26 %uint_4
%SSBO = OpTypeStruct %v4float
%uint_10 = OpConstant %uint 10
%30 = OpExtInst %void %1 DebugTypeMember %31 %28 %18 %uint_3 %uint_10 %uint_0 %uint_0 %uint_3
%33 = OpExtInst %void %1 DebugTypeComposite %34 %uint_1 %18 %uint_2 %uint_0 %20 %34 %uint_0 %uint_3 %30
%_ptr_StorageBuffer_SSBO = OpTypePointer Uniform %SSBO
%uint_12 = OpConstant %uint 12
%37 = OpExtInst %void %1 DebugTypePointer %33 %uint_12 %uint_0
%x = OpVariable %_ptr_StorageBuffer_SSBO StorageBuffer
%uint_8 = OpConstant %uint 8
%39 = OpExtInst %void %1 DebugGlobalVariable %40 %33 %18 %uint_2 %uint_0 %20 %40 %x %uint_8
%float_0 = OpConstant %float 0
%50 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
%main = OpFunction %void None %5
%15 = OpLabel
%53 = OpAccessChain %_ptr_StorageBuffer_v4float %x %uint_0
OpStore %53 %50
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"( --> a.comp:2:0
|
2 | layout(set = 0, binding = 1, std430) buffer SSBO {
|)"));
}
// Test if no DebugGlobalVariable is found, things still work
TEST_F(ValidateShaderDebugInfo, NoDebugGlobalVariable) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %x
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%8 = OpString "uint"
%19 = OpString "BAD"
%25 = OpString "float"
OpDecorate %SSBO Block
OpMemberDecorate %SSBO 0 Offset 0
OpDecorate %x Binding 1
OpDecorate %x DescriptorSet 0
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%18 = OpExtInst %void %1 DebugSource %2 %19
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%uint_2 = OpConstant %uint 2
%20 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %18 %uint_2
%float = OpTypeFloat 32
%26 = OpExtInst %void %1 DebugTypeBasic %25 %uint_32 %uint_3 %uint_0
%v4float = OpTypeVector %float 4
%28 = OpExtInst %void %1 DebugTypeVector %26 %uint_4
%SSBO = OpTypeStruct %v4float
%uint_10 = OpConstant %uint 10
%_ptr_StorageBuffer_SSBO = OpTypePointer Uniform %SSBO
%uint_12 = OpConstant %uint 12
%x = OpVariable %_ptr_StorageBuffer_SSBO StorageBuffer
%uint_8 = OpConstant %uint 8
%float_0 = OpConstant %float 0
%50 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float
%main = OpFunction %void None %5
%15 = OpLabel
%53 = OpAccessChain %_ptr_StorageBuffer_v4float %x %uint_0
OpStore %53 %50
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), Not(HasSubstr("a.comp")));
}
TEST_F(ValidateShaderDebugInfo, DebugLocalVariable) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%8 = OpString "uint"
%16 = OpString "main"
%19 = OpString "#version 450
void main() {
uint x = 0;
int y = int(x);
}"
%32 = OpString "x"
%37 = OpString "int"
%43 = OpString "y"
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%18 = OpExtInst %void %1 DebugSource %2 %19
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%uint_2 = OpConstant %uint 2
%20 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %18 %uint_2
%17 = OpExtInst %void %1 DebugFunction %16 %6 %18 %uint_3 %uint_0 %20 %16 %uint_3 %uint_3
%_ptr_Function_uint = OpTypePointer Function %uint
%uint_7 = OpConstant %uint 7
%29 = OpExtInst %void %1 DebugTypePointer %9 %uint_7 %uint_0
%31 = OpExtInst %void %1 DebugLocalVariable %32 %9 %18 %uint_4 %uint_0 %17 %uint_4
%34 = OpExtInst %void %1 DebugExpression
%int = OpTypeInt 32 1
%38 = OpExtInst %void %1 DebugTypeBasic %37 %uint_32 %uint_4 %uint_0
%_ptr_Function_int = OpTypePointer Function %int
%40 = OpExtInst %void %1 DebugTypePointer %38 %uint_7 %uint_0
%uint_5 = OpConstant %uint 5
%42 = OpExtInst %void %1 DebugLocalVariable %43 %38 %18 %uint_5 %uint_0 %17 %uint_4
%main = OpFunction %void None %5
%15 = OpLabel
%x = OpVariable %_ptr_Function_uint Uniform
%y = OpVariable %_ptr_Function_int Function
%25 = OpExtInst %void %1 DebugScope %17
%26 = OpExtInst %void %1 DebugLine %18 %uint_3 %uint_3 %uint_0 %uint_0
%24 = OpExtInst %void %1 DebugFunctionDefinition %17 %main
%35 = OpExtInst %void %1 DebugLine %18 %uint_4 %uint_4 %uint_0 %uint_0
%33 = OpExtInst %void %1 DebugDeclare %31 %x %34
OpStore %x %uint_0
%46 = OpExtInst %void %1 DebugLine %18 %uint_5 %uint_5 %uint_0 %uint_0
%45 = OpExtInst %void %1 DebugDeclare %42 %y %34
%47 = OpLoad %uint %x
%48 = OpBitcast %int %47
OpStore %y %48
%49 = OpExtInst %void %1 DebugLine %18 %uint_6 %uint_6 %uint_0 %uint_0
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"( --> a.comp:4:0
|
4 | uint x = 0;
|)"));
}
// Test if no DebugLocalVariable is found, things still work
TEST_F(ValidateShaderDebugInfo, NoDebugLocalVariable) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%8 = OpString "uint"
%16 = OpString "main"
%19 = OpString "#version 450
void main() {
uint x = 0;
int y = int(x);
}"
%32 = OpString "x"
%37 = OpString "int"
%43 = OpString "y"
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%18 = OpExtInst %void %1 DebugSource %2 %19
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%uint_2 = OpConstant %uint 2
%20 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %18 %uint_2
%17 = OpExtInst %void %1 DebugFunction %16 %6 %18 %uint_3 %uint_0 %20 %16 %uint_3 %uint_3
%_ptr_Function_uint = OpTypePointer Function %uint
%uint_7 = OpConstant %uint 7
%29 = OpExtInst %void %1 DebugTypePointer %9 %uint_7 %uint_0
%31 = OpExtInst %void %1 DebugLocalVariable %32 %9 %18 %uint_4 %uint_0 %17 %uint_4
%34 = OpExtInst %void %1 DebugExpression
%int = OpTypeInt 32 1
%38 = OpExtInst %void %1 DebugTypeBasic %37 %uint_32 %uint_4 %uint_0
%_ptr_Function_int = OpTypePointer Function %int
%40 = OpExtInst %void %1 DebugTypePointer %38 %uint_7 %uint_0
%uint_5 = OpConstant %uint 5
%42 = OpExtInst %void %1 DebugLocalVariable %43 %38 %18 %uint_5 %uint_0 %17 %uint_4
%main = OpFunction %void None %5
%15 = OpLabel
%x = OpVariable %_ptr_Function_uint Uniform
%y = OpVariable %_ptr_Function_int Function
%25 = OpExtInst %void %1 DebugScope %17
%26 = OpExtInst %void %1 DebugLine %18 %uint_3 %uint_3 %uint_0 %uint_0
%24 = OpExtInst %void %1 DebugFunctionDefinition %17 %main
%35 = OpExtInst %void %1 DebugLine %18 %uint_4 %uint_4 %uint_0 %uint_0
OpStore %x %uint_0
%46 = OpExtInst %void %1 DebugLine %18 %uint_5 %uint_5 %uint_0 %uint_0
%47 = OpLoad %uint %x
%48 = OpBitcast %int %47
OpStore %y %48
%49 = OpExtInst %void %1 DebugLine %18 %uint_6 %uint_6 %uint_0 %uint_0
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), Not(HasSubstr("a.comp")));
}
TEST_F(ValidateShaderDebugInfo, FunctionCall) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%8 = OpString "uint"
%24 = OpString "foo"
%27 = OpString "#version 450
int foo(int z) {
return z * 3;
}
void main() {
uint x = 0;
int y = foo(x);
}"
%33 = OpString "z"
%38 = OpString "main"
%54 = OpString "x"
%60 = OpString "y"
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%int = OpTypeInt 32 1
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%int_3 = OpConstant %int 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%_ptr_Function_uint = OpTypePointer Function %uint
%_ptr_Function_int = OpTypePointer Function %int
%uint_7 = OpConstant %uint 7
%18 = OpExtInst %void %1 DebugTypePointer %9 %uint_7 %uint_0
%19 = OpTypeFunction %int %_ptr_Function_int
%20 = OpExtInst %void %1 DebugTypeFunction %uint_3 %9 %9
%26 = OpExtInst %void %1 DebugSource %2 %27
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%uint_2 = OpConstant %uint 2
%28 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %26 %uint_2
%25 = OpExtInst %void %1 DebugFunction %24 %20 %26 %uint_3 %uint_0 %28 %24 %uint_3 %uint_3
%32 = OpExtInst %void %1 DebugLocalVariable %33 %9 %26 %uint_3 %uint_0 %25 %uint_4 %uint_1
%35 = OpExtInst %void %1 DebugExpression
%39 = OpExtInst %void %1 DebugFunction %38 %6 %26 %uint_7 %uint_0 %28 %38 %uint_3 %uint_7
%uint_5 = OpConstant %uint 5
%uint_8 = OpConstant %uint 8
%53 = OpExtInst %void %1 DebugLocalVariable %54 %9 %26 %uint_8 %uint_0 %39 %uint_4
%uint_9 = OpConstant %uint 9
%59 = OpExtInst %void %1 DebugLocalVariable %60 %9 %26 %uint_9 %uint_0 %39 %uint_4
%uint_10 = OpConstant %uint 10
%main = OpFunction %void None %5
%15 = OpLabel
%x = OpVariable %_ptr_Function_uint Function
%y = OpVariable %_ptr_Function_uint Function
%param = OpVariable %_ptr_Function_uint Function
%50 = OpExtInst %void %1 DebugScope %39
%51 = OpExtInst %void %1 DebugLine %26 %uint_7 %uint_7 %uint_0 %uint_0
%49 = OpExtInst %void %1 DebugFunctionDefinition %39 %main
%57 = OpExtInst %void %1 DebugLine %26 %uint_8 %uint_8 %uint_0 %uint_0
%56 = OpExtInst %void %1 DebugDeclare %53 %x %35
OpStore %x %uint_0
%63 = OpExtInst %void %1 DebugLine %26 %uint_9 %uint_9 %uint_0 %uint_0
%62 = OpExtInst %void %1 DebugDeclare %59 %y %35
%65 = OpLoad %uint %x
OpStore %param %65
%66 = OpFunctionCall %int %foo_u1_ %param
OpStore %y %66
OpReturn
OpFunctionEnd
%foo_u1_ = OpFunction %int None %19
%z = OpFunctionParameter %_ptr_Function_int
%23 = OpLabel
%36 = OpExtInst %void %1 DebugScope %25
%37 = OpExtInst %void %1 DebugLine %26 %uint_3 %uint_3 %uint_0 %uint_0
%34 = OpExtInst %void %1 DebugDeclare %32 %z %35
%40 = OpExtInst %void %1 DebugFunctionDefinition %25 %foo_u1_
%42 = OpExtInst %void %1 DebugLine %26 %uint_4 %uint_4 %uint_0 %uint_0
%41 = OpLoad %int %z
%43 = OpIMul %int %41 %int_3
OpReturnValue %43
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"( --> a.comp:9:0
|
9 | int y = foo(x);
|
--> a.comp:3:0
|
3 | int foo(int z) {
|)"));
}
// If we can only find the caller, not the callee
TEST_F(ValidateShaderDebugInfo, FunctionCallNoCallee) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%8 = OpString "uint"
%24 = OpString "foo"
%27 = OpString "#version 450
int foo(int z) {
return z * 3;
}
void main() {
uint x = 0;
int y = foo(x);
}"
%33 = OpString "z"
%38 = OpString "main"
%54 = OpString "x"
%60 = OpString "y"
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%int = OpTypeInt 32 1
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%int_3 = OpConstant %int 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%_ptr_Function_uint = OpTypePointer Function %uint
%_ptr_Function_int = OpTypePointer Function %int
%uint_7 = OpConstant %uint 7
%18 = OpExtInst %void %1 DebugTypePointer %9 %uint_7 %uint_0
%19 = OpTypeFunction %int %_ptr_Function_int
%20 = OpExtInst %void %1 DebugTypeFunction %uint_3 %9 %9
%26 = OpExtInst %void %1 DebugSource %2 %27
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%uint_2 = OpConstant %uint 2
%28 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %26 %uint_2
%25 = OpExtInst %void %1 DebugFunction %24 %20 %26 %uint_3 %uint_0 %28 %24 %uint_3 %uint_3
%32 = OpExtInst %void %1 DebugLocalVariable %33 %9 %26 %uint_3 %uint_0 %25 %uint_4 %uint_1
%35 = OpExtInst %void %1 DebugExpression
%39 = OpExtInst %void %1 DebugFunction %38 %6 %26 %uint_7 %uint_0 %28 %38 %uint_3 %uint_7
%uint_5 = OpConstant %uint 5
%uint_8 = OpConstant %uint 8
%53 = OpExtInst %void %1 DebugLocalVariable %54 %9 %26 %uint_8 %uint_0 %39 %uint_4
%uint_9 = OpConstant %uint 9
%59 = OpExtInst %void %1 DebugLocalVariable %60 %9 %26 %uint_9 %uint_0 %39 %uint_4
%uint_10 = OpConstant %uint 10
%main = OpFunction %void None %5
%15 = OpLabel
%x = OpVariable %_ptr_Function_uint Function
%y = OpVariable %_ptr_Function_uint Function
%param = OpVariable %_ptr_Function_uint Function
%50 = OpExtInst %void %1 DebugScope %39
%51 = OpExtInst %void %1 DebugLine %26 %uint_7 %uint_7 %uint_0 %uint_0
%49 = OpExtInst %void %1 DebugFunctionDefinition %39 %main
%57 = OpExtInst %void %1 DebugLine %26 %uint_8 %uint_8 %uint_0 %uint_0
%56 = OpExtInst %void %1 DebugDeclare %53 %x %35
OpStore %x %uint_0
%63 = OpExtInst %void %1 DebugLine %26 %uint_9 %uint_9 %uint_0 %uint_0
%62 = OpExtInst %void %1 DebugDeclare %59 %y %35
%65 = OpLoad %uint %x
OpStore %param %65
%66 = OpFunctionCall %int %foo_u1_ %param
OpStore %y %66
OpReturn
OpFunctionEnd
%foo_u1_ = OpFunction %int None %19
%z = OpFunctionParameter %_ptr_Function_int
%23 = OpLabel
%41 = OpLoad %int %z
%43 = OpIMul %int %41 %int_3
OpReturnValue %43
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"( --> a.comp:9:0
|
9 | int y = foo(x);
|)"));
}
TEST_F(ValidateShaderDebugInfo, FunctionCallAcrossFile) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%file_name_0 = OpString "file_a.comp"
%file_name_1 = OpString "file_b.comp"
%8 = OpString "uint"
%24 = OpString "foo"
%file_0 = OpString "
int foo(int z) {
return z * 3;
}
"
%file_1 = OpString "#version 450
void main() {
uint x = 0;
int y = foo(
x
);
}"
%33 = OpString "z"
%38 = OpString "main"
%54 = OpString "x"
%60 = OpString "y"
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%int = OpTypeInt 32 1
%uint_32 = OpConstant %uint 32
%uint_0 = OpConstant %uint 0
%uint_1 = OpConstant %uint 1
%uint_2 = OpConstant %uint 2
%uint_3 = OpConstant %uint 3
%uint_4 = OpConstant %uint 4
%uint_6 = OpConstant %uint 6
%uint_7 = OpConstant %uint 7
%int_3 = OpConstant %int 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%_ptr_Function_uint = OpTypePointer Function %uint
%_ptr_Function_int = OpTypePointer Function %int
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%18 = OpExtInst %void %1 DebugTypePointer %9 %uint_7 %uint_0
%19 = OpTypeFunction %int %_ptr_Function_int
%20 = OpExtInst %void %1 DebugTypeFunction %uint_3 %9 %9
%source_0 = OpExtInst %void %1 DebugSource %file_name_0 %file_0
%source_1 = OpExtInst %void %1 DebugSource %file_name_1 %file_1
%28 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %source_0 %uint_2
%25 = OpExtInst %void %1 DebugFunction %24 %20 %source_0 %uint_2 %uint_0 %28 %24 %uint_3 %uint_3
%39 = OpExtInst %void %1 DebugFunction %38 %6 %source_1 %uint_2 %uint_0 %28 %38 %uint_3 %uint_7
%main = OpFunction %void None %5
%15 = OpLabel
%x = OpVariable %_ptr_Function_uint Function
%y = OpVariable %_ptr_Function_uint Function
%param = OpVariable %_ptr_Function_uint Function
%51 = OpExtInst %void %1 DebugLine %source_1 %uint_2 %uint_2 %uint_0 %uint_0
%49 = OpExtInst %void %1 DebugFunctionDefinition %39 %main
%57 = OpExtInst %void %1 DebugLine %source_1 %uint_3 %uint_3 %uint_0 %uint_0
OpStore %x %uint_0
%63 = OpExtInst %void %1 DebugLine %source_1 %uint_4 %uint_6 %uint_0 %uint_0
%65 = OpLoad %uint %x
OpStore %param %65
%66 = OpFunctionCall %int %foo_u1_ %param
OpStore %y %66
OpReturn
OpFunctionEnd
%foo_u1_ = OpFunction %int None %19
%z = OpFunctionParameter %_ptr_Function_int
%23 = OpLabel
%37 = OpExtInst %void %1 DebugLine %source_0 %uint_2 %uint_2 %uint_0 %uint_0
%40 = OpExtInst %void %1 DebugFunctionDefinition %25 %foo_u1_
%42 = OpExtInst %void %1 DebugLine %source_0 %uint_3 %uint_3 %uint_0 %uint_0
%41 = OpLoad %int %z
%43 = OpIMul %int %41 %int_3
OpReturnValue %43
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"( --> file_b.comp:4:0
|
4 | int y = foo(
5 | x
6 | );
|
--> file_a.comp:2:0
|
2 | int foo(int z) {
|)"));
}
TEST_F(ValidateShaderDebugInfo, ExecutionMode) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 0 1 1
%2 = OpString "a.comp"
%8 = OpString "uint"
%16 = OpString "main"
%19 = OpString "#version 450
void main() {
}"
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%18 = OpExtInst %void %1 DebugSource %2 %19
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%uint_2 = OpConstant %uint 2
%20 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %18 %uint_2
%17 = OpExtInst %void %1 DebugFunction %16 %6 %18 %uint_3 %uint_0 %20 %16 %uint_3 %uint_3
%main = OpFunction %void None %5
%15 = OpLabel
%25 = OpExtInst %void %1 DebugScope %17
%26 = OpExtInst %void %1 DebugLine %18 %uint_3 %uint_3 %uint_0 %uint_0
%24 = OpExtInst %void %1 DebugFunctionDefinition %17 %main
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"(--> a.comp:3:0
|
3 | void main() {
|)"));
}
TEST_F(ValidateShaderDebugInfo, EntryPoint) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%8 = OpString "uint"
%16 = OpString "main"
%19 = OpString "#version 450
void main() {
}"
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%18 = OpExtInst %void %1 DebugSource %2 %19
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%uint_2 = OpConstant %uint 2
%20 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %18 %uint_2
%17 = OpExtInst %void %1 DebugFunction %16 %6 %18 %uint_3 %uint_0 %20 %16 %uint_3 %uint_3
%main = OpFunction %uint None %5
%15 = OpLabel
%25 = OpExtInst %void %1 DebugScope %17
%26 = OpExtInst %void %1 DebugLine %18 %uint_3 %uint_3 %uint_0 %uint_0
%24 = OpExtInst %void %1 DebugFunctionDefinition %17 %main
OpReturnValue %uint_1
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"(--> a.comp:3:0
|
3 | void main() {
|)"));
}
TEST_F(ValidateShaderDebugInfo, ReturnValue) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%8 = OpString "uint"
%20 = OpString "foo"
%23 = OpString "#version 450
uint foo() {
return 4;
}
void main() {
int a = 0;
uint b = foo();
}"
%28 = OpString "main"
%44 = OpString "int"
%50 = OpString "a"
%60 = OpString "b"
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%int = OpTypeInt 32 1
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%16 = OpTypeFunction %uint
%17 = OpExtInst %void %1 DebugTypeFunction %uint_3 %9
%22 = OpExtInst %void %1 DebugSource %2 %23
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%int_4 = OpConstant %int 4
%uint_2 = OpConstant %uint 2
%24 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %22 %uint_2
%21 = OpExtInst %void %1 DebugFunction %20 %17 %22 %uint_3 %uint_0 %24 %20 %uint_3 %uint_3
%uint_7 = OpConstant %uint 7
%29 = OpExtInst %void %1 DebugFunction %28 %6 %22 %uint_7 %uint_0 %24 %28 %uint_3 %uint_7
%uint_5 = OpConstant %uint 5
%45 = OpExtInst %void %1 DebugTypeBasic %44 %uint_32 %uint_4 %uint_0
%_ptr_Function_int = OpTypePointer Function %int
%47 = OpExtInst %void %1 DebugTypePointer %45 %uint_7 %uint_0
%uint_8 = OpConstant %uint 8
%49 = OpExtInst %void %1 DebugLocalVariable %50 %45 %22 %uint_8 %uint_0 %29 %uint_4
%53 = OpExtInst %void %1 DebugExpression
%int_0 = OpConstant %int 0
%_ptr_Function_uint = OpTypePointer Function %uint
%57 = OpExtInst %void %1 DebugTypePointer %9 %uint_7 %uint_0
%uint_9 = OpConstant %uint 9
%59 = OpExtInst %void %1 DebugLocalVariable %60 %9 %22 %uint_9 %uint_0 %29 %uint_4
%uint_10 = OpConstant %uint 10
%main = OpFunction %void None %5
%15 = OpLabel
%a = OpVariable %_ptr_Function_int Function
%b = OpVariable %_ptr_Function_uint Function
%41 = OpExtInst %void %1 DebugScope %29
%42 = OpExtInst %void %1 DebugLine %22 %uint_7 %uint_7 %uint_0 %uint_0
%40 = OpExtInst %void %1 DebugFunctionDefinition %29 %main
%54 = OpExtInst %void %1 DebugLine %22 %uint_8 %uint_8 %uint_0 %uint_0
%52 = OpExtInst %void %1 DebugDeclare %49 %a %53
OpStore %a %int_0
%63 = OpExtInst %void %1 DebugLine %22 %uint_9 %uint_9 %uint_0 %uint_0
%62 = OpExtInst %void %1 DebugDeclare %59 %b %53
%64 = OpFunctionCall %uint %foo_
OpStore %b %64
%65 = OpExtInst %void %1 DebugLine %22 %uint_10 %uint_10 %uint_0 %uint_0
OpReturn
OpFunctionEnd
%foo_ = OpFunction %uint None %16
%19 = OpLabel
%32 = OpExtInst %void %1 DebugScope %21
%33 = OpExtInst %void %1 DebugLine %22 %uint_3 %uint_3 %uint_0 %uint_0
%31 = OpExtInst %void %1 DebugFunctionDefinition %21 %foo_
%34 = OpExtInst %void %1 DebugLine %22 %uint_4 %uint_4 %uint_0 %uint_0
OpReturnValue %int_4
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"(--> a.comp:4:0
|
4 | return 4;
|
--> a.comp:3:0
|
3 | uint foo() {
|)"));
}
TEST_F(ValidateShaderDebugInfo, ReturnValueVoid) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%8 = OpString "uint"
%20 = OpString "foo"
%23 = OpString "#version 450
uint foo() {
return 4;
}
void main() {
int a = 0;
uint b = foo();
}"
%28 = OpString "main"
%44 = OpString "int"
%50 = OpString "a"
%60 = OpString "b"
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%int = OpTypeInt 32 1
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%16 = OpTypeFunction %uint
%17 = OpExtInst %void %1 DebugTypeFunction %uint_3 %9
%22 = OpExtInst %void %1 DebugSource %2 %23
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%int_4 = OpConstant %int 4
%uint_2 = OpConstant %uint 2
%24 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %22 %uint_2
%21 = OpExtInst %void %1 DebugFunction %20 %17 %22 %uint_3 %uint_0 %24 %20 %uint_3 %uint_3
%uint_7 = OpConstant %uint 7
%29 = OpExtInst %void %1 DebugFunction %28 %6 %22 %uint_7 %uint_0 %24 %28 %uint_3 %uint_7
%uint_5 = OpConstant %uint 5
%45 = OpExtInst %void %1 DebugTypeBasic %44 %uint_32 %uint_4 %uint_0
%_ptr_Function_int = OpTypePointer Function %int
%47 = OpExtInst %void %1 DebugTypePointer %45 %uint_7 %uint_0
%uint_8 = OpConstant %uint 8
%49 = OpExtInst %void %1 DebugLocalVariable %50 %45 %22 %uint_8 %uint_0 %29 %uint_4
%53 = OpExtInst %void %1 DebugExpression
%int_0 = OpConstant %int 0
%_ptr_Function_uint = OpTypePointer Function %uint
%57 = OpExtInst %void %1 DebugTypePointer %9 %uint_7 %uint_0
%uint_9 = OpConstant %uint 9
%59 = OpExtInst %void %1 DebugLocalVariable %60 %9 %22 %uint_9 %uint_0 %29 %uint_4
%uint_10 = OpConstant %uint 10
%main = OpFunction %void None %5
%15 = OpLabel
%a = OpVariable %_ptr_Function_int Function
%b = OpVariable %_ptr_Function_uint Function
%41 = OpExtInst %void %1 DebugScope %29
%42 = OpExtInst %void %1 DebugLine %22 %uint_7 %uint_7 %uint_0 %uint_0
%40 = OpExtInst %void %1 DebugFunctionDefinition %29 %main
%54 = OpExtInst %void %1 DebugLine %22 %uint_8 %uint_8 %uint_0 %uint_0
%52 = OpExtInst %void %1 DebugDeclare %49 %a %53
OpStore %a %int_0
%63 = OpExtInst %void %1 DebugLine %22 %uint_9 %uint_9 %uint_0 %uint_0
%62 = OpExtInst %void %1 DebugDeclare %59 %b %53
%64 = OpFunctionCall %uint %foo_
OpStore %b %64
%65 = OpExtInst %void %1 DebugLine %22 %uint_10 %uint_10 %uint_0 %uint_0
OpReturnValue %int_0
OpFunctionEnd
%foo_ = OpFunction %uint None %16
%19 = OpLabel
%32 = OpExtInst %void %1 DebugScope %21
%33 = OpExtInst %void %1 DebugLine %22 %uint_3 %uint_3 %uint_0 %uint_0
%31 = OpExtInst %void %1 DebugFunctionDefinition %21 %foo_
%34 = OpExtInst %void %1 DebugLine %22 %uint_4 %uint_4 %uint_0 %uint_0
OpReturnValue %int_4
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"(--> a.comp:10:0
|
10 | }
|
--> a.comp:7:0
|
7 | void main() {
|)"));
}
TEST_F(ValidateShaderDebugInfo, FunctionParameter) {
const std::string str = R"(
OpCapability Shader
OpExtension "SPV_KHR_non_semantic_info"
%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
%3 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%2 = OpString "a.comp"
%8 = OpString "uint"
%24 = OpString "foo"
%27 = OpString "#version 450
uint foo(uint a) {
return a * 4;
}
void main() {
int a = 0;
uint b = foo(a);
}"
%33 = OpString "a"
%38 = OpString "main"
%53 = OpString "int"
%65 = OpString "b"
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_32 = OpConstant %uint 32
%uint_6 = OpConstant %uint 6
%uint_0 = OpConstant %uint 0
%9 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_6 %uint_0
%uint_3 = OpConstant %uint 3
%6 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
%_ptr_Function_uint = OpTypePointer Function %uint
%uint_7 = OpConstant %uint 7
%18 = OpExtInst %void %1 DebugTypePointer %9 %uint_7 %uint_0
%19 = OpTypeFunction %uint %_ptr_Function_uint
%20 = OpExtInst %void %1 DebugTypeFunction %uint_3 %9 %9
%26 = OpExtInst %void %1 DebugSource %2 %27
%uint_1 = OpConstant %uint 1
%uint_4 = OpConstant %uint 4
%uint_2 = OpConstant %uint 2
%28 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %26 %uint_2
%25 = OpExtInst %void %1 DebugFunction %24 %20 %26 %uint_3 %uint_0 %28 %24 %uint_3 %uint_3
%32 = OpExtInst %void %1 DebugLocalVariable %33 %9 %26 %uint_3 %uint_0 %25 %uint_4 %uint_1
%35 = OpExtInst %void %1 DebugExpression
%39 = OpExtInst %void %1 DebugFunction %38 %6 %26 %uint_7 %uint_0 %28 %38 %uint_3 %uint_7
%uint_5 = OpConstant %uint 5
%int = OpTypeInt 32 1
%54 = OpExtInst %void %1 DebugTypeBasic %53 %uint_32 %uint_4 %uint_0
%_ptr_Function_int = OpTypePointer Function %int
%56 = OpExtInst %void %1 DebugTypePointer %54 %uint_7 %uint_0
%uint_8 = OpConstant %uint 8
%58 = OpExtInst %void %1 DebugLocalVariable %33 %54 %26 %uint_8 %uint_0 %39 %uint_4
%int_0 = OpConstant %int 0
%uint_9 = OpConstant %uint 9
%64 = OpExtInst %void %1 DebugLocalVariable %65 %9 %26 %uint_9 %uint_0 %39 %uint_4
%uint_10 = OpConstant %uint 10
%main = OpFunction %void None %5
%15 = OpLabel
%a_0 = OpVariable %_ptr_Function_int Function
%b = OpVariable %_ptr_Function_uint Function
%param = OpVariable %_ptr_Function_uint Function
%50 = OpExtInst %void %1 DebugScope %39
%51 = OpExtInst %void %1 DebugLine %26 %uint_7 %uint_7 %uint_0 %uint_0
%49 = OpExtInst %void %1 DebugFunctionDefinition %39 %main
%61 = OpExtInst %void %1 DebugLine %26 %uint_8 %uint_8 %uint_0 %uint_0
%60 = OpExtInst %void %1 DebugDeclare %58 %a_0 %35
OpStore %a_0 %int_0
%68 = OpExtInst %void %1 DebugLine %26 %uint_9 %uint_9 %uint_0 %uint_0
%67 = OpExtInst %void %1 DebugDeclare %64 %b %35
%69 = OpLoad %int %a_0
%70 = OpBitcast %uint %69
OpStore %param %70
%72 = OpFunctionCall %uint %foo_u1_ %param
OpStore %b %72
%73 = OpExtInst %void %1 DebugLine %26 %uint_10 %uint_10 %uint_0 %uint_0
OpReturn
OpFunctionEnd
%foo_u1_ = OpFunction %uint None %19
%a = OpFunctionParameter %_ptr_Function_int
%23 = OpLabel
%36 = OpExtInst %void %1 DebugScope %25
%37 = OpExtInst %void %1 DebugLine %26 %uint_3 %uint_3 %uint_0 %uint_0
%34 = OpExtInst %void %1 DebugDeclare %32 %a %35
%40 = OpExtInst %void %1 DebugFunctionDefinition %25 %foo_u1_
%42 = OpExtInst %void %1 DebugLine %26 %uint_4 %uint_4 %uint_0 %uint_0
%41 = OpLoad %uint %a
%43 = OpIMul %uint %41 %uint_4
OpReturnValue %43
OpFunctionEnd
)";
CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_3);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
EXPECT_THAT(getDiagnosticString(), HasSubstr(R"(--> a.comp:3:0
|
3 | uint foo(uint a) {
|)"));
}
} // namespace
} // namespace val
} // namespace spvtools