iris: Defer cbuf0 upload to draw time
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 9 Nov 2018 07:10:46 +0000 (23:10 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Thu, 21 Feb 2019 18:26:09 +0000 (10:26 -0800)
src/gallium/drivers/iris/iris_context.h
src/gallium/drivers/iris/iris_state.c

index b2f90845024c310167760af8f084959a4a511699..68d2991ddd60cf8cca40b7ba5ffc4c1186176257 100644 (file)
@@ -260,6 +260,9 @@ struct iris_shader_state {
    /** Uniform Buffers */
    struct iris_const_buffer constbuf[PIPE_MAX_CONSTANT_BUFFERS];
 
+   struct pipe_constant_buffer cbuf0;
+   bool cbuf0_needs_upload;
+
    /** Shader Storage Buffers */
    struct pipe_resource *ssbo[PIPE_MAX_SHADER_BUFFERS];
    struct iris_state_ref ssbo_surface_state[PIPE_MAX_SHADER_BUFFERS];
index dec914b550b1f111db33d2976fbd0cbd93c70be6..4d75348a06d999e3ae0d0b8bf3f54ef8c2da901c 100644 (file)
@@ -2085,6 +2085,36 @@ iris_set_framebuffer_state(struct pipe_context *ctx,
 #endif
 }
 
+static void
+upload_ubo_surf_state(struct iris_context *ice,
+                      struct iris_const_buffer *cbuf,
+                      unsigned buffer_size)
+{
+   struct pipe_context *ctx = &ice->ctx;
+   struct iris_screen *screen = (struct iris_screen *) ctx->screen;
+
+   // XXX: these are not retained forever, use a separate uploader?
+   void *map =
+      upload_state(ice->state.surface_uploader, &cbuf->surface_state,
+                   4 * GENX(RENDER_SURFACE_STATE_length), 64);
+   if (!unlikely(map)) {
+      pipe_resource_reference(&cbuf->data.res, NULL);
+      return;
+   }
+
+   struct iris_resource *res = (void *) cbuf->data.res;
+   struct iris_bo *surf_bo = iris_resource_bo(cbuf->surface_state.res);
+   cbuf->surface_state.offset += iris_bo_offset_from_base_address(surf_bo);
+
+   isl_buffer_fill_state(&screen->isl_dev, map,
+                         .address = res->bo->gtt_offset + cbuf->data.offset,
+                         .size_B = MIN2(buffer_size,
+                                        res->bo->size - cbuf->data.offset),
+                         .format = ISL_FORMAT_R32G32B32A32_FLOAT,
+                         .stride_B = 1,
+                         .mocs = MOCS_WB)
+}
+
 /**
  * The pipe->set_constant_buffer() driver hook.
  *
@@ -2097,46 +2127,31 @@ iris_set_constant_buffer(struct pipe_context *ctx,
                          const struct pipe_constant_buffer *input)
 {
    struct iris_context *ice = (struct iris_context *) ctx;
-   struct iris_screen *screen = (struct iris_screen *)ctx->screen;
    gl_shader_stage stage = stage_from_pipe(p_stage);
    struct iris_shader_state *shs = &ice->state.shaders[stage];
    struct iris_const_buffer *cbuf = &shs->constbuf[index];
 
-   if (input && (input->buffer || input->user_buffer)) {
-      if (input->user_buffer) {
-         u_upload_data(ctx->const_uploader, 0, input->buffer_size, 32,
-                       input->user_buffer, &cbuf->data.offset,
-                       &cbuf->data.res);
-      } else {
-         pipe_resource_reference(&cbuf->data.res, input->buffer);
-         cbuf->data.offset = input->buffer_offset;
-      }
+   if (input && input->buffer) {
+      assert(index > 0);
 
-      // XXX: these are not retained forever, use a separate uploader?
-      void *map =
-         upload_state(ice->state.surface_uploader, &cbuf->surface_state,
-                      4 * GENX(RENDER_SURFACE_STATE_length), 64);
-      if (!unlikely(map)) {
-         pipe_resource_reference(&cbuf->data.res, NULL);
-         return;
-      }
+      pipe_resource_reference(&cbuf->data.res, input->buffer);
+      cbuf->data.offset = input->buffer_offset;
 
-      struct iris_resource *res = (void *) cbuf->data.res;
-      struct iris_bo *surf_bo = iris_resource_bo(cbuf->surface_state.res);
-      cbuf->surface_state.offset += iris_bo_offset_from_base_address(surf_bo);
-
-      isl_buffer_fill_state(&screen->isl_dev, map,
-                            .address = res->bo->gtt_offset + cbuf->data.offset,
-                            .size_B = MIN2(input->buffer_size,
-                                           res->bo->size - cbuf->data.offset),
-                            .format = ISL_FORMAT_R32G32B32A32_FLOAT,
-                            .stride_B = 1,
-                            .mocs = MOCS_WB)
+      upload_ubo_surf_state(ice, cbuf, input->buffer_size);
    } else {
       pipe_resource_reference(&cbuf->data.res, NULL);
       pipe_resource_reference(&cbuf->surface_state.res, NULL);
    }
 
+   if (index == 0) {
+      if (input)
+         memcpy(&shs->cbuf0, input, sizeof(shs->cbuf0));
+      else
+         memset(&shs->cbuf0, 0, sizeof(shs->cbuf0));
+
+      shs->cbuf0_needs_upload = true;
+   }
+
    ice->state.dirty |= IRIS_DIRTY_CONSTANTS_VS << stage;
    // XXX: maybe not necessary all the time...?
    // XXX: we need 3DS_BTP to commit these changes, and if we fell back to
@@ -2144,6 +2159,22 @@ iris_set_constant_buffer(struct pipe_context *ctx,
    ice->state.dirty |= IRIS_DIRTY_BINDINGS_VS << stage;
 }
 
+static void
+upload_uniforms(struct iris_context *ice,
+                gl_shader_stage stage)
+{
+   struct iris_shader_state *shs = &ice->state.shaders[stage];
+   struct iris_const_buffer *cbuf = &shs->constbuf[0];
+
+   if (shs->cbuf0.user_buffer) {
+      u_upload_data(ice->ctx.const_uploader, 0, shs->cbuf0.buffer_size, 32,
+                    shs->cbuf0.user_buffer, &cbuf->data.offset,
+                    &cbuf->data.res);
+
+      upload_ubo_surf_state(ice, cbuf, shs->cbuf0.buffer_size);
+   }
+}
+
 /**
  * The pipe->set_shader_buffers() driver hook.
  *
@@ -3945,6 +3976,9 @@ iris_upload_dirty_render_state(struct iris_context *ice,
       if (!shader)
          continue;
 
+      if (shs->cbuf0_needs_upload)
+         upload_uniforms(ice, stage);
+
       struct brw_stage_prog_data *prog_data = (void *) shader->prog_data;
 
       iris_emit_cmd(batch, GENX(3DSTATE_CONSTANT_VS), pkt) {