spirv-reader: ignore NonSemantic. extended instructions
This is the first step in being able to read code generated by Clspv. Actively ignore the instructions instead of applying stripping transform before hand. That way we have a chance at properly counting instructions, which helps produce better diagnostics. Bug: tint:3 Change-Id: I82bde88897485380d70dc8b287c3843eae5489b6 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/41641 Auto-Submit: David Neto <dneto@google.com> Commit-Queue: dan sinclair <dsinclair@chromium.org> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
c8fa020a5e
commit
909c166034
|
@ -3142,6 +3142,12 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) {
|
|||
case SpvOpFunctionCall:
|
||||
return EmitFunctionCall(inst);
|
||||
|
||||
case SpvOpExtInst:
|
||||
if (parser_impl_.IsIgnoredExtendedInstruction(inst)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -3246,9 +3252,13 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
|
|||
}
|
||||
|
||||
if (opcode == SpvOpExtInst) {
|
||||
const auto import = inst.GetSingleWordInOperand(0);
|
||||
if (parser_impl_.glsl_std_450_imports().count(import) == 0) {
|
||||
Fail() << "unhandled extended instruction import with ID " << import;
|
||||
if (parser_impl_.IsIgnoredExtendedInstruction(inst)) {
|
||||
// Ignore it but don't error out.
|
||||
return {};
|
||||
}
|
||||
if (!parser_impl_.IsGlslExtendedInstruction(inst)) {
|
||||
Fail() << "unhandled extended instruction import with ID "
|
||||
<< inst.GetSingleWordInOperand(0);
|
||||
return {};
|
||||
}
|
||||
return EmitGlslStd450ExtInst(inst);
|
||||
|
|
|
@ -613,6 +613,8 @@ bool ParserImpl::RegisterExtendedInstructionImports() {
|
|||
// TODO(dneto): Handle other extended instruction sets when needed.
|
||||
if (name == "GLSL.std.450") {
|
||||
glsl_std_450_imports_.insert(import.result_id());
|
||||
} else if (name.find("NonSemantic.") == 0) {
|
||||
ignored_imports_.insert(import.result_id());
|
||||
} else {
|
||||
return Fail() << "Unrecognized extended instruction set: " << name;
|
||||
}
|
||||
|
@ -626,6 +628,12 @@ bool ParserImpl::IsGlslExtendedInstruction(
|
|||
(glsl_std_450_imports_.count(inst.GetSingleWordInOperand(0)) > 0);
|
||||
}
|
||||
|
||||
bool ParserImpl::IsIgnoredExtendedInstruction(
|
||||
const spvtools::opt::Instruction& inst) const {
|
||||
return (inst.opcode() == SpvOpExtInst) &&
|
||||
(ignored_imports_.count(inst.GetSingleWordInOperand(0)) > 0);
|
||||
}
|
||||
|
||||
bool ParserImpl::RegisterUserAndStructMemberNames() {
|
||||
if (!success_) {
|
||||
return false;
|
||||
|
|
|
@ -242,6 +242,13 @@ class ParserImpl : Reader {
|
|||
/// @returns true if its an SpvOpExtInst for GLSL.std.450
|
||||
bool IsGlslExtendedInstruction(const spvtools::opt::Instruction& inst) const;
|
||||
|
||||
/// Returns true when the given instruction is an extended instruction
|
||||
/// from an ignored extended instruction set.
|
||||
/// @param inst a SPIR-V instruction
|
||||
/// @returns true if its an SpvOpExtInst for an ignored extended instruction
|
||||
bool IsIgnoredExtendedInstruction(
|
||||
const spvtools::opt::Instruction& inst) const;
|
||||
|
||||
/// Registers user names for SPIR-V objects, from OpName, and OpMemberName.
|
||||
/// Also synthesizes struct field names. Ensures uniqueness for names for
|
||||
/// SPIR-V IDs, and uniqueness of names of fields within any single struct.
|
||||
|
@ -596,6 +603,9 @@ class ParserImpl : Reader {
|
|||
// The set of IDs that are imports of the GLSL.std.450 extended instruction
|
||||
// sets.
|
||||
std::unordered_set<uint32_t> glsl_std_450_imports_;
|
||||
// The set of IDs of imports that are ignored. For example, any
|
||||
// "NonSemanticInfo." import is ignored.
|
||||
std::unordered_set<uint32_t> ignored_imports_;
|
||||
|
||||
// Maps a SPIR-V type ID to the corresponding Tint type.
|
||||
std::unordered_map<uint32_t, type::Type*> id_to_type_;
|
||||
|
|
|
@ -46,6 +46,70 @@ TEST_F(SpvParserTest, Import_ImportGlslStd450) {
|
|||
EXPECT_THAT(p->glsl_std_450_imports(), ElementsAre(1));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest, Import_NonSemantic_IgnoredImport) {
|
||||
auto p = parser(test::Assemble(
|
||||
R"(%40 = OpExtInstImport "NonSemantic.ClspvReflection.1")"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest, Import_NonSemantic_IgnoredExtInsts) {
|
||||
// This is the clspv-compiled output of this OpenCL C:
|
||||
// kernel void foo(global int*A) { A=A; }
|
||||
// It emits NonSemantic.ClspvReflection.1 extended instructions.
|
||||
// But *tweaked*:
|
||||
// - to remove gl_WorkgroupSize
|
||||
// - to move one of the ExtInsts into the globals-and-constants
|
||||
// section
|
||||
// - to move one of the ExtInsts into the function body.
|
||||
auto p = parser(test::Assemble(R"(
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
OpExtension "SPV_KHR_non_semantic_info"
|
||||
%20 = OpExtInstImport "NonSemantic.ClspvReflection.1"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %15 "foo"
|
||||
OpSource OpenCL_C 120
|
||||
%21 = OpString "foo"
|
||||
%23 = OpString "A"
|
||||
OpDecorate %_runtimearr_uint ArrayStride 4
|
||||
OpMemberDecorate %_struct_3 0 Offset 0
|
||||
OpDecorate %_struct_3 Block
|
||||
OpDecorate %12 DescriptorSet 0
|
||||
OpDecorate %12 Binding 0
|
||||
OpDecorate %7 SpecId 0
|
||||
OpDecorate %8 SpecId 1
|
||||
OpDecorate %9 SpecId 2
|
||||
%24 = OpExtInst %void %20 ArgumentInfo %23
|
||||
%uint = OpTypeInt 32 0
|
||||
%_runtimearr_uint = OpTypeRuntimeArray %uint
|
||||
%_struct_3 = OpTypeStruct %_runtimearr_uint
|
||||
%_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%_ptr_Private_v3uint = OpTypePointer Private %v3uint
|
||||
%7 = OpSpecConstant %uint 1
|
||||
%8 = OpSpecConstant %uint 1
|
||||
%9 = OpSpecConstant %uint 1
|
||||
%void = OpTypeVoid
|
||||
%14 = OpTypeFunction %void
|
||||
%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%uint_2 = OpConstant %uint 2
|
||||
%12 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer
|
||||
%15 = OpFunction %void Const %14
|
||||
%16 = OpLabel
|
||||
%19 = OpAccessChain %_ptr_StorageBuffer_uint %12 %uint_0 %uint_0
|
||||
%22 = OpExtInst %void %20 Kernel %15 %21
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%25 = OpExtInst %void %20 ArgumentStorageBuffer %22 %uint_0 %uint_0 %uint_0 %24
|
||||
%28 = OpExtInst %void %20 SpecConstantWorkgroupSize %uint_0 %uint_1 %uint_2
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
// TODO(dneto): We don't currently support other kinds of extended instruction
|
||||
// imports.
|
||||
|
||||
|
|
Loading…
Reference in New Issue