From 954644022771f45b1e6f719cab399a949a3fbb22 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Tue, 24 Mar 2020 11:51:37 +1100 Subject: [PATCH] glsl: add bindless support to nir uniform linker MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reviewed-by: Alejandro Piñeiro Part-of: --- src/compiler/glsl/gl_nir_link_uniforms.c | 249 ++++++++++++++++------- 1 file changed, 172 insertions(+), 77 deletions(-) diff --git a/src/compiler/glsl/gl_nir_link_uniforms.c b/src/compiler/glsl/gl_nir_link_uniforms.c index 7ed48444460..175af7c7edb 100644 --- a/src/compiler/glsl/gl_nir_link_uniforms.c +++ b/src/compiler/glsl/gl_nir_link_uniforms.c @@ -469,6 +469,8 @@ struct nir_link_uniforms_state { unsigned next_subroutine; /* per-shader stage */ + unsigned next_bindless_image_index; + unsigned next_bindless_sampler_index; unsigned next_image_index; unsigned next_sampler_index; unsigned num_shader_samplers; @@ -500,7 +502,8 @@ add_parameter(struct gl_uniform_storage *uniform, const struct glsl_type *type, struct nir_link_uniforms_state *state) { - if (!state->params || uniform->is_shader_storage || glsl_contains_opaque(type)) + if (!state->params || uniform->is_shader_storage || + (glsl_contains_opaque(type) && !state->current_var->data.bindless)) return; unsigned num_params = glsl_get_aoa_size(type); @@ -662,45 +665,59 @@ find_and_update_named_uniform_storage(struct gl_context *ctx, unsigned values = glsl_get_component_slots(type); const struct glsl_type *type_no_array = glsl_without_array(type); if (glsl_type_is_sampler(type_no_array)) { - struct gl_linked_shader *sh = prog->_LinkedShaders[stage]; bool init_idx; - unsigned sampler_index = - get_next_index(state, uniform, &state->next_sampler_index, - &init_idx); + unsigned *next_index = state->current_var->data.bindless ? + &state->next_bindless_sampler_index : + &state->next_sampler_index; + int sampler_index = + get_next_index(state, uniform, next_index, &init_idx); + struct gl_linked_shader *sh = prog->_LinkedShaders[stage]; - /* Samplers (bound or bindless) are counted as two components as - * specified by ARB_bindless_texture. - */ - state->num_shader_samplers += values / 2; + if (state->current_var->data.bindless) { + if (init_idx) { + sh->Program->sh.BindlessSamplers = + rerzalloc(sh->Program, sh->Program->sh.BindlessSamplers, + struct gl_bindless_sampler, + sh->Program->sh.NumBindlessSamplers, + state->next_bindless_sampler_index); + + for (unsigned j = sh->Program->sh.NumBindlessSamplers; + j < state->next_bindless_sampler_index; j++) { + sh->Program->sh.BindlessSamplers[j].target = + glsl_get_sampler_target(type_no_array); + } - uniform->opaque[stage].active = true; - uniform->opaque[stage].index = sampler_index; + sh->Program->sh.NumBindlessSamplers = + state->next_bindless_sampler_index; + } - if (init_idx) { - const unsigned shadow = - glsl_sampler_type_is_shadow(type_no_array); - for (unsigned i = sampler_index; - i < MIN2(state->next_sampler_index, MAX_SAMPLERS); - i++) { - sh->Program->sh.SamplerTargets[i] = - glsl_get_sampler_target(type_no_array); - state->shader_samplers_used |= 1U << i; - state->shader_shadow_samplers |= shadow << i; + if (!state->var_is_in_block) + state->num_shader_uniform_components += values; + + } else { + /* Samplers (bound or bindless) are counted as two components + * as specified by ARB_bindless_texture. + */ + state->num_shader_samplers += values / 2; + + if (init_idx) { + const unsigned shadow = + glsl_sampler_type_is_shadow(type_no_array); + for (unsigned i = sampler_index; + i < MIN2(state->next_sampler_index, MAX_SAMPLERS); + i++) { + sh->Program->sh.SamplerTargets[i] = + glsl_get_sampler_target(type_no_array); + state->shader_samplers_used |= 1U << i; + state->shader_shadow_samplers |= shadow << i; + } } } - } else if (glsl_type_is_image(type_no_array)) { - struct gl_linked_shader *sh = prog->_LinkedShaders[stage]; - int image_index = state->next_image_index; - /* TODO: handle structs when bindless support is added */ - state->next_image_index += MAX2(1, uniform->array_elements); - - /* Images (bound or bindless) are counted as two components as - * specified by ARB_bindless_texture. - */ - state->num_shader_images += values / 2; uniform->opaque[stage].active = true; - uniform->opaque[stage].index = image_index; + uniform->opaque[stage].index = sampler_index; + } else if (glsl_type_is_image(type_no_array)) { + struct gl_linked_shader *sh = prog->_LinkedShaders[stage]; /* Set image access qualifiers */ enum gl_access_qualifier image_access = @@ -711,11 +728,48 @@ find_and_update_named_uniform_storage(struct gl_context *ctx, GL_READ_ONLY) : ((image_access & ACCESS_NON_READABLE) ? GL_WRITE_ONLY : GL_READ_WRITE); - for (unsigned i = image_index; - i < MIN2(state->next_image_index, MAX_IMAGE_UNIFORMS); - i++) { - sh->Program->sh.ImageAccess[i] = access; + + int image_index; + if (state->current_var->data.bindless) { + image_index = state->next_bindless_image_index; + state->next_bindless_image_index += + MAX2(1, uniform->array_elements); + + sh->Program->sh.BindlessImages = + rerzalloc(sh->Program, sh->Program->sh.BindlessImages, + struct gl_bindless_image, + sh->Program->sh.NumBindlessImages, + state->next_bindless_image_index); + + for (unsigned j = sh->Program->sh.NumBindlessImages; + j < state->next_bindless_image_index; j++) { + sh->Program->sh.BindlessImages[j].access = access; + } + + sh->Program->sh.NumBindlessImages = + state->next_bindless_image_index; + + } else { + image_index = state->next_image_index; + state->next_image_index += MAX2(1, uniform->array_elements); + + /* Images (bound or bindless) are counted as two components as + * specified by ARB_bindless_texture. + */ + state->num_shader_images += values / 2; + + for (unsigned i = image_index; + i < MIN2(state->next_image_index, MAX_IMAGE_UNIFORMS); + i++) { + sh->Program->sh.ImageAccess[i] = access; + } } + + uniform->opaque[stage].active = true; + uniform->opaque[stage].index = image_index; + + if (!uniform->is_shader_storage) + state->num_shader_uniform_components += values; } struct hash_entry *entry = @@ -1115,6 +1169,7 @@ nir_link_uniform(struct gl_context *ctx, state->num_hidden_uniforms++; uniform->is_shader_storage = nir_variable_is_in_ssbo(state->current_var); + uniform->is_bindless = state->current_var->data.bindless; /* Set fields whose default value depend on the variable being inside a * block. @@ -1229,14 +1284,8 @@ nir_link_uniform(struct gl_context *ctx, } uniform->block_index = buffer_block_index; - - /* @FIXME: the initialization of the following will be done as we - * implement support for their specific features, like SSBO, atomics, - * etc. - */ uniform->builtin = is_gl_identifier(uniform->name); uniform->atomic_buffer_index = -1; - uniform->is_bindless = false; /* The following are not for features not supported by ARB_gl_spirv */ uniform->num_compatible_subroutines = 0; @@ -1246,45 +1295,56 @@ nir_link_uniform(struct gl_context *ctx, if (glsl_type_is_sampler(type_no_array)) { bool init_idx; + unsigned *next_index = state->current_var->data.bindless ? + &state->next_bindless_sampler_index : &state->next_sampler_index; int sampler_index = - get_next_index(state, uniform, &state->next_sampler_index, - &init_idx); + get_next_index(state, uniform, next_index, &init_idx); - /* Samplers (bound or bindless) are counted as two components as - * specified by ARB_bindless_texture. - */ - state->num_shader_samplers += values / 2; + if (state->current_var->data.bindless) { - uniform->opaque[stage].active = true; - uniform->opaque[stage].index = sampler_index; + if (init_idx) { + stage_program->sh.BindlessSamplers = + rerzalloc(stage_program, stage_program->sh.BindlessSamplers, + struct gl_bindless_sampler, + stage_program->sh.NumBindlessSamplers, + state->next_bindless_sampler_index); + + for (unsigned j = stage_program->sh.NumBindlessSamplers; + j < state->next_bindless_sampler_index; j++) { + stage_program->sh.BindlessSamplers[j].target = + glsl_get_sampler_target(type_no_array); + } - if (init_idx) { - const unsigned shadow = glsl_sampler_type_is_shadow(type_no_array); - for (unsigned i = sampler_index; - i < MIN2(state->next_sampler_index, MAX_SAMPLERS); - i++) { - stage_program->sh.SamplerTargets[i] = - glsl_get_sampler_target(type_no_array); - state->shader_samplers_used |= 1U << i; - state->shader_shadow_samplers |= shadow << i; + stage_program->sh.NumBindlessSamplers = + state->next_bindless_sampler_index; } - } - } else if (glsl_type_is_image(type_no_array)) { - /* @FIXME: image_index should match that of the same image - * uniform in other shaders. This means we need to match image - * uniforms by location (GLSL does it by variable name, but we - * want to avoid that). - */ - int image_index = state->next_image_index; - state->next_image_index += entries; - /* Images (bound or bindless) are counted as two components as - * specified by ARB_bindless_texture. - */ - state->num_shader_images += values / 2; + if (!state->var_is_in_block) + state->num_shader_uniform_components += values; + + } else { + /* Samplers (bound or bindless) are counted as two components as + * specified by ARB_bindless_texture. + */ + state->num_shader_samplers += values / 2; + + if (init_idx) { + const unsigned shadow = + glsl_sampler_type_is_shadow(type_no_array); + for (unsigned i = sampler_index; + i < MIN2(state->next_sampler_index, MAX_SAMPLERS); + i++) { + stage_program->sh.SamplerTargets[i] = + glsl_get_sampler_target(type_no_array); + state->shader_samplers_used |= 1U << i; + state->shader_shadow_samplers |= shadow << i; + } + } + } uniform->opaque[stage].active = true; - uniform->opaque[stage].index = image_index; + uniform->opaque[stage].index = sampler_index; + } else if (glsl_type_is_image(type_no_array)) { /* Set image access qualifiers */ enum gl_access_qualifier image_access = @@ -1295,12 +1355,45 @@ nir_link_uniform(struct gl_context *ctx, GL_READ_ONLY) : ((image_access & ACCESS_NON_READABLE) ? GL_WRITE_ONLY : GL_READ_WRITE); - for (unsigned i = image_index; - i < MIN2(state->next_image_index, MAX_IMAGE_UNIFORMS); - i++) { - stage_program->sh.ImageAccess[i] = access; + + int image_index; + if (state->current_var->data.bindless) { + image_index = state->next_bindless_image_index; + state->next_bindless_image_index += entries; + + stage_program->sh.BindlessImages = + rerzalloc(stage_program, stage_program->sh.BindlessImages, + struct gl_bindless_image, + stage_program->sh.NumBindlessImages, + state->next_bindless_image_index); + + for (unsigned j = stage_program->sh.NumBindlessImages; + j < state->next_bindless_image_index; j++) { + stage_program->sh.BindlessImages[j].access = access; + } + + stage_program->sh.NumBindlessImages = + state->next_bindless_image_index; + + } else { + image_index = state->next_image_index; + state->next_image_index += entries; + + /* Images (bound or bindless) are counted as two components as + * specified by ARB_bindless_texture. + */ + state->num_shader_images += values / 2; + + for (unsigned i = image_index; + i < MIN2(state->next_image_index, MAX_IMAGE_UNIFORMS); + i++) { + stage_program->sh.ImageAccess[i] = access; + } } + uniform->opaque[stage].active = true; + uniform->opaque[stage].index = image_index; + if (!uniform->is_shader_storage) state->num_shader_uniform_components += values; } else { @@ -1367,6 +1460,8 @@ gl_nir_link_uniforms(struct gl_context *ctx, state.referenced_uniforms = _mesa_hash_table_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); + state.next_bindless_image_index = 0; + state.next_bindless_sampler_index = 0; state.next_image_index = 0; state.next_sampler_index = 0; state.num_shader_samplers = 0; -- 2.30.2