spirv-reader: refactor getting image, sampler
Change-Id: I6620781f620067e4df8f7e39f2bb2a80b32f9ecf
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/38180
Auto-Submit: David Neto <dneto@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: David Neto <dneto@google.com>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 30daec5..41fb4bf 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -4019,35 +4019,82 @@
return parser_impl_.GetSourceForInst(&inst);
}
-bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
- uint32_t arg_index = 0; // The SPIR-V input argument index
- ast::ExpressionList params;
-
- const auto image_or_sampled_image_operand_id =
- inst.GetSingleWordInOperand(arg_index);
- // Form the texture operand.
+const spvtools::opt::Instruction* FunctionEmitter::GetImage(
+ const spvtools::opt::Instruction& inst) {
+ if (inst.NumInOperands() == 0) {
+ Fail() << "not an image access instruction: " << inst.PrettyPrint();
+ return nullptr;
+ }
+ // The image or sampled image operand is always the first operand.
+ const auto image_or_sampled_image_operand_id = inst.GetSingleWordInOperand(0);
const auto* image = parser_impl_.GetMemoryObjectDeclarationForHandle(
image_or_sampled_image_operand_id, true);
if (!image) {
- return Fail() << "internal error: couldn't find image for "
- << inst.PrettyPrint();
+ Fail() << "internal error: couldn't find image for " << inst.PrettyPrint();
+ return nullptr;
+ }
+ return image;
+}
+
+type::Texture* FunctionEmitter::GetImageType(
+ const spvtools::opt::Instruction& image) {
+ type::Pointer* ptr_type = parser_impl_.GetTypeForHandleVar(image);
+ if (!parser_impl_.success()) {
+ Fail();
+ return nullptr;
+ }
+ if (!ptr_type || !ptr_type->type()->UnwrapAll()->Is<type::Texture>()) {
+ Fail() << "invalid texture type for " << image.PrettyPrint();
+ return nullptr;
+ }
+ return As<type::Texture>(ptr_type->type()->UnwrapAll());
+}
+
+ast::Expression* FunctionEmitter::GetImageExpression(
+ const spvtools::opt::Instruction& inst) {
+ auto* image = GetImage(inst);
+ if (!image) {
+ return nullptr;
}
auto name = namer_.Name(image->result_id());
- params.push_back(create<ast::IdentifierExpression>(
- Source{}, ast_module_.RegisterSymbol(name)));
+ return create<ast::IdentifierExpression>(GetSourceForInst(inst),
+ ast_module_.RegisterSymbol(name));
+}
+ast::Expression* FunctionEmitter::GetSamplerExpression(
+ const spvtools::opt::Instruction& inst) {
+ // The sampled image operand is always the first operand.
+ const auto image_or_sampled_image_operand_id = inst.GetSingleWordInOperand(0);
+ const auto* image = parser_impl_.GetMemoryObjectDeclarationForHandle(
+ image_or_sampled_image_operand_id, false);
+ if (!image) {
+ Fail() << "internal error: couldn't find sampler for "
+ << inst.PrettyPrint();
+ return nullptr;
+ }
+ auto name = namer_.Name(image->result_id());
+ return create<ast::IdentifierExpression>(GetSourceForInst(inst),
+ ast_module_.RegisterSymbol(name));
+}
+
+bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
+ ast::ExpressionList params;
const auto opcode = inst.opcode();
+
+ // Form the texture operand.
+ const spvtools::opt::Instruction* image = GetImage(inst);
+ if (!image) {
+ return false;
+ }
+ params.push_back(GetImageExpression(inst));
+
if (IsSampledImageAccess(opcode)) {
// Form the sampler operand.
- const auto* sampler = parser_impl_.GetMemoryObjectDeclarationForHandle(
- image_or_sampled_image_operand_id, false);
- if (!sampler) {
- return Fail() << "internal error: couldn't find sampler for "
- << inst.PrettyPrint();
+ if (auto* sampler = GetSamplerExpression(inst)) {
+ params.push_back(sampler);
+ } else {
+ return false;
}
- auto param_name = namer_.Name(sampler->result_id());
- params.push_back(create<ast::IdentifierExpression>(
- Source{}, ast_module_.RegisterSymbol(param_name)));
}
type::Pointer* texture_ptr_type = parser_impl_.GetTypeForHandleVar(*image);
@@ -4060,8 +4107,8 @@
return Fail();
}
- // We're done with the first SPIR-V operand. Move on to the next.
- arg_index++;
+ // This is the SPIR-V operand index. We're done with the first operand.
+ uint32_t arg_index = 1;
// Push the coordinates operands.
auto coords = MakeCoordinateOperandsForImageAccess(inst);
@@ -4291,16 +4338,8 @@
Fail();
return {};
}
- if (inst.NumInOperands() == 0) {
- Fail() << "internal error: not an image access instruction: "
- << inst.PrettyPrint();
- return {};
- }
- const auto sampled_image_id = inst.GetSingleWordInOperand(0);
- const auto* image =
- parser_impl_.GetMemoryObjectDeclarationForHandle(sampled_image_id, true);
+ const spvtools::opt::Instruction* image = GetImage(inst);
if (!image) {
- Fail() << "internal error: couldn't find image for " << inst.PrettyPrint();
return {};
}
if (image->NumInOperands() < 1) {
@@ -4325,24 +4364,18 @@
if (!raw_coords.type) {
return {};
}
- type::Pointer* type = parser_impl_.GetTypeForHandleVar(*image);
- if (!parser_impl_.success()) {
- Fail();
+ type::Texture* texture_type = GetImageType(*image);
+ if (!texture_type) {
return {};
}
- if (!type || !type->type()->UnwrapAll()->Is<type::Texture>()) {
- Fail() << "invalid texture type for " << image->PrettyPrint();
- return {};
- }
-
- auto* unwrapped_type = type->type()->UnwrapAll();
- type::TextureDimension dim = unwrapped_type->As<type::Texture>()->dim();
+ type::TextureDimension dim = texture_type->dim();
// Number of regular coordinates.
uint32_t num_axes = type::NumCoordinateAxes(dim);
bool is_arrayed = type::IsTextureArray(dim);
if ((num_axes == 0) || (num_axes > 3)) {
- Fail() << "unsupported image dimensionality for " << type->type_name()
- << " prompted by " << inst.PrettyPrint();
+ Fail() << "unsupported image dimensionality for "
+ << texture_type->type_name() << " prompted by "
+ << inst.PrettyPrint();
}
const auto num_coords_required = num_axes + (is_arrayed ? 1 : 0);
uint32_t num_coords_supplied = 0;
diff --git a/src/reader/spirv/function.h b/src/reader/spirv/function.h
index b2206fd..6650059 100644
--- a/src/reader/spirv/function.h
+++ b/src/reader/spirv/function.h
@@ -42,6 +42,7 @@
#include "src/reader/spirv/namer.h"
#include "src/reader/spirv/parser_impl.h"
#include "src/type/i32_type.h"
+#include "src/type/texture_type.h"
namespace tint {
namespace reader {
@@ -856,6 +857,31 @@
/// @returns an expression
TypedExpression MakeOuterProduct(const spvtools::opt::Instruction& inst);
+ /// Get the SPIR-V instruction for the image memory object declaration for
+ /// the image operand to the given instruction.
+ /// @param inst the SPIR-V instruction
+ /// @returns a SPIR-V OpVariable or OpFunctionParameter instruction, or null
+ /// on error
+ const spvtools::opt::Instruction* GetImage(
+ const spvtools::opt::Instruction& inst);
+
+ /// Get the AST texture the SPIR-V image memory object declaration.
+ /// @param inst the SPIR-V memory object declaration for the image.
+ /// @returns a texture type, or null on error
+ type::Texture* GetImageType(const spvtools::opt::Instruction& inst);
+
+ /// Get the expression for the image operand from the first operand to the
+ /// given instruction.
+ /// @param inst the SPIR-V instruction
+ /// @returns an identifier expression, or null on error
+ ast::Expression* GetImageExpression(const spvtools::opt::Instruction& inst);
+
+ /// Get the expression for the sampler operand from the first operand to the
+ /// given instruction.
+ /// @param inst the SPIR-V instruction
+ /// @returns an identifier expression, or null on error
+ ast::Expression* GetSamplerExpression(const spvtools::opt::Instruction& inst);
+
/// Emits a texture builtin function call for a SPIR-V instruction that
/// accesses an image or sampled image.
/// @param inst the SPIR-V instruction
diff --git a/src/reader/spirv/parser_impl_handle_test.cc b/src/reader/spirv/parser_impl_handle_test.cc
index 8c4d6da..8844c6c 100644
--- a/src/reader/spirv/parser_impl_handle_test.cc
+++ b/src/reader/spirv/parser_impl_handle_test.cc
@@ -4282,8 +4282,7 @@
::testing::ValuesIn(std::vector<ImageCoordsCase>{
{"%float 1D 0 0 0 1 Unknown",
"OpNop",
- "internal error: not an image access "
- "instruction: OpNop",
+ "not an image access instruction: OpNop",
{}},
{"%float 1D 0 0 0 1 Unknown",
"%50 = OpCopyObject %float %float_1",