ilo: support copying constant buffer 0 to PCB
authorChia-I Wu <olvaffe@gmail.com>
Wed, 17 Jul 2013 21:58:42 +0000 (05:58 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Tue, 13 Aug 2013 07:52:41 +0000 (15:52 +0800)
Add ILO_KERNEL_PCB_CBUF0_SIZE so that a kernel can specify how many bytes of
constant buffer 0 need to be copied to PCB.

src/gallium/drivers/ilo/ilo_3d_pipeline.h
src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c
src/gallium/drivers/ilo/ilo_3d_pipeline_gen7.c
src/gallium/drivers/ilo/ilo_shader.c
src/gallium/drivers/ilo/ilo_shader.h

index ba3a4be584f91e40fd8e571eb2cc64f3cf012212..5353ae99f81e793e77c69d7d30d965709cc76b43 100644 (file)
@@ -125,6 +125,8 @@ struct ilo_3d_pipeline {
          uint32_t SURFACE_STATE[ILO_MAX_WM_SURFACES];
          uint32_t SAMPLER_STATE;
          uint32_t SAMPLER_BORDER_COLOR_STATE[ILO_MAX_SAMPLERS];
+         uint32_t PUSH_CONSTANT_BUFFER;
+         int PUSH_CONSTANT_BUFFER_size;
       } wm;
    } state;
 };
index ce1558b694ec837d3f92626811409b320c53290e..dca49311ab3797d047f2acc545fd772d7fa132ca 100644 (file)
@@ -653,8 +653,12 @@ gen6_pipeline_wm(struct ilo_3d_pipeline *p,
                  struct gen6_pipeline_session *session)
 {
    /* 3DSTATE_CONSTANT_PS */
-   if (session->pcb_state_fs_changed)
-      gen6_emit_3DSTATE_CONSTANT_PS(p->dev, NULL, NULL, 0, p->cp);
+   if (session->pcb_state_fs_changed) {
+      gen6_emit_3DSTATE_CONSTANT_PS(p->dev,
+            &p->state.wm.PUSH_CONSTANT_BUFFER,
+            &p->state.wm.PUSH_CONSTANT_BUFFER_size,
+            1, p->cp);
+   }
 
    /* 3DSTATE_WM */
    if (DIRTY(FS) || DIRTY(SAMPLER_FS) || DIRTY(BLEND) || DIRTY(DSA) ||
@@ -1189,27 +1193,83 @@ gen6_pipeline_state_pcb(struct ilo_3d_pipeline *p,
                         struct gen6_pipeline_session *session)
 {
    /* push constant buffer for VS */
-   if (DIRTY(VS) || DIRTY(CLIP)) {
+   if (DIRTY(VS) || DIRTY(CBUF) || DIRTY(CLIP)) {
+      const int cbuf0_size = (ilo->vs) ?
+            ilo_shader_get_kernel_param(ilo->vs,
+                  ILO_KERNEL_PCB_CBUF0_SIZE) : 0;
       const int clip_state_size = (ilo->vs) ?
             ilo_shader_get_kernel_param(ilo->vs,
                   ILO_KERNEL_VS_PCB_UCP_SIZE) : 0;
+      const int total_size = cbuf0_size + clip_state_size;
 
-      if (clip_state_size) {
+      if (total_size) {
          void *pcb;
 
-         p->state.vs.PUSH_CONSTANT_BUFFER_size = clip_state_size;
          p->state.vs.PUSH_CONSTANT_BUFFER =
-            gen6_emit_push_constant_buffer(p->dev,
-                  p->state.vs.PUSH_CONSTANT_BUFFER_size, &pcb, p->cp);
+            gen6_emit_push_constant_buffer(p->dev, total_size, &pcb, p->cp);
+         p->state.vs.PUSH_CONSTANT_BUFFER_size = total_size;
+
+         if (cbuf0_size) {
+            const struct ilo_cbuf_state *cbuf =
+               &ilo->cbuf[PIPE_SHADER_VERTEX];
+
+            if (cbuf0_size <= cbuf->cso[0].user_buffer_size) {
+               memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size);
+            }
+            else {
+               memcpy(pcb, cbuf->cso[0].user_buffer,
+                     cbuf->cso[0].user_buffer_size);
+               memset(pcb + cbuf->cso[0].user_buffer_size, 0,
+                     cbuf0_size - cbuf->cso[0].user_buffer_size);
+            }
+
+            pcb += cbuf0_size;
+         }
 
-         memcpy(pcb, &ilo->clip, clip_state_size);
+         if (clip_state_size)
+            memcpy(pcb, &ilo->clip, clip_state_size);
+
+         session->pcb_state_vs_changed = true;
       }
-      else {
-         p->state.vs.PUSH_CONSTANT_BUFFER_size = 0;
+      else if (p->state.vs.PUSH_CONSTANT_BUFFER_size) {
          p->state.vs.PUSH_CONSTANT_BUFFER = 0;
+         p->state.vs.PUSH_CONSTANT_BUFFER_size = 0;
+
+         session->pcb_state_vs_changed = true;
       }
+   }
 
-      session->pcb_state_vs_changed = true;
+   /* push constant buffer for FS */
+   if (DIRTY(FS) || DIRTY(CBUF)) {
+      const int cbuf0_size = (ilo->fs) ?
+         ilo_shader_get_kernel_param(ilo->fs, ILO_KERNEL_PCB_CBUF0_SIZE) : 0;
+
+      if (cbuf0_size) {
+         const struct ilo_cbuf_state *cbuf = &ilo->cbuf[PIPE_SHADER_FRAGMENT];
+         void *pcb;
+
+         p->state.wm.PUSH_CONSTANT_BUFFER =
+            gen6_emit_push_constant_buffer(p->dev, cbuf0_size, &pcb, p->cp);
+         p->state.wm.PUSH_CONSTANT_BUFFER_size = cbuf0_size;
+
+         if (cbuf0_size <= cbuf->cso[0].user_buffer_size) {
+            memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size);
+         }
+         else {
+            memcpy(pcb, cbuf->cso[0].user_buffer,
+                  cbuf->cso[0].user_buffer_size);
+            memset(pcb + cbuf->cso[0].user_buffer_size, 0,
+                  cbuf0_size - cbuf->cso[0].user_buffer_size);
+         }
+
+         session->pcb_state_fs_changed = true;
+      }
+      else if (p->state.wm.PUSH_CONSTANT_BUFFER_size) {
+         p->state.wm.PUSH_CONSTANT_BUFFER = 0;
+         p->state.wm.PUSH_CONSTANT_BUFFER_size = 0;
+
+         session->pcb_state_fs_changed = true;
+      }
    }
 }
 
@@ -1551,13 +1611,23 @@ gen6_pipeline_estimate_states(const struct ilo_3d_pipeline *p,
    }
 
    /* pcb (vs) */
-   if (ilo->vs &&
-       ilo_shader_get_kernel_param(ilo->vs, ILO_KERNEL_VS_PCB_UCP_SIZE)) {
-      const int pcb_size =
+   if (ilo->vs) {
+      const int cbuf0_size =
+         ilo_shader_get_kernel_param(ilo->vs, ILO_KERNEL_PCB_CBUF0_SIZE);
+      const int ucp_size =
          ilo_shader_get_kernel_param(ilo->vs, ILO_KERNEL_VS_PCB_UCP_SIZE);
 
       size += ilo_gpe_gen6_estimate_state_size(p->dev,
-            ILO_GPE_GEN6_PUSH_CONSTANT_BUFFER, pcb_size);
+            ILO_GPE_GEN6_PUSH_CONSTANT_BUFFER, cbuf0_size + ucp_size);
+   }
+
+   /* pcb (fs) */
+   if (ilo->fs) {
+      const int cbuf0_size =
+         ilo_shader_get_kernel_param(ilo->fs, ILO_KERNEL_PCB_CBUF0_SIZE);
+
+      size += ilo_gpe_gen6_estimate_state_size(p->dev,
+            ILO_GPE_GEN6_PUSH_CONSTANT_BUFFER, cbuf0_size);
    }
 
    return size;
index b489624a728078d5cb99b87b9962ab33fba4c0b7..b395f9beffb69e48bed10d6ab77490a65ba2a7b4 100644 (file)
@@ -754,13 +754,23 @@ gen7_pipeline_estimate_states(const struct ilo_3d_pipeline *p,
    }
 
    /* pcb (vs) */
-   if (ilo->vs &&
-       ilo_shader_get_kernel_param(ilo->vs, ILO_KERNEL_VS_PCB_UCP_SIZE)) {
-      const int pcb_size =
+   if (ilo->vs) {
+      const int cbuf0_size =
+         ilo_shader_get_kernel_param(ilo->vs, ILO_KERNEL_PCB_CBUF0_SIZE);
+      const int ucp_size =
          ilo_shader_get_kernel_param(ilo->vs, ILO_KERNEL_VS_PCB_UCP_SIZE);
 
       size += ilo_gpe_gen7_estimate_state_size(p->dev,
-            ILO_GPE_GEN7_PUSH_CONSTANT_BUFFER, pcb_size);
+            ILO_GPE_GEN7_PUSH_CONSTANT_BUFFER, cbuf0_size + ucp_size);
+   }
+
+   /* pcb (fs) */
+   if (ilo->fs) {
+      const int cbuf0_size =
+         ilo_shader_get_kernel_param(ilo->fs, ILO_KERNEL_PCB_CBUF0_SIZE);
+
+      size += ilo_gpe_gen7_estimate_state_size(p->dev,
+            ILO_GPE_GEN7_PUSH_CONSTANT_BUFFER, cbuf0_size);
    }
 
    return size;
index 0db03966c6b2bbcaeeb2b4c0bb33246e0f413a0a..b1a11a1391b4051bcfdb8cb8924cbb1e921c36e4 100644 (file)
@@ -1063,6 +1063,9 @@ ilo_shader_get_kernel_param(const struct ilo_shader_state *shader,
    case ILO_KERNEL_SKIP_CBUF0_UPLOAD:
       val = false;
       break;
+   case ILO_KERNEL_PCB_CBUF0_SIZE:
+      val = 0;
+      break;
 
    case ILO_KERNEL_VS_INPUT_INSTANCEID:
       val = shader->info.has_instanceid;
index 67f190c7bc04e42beae1f1d798f4eeb813716c18..d12b086ec8140588690819c952fcff555d7716a9 100644 (file)
@@ -35,6 +35,7 @@ enum ilo_kernel_param {
    ILO_KERNEL_OUTPUT_COUNT,
    ILO_KERNEL_URB_DATA_START_REG,
    ILO_KERNEL_SKIP_CBUF0_UPLOAD,
+   ILO_KERNEL_PCB_CBUF0_SIZE,
 
    ILO_KERNEL_VS_INPUT_INSTANCEID,
    ILO_KERNEL_VS_INPUT_VERTEXID,