Skip to content

Commit

Permalink
WIP: Allow OpExtInst for DebugInfo between secion 9 and 10
Browse files Browse the repository at this point in the history
  • Loading branch information
jaebaek committed Jan 21, 2020
1 parent ab7ac60 commit cb10548
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 2 deletions.
8 changes: 8 additions & 0 deletions source/ext_inst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ bool spvExtInstIsNonSemantic(const spv_ext_inst_type_t type) {
return false;
}

bool spvExtInstIsDebugInfo(const spv_ext_inst_type_t type) {
if (type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
type == SPV_EXT_INST_TYPE_DEBUGINFO) {
return true;
}
return false;
}

spv_result_t spvExtInstTableNameLookup(const spv_ext_inst_table table,
const spv_ext_inst_type_t type,
const char* name,
Expand Down
3 changes: 3 additions & 0 deletions source/ext_inst.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ spv_ext_inst_type_t spvExtInstImportTypeGet(const char* name);
// Returns true if the extended instruction set is non-semantic
bool spvExtInstIsNonSemantic(const spv_ext_inst_type_t type);

// Returns true if the extended instruction set is debug info
bool spvExtInstIsDebugInfo(const spv_ext_inst_type_t type);

// Finds the named extented instruction of the given type in the given extended
// instruction table. On success, returns SPV_SUCCESS and writes a handle of
// the instruction entry into *entry.
Expand Down
48 changes: 46 additions & 2 deletions source/val/validate_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@

// Source code for logical layout validation as described in section 2.4

#include "source/val/validate.h"

#include <cassert>

#include "OpenCLDebugInfo100.h"
#include "source/diagnostic.h"
#include "source/opcode.h"
#include "source/operand.h"
#include "source/val/function.h"
#include "source/val/instruction.h"
#include "source/val/validate.h"
#include "source/val/validation_state.h"

namespace spvtools {
Expand All @@ -46,6 +46,19 @@ spv_result_t ModuleScopedInstructions(ValidationState_t& _,
<< "Non-semantic OpExtInst must not appear before types "
<< "section";
}
} else if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
// Debug info extinst opcodes other than DebugScope, DebugNoScope,
// DebugDeclare, DebugValue must be placed between section 9 (types,
// constants, global variables) and section 10 (function declarations).
if (_.current_layout_section() < kLayoutTypes ||
_.current_layout_section() > kLayoutFunctionDeclarations) {
return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
<< "OpenCL.DebugInfo.100 instructions other than "
<< "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
<< "must appear between section 9 (types, constants, "
<< "global variables) and section 10 (function "
<< "declarations)";
}
} else {
// otherwise they must be used in a block
if (_.current_layout_section() < kLayoutFunctionDefinitions) {
Expand Down Expand Up @@ -182,6 +195,37 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _,
<< "Non-semantic OpExtInst within function definition must "
"appear in a block";
}
} else if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
const uint32_t ext_inst_index = inst->word(4);
const OpenCLDebugInfo100Instructions ext_inst_key =
OpenCLDebugInfo100Instructions(ext_inst_index);
if (ext_inst_key == OpenCLDebugInfo100DebugScope ||
ext_inst_key == OpenCLDebugInfo100DebugNoScope ||
ext_inst_key == OpenCLDebugInfo100DebugDeclare ||
ext_inst_key == OpenCLDebugInfo100DebugValue) {
if (_.in_function_body() == false) {
// DebugScope, DebugNoScope, DebugDeclare, DebugValue must
// appear in a function body.
return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
<< "OpenCL.DebugInfo.100 DebugScope, DebugNoScope, "
<< "DebugDeclare, DebugValue must appear in a function "
<< "body";
}
} else {
// Debug info extinst opcodes other than DebugScope, DebugNoScope,
// DebugDeclare, DebugValue must be placed between section 9 (types,
// constants, global variables) and section 10 (function
// declarations).
if (_.current_layout_section() < kLayoutTypes ||
_.current_layout_section() > kLayoutFunctionDeclarations) {
return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
<< "OpenCL.DebugInfo.100 instructions other than "
<< "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
<< "must appear between section 9 (types, constants, "
<< "global variables) and section 10 (function "
<< "declarations)";
}
}
} else {
// otherwise they must be used in a block
if (_.in_block() == false) {
Expand Down
224 changes: 224 additions & 0 deletions test/val/val_ext_inst_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ using ::testing::HasSubstr;
using ::testing::Not;

using ValidateExtInst = spvtest::ValidateBase<bool>;
using ValidateOpenCL100DebugInfo = spvtest::ValidateBase<std::string>;
using ValidateGlslStd450SqrtLike = spvtest::ValidateBase<std::string>;
using ValidateGlslStd450FMinLike = spvtest::ValidateBase<std::string>;
using ValidateGlslStd450FClampLike = spvtest::ValidateBase<std::string>;
Expand Down Expand Up @@ -460,6 +461,229 @@ OpFunctionEnd)";
return ss.str();
}

std::string GenerateShaderCodeForDebugInfo(
const std::string& op_string_instructions,
const std::string& op_const_instructions,
const std::string& debug_instructions_before_main, const std::string& body,
const std::string& capabilities_and_extensions = "",
const std::string& execution_model = "Fragment") {
std::ostringstream ss;
ss << R"(
OpCapability Shader
OpCapability Float16
OpCapability Float64
OpCapability Int16
OpCapability Int64
)";

ss << capabilities_and_extensions;
ss << "%extinst = OpExtInstImport \"GLSL.std.450\"\n";
ss << "OpMemoryModel Logical GLSL450\n";
ss << "OpEntryPoint " << execution_model << " %main \"main\""
<< " %f32_output"
<< " %f32vec2_output"
<< " %u32_output"
<< " %u32vec2_output"
<< " %u64_output"
<< " %f32_input"
<< " %f32vec2_input"
<< " %u32_input"
<< " %u32vec2_input"
<< " %u64_input"
<< "\n";
if (execution_model == "Fragment") {
ss << "OpExecutionMode %main OriginUpperLeft\n";
}

ss << op_string_instructions;

ss << R"(
%void = OpTypeVoid
%func = OpTypeFunction %void
%bool = OpTypeBool
%f16 = OpTypeFloat 16
%f32 = OpTypeFloat 32
%f64 = OpTypeFloat 64
%u32 = OpTypeInt 32 0
%s32 = OpTypeInt 32 1
%u64 = OpTypeInt 64 0
%s64 = OpTypeInt 64 1
%u16 = OpTypeInt 16 0
%s16 = OpTypeInt 16 1
%f32vec2 = OpTypeVector %f32 2
%f32vec3 = OpTypeVector %f32 3
%f32vec4 = OpTypeVector %f32 4
%f64vec2 = OpTypeVector %f64 2
%f64vec3 = OpTypeVector %f64 3
%f64vec4 = OpTypeVector %f64 4
%u32vec2 = OpTypeVector %u32 2
%u32vec3 = OpTypeVector %u32 3
%s32vec2 = OpTypeVector %s32 2
%u32vec4 = OpTypeVector %u32 4
%s32vec4 = OpTypeVector %s32 4
%u64vec2 = OpTypeVector %u64 2
%s64vec2 = OpTypeVector %s64 2
%f64mat22 = OpTypeMatrix %f64vec2 2
%f32mat22 = OpTypeMatrix %f32vec2 2
%f32mat23 = OpTypeMatrix %f32vec2 3
%f32mat32 = OpTypeMatrix %f32vec3 2
%f32mat33 = OpTypeMatrix %f32vec3 3
%f32_0 = OpConstant %f32 0
%f32_1 = OpConstant %f32 1
%f32_2 = OpConstant %f32 2
%f32_3 = OpConstant %f32 3
%f32_4 = OpConstant %f32 4
%f32_h = OpConstant %f32 0.5
%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
%f64_0 = OpConstant %f64 0
%f64_1 = OpConstant %f64 1
%f64_2 = OpConstant %f64 2
%f64_3 = OpConstant %f64 3
%f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1
%f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2
%f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
%f16_0 = OpConstant %f16 0
%f16_1 = OpConstant %f16 1
%f16_h = OpConstant %f16 0.5
%u32_0 = OpConstant %u32 0
%u32_1 = OpConstant %u32 1
%u32_2 = OpConstant %u32 2
%u32_3 = OpConstant %u32 3
%s32_0 = OpConstant %s32 0
%s32_1 = OpConstant %s32 1
%s32_2 = OpConstant %s32 2
%s32_3 = OpConstant %s32 3
%u64_0 = OpConstant %u64 0
%u64_1 = OpConstant %u64 1
%u64_2 = OpConstant %u64 2
%u64_3 = OpConstant %u64 3
%s64_0 = OpConstant %s64 0
%s64_1 = OpConstant %s64 1
%s64_2 = OpConstant %s64 2
%s64_3 = OpConstant %s64 3
)";

ss << op_const_instructions;

ss << R"(
%s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1
%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
%s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2
%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
%s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3
%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
%s64vec2_01 = OpConstantComposite %s64vec2 %s64_0 %s64_1
%u64vec2_01 = OpConstantComposite %u64vec2 %u64_0 %u64_1
%f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12
%f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
%f32_ptr_output = OpTypePointer Output %f32
%f32vec2_ptr_output = OpTypePointer Output %f32vec2
%u32_ptr_output = OpTypePointer Output %u32
%u32vec2_ptr_output = OpTypePointer Output %u32vec2
%u64_ptr_output = OpTypePointer Output %u64
%f32_output = OpVariable %f32_ptr_output Output
%f32vec2_output = OpVariable %f32vec2_ptr_output Output
%u32_output = OpVariable %u32_ptr_output Output
%u32vec2_output = OpVariable %u32vec2_ptr_output Output
%u64_output = OpVariable %u64_ptr_output Output
%f32_ptr_input = OpTypePointer Input %f32
%f32vec2_ptr_input = OpTypePointer Input %f32vec2
%u32_ptr_input = OpTypePointer Input %u32
%u32vec2_ptr_input = OpTypePointer Input %u32vec2
%u64_ptr_input = OpTypePointer Input %u64
%f32_input = OpVariable %f32_ptr_input Input
%f32vec2_input = OpVariable %f32vec2_ptr_input Input
%u32_input = OpVariable %u32_ptr_input Input
%u32vec2_input = OpVariable %u32vec2_ptr_input Input
%u64_input = OpVariable %u64_ptr_input Input
%struct_f16_u16 = OpTypeStruct %f16 %u16
%struct_f32_f32 = OpTypeStruct %f32 %f32
%struct_f32_f32_f32 = OpTypeStruct %f32 %f32 %f32
%struct_f32_u32 = OpTypeStruct %f32 %u32
%struct_f32_u32_f32 = OpTypeStruct %f32 %u32 %f32
%struct_u32_f32 = OpTypeStruct %u32 %f32
%struct_u32_u32 = OpTypeStruct %u32 %u32
%struct_f32_f64 = OpTypeStruct %f32 %f64
%struct_f32vec2_f32vec2 = OpTypeStruct %f32vec2 %f32vec2
%struct_f32vec2_u32vec2 = OpTypeStruct %f32vec2 %u32vec2
)";

ss << debug_instructions_before_main;

ss << R"(
%main = OpFunction %void None %func
%main_entry = OpLabel
)";

ss << body;

ss << R"(
OpReturn
OpFunctionEnd)";

return ss.str();
}

TEST_F(ValidateOpenCL100DebugInfo, UseDebugInstructionOutOfFunction) {
const std::string src = R"(
%src = OpString "simple.hlsl"
%code = OpString "struct VS_OUTPUT {
float4 pos : SV_POSITION;
float4 color : COLOR;
};
VS_OUTPUT main(float4 pos : POSITION,
float4 color : COLOR) {
VS_OUTPUT vout;
vout.pos = pos;
vout.color = color;
return vout;
}
"
)";

const std::string dbg_inst = R"(
%dbg_src = OpExtInst %void %DbgExt DebugSource %src %code
)";

const std::string extension = R"(
%DbgExt = OpExtInstImport "OpenCL.DebugInfo.100"
)";

CompileSuccessfully(GenerateShaderCodeForDebugInfo(src, "", dbg_inst, "",
extension, "Vertex"));
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}

TEST_P(ValidateGlslStd450SqrtLike, Success) {
const std::string ext_inst_name = GetParam();
std::ostringstream ss;
Expand Down

0 comments on commit cb10548

Please sign in to comment.