[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/parser_impl_convert_type_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_user_name_test.cc
|
||||
reader/spirv/parser_impl_test.cc
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include "source/opt/build_module.h"
|
||||
#include "source/opt/decoration_manager.h"
|
||||
#include "source/opt/instruction.h"
|
||||
#include "source/opt/module.h"
|
||||
#include "source/opt/type_manager.h"
|
||||
|
@ -252,6 +253,42 @@ ast::type::Type* ParserImpl::ConvertType(uint32_t type_id) {
|
|||
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() {
|
||||
tools_.SetMessageConsumer(message_consumer_);
|
||||
|
||||
|
|
|
@ -41,6 +41,13 @@ namespace tint {
|
|||
namespace reader {
|
||||
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.
|
||||
class ParserImpl : Reader {
|
||||
public:
|
||||
|
@ -95,6 +102,22 @@ class ParserImpl : Reader {
|
|||
/// @returns the namer object
|
||||
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:
|
||||
/// Builds the internal representation of the SPIR-V module.
|
||||
/// 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