Mesa (master): zink: handle dynamic sampler array indexing for arb_gpu_shader5
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon Jan 4 15:10:13 UTC 2021
Module: Mesa
Branch: master
Commit: 9c18491e4104a2d31992fb0e1304136b21e8e463
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=9c18491e4104a2d31992fb0e1304136b21e8e463
Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date: Tue Jul 28 14:50:45 2020 -0400
zink: handle dynamic sampler array indexing for arb_gpu_shader5
this requires that arrays of samplers be declared as single variables with
a single binding point, which is then propagated through to the descriptor
set updates
constant sampler array indexing is now un-lowered during access so we can
construct an access chain for both constant and dynamic offset paths
Reviewed-by: Erik Faye-Lund <erik.faye-lund at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8155>
---
.../drivers/zink/nir_to_spirv/nir_to_spirv.c | 115 +++++++++++----------
src/gallium/drivers/zink/zink_compiler.c | 29 ++----
src/gallium/drivers/zink/zink_compiler.h | 1 +
src/gallium/drivers/zink/zink_draw.c | 58 ++++++-----
src/gallium/drivers/zink/zink_program.c | 2 +-
5 files changed, 103 insertions(+), 102 deletions(-)
diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
index f7501d316bb..4c1af8192bb 100644
--- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
+++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
@@ -45,6 +45,7 @@ struct ntv_context {
size_t num_ubos;
SpvId image_types[PIPE_MAX_SAMPLERS];
SpvId samplers[PIPE_MAX_SAMPLERS];
+ unsigned char sampler_array_sizes[PIPE_MAX_SAMPLERS];
unsigned samplers_used : PIPE_MAX_SAMPLERS;
SpvId entry_ifaces[PIPE_MAX_SHADER_INPUTS * 4 + PIPE_MAX_SHADER_OUTPUTS * 4];
size_t num_entry_ifaces;
@@ -582,58 +583,36 @@ emit_sampler(struct ntv_context *ctx, struct nir_variable *var)
SpvId sampled_type = spirv_builder_type_sampled_image(&ctx->builder,
image_type);
+
+ int index = var->data.binding;
+ assert(!(ctx->samplers_used & (1 << index)));
+ assert(!ctx->image_types[index]);
+
+ if (glsl_type_is_array(var->type)) {
+ sampled_type = spirv_builder_type_array(&ctx->builder, sampled_type,
+ emit_uint_const(ctx, 32, glsl_get_aoa_size(var->type)));
+ spirv_builder_emit_array_stride(&ctx->builder, sampled_type, sizeof(void*));
+ ctx->sampler_array_sizes[index] = glsl_get_aoa_size(var->type);
+ }
SpvId pointer_type = spirv_builder_type_pointer(&ctx->builder,
SpvStorageClassUniformConstant,
sampled_type);
- if (glsl_type_is_array(var->type)) {
- /* ARB_arrays_of_arrays from GLSL 1.30 allows nesting of arrays, so we just
- * use the total array size if we encounter a nested array
- */
- unsigned size = glsl_get_aoa_size(var->type);
- for (int i = 0; i < size; ++i) {
- SpvId var_id = spirv_builder_emit_var(&ctx->builder, pointer_type,
- SpvStorageClassUniformConstant);
-
- if (var->name) {
- char element_name[100];
- snprintf(element_name, sizeof(element_name), "%s_%d", var->name, i);
- spirv_builder_emit_name(&ctx->builder, var_id, var->name);
- }
+ SpvId var_id = spirv_builder_emit_var(&ctx->builder, pointer_type,
+ SpvStorageClassUniformConstant);
- int index = var->data.binding + i;
- assert(!(ctx->samplers_used & (1 << index)));
- assert(!ctx->image_types[index]);
- ctx->image_types[index] = image_type;
- ctx->samplers[index] = var_id;
- ctx->samplers_used |= 1 << index;
-
- spirv_builder_emit_descriptor_set(&ctx->builder, var_id, 0);
- int binding = zink_binding(ctx->stage,
- zink_sampler_type(glsl_without_array(var->type)),
- var->data.binding + i);
- spirv_builder_emit_binding(&ctx->builder, var_id, binding);
- }
- } else {
- SpvId var_id = spirv_builder_emit_var(&ctx->builder, pointer_type,
- SpvStorageClassUniformConstant);
-
- if (var->name)
- spirv_builder_emit_name(&ctx->builder, var_id, var->name);
-
- int index = var->data.binding;
- assert(!(ctx->samplers_used & (1 << index)));
- assert(!ctx->image_types[index]);
- ctx->image_types[index] = image_type;
- ctx->samplers[index] = var_id;
- ctx->samplers_used |= 1 << index;
-
- spirv_builder_emit_descriptor_set(&ctx->builder, var_id, 0);
- int binding = zink_binding(ctx->stage,
- zink_sampler_type(var->type),
- var->data.binding);
- spirv_builder_emit_binding(&ctx->builder, var_id, binding);
- }
+ if (var->name)
+ spirv_builder_emit_name(&ctx->builder, var_id, var->name);
+
+ ctx->image_types[index] = image_type;
+ ctx->samplers[index] = var_id;
+ ctx->samplers_used |= 1 << index;
+
+ spirv_builder_emit_descriptor_set(&ctx->builder, var_id, 0);
+ int binding = zink_binding(ctx->stage,
+ zink_sampler_type(type),
+ var->data.binding);
+ spirv_builder_emit_binding(&ctx->builder, var_id, binding);
}
static void
@@ -2153,7 +2132,7 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
assert(tex->texture_index == tex->sampler_index);
SpvId coord = 0, proj = 0, bias = 0, lod = 0, dref = 0, dx = 0, dy = 0,
- offset = 0, sample = 0;
+ offset = 0, sample = 0, tex_offset = 0;
unsigned coord_components = 0, coord_bitsize = 0, offset_components = 0;
for (unsigned i = 0; i < tex->num_srcs; i++) {
switch (tex->src[i].src_type) {
@@ -2216,6 +2195,14 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
assert(dy != 0);
break;
+ case nir_tex_src_texture_offset:
+ tex_offset = get_src_int(ctx, &tex->src[i].src);
+ break;
+
+ case nir_tex_src_sampler_offset:
+ /* don't care */
+ break;
+
default:
fprintf(stderr, "texture source: %d\n", tex->src[i].src_type);
unreachable("unknown texture source");
@@ -2227,13 +2214,35 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
assert(lod != 0);
}
- SpvId image_type = ctx->image_types[tex->texture_index];
+ unsigned texture_index = tex->texture_index;
+ if (!tex_offset) {
+ /* convert constant index back to base + offset */
+ unsigned last_sampler = util_last_bit(ctx->samplers_used);
+ for (unsigned i = 0; i < last_sampler; i++) {
+ if (!ctx->sampler_array_sizes[i]) {
+ if (i == texture_index)
+ /* this is a non-array sampler, so we don't need an access chain */
+ break;
+ } else if (texture_index <= i + ctx->sampler_array_sizes[i] - 1) {
+ /* this is the first member of a sampler array */
+ tex_offset = emit_uint_const(ctx, 32, texture_index - i);
+ texture_index = i;
+ break;
+ }
+ }
+ }
+ SpvId image_type = ctx->image_types[texture_index];
+ assert(image_type);
SpvId sampled_type = spirv_builder_type_sampled_image(&ctx->builder,
image_type);
-
- assert(ctx->samplers_used & (1u << tex->texture_index));
- SpvId load = spirv_builder_emit_load(&ctx->builder, sampled_type,
- ctx->samplers[tex->texture_index]);
+ assert(sampled_type);
+ assert(ctx->samplers_used & (1u << texture_index));
+ SpvId sampler_id = ctx->samplers[texture_index];
+ if (tex_offset) {
+ SpvId ptr = spirv_builder_type_pointer(&ctx->builder, SpvStorageClassUniformConstant, sampled_type);
+ sampler_id = spirv_builder_emit_access_chain(&ctx->builder, ptr, sampler_id, &tex_offset, 1);
+ }
+ SpvId load = spirv_builder_emit_load(&ctx->builder, sampled_type, sampler_id);
SpvId dest_type = get_dest_type(ctx, &tex->dest, tex->dest_type);
diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c
index 5e2516e6194..76e5ed590e7 100644
--- a/src/gallium/drivers/zink/zink_compiler.c
+++ b/src/gallium/drivers/zink/zink_compiler.c
@@ -452,37 +452,24 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
ret->bindings[ret->num_bindings].index = ubo_index++;
ret->bindings[ret->num_bindings].binding = binding;
ret->bindings[ret->num_bindings].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ ret->bindings[ret->num_bindings].size = 1;
ret->num_bindings++;
} else {
assert(var->data.mode == nir_var_uniform);
- if (glsl_type_is_sampler(var->type)) {
- VkDescriptorType vktype = zink_sampler_type(var->type);
+ const struct glsl_type *type = glsl_without_array(var->type);
+ if (glsl_type_is_sampler(type)) {
+ VkDescriptorType vktype = zink_sampler_type(type);
int binding = zink_binding(nir->info.stage,
vktype,
var->data.binding);
ret->bindings[ret->num_bindings].index = var->data.binding;
ret->bindings[ret->num_bindings].binding = binding;
ret->bindings[ret->num_bindings].type = vktype;
+ if (glsl_type_is_array(var->type))
+ ret->bindings[ret->num_bindings].size = glsl_get_aoa_size(var->type);
+ else
+ ret->bindings[ret->num_bindings].size = 1;
ret->num_bindings++;
- } else if (glsl_type_is_array(var->type)) {
- /* need to unroll possible arrays of arrays before checking type
- * in order to handle ARB_arrays_of_arrays extension
- */
- const struct glsl_type *type = glsl_without_array(var->type);
- if (!glsl_type_is_sampler(type))
- continue;
- VkDescriptorType vktype = zink_sampler_type(type);
-
- unsigned size = glsl_get_aoa_size(var->type);
- for (int i = 0; i < size; ++i) {
- int binding = zink_binding(nir->info.stage,
- vktype,
- var->data.binding + i);
- ret->bindings[ret->num_bindings].index = var->data.binding + i;
- ret->bindings[ret->num_bindings].binding = binding;
- ret->bindings[ret->num_bindings].type = vktype;
- ret->num_bindings++;
- }
}
}
}
diff --git a/src/gallium/drivers/zink/zink_compiler.h b/src/gallium/drivers/zink/zink_compiler.h
index 379595876e6..5e3d8002c1e 100644
--- a/src/gallium/drivers/zink/zink_compiler.h
+++ b/src/gallium/drivers/zink/zink_compiler.h
@@ -68,6 +68,7 @@ struct zink_shader {
int index;
int binding;
VkDescriptorType type;
+ unsigned char size;
} bindings[PIPE_MAX_CONSTANT_BUFFERS + PIPE_MAX_SHADER_SAMPLER_VIEWS];
size_t num_bindings;
struct set *programs;
diff --git a/src/gallium/drivers/zink/zink_draw.c b/src/gallium/drivers/zink/zink_draw.c
index 5d8297f7072..9f5bddbf301 100644
--- a/src/gallium/drivers/zink/zink_draw.c
+++ b/src/gallium/drivers/zink/zink_draw.c
@@ -337,35 +337,39 @@ zink_draw_vbo(struct pipe_context *pctx,
wds[num_wds].pBufferInfo = buffer_infos + num_buffer_info;
++num_buffer_info;
} else {
- struct pipe_sampler_view *psampler_view = ctx->image_views[i][index];
- struct zink_sampler_view *sampler_view = zink_sampler_view(psampler_view);
-
- struct zink_resource *res = psampler_view ? zink_resource(psampler_view->texture) : NULL;
- write_desc_resources[num_wds] = res;
- if (!res) {
- /* if we're hitting this assert often, we can probably just throw a junk buffer in since
- * the results of this codepath are undefined in ARB_texture_buffer_object spec
- */
- assert(screen->info.rb2_feats.nullDescriptor);
- if (shader->bindings[j].type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER)
- wds[num_wds].pTexelBufferView = &buffer_view[0];
+ for (unsigned k = 0; k < shader->bindings[j].size; k++) {
+ struct pipe_sampler_view *psampler_view = ctx->image_views[i][index + k];
+ struct zink_sampler_view *sampler_view = zink_sampler_view(psampler_view);
+
+ struct zink_resource *res = psampler_view ? zink_resource(psampler_view->texture) : NULL;
+ write_desc_resources[num_wds] = res;
+ if (!res) {
+ /* if we're hitting this assert often, we can probably just throw a junk buffer in since
+ * the results of this codepath are undefined in ARB_texture_buffer_object spec
+ */
+ assert(screen->info.rb2_feats.nullDescriptor);
+ if (shader->bindings[j].type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER)
+ wds[num_wds].pTexelBufferView = &buffer_view[0];
+ else {
+ image_infos[num_image_info].imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ image_infos[num_image_info].imageView = VK_NULL_HANDLE;
+ image_infos[num_image_info].sampler = ctx->samplers[i][index + k];
+ if (!k)
+ wds[num_wds].pImageInfo = image_infos + num_image_info;
+ ++num_image_info;
+ }
+ } else if (res->base.target == PIPE_BUFFER)
+ wds[num_wds].pTexelBufferView = &sampler_view->buffer_view;
else {
- image_infos[num_image_info].imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- image_infos[num_image_info].imageView = VK_NULL_HANDLE;
- image_infos[num_image_info].sampler = ctx->samplers[i][index];
- wds[num_wds].pImageInfo = image_infos + num_image_info;
+ if (res->layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
+ transitions[num_transitions++] = res;
+ image_infos[num_image_info].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ image_infos[num_image_info].imageView = sampler_view->image_view;
+ image_infos[num_image_info].sampler = ctx->samplers[i][index + k];
+ if (!k)
+ wds[num_wds].pImageInfo = image_infos + num_image_info;
++num_image_info;
}
- } else if (res->base.target == PIPE_BUFFER)
- wds[num_wds].pTexelBufferView = &sampler_view->buffer_view;
- else {
- if (res->layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
- transitions[num_transitions++] = res;
- image_infos[num_image_info].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- image_infos[num_image_info].imageView = sampler_view->image_view;
- image_infos[num_image_info].sampler = ctx->samplers[i][index];
- wds[num_wds].pImageInfo = image_infos + num_image_info;
- ++num_image_info;
}
}
@@ -373,7 +377,7 @@ zink_draw_vbo(struct pipe_context *pctx,
wds[num_wds].pNext = NULL;
wds[num_wds].dstBinding = shader->bindings[j].binding;
wds[num_wds].dstArrayElement = 0;
- wds[num_wds].descriptorCount = 1;
+ wds[num_wds].descriptorCount = shader->bindings[j].size;
wds[num_wds].descriptorType = shader->bindings[j].type;
++num_wds;
}
diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c
index cd58980f5db..3ab700d71fd 100644
--- a/src/gallium/drivers/zink/zink_program.c
+++ b/src/gallium/drivers/zink/zink_program.c
@@ -116,7 +116,7 @@ create_desc_set_layout(VkDevice dev,
assert(num_bindings < ARRAY_SIZE(bindings));
bindings[num_bindings].binding = shader->bindings[j].binding;
bindings[num_bindings].descriptorType = shader->bindings[j].type;
- bindings[num_bindings].descriptorCount = 1;
+ bindings[num_bindings].descriptorCount = shader->bindings[j].size;
bindings[num_bindings].stageFlags = stage_flags;
bindings[num_bindings].pImmutableSamplers = NULL;
++num_bindings;
More information about the mesa-commit
mailing list