[Mesa-dev] [PATCH 20/27] i965/fs: Pack UBO registers right after uniform registers

Abdiel Janulgue abdiel.janulgue at linux.intel.com
Tue Apr 28 13:08:17 PDT 2015


By generating the generating the gather constants channel mask.
Each gather push constant entry equates to a constant buffer
fetch for entries scattered around the buffer in 128-bit increments.
To select which bits are loaded into an entry, a channel mask
interface is provided by the hardware to narrow down which channels
are loaded to the packing gather pool.This patch generates the mask
for enabled entries.

This is accomplished by basically walking and appending the live registers
to this channel mask. Note that the the ir_swizzle visitor which is run
prior to assign_push_constant_locations() determines which registers
are loaded in the push constant array.

We have two sources of constant buffers: UBOs and ordinary uniforms.
After assigning a block of push constant hw-register to normal uniforms,
just pack the UBO registers right after it.

Signed-off-by: Abdiel Janulgue <abdiel.janulgue at linux.intel.com>
---
 src/mesa/drivers/dri/i965/brw_fs.cpp | 43 ++++++++++++++++++++++++++++--------
 1 file changed, 34 insertions(+), 9 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 031d807..e4d6300 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -1145,7 +1145,10 @@ fs_visitor::import_uniforms(fs_visitor *v)
    this->push_constant_loc = v->push_constant_loc;
    this->pull_constant_loc = v->pull_constant_loc;
    this->uniforms = v->uniforms;
+   this->ubo_uniforms = v->ubo_uniforms;
    this->param_size = v->param_size;
+   this->nr_ubo_gather_table = v->nr_ubo_gather_table;
+   this->ubo_gather_table = v->ubo_gather_table;
 }
 
 /* Our support for uniforms is piggy-backed on the struct
@@ -1724,7 +1727,8 @@ fs_visitor::assign_curb_setup()
       prog_data->dispatch_grf_start_reg_16 = payload.num_regs;
    }
 
-   prog_data->curb_read_length = ALIGN(stage_prog_data->nr_params, 8) / 8;
+   prog_data->curb_read_length = ALIGN(stage_prog_data->nr_params + stage_prog_data->nr_ubo_params,
+                                       8) / 8;
 
    /* Map the offsets in the UNIFORM file to fixed HW regs. */
    foreach_block_and_inst(block, fs_inst, inst, cfg) {
@@ -1732,7 +1736,7 @@ fs_visitor::assign_curb_setup()
 	 if (inst->src[i].file == UNIFORM) {
             int uniform_nr = inst->src[i].reg + inst->src[i].reg_offset;
             int constant_nr;
-            if (uniform_nr >= 0 && uniform_nr < (int) uniforms) {
+            if (uniform_nr >= 0 && uniform_nr < (int) (uniforms + ubo_uniforms)) {
                constant_nr = push_constant_loc[uniform_nr];
             } else {
                /* Section 5.11 of the OpenGL 4.1 spec says:
@@ -2167,8 +2171,9 @@ fs_visitor::move_uniform_array_access_to_pull_constants()
    if (dispatch_width != 8)
       return;
 
-   pull_constant_loc = ralloc_array(mem_ctx, int, uniforms);
-   memset(pull_constant_loc, -1, sizeof(pull_constant_loc[0]) * uniforms);
+   unsigned int total_uniforms = uniforms + ubo_uniforms;
+   pull_constant_loc = ralloc_array(mem_ctx, int, total_uniforms);
+   memset(pull_constant_loc, -1, sizeof(pull_constant_loc[0]) * total_uniforms);
 
    /* Walk through and find array access of uniforms.  Put a copy of that
     * uniform in the pull constant buffer.
@@ -2218,9 +2223,10 @@ fs_visitor::assign_constant_locations()
    if (dispatch_width != 8)
       return;
 
+   unsigned int total_uniforms = uniforms + ubo_uniforms;
    /* Find which UNIFORM registers are still in use. */
-   bool is_live[uniforms];
-   for (unsigned int i = 0; i < uniforms; i++) {
+   bool is_live[total_uniforms];
+   for (unsigned int i = 0; i < total_uniforms; i++) {
       is_live[i] = false;
    }
 
@@ -2230,8 +2236,26 @@ fs_visitor::assign_constant_locations()
             continue;
 
          int constant_nr = inst->src[i].reg + inst->src[i].reg_offset;
-         if (constant_nr >= 0 && constant_nr < (int) uniforms)
+         if (constant_nr >= 0 && constant_nr < (int) total_uniforms) {
             is_live[constant_nr] = true;
+
+            for (unsigned int p = 0; p < this->nr_ubo_gather_table; p++) {
+               if (this->ubo_gather_table[p].reg == inst->src[i].reg) {
+                  /* Generate the channel mask to determine which entries starting from
+                   * the offset above should be packed into the 16-byte entry. If the
+                   * offset is aligned to a 16-byte boundary, just set the position based on
+                   * the reg_offset. Otherwise, set the mask based on the positon of the offset
+                   * from the boundary.
+                   */
+                  unsigned mask = ((this->ubo_gather_table[p].const_offset % 16) == 0) ?
+                     1 << inst->src[i].reg_offset :
+                     1 << ((this->ubo_gather_table[p].const_offset % 16) / 4);
+
+                  this->ubo_gather_table[p].channel_mask |= mask;
+                  break;
+               }
+            }
+         }
       }
    }
 
@@ -2246,9 +2270,9 @@ fs_visitor::assign_constant_locations()
    unsigned int max_push_components = 16 * 8;
    unsigned int num_push_constants = 0;
 
-   push_constant_loc = ralloc_array(mem_ctx, int, uniforms);
+   push_constant_loc = ralloc_array(mem_ctx, int, total_uniforms);
 
-   for (unsigned int i = 0; i < uniforms; i++) {
+   for (unsigned int i = 0; i < total_uniforms; i++) {
       if (!is_live[i] || pull_constant_loc[i] != -1) {
          /* This UNIFORM register is either dead, or has already been demoted
           * to a pull const.  Mark it as no longer living in the param[] array.
@@ -2267,6 +2291,7 @@ fs_visitor::assign_constant_locations()
          push_constant_loc[i] = -1;
 
          int pull_index = stage_prog_data->nr_pull_params++;
+         assert(pull_index < ubo_uniforms);
          stage_prog_data->pull_param[pull_index] = stage_prog_data->param[i];
          pull_constant_loc[i] = pull_index;
       }
-- 
1.9.1



More information about the mesa-dev mailing list