zink: handle arrays of ubos

with the nir pass removing all dynamic indexing, all that's needed here
is generating extra binding points for each array member, as everything else
is already handled

Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8314>
This commit is contained in:
Mike Blumenkrantz 2020-07-29 20:33:50 -04:00
parent dbba989907
commit 22be7b9674
2 changed files with 47 additions and 23 deletions

View File

@ -618,10 +618,11 @@ emit_sampler(struct ntv_context *ctx, struct nir_variable *var)
static void
emit_ubo(struct ntv_context *ctx, struct nir_variable *var)
{
bool is_ubo_array = glsl_type_is_array(var->type) && glsl_type_is_interface(glsl_without_array(var->type));
/* variables accessed inside a uniform block will get merged into a big
* memory blob and accessed by offset
*/
if (var->data.location)
if (var->data.location && !is_ubo_array)
return;
uint32_t size = glsl_count_attribute_slots(var->interface_type, false);
@ -643,24 +644,36 @@ emit_ubo(struct ntv_context *ctx, struct nir_variable *var)
SpvDecorationBlock);
spirv_builder_emit_member_offset(&ctx->builder, struct_type, 0, 0);
SpvId pointer_type = spirv_builder_type_pointer(&ctx->builder,
SpvStorageClassUniform,
struct_type);
SpvId var_id = spirv_builder_emit_var(&ctx->builder, pointer_type,
SpvStorageClassUniform);
if (var->name)
spirv_builder_emit_name(&ctx->builder, var_id, var->name);
/* if this is a ubo array, create a binding point for each array member:
*
"For uniform blocks declared as arrays, each individual array element
corresponds to a separate buffer object backing one instance of the block."
- ARB_gpu_shader5
assert(ctx->num_ubos < ARRAY_SIZE(ctx->ubos));
ctx->ubos[ctx->num_ubos++] = var_id;
(also it's just easier)
*/
for (unsigned i = 0; i < (is_ubo_array ? glsl_get_aoa_size(var->type) : 1); i++) {
SpvId var_id = spirv_builder_emit_var(&ctx->builder, pointer_type,
SpvStorageClassUniform);
if (var->name) {
char struct_name[100];
snprintf(struct_name, sizeof(struct_name), "%s[%u]", var->name, i);
spirv_builder_emit_name(&ctx->builder, var_id, var->name);
}
spirv_builder_emit_descriptor_set(&ctx->builder, var_id, 0);
int binding = zink_binding(ctx->stage,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
var->data.binding);
spirv_builder_emit_binding(&ctx->builder, var_id, binding);
assert(ctx->num_ubos < ARRAY_SIZE(ctx->ubos));
ctx->ubos[ctx->num_ubos++] = var_id;
spirv_builder_emit_descriptor_set(&ctx->builder, var_id, 0);
int binding = zink_binding(ctx->stage,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
var->data.binding + i);
spirv_builder_emit_binding(&ctx->builder, var_id, binding);
}
}
static void

View File

@ -476,18 +476,29 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
nir_var_mem_ssbo)) {
if (var->data.mode == nir_var_mem_ubo) {
/* ignore variables being accessed if they aren't the base of the UBO */
if (var->data.location)
bool ubo_array = glsl_type_is_array(var->type) && glsl_type_is_interface(glsl_without_array(var->type));
if (var->data.location && !ubo_array)
continue;
var->data.binding = cur_ubo++;
var->data.binding = cur_ubo;
/* if this is a ubo array, create a binding point for each array member:
*
"For uniform blocks declared as arrays, each individual array element
corresponds to a separate buffer object backing one instance of the block."
- ARB_gpu_shader5
int binding = zink_binding(nir->info.stage,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
var->data.binding);
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++;
(also it's just easier)
*/
for (unsigned i = 0; i < (ubo_array ? glsl_get_aoa_size(var->type) : 1); i++) {
int binding = zink_binding(nir->info.stage,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
cur_ubo++);
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);
const struct glsl_type *type = glsl_without_array(var->type);