From dd84769c55d1794ce9df2238fd7be30f9aa01379 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Tue, 28 Dec 2021 22:14:11 +0800 Subject: [PATCH] glsl: ir_texture support sprase texture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sparse ir_texture will set is_sparse and use struct type to hold both residency code and sampled texel. Reviewed-by: Marek Olšák Signed-off-by: Qiang Yu Part-of: --- src/compiler/glsl/ir.cpp | 11 ++++++++- src/compiler/glsl/ir.h | 31 ++++++++++++++----------- src/compiler/glsl/ir_clone.cpp | 2 +- src/compiler/glsl/ir_equals.cpp | 3 +++ src/compiler/glsl/ir_print_visitor.cpp | 3 +++ src/compiler/glsl/ir_reader.cpp | 32 +++++++++++++++++++++----- 6 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/compiler/glsl/ir.cpp b/src/compiler/glsl/ir.cpp index f9e9c321db4..2035aef1e59 100644 --- a/src/compiler/glsl/ir.cpp +++ b/src/compiler/glsl/ir.cpp @@ -1807,7 +1807,16 @@ ir_texture::set_sampler(ir_dereference *sampler, const glsl_type *type) assert(sampler != NULL); assert(type != NULL); this->sampler = sampler; - this->type = type; + + if (this->is_sparse) { + /* code holds residency info */ + glsl_struct_field fields[2] = { + glsl_struct_field(glsl_type::int_type, "code"), + glsl_struct_field(type, "texel"), + }; + this->type = glsl_type::get_struct_instance(fields, 2, "struct"); + } else + this->type = type; if (this->op == ir_txs || this->op == ir_query_levels || this->op == ir_texture_samples) { diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h index a22c27348d2..de61e149278 100644 --- a/src/compiler/glsl/ir.h +++ b/src/compiler/glsl/ir.h @@ -1878,30 +1878,30 @@ enum ir_texture_opcode { * selected from \c ir_texture_opcodes. In the printed IR, these will * appear as: * - * Texel offset (0 or an expression) - * | Projection divisor - * | | Shadow comparator - * | | | - * v v v - * (tex 0 1 ( )) - * (txb 0 1 ( ) ) - * (txl 0 1 ( ) ) - * (txd 0 1 ( ) (dPdx dPdy)) - * (txf 0 ) + * Texel offset (0 or an expression) + * | Projection divisor + * | | Shadow comparator + * | | | + * v v v + * (tex 0 1 ( )) + * (txb 0 1 ( ) ) + * (txl 0 1 ( ) ) + * (txd 0 1 ( ) (dPdx dPdy)) + * (txf 0 ) * (txf_ms - * ) + * ) * (txs ) * (lod ) - * (tg4 ) + * (tg4 ) * (query_levels ) * (samples_identical ) */ class ir_texture : public ir_rvalue { public: - ir_texture(enum ir_texture_opcode op) + ir_texture(enum ir_texture_opcode op, bool sparse = false) : ir_rvalue(ir_type_texture), op(op), sampler(NULL), coordinate(NULL), projector(NULL), - shadow_comparator(NULL), offset(NULL) + shadow_comparator(NULL), offset(NULL), is_sparse(sparse) { memset(&lod_info, 0, sizeof(lod_info)); } @@ -1972,6 +1972,9 @@ public: ir_rvalue *dPdy; /**< Partial derivative of coordinate wrt Y */ } grad; } lod_info; + + /* Whether a sparse texture */ + bool is_sparse; }; diff --git a/src/compiler/glsl/ir_clone.cpp b/src/compiler/glsl/ir_clone.cpp index a64e88b3d63..857a1b85d96 100644 --- a/src/compiler/glsl/ir_clone.cpp +++ b/src/compiler/glsl/ir_clone.cpp @@ -210,7 +210,7 @@ ir_dereference_record::clone(void *mem_ctx, struct hash_table *ht) const ir_texture * ir_texture::clone(void *mem_ctx, struct hash_table *ht) const { - ir_texture *new_tex = new(mem_ctx) ir_texture(this->op); + ir_texture *new_tex = new(mem_ctx) ir_texture(this->op, this->is_sparse); new_tex->type = this->type; new_tex->sampler = this->sampler->clone(mem_ctx, ht); diff --git a/src/compiler/glsl/ir_equals.cpp b/src/compiler/glsl/ir_equals.cpp index f7359e23904..8ad6fa93f64 100644 --- a/src/compiler/glsl/ir_equals.cpp +++ b/src/compiler/glsl/ir_equals.cpp @@ -137,6 +137,9 @@ ir_texture::equals(const ir_instruction *ir, enum ir_node_type ignore) const if (op != other->op) return false; + if (is_sparse != other->is_sparse) + return false; + if (!possibly_null_equals(coordinate, other->coordinate, ignore)) return false; diff --git a/src/compiler/glsl/ir_print_visitor.cpp b/src/compiler/glsl/ir_print_visitor.cpp index c228493e708..3da0abede14 100644 --- a/src/compiler/glsl/ir_print_visitor.cpp +++ b/src/compiler/glsl/ir_print_visitor.cpp @@ -321,6 +321,9 @@ void ir_print_visitor::visit(ir_texture *ir) fprintf(f, " "); + if (ir->op != ir_lod && ir->op != ir_samples_identical) + fprintf(f, "%d ", ir->is_sparse); + if (ir->offset != NULL) { ir->offset->accept(this); } else { diff --git a/src/compiler/glsl/ir_reader.cpp b/src/compiler/glsl/ir_reader.cpp index d4f0e58b155..c7eb5624c3a 100644 --- a/src/compiler/glsl/ir_reader.cpp +++ b/src/compiler/glsl/ir_reader.cpp @@ -936,6 +936,7 @@ ir_texture * ir_reader::read_texture(s_expression *expr) { s_symbol *tag = NULL; + s_expression *s_sparse = NULL; s_expression *s_type = NULL; s_expression *s_sampler = NULL; s_expression *s_coord = NULL; @@ -949,23 +950,23 @@ ir_reader::read_texture(s_expression *expr) ir_texture_opcode op = ir_tex; /* silence warning */ s_pattern tex_pattern[] = - { "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow }; + { "tex", s_type, s_sampler, s_coord, s_sparse, s_offset, s_proj, s_shadow }; s_pattern lod_pattern[] = { "lod", s_type, s_sampler, s_coord }; s_pattern txf_pattern[] = - { "txf", s_type, s_sampler, s_coord, s_offset, s_lod }; + { "txf", s_type, s_sampler, s_coord, s_sparse, s_offset, s_lod }; s_pattern txf_ms_pattern[] = - { "txf_ms", s_type, s_sampler, s_coord, s_sample_index }; + { "txf_ms", s_type, s_sampler, s_coord, s_sparse, s_sample_index }; s_pattern txs_pattern[] = { "txs", s_type, s_sampler, s_lod }; s_pattern tg4_pattern[] = - { "tg4", s_type, s_sampler, s_coord, s_offset, s_component }; + { "tg4", s_type, s_sampler, s_coord, s_sparse, s_offset, s_component }; s_pattern query_levels_pattern[] = { "query_levels", s_type, s_sampler }; s_pattern texture_samples_pattern[] = { "samples", s_type, s_sampler }; s_pattern other_pattern[] = - { tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod }; + { tag, s_type, s_sampler, s_coord, s_sparse, s_offset, s_proj, s_shadow, s_lod }; if (MATCH(expr, lod_pattern)) { op = ir_lod; @@ -992,7 +993,17 @@ ir_reader::read_texture(s_expression *expr) return NULL; } - ir_texture *tex = new(mem_ctx) ir_texture(op); + bool is_sparse = false; + if (s_sparse) { + s_int *sparse = SX_AS_INT(s_sparse); + if (sparse == NULL) { + ir_read_error(NULL, "when reading sparse"); + return NULL; + } + is_sparse = sparse->value(); + } + + ir_texture *tex = new(mem_ctx) ir_texture(op, is_sparse); // Read return type const glsl_type *type = read_type(s_type); @@ -1009,6 +1020,15 @@ ir_reader::read_texture(s_expression *expr) tex->opcode_string()); return NULL; } + + if (is_sparse) { + const glsl_type *texel = type->field_type("texel"); + if (texel == glsl_type::error_type) { + ir_read_error(NULL, "invalid type for sparse texture"); + return NULL; + } + type = texel; + } tex->set_sampler(sampler, type); if (op != ir_txs) {