From 43ac954e25f28d240da65ed816458d3529675a04 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 18 Nov 2015 15:14:05 -0800 Subject: [PATCH] anv: Add initial support for pushing image params The helper to fill out the image params data-structure is stilly a dummy, but this puts the infastructure in place. --- src/vulkan/anv_cmd_buffer.c | 26 ++++++- src/vulkan/anv_image.c | 9 +++ src/vulkan/anv_nir.h | 1 + src/vulkan/anv_nir_apply_pipeline_layout.c | 80 ++++++++++++++++++++++ src/vulkan/anv_pipeline.c | 6 +- src/vulkan/anv_private.h | 4 ++ 6 files changed, 124 insertions(+), 2 deletions(-) diff --git a/src/vulkan/anv_cmd_buffer.c b/src/vulkan/anv_cmd_buffer.c index ee437aa6330..aacd2ab60e3 100644 --- a/src/vulkan/anv_cmd_buffer.c +++ b/src/vulkan/anv_cmd_buffer.c @@ -668,6 +668,16 @@ anv_cmd_buffer_emit_binding_table(struct anv_cmd_buffer *cmd_buffer, if (layout == NULL) goto out; + if (layout->stage[stage].image_count > 0) { + VkResult result = + anv_cmd_buffer_ensure_push_constant_field(cmd_buffer, stage, images); + if (result != VK_SUCCESS) + return result; + + cmd_buffer->state.push_constants_dirty |= 1 << stage; + } + + uint32_t image = 0; for (uint32_t s = 0; s < layout->stage[stage].surface_count; s++) { struct anv_pipeline_binding *binding = &layout->stage[stage].surface_to_descriptor[s]; @@ -713,7 +723,20 @@ anv_cmd_buffer_emit_binding_table(struct anv_cmd_buffer *cmd_buffer, bo_offset = desc->image_view->offset; break; - case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { + surface_state = desc->image_view->storage_surface_state; + bo = desc->image_view->bo; + bo_offset = desc->image_view->offset; + + struct brw_image_param *image_param = + &cmd_buffer->state.push_constants[stage]->images[image++]; + + anv_image_view_fill_image_param(cmd_buffer->device, desc->image_view, + image_param); + image_param->surface_idx = bias + s; + break; + } + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: assert(!"Unsupported descriptor type"); @@ -727,6 +750,7 @@ anv_cmd_buffer_emit_binding_table(struct anv_cmd_buffer *cmd_buffer, bt_map[bias + s] = surface_state.offset + state_offset; add_surface_state_reloc(cmd_buffer, surface_state, bo, bo_offset); } + assert(image == layout->stage[stage].image_count); out: if (!cmd_buffer->device->info.has_llc) diff --git a/src/vulkan/anv_image.c b/src/vulkan/anv_image.c index 09993180e7e..68f9b086855 100644 --- a/src/vulkan/anv_image.c +++ b/src/vulkan/anv_image.c @@ -592,3 +592,12 @@ anv_image_get_surface_for_aspect_mask(struct anv_image *image, VkImageAspectFlag return NULL; } } + +void +anv_image_view_fill_image_param(struct anv_device *device, + struct anv_image_view *view, + struct brw_image_param *param) +{ + memset(param, 0, sizeof *param); + anv_finishme("Actually fill out brw_image_param"); +} diff --git a/src/vulkan/anv_nir.h b/src/vulkan/anv_nir.h index 666b127451a..9a7a76fe216 100644 --- a/src/vulkan/anv_nir.h +++ b/src/vulkan/anv_nir.h @@ -36,6 +36,7 @@ void anv_nir_apply_dynamic_offsets(struct anv_pipeline *pipeline, nir_shader *shader, struct brw_stage_prog_data *prog_data); bool anv_nir_apply_pipeline_layout(nir_shader *shader, + struct brw_stage_prog_data *prog_data, const struct anv_pipeline_layout *layout); #ifdef __cplusplus diff --git a/src/vulkan/anv_nir_apply_pipeline_layout.c b/src/vulkan/anv_nir_apply_pipeline_layout.c index 1b196cd62b7..8632dc74e57 100644 --- a/src/vulkan/anv_nir_apply_pipeline_layout.c +++ b/src/vulkan/anv_nir_apply_pipeline_layout.c @@ -82,6 +82,29 @@ get_sampler_index(unsigned set, unsigned binding, nir_texop tex_op, return sampler_index; } +static uint32_t +get_image_index(unsigned set, unsigned binding, + struct apply_pipeline_layout_state *state) +{ + assert(set < state->layout->num_sets); + struct anv_descriptor_set_layout *set_layout = + state->layout->set[set].layout; + + assert(binding < set_layout->binding_count); + + gl_shader_stage stage = state->shader->stage; + + assert(set_layout->binding[binding].stage[stage].image_index >= 0); + + uint32_t image_index = + state->layout->set[set].stage[stage].image_start + + set_layout->binding[binding].stage[stage].image_index; + + assert(image_index < state->layout->stage[stage].image_count); + + return image_index; +} + static void lower_res_index_intrinsic(nir_intrinsic_instr *intrin, struct apply_pipeline_layout_state *state) @@ -214,8 +237,23 @@ apply_pipeline_layout_block(nir_block *block, void *void_state) return true; } +static void +setup_vec4_uniform_value(const gl_constant_value **params, + const gl_constant_value *values, + unsigned n) +{ + static const gl_constant_value zero = { 0 }; + + for (unsigned i = 0; i < n; ++i) + params[i] = &values[i]; + + for (unsigned i = n; i < 4; ++i) + params[i] = &zero; +} + bool anv_nir_apply_pipeline_layout(nir_shader *shader, + struct brw_stage_prog_data *prog_data, const struct anv_pipeline_layout *layout) { struct apply_pipeline_layout_state state = { @@ -232,5 +270,47 @@ anv_nir_apply_pipeline_layout(nir_shader *shader, } } + if (layout->stage[shader->stage].image_count > 0) { + nir_foreach_variable(var, &shader->uniforms) { + if (glsl_type_is_image(var->type) || + (glsl_type_is_array(var->type) && + glsl_type_is_image(glsl_get_array_element(var->type)))) { + /* Images are represented as uniform push constants and the actual + * information required for reading/writing to/from the image is + * storred in the uniform. + */ + unsigned image_index = get_image_index(var->data.descriptor_set, + var->data.binding, &state); + + var->data.driver_location = shader->num_uniforms + + image_index * BRW_IMAGE_PARAM_SIZE; + } + } + + struct anv_push_constants *null_data = NULL; + const gl_constant_value **param = prog_data->param + shader->num_uniforms; + const struct brw_image_param *image_param = null_data->images; + for (uint32_t i = 0; i < layout->stage[shader->stage].image_count; i++) { + setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_SURFACE_IDX_OFFSET, + (const gl_constant_value *)&image_param->surface_idx, 1); + setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_OFFSET_OFFSET, + (const gl_constant_value *)image_param->offset, 2); + setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_SIZE_OFFSET, + (const gl_constant_value *)image_param->size, 3); + setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_STRIDE_OFFSET, + (const gl_constant_value *)image_param->stride, 4); + setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_TILING_OFFSET, + (const gl_constant_value *)image_param->tiling, 3); + setup_vec4_uniform_value(param + BRW_IMAGE_PARAM_SWIZZLING_OFFSET, + (const gl_constant_value *)image_param->swizzling, 2); + + param += BRW_IMAGE_PARAM_SIZE; + image_param ++; + } + + shader->num_uniforms += layout->stage[shader->stage].image_count * + BRW_IMAGE_PARAM_SIZE; + } + return state.progress; } diff --git a/src/vulkan/anv_pipeline.c b/src/vulkan/anv_pipeline.c index 821f5e33774..9b6eef8074b 100644 --- a/src/vulkan/anv_pipeline.c +++ b/src/vulkan/anv_pipeline.c @@ -315,6 +315,10 @@ anv_pipeline_compile(struct anv_pipeline *pipeline, if (pipeline->layout && pipeline->layout->stage[stage].has_dynamic_offsets) prog_data->nr_params += MAX_DYNAMIC_BUFFERS * 2; + if (pipeline->layout && pipeline->layout->stage[stage].image_count > 0) + prog_data->nr_params += pipeline->layout->stage[stage].image_count * + BRW_IMAGE_PARAM_SIZE; + if (prog_data->nr_params > 0) { /* XXX: I think we're leaking this */ prog_data->param = (const gl_constant_value **) @@ -339,7 +343,7 @@ anv_pipeline_compile(struct anv_pipeline *pipeline, /* Apply the actual pipeline layout to UBOs, SSBOs, and textures */ if (pipeline->layout) - anv_nir_apply_pipeline_layout(nir, pipeline->layout); + anv_nir_apply_pipeline_layout(nir, prog_data, pipeline->layout); /* All binding table offsets provided by apply_pipeline_layout() are * relative to the start of the bindint table (plus MAX_RTS for VS). diff --git a/src/vulkan/anv_private.h b/src/vulkan/anv_private.h index b3829216dd4..4b672d38f1c 100644 --- a/src/vulkan/anv_private.h +++ b/src/vulkan/anv_private.h @@ -1541,6 +1541,10 @@ void gen9_fill_buffer_surface_state(void *state, const struct anv_format *format uint32_t offset, uint32_t range, uint32_t stride); +void anv_image_view_fill_image_param(struct anv_device *device, + struct anv_image_view *view, + struct brw_image_param *param); + struct anv_sampler { uint32_t state[4]; }; -- 2.30.2