spirv-reader: add GetMemoryObjectDeclarationForHandle
Bug: tint:109 Change-Id: Ifb437ce9a39db7f92ca081e7ea551a576b0ecb2b Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32740 Reviewed-by: David Neto <dneto@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org> Commit-Queue: David Neto <dneto@google.com> Auto-Submit: David Neto <dneto@google.com>
This commit is contained in:
parent
0ae939bc0c
commit
cebde298f9
1
BUILD.gn
1
BUILD.gn
|
@ -846,6 +846,7 @@ source_set("tint_unittests_spv_reader_src") {
|
||||||
"src/reader/spirv/parser_impl_convert_type_test.cc",
|
"src/reader/spirv/parser_impl_convert_type_test.cc",
|
||||||
"src/reader/spirv/parser_impl_function_decl_test.cc",
|
"src/reader/spirv/parser_impl_function_decl_test.cc",
|
||||||
"src/reader/spirv/parser_impl_get_decorations_test.cc",
|
"src/reader/spirv/parser_impl_get_decorations_test.cc",
|
||||||
|
"src/reader/spirv/parser_impl_handle_test.cc",
|
||||||
"src/reader/spirv/parser_impl_import_test.cc",
|
"src/reader/spirv/parser_impl_import_test.cc",
|
||||||
"src/reader/spirv/parser_impl_module_var_test.cc",
|
"src/reader/spirv/parser_impl_module_var_test.cc",
|
||||||
"src/reader/spirv/parser_impl_named_types_test.cc",
|
"src/reader/spirv/parser_impl_named_types_test.cc",
|
||||||
|
|
|
@ -450,6 +450,7 @@ if(${TINT_BUILD_SPV_READER})
|
||||||
reader/spirv/parser_impl_convert_type_test.cc
|
reader/spirv/parser_impl_convert_type_test.cc
|
||||||
reader/spirv/parser_impl_function_decl_test.cc
|
reader/spirv/parser_impl_function_decl_test.cc
|
||||||
reader/spirv/parser_impl_get_decorations_test.cc
|
reader/spirv/parser_impl_get_decorations_test.cc
|
||||||
|
reader/spirv/parser_impl_handle_test.cc
|
||||||
reader/spirv/parser_impl_import_test.cc
|
reader/spirv/parser_impl_import_test.cc
|
||||||
reader/spirv/parser_impl_module_var_test.cc
|
reader/spirv/parser_impl_module_var_test.cc
|
||||||
reader/spirv/parser_impl_named_types_test.cc
|
reader/spirv/parser_impl_named_types_test.cc
|
||||||
|
|
|
@ -1503,6 +1503,88 @@ bool ParserImpl::EmitFunctions() {
|
||||||
return success_;
|
return success_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const spvtools::opt::Instruction*
|
||||||
|
ParserImpl::GetMemoryObjectDeclarationForHandle(uint32_t id,
|
||||||
|
bool follow_image) {
|
||||||
|
auto local_fail = [this, id,
|
||||||
|
follow_image]() -> const spvtools::opt::Instruction* {
|
||||||
|
const auto* inst = def_use_mgr_->GetDef(id);
|
||||||
|
Fail() << "Could not find memory object declaration for the "
|
||||||
|
<< (follow_image ? "image" : "sampler") << " underlying id " << id
|
||||||
|
<< (inst ? inst->PrettyPrint() : std::string());
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto& memo_table =
|
||||||
|
(follow_image ? mem_obj_decl_image_ : mem_obj_decl_sampler_);
|
||||||
|
|
||||||
|
// Use a visited set to defend against bad input which might have long
|
||||||
|
// chains or even loops.
|
||||||
|
std::unordered_set<uint32_t> visited;
|
||||||
|
|
||||||
|
// Trace backward in the SSA data flow until we hit a memory object
|
||||||
|
// declaration.
|
||||||
|
while (true) {
|
||||||
|
auto where = memo_table.find(id);
|
||||||
|
if (where != memo_table.end()) {
|
||||||
|
return where->second;
|
||||||
|
}
|
||||||
|
// Protect against loops.
|
||||||
|
auto visited_iter = visited.find(id);
|
||||||
|
if (visited_iter != visited.end()) {
|
||||||
|
// We've hit a loop. Mark all the visited nodes
|
||||||
|
// as dead ends.
|
||||||
|
for (auto iter : visited) {
|
||||||
|
memo_table[iter] = nullptr;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
visited.insert(id);
|
||||||
|
|
||||||
|
const auto* inst = def_use_mgr_->GetDef(id);
|
||||||
|
if (inst == nullptr) {
|
||||||
|
return local_fail();
|
||||||
|
}
|
||||||
|
switch (inst->opcode()) {
|
||||||
|
case SpvOpFunctionParameter:
|
||||||
|
case SpvOpVariable:
|
||||||
|
// We found the memory object declaration.
|
||||||
|
// Remember it as the answer for the whole path.
|
||||||
|
for (auto iter : visited) {
|
||||||
|
memo_table[iter] = inst;
|
||||||
|
}
|
||||||
|
return inst;
|
||||||
|
case SpvOpLoad:
|
||||||
|
// Follow the pointer being loaded
|
||||||
|
id = inst->GetSingleWordInOperand(0);
|
||||||
|
break;
|
||||||
|
case SpvOpCopyObject:
|
||||||
|
// Follow the object being copied.
|
||||||
|
id = inst->GetSingleWordInOperand(0);
|
||||||
|
break;
|
||||||
|
case SpvOpAccessChain:
|
||||||
|
case SpvOpInBoundsAccessChain:
|
||||||
|
case SpvOpPtrAccessChain:
|
||||||
|
case SpvOpInBoundsPtrAccessChain:
|
||||||
|
// Follow the base pointer.
|
||||||
|
id = inst->GetSingleWordInOperand(0);
|
||||||
|
break;
|
||||||
|
case SpvOpSampledImage:
|
||||||
|
// Follow the image or the sampler, depending on the follow_image
|
||||||
|
// parameter.
|
||||||
|
id = inst->GetSingleWordInOperand(follow_image ? 0 : 1);
|
||||||
|
break;
|
||||||
|
case SpvOpImage:
|
||||||
|
// Follow the sampled image
|
||||||
|
id = inst->GetSingleWordInOperand(0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// This is not valid.
|
||||||
|
return local_fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace reader
|
} // namespace reader
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -375,6 +375,22 @@ class ParserImpl : Reader {
|
||||||
return scalar_spec_constants_.find(id) != scalar_spec_constants_.end();
|
return scalar_spec_constants_.find(id) != scalar_spec_constants_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For a SPIR-V ID that defines a sampler, image, or sampled image value,
|
||||||
|
/// return the SPIR-V instruction that represents the memory object
|
||||||
|
/// declaration for the object. If we encounter an OpSampledImage along the
|
||||||
|
/// way, follow the image operand when follow_image is true; otherwise follow
|
||||||
|
/// the sampler operand. Returns null and emits an error if it can't trace
|
||||||
|
/// back to a memory object declaration.
|
||||||
|
/// This method can be used any time after BuildInternalModule has been
|
||||||
|
/// invoked.
|
||||||
|
/// @param id the SPIR-V ID of the sampler, image, or sampled image
|
||||||
|
/// @param follow_image indicates whether to follow the image operand of
|
||||||
|
/// OpSampledImage
|
||||||
|
/// @returns the memory object declaration for the handle, or nullptr on error
|
||||||
|
const spvtools::opt::Instruction* GetMemoryObjectDeclarationForHandle(
|
||||||
|
uint32_t id,
|
||||||
|
bool follow_image);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Converts a specific SPIR-V type to a Tint type. Integer case
|
/// Converts a specific SPIR-V type to a Tint type. Integer case
|
||||||
ast::type::Type* ConvertType(const spvtools::opt::analysis::Integer* int_ty);
|
ast::type::Type* ConvertType(const spvtools::opt::analysis::Integer* int_ty);
|
||||||
|
@ -497,6 +513,18 @@ class ParserImpl : Reader {
|
||||||
// Maps function_id to a list of entrypoint information
|
// Maps function_id to a list of entrypoint information
|
||||||
std::unordered_map<uint32_t, std::vector<EntryPointInfo>>
|
std::unordered_map<uint32_t, std::vector<EntryPointInfo>>
|
||||||
function_to_ep_info_;
|
function_to_ep_info_;
|
||||||
|
|
||||||
|
// Maps from a SPIR-V ID to its underlying memory object declaration,
|
||||||
|
// following image paths. This a memoization table for
|
||||||
|
// GetMemoryObjectDeclarationForHandle. (A SPIR-V memory object declaration is
|
||||||
|
// an OpVariable or an OpFunctinParameter with pointer type).
|
||||||
|
std::unordered_map<uint32_t, const spvtools::opt::Instruction*>
|
||||||
|
mem_obj_decl_image_;
|
||||||
|
// Maps from a SPIR-V ID to its underlying memory object declaration,
|
||||||
|
// following sampler paths. This a memoization table for
|
||||||
|
// GetMemoryObjectDeclarationForHandle.
|
||||||
|
std::unordered_map<uint32_t, const spvtools::opt::Instruction*>
|
||||||
|
mem_obj_decl_sampler_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
|
|
|
@ -0,0 +1,749 @@
|
||||||
|
// 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 <string>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "src/reader/spirv/function.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::HasSubstr;
|
||||||
|
using ::testing::Not;
|
||||||
|
|
||||||
|
std::string Preamble() {
|
||||||
|
return R"(
|
||||||
|
OpCapability Shader
|
||||||
|
OpCapability Sampled1D
|
||||||
|
OpCapability Image1D
|
||||||
|
OpCapability StorageImageExtendedFormats
|
||||||
|
OpMemoryModel Logical Simple
|
||||||
|
)";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CommonTypes() {
|
||||||
|
return R"(
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%voidfn = OpTypeFunction %void
|
||||||
|
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%uint = OpTypeInt 32 0
|
||||||
|
%int = OpTypeInt 32 1
|
||||||
|
|
||||||
|
%uint_1 = OpConstant %uint 1
|
||||||
|
%uint_2 = OpConstant %uint 2
|
||||||
|
%uint_100 = OpConstant %uint 100
|
||||||
|
|
||||||
|
%v4uint = OpTypeVector %uint 4
|
||||||
|
%v4int = OpTypeVector %int 4
|
||||||
|
%v4float = OpTypeVector %float 4
|
||||||
|
|
||||||
|
; Define types for all sampler and texture types that can map to WGSL,
|
||||||
|
; modulo texel formats for storage textures. For now, we limit
|
||||||
|
; ourselves to 2-channel 32-bit texel formats.
|
||||||
|
|
||||||
|
; Because the SPIR-V reader also already generalizes so it can work with
|
||||||
|
; combined image-samplers, we also test that too.
|
||||||
|
|
||||||
|
%sampler = OpTypeSampler
|
||||||
|
|
||||||
|
; sampled images
|
||||||
|
%f_texture_1d = OpTypeImage %float 1D 0 0 0 1 Unknown
|
||||||
|
%f_texture_1d_array = OpTypeImage %float 1D 0 1 0 1 Unknown
|
||||||
|
%f_texture_2d = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||||
|
%f_texture_2d_ms = OpTypeImage %float 2D 0 0 1 1 Unknown
|
||||||
|
%f_texture_2d_array = OpTypeImage %float 2D 0 1 0 1 Unknown
|
||||||
|
%f_texture_2d_ms_array = OpTypeImage %float 2D 0 1 1 1 Unknown ; not in WebGPU
|
||||||
|
%f_texture_3d = OpTypeImage %float 3D 0 0 0 1 Unknown
|
||||||
|
%f_texture_cube = OpTypeImage %float Cube 0 0 0 1 Unknown
|
||||||
|
%f_texture_cube_array = OpTypeImage %float Cube 0 1 0 1 Unknown
|
||||||
|
|
||||||
|
; storage images
|
||||||
|
%f_storage_1d = OpTypeImage %float 1D 0 0 0 1 Rg32f
|
||||||
|
%f_storage_1d_array = OpTypeImage %float 1D 0 1 0 1 Rg32f
|
||||||
|
%f_storage_2d = OpTypeImage %float 2D 0 0 0 1 Rg32f
|
||||||
|
%f_storage_2d_array = OpTypeImage %float 2D 0 1 0 1 Rg32f
|
||||||
|
%f_storage_3d = OpTypeImage %float 3D 0 0 0 1 Rg32f
|
||||||
|
|
||||||
|
; Now all the same, but for unsigned integer sampled type.
|
||||||
|
|
||||||
|
%u_texture_1d = OpTypeImage %uint 1D 0 0 0 1 Unknown
|
||||||
|
%u_texture_1d_array = OpTypeImage %uint 1D 0 1 0 1 Unknown
|
||||||
|
%u_texture_2d = OpTypeImage %uint 2D 0 0 0 1 Unknown
|
||||||
|
%u_texture_2d_ms = OpTypeImage %uint 2D 0 0 1 1 Unknown
|
||||||
|
%u_texture_2d_array = OpTypeImage %uint 2D 0 1 0 1 Unknown
|
||||||
|
%u_texture_2d_ms_array = OpTypeImage %uint 2D 0 1 1 1 Unknown ; not in WebGPU
|
||||||
|
%u_texture_3d = OpTypeImage %uint 3D 0 0 0 1 Unknown
|
||||||
|
%u_texture_cube = OpTypeImage %uint Cube 0 0 0 1 Unknown
|
||||||
|
%u_texture_cube_array = OpTypeImage %uint Cube 0 1 0 1 Unknown
|
||||||
|
|
||||||
|
%u_storage_1d = OpTypeImage %uint 1D 0 0 0 1 Rg32ui
|
||||||
|
%u_storage_1d_array = OpTypeImage %uint 1D 0 1 0 1 Rg32ui
|
||||||
|
%u_storage_2d = OpTypeImage %uint 2D 0 0 0 1 Rg32ui
|
||||||
|
%u_storage_2d_array = OpTypeImage %uint 2D 0 1 0 1 Rg32ui
|
||||||
|
%u_storage_3d = OpTypeImage %uint 3D 0 0 0 1 Rg32ui
|
||||||
|
|
||||||
|
; Now all the same, but for signed integer sampled type.
|
||||||
|
|
||||||
|
%i_texture_1d = OpTypeImage %int 1D 0 0 0 1 Unknown
|
||||||
|
%i_texture_1d_array = OpTypeImage %int 1D 0 1 0 1 Unknown
|
||||||
|
%i_texture_2d = OpTypeImage %int 2D 0 0 0 1 Unknown
|
||||||
|
%i_texture_2d_ms = OpTypeImage %int 2D 0 0 1 1 Unknown
|
||||||
|
%i_texture_2d_array = OpTypeImage %int 2D 0 1 0 1 Unknown
|
||||||
|
%i_texture_2d_ms_array = OpTypeImage %int 2D 0 1 1 1 Unknown ; not in WebGPU
|
||||||
|
%i_texture_3d = OpTypeImage %int 3D 0 0 0 1 Unknown
|
||||||
|
%i_texture_cube = OpTypeImage %int Cube 0 0 0 1 Unknown
|
||||||
|
%i_texture_cube_array = OpTypeImage %int Cube 0 1 0 1 Unknown
|
||||||
|
|
||||||
|
%i_storage_1d = OpTypeImage %int 1D 0 0 0 1 Rg32i
|
||||||
|
%i_storage_1d_array = OpTypeImage %int 1D 0 1 0 1 Rg32i
|
||||||
|
%i_storage_2d = OpTypeImage %int 2D 0 0 0 1 Rg32i
|
||||||
|
%i_storage_2d_array = OpTypeImage %int 2D 0 1 0 1 Rg32i
|
||||||
|
%i_storage_3d = OpTypeImage %int 3D 0 0 0 1 Rg32i
|
||||||
|
|
||||||
|
;; Now pointers to each of the above, so we can declare variables for them.
|
||||||
|
|
||||||
|
%ptr_sampler = OpTypePointer UniformConstant %sampler
|
||||||
|
|
||||||
|
%ptr_f_texture_1d = OpTypePointer UniformConstant %f_texture_1d
|
||||||
|
%ptr_f_texture_1d_array = OpTypePointer UniformConstant %f_texture_1d_array
|
||||||
|
%ptr_f_texture_2d = OpTypePointer UniformConstant %f_texture_2d
|
||||||
|
%ptr_f_texture_2d_ms = OpTypePointer UniformConstant %f_texture_2d_ms
|
||||||
|
%ptr_f_texture_2d_array = OpTypePointer UniformConstant %f_texture_2d_array
|
||||||
|
%ptr_f_texture_2d_ms_array = OpTypePointer UniformConstant %f_texture_2d_ms_array
|
||||||
|
%ptr_f_texture_3d = OpTypePointer UniformConstant %f_texture_3d
|
||||||
|
%ptr_f_texture_cube = OpTypePointer UniformConstant %f_texture_cube
|
||||||
|
%ptr_f_texture_cube_array = OpTypePointer UniformConstant %f_texture_cube_array
|
||||||
|
|
||||||
|
; storage images
|
||||||
|
%ptr_f_storage_1d = OpTypePointer UniformConstant %f_storage_1d
|
||||||
|
%ptr_f_storage_1d_array = OpTypePointer UniformConstant %f_storage_1d_array
|
||||||
|
%ptr_f_storage_2d = OpTypePointer UniformConstant %f_storage_2d
|
||||||
|
%ptr_f_storage_2d_array = OpTypePointer UniformConstant %f_storage_2d_array
|
||||||
|
%ptr_f_storage_3d = OpTypePointer UniformConstant %f_storage_3d
|
||||||
|
|
||||||
|
; Now all the same, but for unsigned integer sampled type.
|
||||||
|
|
||||||
|
%ptr_u_texture_1d = OpTypePointer UniformConstant %u_texture_1d
|
||||||
|
%ptr_u_texture_1d_array = OpTypePointer UniformConstant %u_texture_1d_array
|
||||||
|
%ptr_u_texture_2d = OpTypePointer UniformConstant %u_texture_2d
|
||||||
|
%ptr_u_texture_2d_ms = OpTypePointer UniformConstant %u_texture_2d_ms
|
||||||
|
%ptr_u_texture_2d_array = OpTypePointer UniformConstant %u_texture_2d_array
|
||||||
|
%ptr_u_texture_2d_ms_array = OpTypePointer UniformConstant %u_texture_2d_ms_array
|
||||||
|
%ptr_u_texture_3d = OpTypePointer UniformConstant %u_texture_3d
|
||||||
|
%ptr_u_texture_cube = OpTypePointer UniformConstant %u_texture_cube
|
||||||
|
%ptr_u_texture_cube_array = OpTypePointer UniformConstant %u_texture_cube_array
|
||||||
|
|
||||||
|
%ptr_u_storage_1d = OpTypePointer UniformConstant %u_storage_1d
|
||||||
|
%ptr_u_storage_1d_array = OpTypePointer UniformConstant %u_storage_1d_array
|
||||||
|
%ptr_u_storage_2d = OpTypePointer UniformConstant %u_storage_2d
|
||||||
|
%ptr_u_storage_2d_array = OpTypePointer UniformConstant %u_storage_2d_array
|
||||||
|
%ptr_u_storage_3d = OpTypePointer UniformConstant %u_storage_3d
|
||||||
|
|
||||||
|
; Now all the same, but for signed integer sampled type.
|
||||||
|
|
||||||
|
%ptr_i_texture_1d = OpTypePointer UniformConstant %i_texture_1d
|
||||||
|
%ptr_i_texture_1d_array = OpTypePointer UniformConstant %i_texture_1d_array
|
||||||
|
%ptr_i_texture_2d = OpTypePointer UniformConstant %i_texture_2d
|
||||||
|
%ptr_i_texture_2d_ms = OpTypePointer UniformConstant %i_texture_2d_ms
|
||||||
|
%ptr_i_texture_2d_array = OpTypePointer UniformConstant %i_texture_2d_array
|
||||||
|
%ptr_i_texture_2d_ms_array = OpTypePointer UniformConstant %i_texture_2d_ms_array
|
||||||
|
%ptr_i_texture_3d = OpTypePointer UniformConstant %i_texture_3d
|
||||||
|
%ptr_i_texture_cube = OpTypePointer UniformConstant %i_texture_cube
|
||||||
|
%ptr_i_texture_cube_array = OpTypePointer UniformConstant %i_texture_cube_array
|
||||||
|
|
||||||
|
%ptr_i_storage_1d = OpTypePointer UniformConstant %i_storage_1d
|
||||||
|
%ptr_i_storage_1d_array = OpTypePointer UniformConstant %i_storage_1d_array
|
||||||
|
%ptr_i_storage_2d = OpTypePointer UniformConstant %i_storage_2d
|
||||||
|
%ptr_i_storage_2d_array = OpTypePointer UniformConstant %i_storage_2d_array
|
||||||
|
%ptr_i_storage_3d = OpTypePointer UniformConstant %i_storage_3d
|
||||||
|
|
||||||
|
)";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetMemoryObjectDeclarationForHandle_Variable_Direct) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%10 = OpVariable %ptr_sampler UniformConstant
|
||||||
|
%20 = OpVariable %ptr_f_texture_1d UniformConstant
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(10, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(20, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest,
|
||||||
|
GetMemoryObjectDeclarationForHandle_Variable_AccessChain) {
|
||||||
|
// Show that we would generalize to arrays of handles, even though that
|
||||||
|
// is not supported in WGSL MVP.
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
|
||||||
|
%sampler_array = OpTypeArray %sampler %uint_100
|
||||||
|
%image_array = OpTypeArray %f_texture_1d %uint_100
|
||||||
|
|
||||||
|
%ptr_sampler_array = OpTypePointer UniformConstant %sampler_array
|
||||||
|
%ptr_image_array = OpTypePointer UniformConstant %image_array
|
||||||
|
|
||||||
|
%10 = OpVariable %ptr_sampler_array UniformConstant
|
||||||
|
%20 = OpVariable %ptr_image_array UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpAccessChain %ptr_sampler %10 %uint_1
|
||||||
|
%120 = OpAccessChain %ptr_f_texture_1d %20 %uint_2
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest,
|
||||||
|
GetMemoryObjectDeclarationForHandle_Variable_InBoundsAccessChain) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
|
||||||
|
%sampler_array = OpTypeArray %sampler %uint_100
|
||||||
|
%image_array = OpTypeArray %f_texture_1d %uint_100
|
||||||
|
|
||||||
|
%ptr_sampler_array = OpTypePointer UniformConstant %sampler_array
|
||||||
|
%ptr_image_array = OpTypePointer UniformConstant %image_array
|
||||||
|
|
||||||
|
%10 = OpVariable %ptr_sampler_array UniformConstant
|
||||||
|
%20 = OpVariable %ptr_image_array UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpInBoundsAccessChain %ptr_sampler %10 %uint_1
|
||||||
|
%120 = OpInBoundsAccessChain %ptr_f_texture_1d %20 %uint_2
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest,
|
||||||
|
GetMemoryObjectDeclarationForHandle_Variable_PtrAccessChain) {
|
||||||
|
// Show that we would generalize to arrays of handles, even though that
|
||||||
|
// is not supported in WGSL MVP.
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
|
||||||
|
%sampler_array = OpTypeArray %sampler %uint_100
|
||||||
|
%image_array = OpTypeArray %f_texture_1d %uint_100
|
||||||
|
|
||||||
|
%ptr_sampler_array = OpTypePointer UniformConstant %sampler_array
|
||||||
|
%ptr_image_array = OpTypePointer UniformConstant %image_array
|
||||||
|
|
||||||
|
%10 = OpVariable %ptr_sampler_array UniformConstant
|
||||||
|
%20 = OpVariable %ptr_image_array UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpPtrAccessChain %ptr_sampler %10 %uint_1 %uint_1
|
||||||
|
%120 = OpPtrAccessChain %ptr_f_texture_1d %20 %uint_1 %uint_2
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest,
|
||||||
|
GetMemoryObjectDeclarationForHandle_Variable_InBoundsPtrAccessChain) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
|
||||||
|
%sampler_array = OpTypeArray %sampler %uint_100
|
||||||
|
%image_array = OpTypeArray %f_texture_1d %uint_100
|
||||||
|
|
||||||
|
%ptr_sampler_array = OpTypePointer UniformConstant %sampler_array
|
||||||
|
%ptr_image_array = OpTypePointer UniformConstant %image_array
|
||||||
|
|
||||||
|
%10 = OpVariable %ptr_sampler_array UniformConstant
|
||||||
|
%20 = OpVariable %ptr_image_array UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpInBoundsPtrAccessChain %ptr_sampler %10 %uint_1 %uint_1
|
||||||
|
%120 = OpInBoundsPtrAccessChain %ptr_f_texture_1d %20 %uint_1 %uint_2
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetMemoryObjectDeclarationForHandle_Variable_CopyObject) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
|
||||||
|
%10 = OpVariable %ptr_sampler UniformConstant
|
||||||
|
%20 = OpVariable %ptr_f_texture_1d UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpCopyObject %ptr_sampler %10
|
||||||
|
%120 = OpCopyObject %ptr_f_texture_1d %20
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetMemoryObjectDeclarationForHandle_Variable_Load) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
|
||||||
|
%10 = OpVariable %ptr_sampler UniformConstant
|
||||||
|
%20 = OpVariable %ptr_f_texture_1d UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpLoad %sampler %10
|
||||||
|
%120 = OpLoad %f_texture_1d %20
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest,
|
||||||
|
GetMemoryObjectDeclarationForHandle_Variable_SampledImage) {
|
||||||
|
// Trace through the sampled image instruction, but in two different
|
||||||
|
// directions.
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%sampled_image_type = OpTypeSampledImage %f_texture_1d
|
||||||
|
|
||||||
|
%10 = OpVariable %ptr_sampler UniformConstant
|
||||||
|
%20 = OpVariable %ptr_f_texture_1d UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%s = OpLoad %sampler %10
|
||||||
|
%im = OpLoad %f_texture_1d %20
|
||||||
|
%100 = OpSampledImage %sampled_image_type %im %s
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(100, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(100, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetMemoryObjectDeclarationForHandle_Variable_Image) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%sampled_image_type = OpTypeSampledImage %f_texture_1d
|
||||||
|
|
||||||
|
%10 = OpVariable %ptr_sampler UniformConstant
|
||||||
|
%20 = OpVariable %ptr_f_texture_1d UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%s = OpLoad %sampler %10
|
||||||
|
%im = OpLoad %f_texture_1d %20
|
||||||
|
%100 = OpSampledImage %sampled_image_type %im %s
|
||||||
|
%200 = OpImage %im %100
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(200, true);
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetMemoryObjectDeclarationForHandle_FuncParam_Direct) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%fty = OpTypeFunction %void %ptr_sampler %ptr_f_texture_1d
|
||||||
|
|
||||||
|
%func = OpFunction %void None %fty
|
||||||
|
%10 = OpFunctionParameter %ptr_sampler
|
||||||
|
%20 = OpFunctionParameter %ptr_f_texture_1d
|
||||||
|
%entry = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(10, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(20, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest,
|
||||||
|
GetMemoryObjectDeclarationForHandle_FuncParam_AccessChain) {
|
||||||
|
// Show that we would generalize to arrays of handles, even though that
|
||||||
|
// is not supported in WGSL MVP.
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%sampler_array = OpTypeArray %sampler %uint_100
|
||||||
|
%image_array = OpTypeArray %f_texture_1d %uint_100
|
||||||
|
|
||||||
|
%ptr_sampler_array = OpTypePointer UniformConstant %sampler_array
|
||||||
|
%ptr_image_array = OpTypePointer UniformConstant %image_array
|
||||||
|
|
||||||
|
%fty = OpTypeFunction %void %ptr_sampler_array %ptr_image_array
|
||||||
|
|
||||||
|
%func = OpFunction %void None %fty
|
||||||
|
%10 = OpFunctionParameter %ptr_sampler_array
|
||||||
|
%20 = OpFunctionParameter %ptr_image_array
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpAccessChain %ptr_sampler %10 %uint_1
|
||||||
|
%120 = OpAccessChain %ptr_f_texture_1d %20 %uint_2
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest,
|
||||||
|
GetMemoryObjectDeclarationForHandle_FuncParam_InBoundsAccessChain) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%sampler_array = OpTypeArray %sampler %uint_100
|
||||||
|
%image_array = OpTypeArray %f_texture_1d %uint_100
|
||||||
|
|
||||||
|
%ptr_sampler_array = OpTypePointer UniformConstant %sampler_array
|
||||||
|
%ptr_image_array = OpTypePointer UniformConstant %image_array
|
||||||
|
|
||||||
|
%fty = OpTypeFunction %void %ptr_sampler_array %ptr_image_array
|
||||||
|
|
||||||
|
%func = OpFunction %void None %fty
|
||||||
|
%10 = OpFunctionParameter %ptr_sampler_array
|
||||||
|
%20 = OpFunctionParameter %ptr_image_array
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpInBoundsAccessChain %ptr_sampler %10 %uint_1
|
||||||
|
%120 = OpInBoundsAccessChain %ptr_f_texture_1d %20 %uint_2
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest,
|
||||||
|
GetMemoryObjectDeclarationForHandle_FuncParam_PtrAccessChain) {
|
||||||
|
// Show that we would generalize to arrays of handles, even though that
|
||||||
|
// is not supported in WGSL MVP.
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%sampler_array = OpTypeArray %sampler %uint_100
|
||||||
|
%image_array = OpTypeArray %f_texture_1d %uint_100
|
||||||
|
|
||||||
|
%ptr_sampler_array = OpTypePointer UniformConstant %sampler_array
|
||||||
|
%ptr_image_array = OpTypePointer UniformConstant %image_array
|
||||||
|
|
||||||
|
%fty = OpTypeFunction %void %ptr_sampler_array %ptr_image_array
|
||||||
|
|
||||||
|
%func = OpFunction %void None %fty
|
||||||
|
%10 = OpFunctionParameter %ptr_sampler_array
|
||||||
|
%20 = OpFunctionParameter %ptr_image_array
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpPtrAccessChain %ptr_sampler %10 %uint_1 %uint_1
|
||||||
|
%120 = OpPtrAccessChain %ptr_f_texture_1d %20 %uint_1 %uint_2
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest,
|
||||||
|
GetMemoryObjectDeclarationForHandle_FuncParam_InBoundsPtrAccessChain) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%sampler_array = OpTypeArray %sampler %uint_100
|
||||||
|
%image_array = OpTypeArray %f_texture_1d %uint_100
|
||||||
|
|
||||||
|
%ptr_sampler_array = OpTypePointer UniformConstant %sampler_array
|
||||||
|
%ptr_image_array = OpTypePointer UniformConstant %image_array
|
||||||
|
|
||||||
|
%fty = OpTypeFunction %void %ptr_sampler_array %ptr_image_array
|
||||||
|
|
||||||
|
%func = OpFunction %void None %fty
|
||||||
|
%10 = OpFunctionParameter %ptr_sampler_array
|
||||||
|
%20 = OpFunctionParameter %ptr_image_array
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpInBoundsPtrAccessChain %ptr_sampler %10 %uint_1 %uint_1
|
||||||
|
%120 = OpInBoundsPtrAccessChain %ptr_f_texture_1d %20 %uint_1 %uint_2
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest,
|
||||||
|
GetMemoryObjectDeclarationForHandle_FuncParam_CopyObject) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%fty = OpTypeFunction %void %ptr_sampler %ptr_f_texture_1d
|
||||||
|
|
||||||
|
%func = OpFunction %void None %fty
|
||||||
|
%10 = OpFunctionParameter %ptr_sampler
|
||||||
|
%20 = OpFunctionParameter %ptr_f_texture_1d
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpCopyObject %ptr_sampler %10
|
||||||
|
%120 = OpCopyObject %ptr_f_texture_1d %20
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetMemoryObjectDeclarationForHandle_FuncParam_Load) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%fty = OpTypeFunction %void %ptr_sampler %ptr_f_texture_1d
|
||||||
|
|
||||||
|
%func = OpFunction %void None %fty
|
||||||
|
%10 = OpFunctionParameter %ptr_sampler
|
||||||
|
%20 = OpFunctionParameter %ptr_f_texture_1d
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%110 = OpLoad %sampler %10
|
||||||
|
%120 = OpLoad %f_texture_1d %20
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(110, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(120, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest,
|
||||||
|
GetMemoryObjectDeclarationForHandle_FuncParam_SampledImage) {
|
||||||
|
// Trace through the sampled image instruction, but in two different
|
||||||
|
// directions.
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%sampled_image_type = OpTypeSampledImage %f_texture_1d
|
||||||
|
|
||||||
|
%fty = OpTypeFunction %void %ptr_sampler %ptr_f_texture_1d
|
||||||
|
|
||||||
|
%func = OpFunction %void None %fty
|
||||||
|
%10 = OpFunctionParameter %ptr_sampler
|
||||||
|
%20 = OpFunctionParameter %ptr_f_texture_1d
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%s = OpLoad %sampler %10
|
||||||
|
%im = OpLoad %f_texture_1d %20
|
||||||
|
%100 = OpSampledImage %sampled_image_type %im %s
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
const auto* sampler = p->GetMemoryObjectDeclarationForHandle(100, false);
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(100, true);
|
||||||
|
|
||||||
|
ASSERT_TRUE(sampler != nullptr);
|
||||||
|
EXPECT_EQ(sampler->result_id(), 10u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GetMemoryObjectDeclarationForHandle_FuncParam_Image) {
|
||||||
|
const auto assembly = Preamble() + CommonTypes() + R"(
|
||||||
|
%sampled_image_type = OpTypeSampledImage %f_texture_1d
|
||||||
|
|
||||||
|
%fty = OpTypeFunction %void %ptr_sampler %ptr_f_texture_1d
|
||||||
|
|
||||||
|
%func = OpFunction %void None %fty
|
||||||
|
%10 = OpFunctionParameter %ptr_sampler
|
||||||
|
%20 = OpFunctionParameter %ptr_f_texture_1d
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%s = OpLoad %sampler %10
|
||||||
|
%im = OpLoad %f_texture_1d %20
|
||||||
|
%100 = OpSampledImage %sampled_image_type %im %s
|
||||||
|
%200 = OpImage %im %100
|
||||||
|
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildInternalModule());
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
|
||||||
|
const auto* image = p->GetMemoryObjectDeclarationForHandle(200, true);
|
||||||
|
ASSERT_TRUE(image != nullptr);
|
||||||
|
EXPECT_EQ(image->result_id(), 20u);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace spirv
|
||||||
|
} // namespace reader
|
||||||
|
} // namespace tint
|
Loading…
Reference in New Issue