[spirv-reader] Get decorations
Bug: tint:3 Change-Id: Idfd49c5bfc8629c17f42f954d65c881865548b8a Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/18140 Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
parent
8ae34868cf
commit
4da4c696e2
|
@ -324,6 +324,7 @@ if(${TINT_BUILD_SPV_READER})
|
||||||
reader/spirv/namer_test.cc
|
reader/spirv/namer_test.cc
|
||||||
reader/spirv/parser_impl_convert_type_test.cc
|
reader/spirv/parser_impl_convert_type_test.cc
|
||||||
reader/spirv/parser_impl_entry_point_test.cc
|
reader/spirv/parser_impl_entry_point_test.cc
|
||||||
|
reader/spirv/parser_impl_get_decorations_test.cc
|
||||||
reader/spirv/parser_impl_import_test.cc
|
reader/spirv/parser_impl_import_test.cc
|
||||||
reader/spirv/parser_impl_user_name_test.cc
|
reader/spirv/parser_impl_user_name_test.cc
|
||||||
reader/spirv/parser_impl_test.cc
|
reader/spirv/parser_impl_test.cc
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "source/opt/build_module.h"
|
#include "source/opt/build_module.h"
|
||||||
|
#include "source/opt/decoration_manager.h"
|
||||||
#include "source/opt/instruction.h"
|
#include "source/opt/instruction.h"
|
||||||
#include "source/opt/module.h"
|
#include "source/opt/module.h"
|
||||||
#include "source/opt/type_manager.h"
|
#include "source/opt/type_manager.h"
|
||||||
|
@ -252,6 +253,42 @@ ast::type::Type* ParserImpl::ConvertType(uint32_t type_id) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DecorationList ParserImpl::GetDecorationsFor(uint32_t id) const {
|
||||||
|
DecorationList result;
|
||||||
|
const auto& decorations = deco_mgr_->GetDecorationsFor(id, true);
|
||||||
|
for (const auto* inst : decorations) {
|
||||||
|
if (inst->opcode() != SpvOpDecorate) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Example: OpDecorate %struct_id Block
|
||||||
|
// Example: OpDecorate %array_ty ArrayStride 16
|
||||||
|
std::vector<uint32_t> inst_as_words;
|
||||||
|
inst->ToBinaryWithoutAttachedDebugInsts(&inst_as_words);
|
||||||
|
Decoration d(inst_as_words.begin() + 2, inst_as_words.end());
|
||||||
|
result.push_back(d);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DecorationList ParserImpl::GetDecorationsForMember(
|
||||||
|
uint32_t id,
|
||||||
|
uint32_t member_index) const {
|
||||||
|
DecorationList result;
|
||||||
|
const auto& decorations = deco_mgr_->GetDecorationsFor(id, true);
|
||||||
|
for (const auto* inst : decorations) {
|
||||||
|
if ((inst->opcode() != SpvOpMemberDecorate) ||
|
||||||
|
(inst->GetSingleWordInOperand(1) != member_index)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Example: OpMemberDecorate %struct_id 2 Offset 24
|
||||||
|
std::vector<uint32_t> inst_as_words;
|
||||||
|
inst->ToBinaryWithoutAttachedDebugInsts(&inst_as_words);
|
||||||
|
Decoration d(inst_as_words.begin() + 3, inst_as_words.end());
|
||||||
|
result.push_back(d);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool ParserImpl::BuildInternalModule() {
|
bool ParserImpl::BuildInternalModule() {
|
||||||
tools_.SetMessageConsumer(message_consumer_);
|
tools_.SetMessageConsumer(message_consumer_);
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,13 @@ namespace tint {
|
||||||
namespace reader {
|
namespace reader {
|
||||||
namespace spirv {
|
namespace spirv {
|
||||||
|
|
||||||
|
/// The binary representation of a SPIR-V decoration enum followed by its
|
||||||
|
/// operands, if any.
|
||||||
|
/// Example: { SpvDecorationBlock }
|
||||||
|
/// Example: { SpvDecorationArrayStride, 16 }
|
||||||
|
using Decoration = std::vector<uint32_t>;
|
||||||
|
using DecorationList = std::vector<Decoration>;
|
||||||
|
|
||||||
/// Parser implementation for SPIR-V.
|
/// Parser implementation for SPIR-V.
|
||||||
class ParserImpl : Reader {
|
class ParserImpl : Reader {
|
||||||
public:
|
public:
|
||||||
|
@ -95,6 +102,22 @@ class ParserImpl : Reader {
|
||||||
/// @returns the namer object
|
/// @returns the namer object
|
||||||
Namer& namer() { return namer_; }
|
Namer& namer() { return namer_; }
|
||||||
|
|
||||||
|
/// Gets the list of decorations for a SPIR-V result ID. Returns an empty
|
||||||
|
/// vector if the ID is not a result ID, or if no decorations target that ID.
|
||||||
|
/// The internal representation must have already been built.
|
||||||
|
/// @param id SPIR-V ID
|
||||||
|
/// @returns the list of decorations on the given ID
|
||||||
|
DecorationList GetDecorationsFor(uint32_t id) const;
|
||||||
|
/// Gets the list of decorations for the member of a struct. Returns an empty
|
||||||
|
/// list if the |id| is not the ID of a struct, or if the member index is out
|
||||||
|
/// of range, or if the target member has no decorations.
|
||||||
|
/// The internal representation must have already been built.
|
||||||
|
/// @param id SPIR-V ID of a struct
|
||||||
|
/// @param member_index the member within the struct
|
||||||
|
/// @returns the list of decorations on the member
|
||||||
|
DecorationList GetDecorationsForMember(uint32_t id,
|
||||||
|
uint32_t member_index) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Builds the internal representation of the SPIR-V module.
|
/// Builds the internal representation of the SPIR-V module.
|
||||||
/// Assumes the module is somewhat well-formed. Normally you
|
/// Assumes the module is somewhat well-formed. Normally you
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
// Copyright 2020 The Tint Authors.
|
||||||
|
//
|
||||||
|
// 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 "gmock/gmock.h"
|
||||||
|
#include "spirv/unified1/spirv.h"
|
||||||
|
#include "src/reader/spirv/parser_impl.h"
|
||||||
|
#include "src/reader/spirv/parser_impl_test_helper.h"
|
||||||
|
#include "src/reader/spirv/spirv_tools_helpers_test.h"
|
||||||
|
|
||||||
|
namespace tint {
|
||||||
|
namespace reader {
|
||||||
|
namespace spirv {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ::testing::Eq;
|
||||||
|
using ::testing::UnorderedElementsAre;
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetDecorationsFor_NotAnId) {
|
||||||
|
auto p = parser(test::Assemble(""));
|
||||||
|
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||||
|
auto decorations = p->GetDecorationsFor(42);
|
||||||
|
EXPECT_TRUE(decorations.empty());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetDecorationsFor_NoDecorations) {
|
||||||
|
auto p = parser(test::Assemble("%1 = OpTypeVoid"));
|
||||||
|
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||||
|
auto decorations = p->GetDecorationsFor(1);
|
||||||
|
EXPECT_TRUE(decorations.empty());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetDecorationsFor_OneDecoration) {
|
||||||
|
auto p = parser(test::Assemble(R"(
|
||||||
|
OpDecorate %10 Block
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%10 = OpTypeStruct %float
|
||||||
|
)"));
|
||||||
|
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||||
|
auto decorations = p->GetDecorationsFor(10);
|
||||||
|
EXPECT_THAT(decorations,
|
||||||
|
UnorderedElementsAre(Decoration{SpvDecorationBlock}));
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetDecorationsFor_MultiDecoration) {
|
||||||
|
auto p = parser(test::Assemble(R"(
|
||||||
|
OpDecorate %5 RelaxedPrecision
|
||||||
|
OpDecorate %5 Location 7 ; Invalid case made up for test
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%5 = OpConstant %float 3.14
|
||||||
|
)"));
|
||||||
|
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||||
|
auto decorations = p->GetDecorationsFor(5);
|
||||||
|
EXPECT_THAT(decorations,
|
||||||
|
UnorderedElementsAre(Decoration{SpvDecorationRelaxedPrecision},
|
||||||
|
Decoration{SpvDecorationLocation, 7}));
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetDecorationsForMember_NotAnId) {
|
||||||
|
auto p = parser(test::Assemble(""));
|
||||||
|
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||||
|
auto decorations = p->GetDecorationsForMember(42, 9);
|
||||||
|
EXPECT_TRUE(decorations.empty());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetDecorationsForMember_NotAStruct) {
|
||||||
|
auto p = parser(test::Assemble("%1 = OpTypeVoid"));
|
||||||
|
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||||
|
auto decorations = p->GetDecorationsFor(1);
|
||||||
|
EXPECT_TRUE(decorations.empty());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetDecorationsForMember_MemberWithoutDecoration) {
|
||||||
|
auto p = parser(test::Assemble(R"(
|
||||||
|
%uint = OpTypeInt 32 0
|
||||||
|
%10 = OpTypeStruct %uint
|
||||||
|
)"));
|
||||||
|
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||||
|
auto decorations = p->GetDecorationsForMember(10, 0);
|
||||||
|
EXPECT_TRUE(decorations.empty());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetDecorationsForMember_OneDecoration) {
|
||||||
|
auto p = parser(test::Assemble(R"(
|
||||||
|
OpMemberDecorate %10 1 ArrayStride 12
|
||||||
|
%uint = OpTypeInt 32 0
|
||||||
|
%uint_2 = OpConstant %uint 2
|
||||||
|
%arr = OpTypeArray %uint %uint_2
|
||||||
|
%10 = OpTypeStruct %uint %arr
|
||||||
|
)"));
|
||||||
|
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||||
|
auto decorations = p->GetDecorationsForMember(10, 1);
|
||||||
|
EXPECT_THAT(decorations,
|
||||||
|
UnorderedElementsAre(Decoration{SpvDecorationArrayStride, 12}));
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetDecorationsForMember_MultiDecoration) {
|
||||||
|
auto p = parser(test::Assemble(R"(
|
||||||
|
OpMemberDecorate %50 1 RelaxedPrecision
|
||||||
|
OpMemberDecorate %50 2 ArrayStride 16
|
||||||
|
OpMemberDecorate %50 2 MatrixStride 8
|
||||||
|
OpMemberDecorate %50 2 ColMajor
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%vec = OpTypeVector %float 2
|
||||||
|
%mat = OpTypeMatrix %vec 2
|
||||||
|
%uint = OpTypeInt 32 0
|
||||||
|
%uint_2 = OpConstant %uint 2
|
||||||
|
%arr = OpTypeArray %mat %uint_2
|
||||||
|
%50 = OpTypeStruct %uint %float %arr
|
||||||
|
)"));
|
||||||
|
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||||
|
|
||||||
|
EXPECT_TRUE(p->GetDecorationsForMember(50, 0).empty());
|
||||||
|
EXPECT_THAT(p->GetDecorationsForMember(50, 1),
|
||||||
|
UnorderedElementsAre(Decoration{SpvDecorationRelaxedPrecision}));
|
||||||
|
EXPECT_THAT(p->GetDecorationsForMember(50, 2),
|
||||||
|
UnorderedElementsAre(Decoration{SpvDecorationColMajor},
|
||||||
|
Decoration{SpvDecorationMatrixStride, 8},
|
||||||
|
Decoration{SpvDecorationArrayStride, 16}));
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace spirv
|
||||||
|
} // namespace reader
|
||||||
|
} // namespace tint
|
Loading…
Reference in New Issue