mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 09:38:07 +02:00
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@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8155>
This commit is contained in:
parent
1a7b7b17ad
commit
9c18491e41
5 changed files with 100 additions and 99 deletions
|
|
@ -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);
|
||||
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);
|
||||
}
|
||||
if (var->name)
|
||||
spirv_builder_emit_name(&ctx->builder, var_id, var->name);
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
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];
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue