diff options
Diffstat (limited to 'src/gallium/drivers/i965/brw_wm_constant_buffer.c')
-rw-r--r-- | src/gallium/drivers/i965/brw_wm_constant_buffer.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/gallium/drivers/i965/brw_wm_constant_buffer.c b/src/gallium/drivers/i965/brw_wm_constant_buffer.c new file mode 100644 index 0000000000..6434c6acf7 --- /dev/null +++ b/src/gallium/drivers/i965/brw_wm_constant_buffer.c @@ -0,0 +1,165 @@ +/* XXX: Constant buffers disabled + */ + + +/** + * Create the constant buffer surface. Vertex/fragment shader constants will be + * read from this buffer with Data Port Read instructions/messages. + */ +enum pipe_error +brw_create_constant_surface( struct brw_context *brw, + struct brw_surface_key *key, + struct brw_winsys_buffer **bo_out ) +{ + const GLint w = key->width - 1; + struct brw_winsys_buffer *bo; + struct brw_winsys_reloc reloc[1]; + enum pipe_error ret; + + /* Emit relocation to surface contents */ + make_reloc(&reloc[0], + BRW_USAGE_SAMPLER, + 0, + offsetof(struct brw_surface_state, ss1), + key->bo); + + + memset(&surf, 0, sizeof(surf)); + + surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; + surf.ss0.surface_type = BRW_SURFACE_BUFFER; + surf.ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; + + surf.ss1.base_addr = 0; /* reloc */ + + surf.ss2.width = w & 0x7f; /* bits 6:0 of size or width */ + surf.ss2.height = (w >> 7) & 0x1fff; /* bits 19:7 of size or width */ + surf.ss3.depth = (w >> 20) & 0x7f; /* bits 26:20 of size or width */ + surf.ss3.pitch = (key->pitch * key->cpp) - 1; /* ignored?? */ + brw_set_surface_tiling(&surf, key->tiling); /* tiling now allowed */ + + ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, + key, sizeof(*key), + reloc, Elements(reloc), + &surf, sizeof(surf), + NULL, NULL, + &bo_out); + if (ret) + return ret; + + return PIPE_OK; +} + + + +/** + * Update the surface state for a WM constant buffer. + * The constant buffer will be (re)allocated here if needed. + */ +static enum pipe_error +brw_update_wm_constant_surface( struct brw_context *brw, + GLuint surf) +{ + struct brw_surface_key key; + struct brw_fragment_shader *fp = brw->curr.fragment_shader; + struct pipe_buffer *cbuf = brw->curr.fragment_constants; + int pitch = cbuf->size / (4 * sizeof(float)); + enum pipe_error ret; + + /* If we're in this state update atom, we need to update WM constants, so + * free the old buffer and create a new one for the new contents. + */ + ret = brw_wm_update_constant_buffer(brw, &fp->const_buffer); + if (ret) + return ret; + + /* If there's no constant buffer, then no surface BO is needed to point at + * it. + */ + if (cbuf == NULL) { + bo_reference(&brw->wm.surf_bo[surf], NULL); + return PIPE_OK; + } + + memset(&key, 0, sizeof(key)); + + key.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; + key.ss0.surface_type = BRW_SURFACE_BUFFER; + key.ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; + + key.bo = brw_buffer(cbuf)->bo; + + key.ss2.width = (pitch-1) & 0x7f; /* bits 6:0 of size or width */ + key.ss2.height = ((pitch-1) >> 7) & 0x1fff; /* bits 19:7 of size or width */ + key.ss3.depth = ((pitch-1) >> 20) & 0x7f; /* bits 26:20 of size or width */ + key.ss3.pitch = (pitch * 4 * sizeof(float)) - 1; /* ignored?? */ + brw_set_surface_tiling(&surf, key->tiling); /* tiling now allowed */ + + + /* + printf("%s:\n", __FUNCTION__); + printf(" width %d height %d depth %d cpp %d pitch %d\n", + key.width, key.height, key.depth, key.cpp, key.pitch); + */ + + if (brw_search_cache(&brw->surface_cache, + BRW_SS_SURFACE, + &key, sizeof(key), + &key.bo, 1, + NULL, + &brw->wm.surf_bo[surf])) + return PIPE_OK; + + ret = brw_create_constant_surface(brw, &key, &brw->wm.surf_bo[surf]); + if (ret) + return ret; + + brw->state.dirty.brw |= BRW_NEW_WM_SURFACES; + return PIPE_OK; +} + +/** + * Updates surface / buffer for fragment shader constant buffer, if + * one is required. + * + * This consumes the state updates for the constant buffer, and produces + * BRW_NEW_WM_SURFACES to get picked up by brw_prepare_wm_surfaces for + * inclusion in the binding table. + */ +static enum pipe_error prepare_wm_constant_surface(struct brw_context *brw ) +{ + struct brw_fragment_program *fp = + (struct brw_fragment_program *) brw->fragment_program; + GLuint surf = SURF_INDEX_FRAG_CONST_BUFFER; + + ret = brw_wm_update_constant_buffer(brw, + &fp->const_buffer); + if (ret) + return ret; + + /* If there's no constant buffer, then no surface BO is needed to point at + * it. + */ + if (fp->const_buffer == 0) { + if (brw->wm.surf_bo[surf] != NULL) { + bo_reference(&brw->wm.surf_bo[surf], NULL); + brw->state.dirty.brw |= BRW_NEW_WM_SURFACES; + } + return PIPE_OK; + } + + ret = brw_update_wm_constant_surface(ctx, surf); + if (ret) + return ret; + + return PIPE_OK +} + +const struct brw_tracked_state brw_wm_constant_surface = { + .dirty = { + .mesa = (_NEW_PROGRAM_CONSTANTS), + .brw = (BRW_NEW_FRAGMENT_PROGRAM), + .cache = 0 + }, + .prepare = prepare_wm_constant_surface, +}; |