anv: Add initial support for pushing image params
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 18 Nov 2015 23:14:05 +0000 (15:14 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 8 Dec 2015 05:08:26 +0000 (21:08 -0800)
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
src/vulkan/anv_image.c
src/vulkan/anv_nir.h
src/vulkan/anv_nir_apply_pipeline_layout.c
src/vulkan/anv_pipeline.c
src/vulkan/anv_private.h

index ee437aa6330e15060b90b3a485c20a87f2315080..aacd2ab60e34cbc3cd228e9b274953346272dad3 100644 (file)
@@ -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)
index 09993180e7ec2431e441e909bdd61b1234344776..68f9b0868553e8d5334f38c449c166e2099decfc 100644 (file)
@@ -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");
+}
index 666b127451a0f7f7a0359c388cbd414be9994d50..9a7a76fe216839462ec516211063b521c31eb95a 100644 (file)
@@ -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
index 1b196cd62b782b14ff0ea771dcf0399323e463ca..8632dc74e5778b05e81fa5cdec69318907a1579a 100644 (file)
@@ -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;
 }
index 821f5e33774781c2d854647e5e5e895ef0e618d9..9b6eef8074b0c51bb03429782abe02c12b797284 100644 (file)
@@ -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).
index b3829216dd447d243aa30b36c47a49b80bf59b12..4b672d38f1ce80067a8df461b6e3eb9bec87b90c 100644 (file)
@@ -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];
 };