r600g: set read/write usage flags for each relocation
[mesa.git] / src / gallium / drivers / r600 / r600_state_common.c
index 30c61817a08c82754e08c42492bf691203718e8d..53a1313a2a8b0b561ea4b5f4f9246e003c1161f8 100644 (file)
@@ -28,6 +28,7 @@
 #include <util/u_format.h>
 #include <pipebuffer/pb_buffer.h>
 #include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
 #include "r600_formats.h"
 #include "r600_pipe.h"
 #include "r600d.h"
@@ -99,6 +100,8 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state)
        if (state == NULL)
                return;
 
+       rctx->clamp_vertex_color = rs->clamp_vertex_color;
+       rctx->clamp_fragment_color = rs->clamp_fragment_color;
        rctx->flatshade = rs->flatshade;
        rctx->sprite_coord_enable = rs->sprite_coord_enable;
        rctx->rasterizer = rs;
@@ -106,13 +109,13 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state)
        rctx->states[rs->rstate.id] = &rs->rstate;
        r600_context_pipe_state_set(&rctx->ctx, &rs->rstate);
 
-       if (rctx->family >= CHIP_CEDAR) {
+       if (rctx->chip_class >= EVERGREEN) {
                evergreen_polygon_offset_update(rctx);
        } else {
                r600_polygon_offset_update(rctx);
        }
        if (rctx->ps_shader && rctx->vs_shader)
-               r600_spi_update(rctx);
+               rctx->spi_dirty = true;
 }
 
 void r600_delete_rs_state(struct pipe_context *ctx, void *state)
@@ -147,7 +150,7 @@ void r600_delete_state(struct pipe_context *ctx, void *state)
                rctx->states[rstate->id] = NULL;
        }
        for (int i = 0; i < rstate->nregs; i++) {
-               r600_bo_reference(rctx->radeon, &rstate->regs[i].bo, NULL);
+               r600_bo_reference(&rstate->regs[i].bo, NULL);
        }
        free(rstate);
 }
@@ -178,7 +181,7 @@ void r600_delete_vertex_element(struct pipe_context *ctx, void *state)
        if (rctx->vertex_elements == state)
                rctx->vertex_elements = NULL;
 
-       r600_bo_reference(rctx->radeon, &v->fetch_shader, NULL);
+       r600_bo_reference(&v->fetch_shader, NULL);
        u_vbuf_mgr_destroy_vertex_elements(rctx->vbuf_mgr, v->vmgr_elements);
        FREE(state);
 }
@@ -209,7 +212,7 @@ void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count,
        /* Zero states. */
        for (i = 0; i < count; i++) {
                if (!buffers[i].buffer) {
-                       if (rctx->family >= CHIP_CEDAR) {
+                       if (rctx->chip_class >= EVERGREEN) {
                                evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
                        } else {
                                r600_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
@@ -217,7 +220,7 @@ void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count,
                }
        }
        for (; i < rctx->vbuf_mgr->nr_real_vertex_buffers; i++) {
-               if (rctx->family >= CHIP_CEDAR) {
+               if (rctx->chip_class >= EVERGREEN) {
                        evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
                } else {
                        r600_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
@@ -257,7 +260,9 @@ void *r600_create_shader_state(struct pipe_context *ctx,
        struct r600_pipe_shader *shader =  CALLOC_STRUCT(r600_pipe_shader);
        int r;
 
-       r =  r600_pipe_shader_create(ctx, shader, state->tokens);
+       shader->tokens = tgsi_dup_tokens(state->tokens);
+
+       r =  r600_pipe_shader_create(ctx, shader);
        if (r) {
                return NULL;
        }
@@ -274,7 +279,7 @@ void r600_bind_ps_shader(struct pipe_context *ctx, void *state)
                r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_shader->rstate);
        }
        if (rctx->ps_shader && rctx->vs_shader) {
-               r600_spi_update(rctx);
+               rctx->spi_dirty = true;
                r600_adjust_gprs(rctx);
        }
 }
@@ -289,7 +294,7 @@ void r600_bind_vs_shader(struct pipe_context *ctx, void *state)
                r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_shader->rstate);
        }
        if (rctx->ps_shader && rctx->vs_shader) {
-               r600_spi_update(rctx);
+               rctx->spi_dirty = true;
                r600_adjust_gprs(rctx);
        }
 }
@@ -303,6 +308,7 @@ void r600_delete_ps_shader(struct pipe_context *ctx, void *state)
                rctx->ps_shader = NULL;
        }
 
+       free(shader->tokens);
        r600_pipe_shader_destroy(ctx, shader);
        free(shader);
 }
@@ -316,6 +322,7 @@ void r600_delete_vs_shader(struct pipe_context *ctx, void *state)
                rctx->vs_shader = NULL;
        }
 
+       free(shader->tokens);
        r600_pipe_shader_destroy(ctx, shader);
        free(shader);
 }
@@ -329,7 +336,7 @@ static void r600_update_alpha_ref(struct r600_pipe_context *rctx)
        rstate.nregs = 0;
        if (rctx->export_16bpc)
                alpha_ref &= ~0x1FFF;
-       r600_pipe_state_add_reg(&rstate, R_028438_SX_ALPHA_REF, alpha_ref, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(&rstate, R_028438_SX_ALPHA_REF, alpha_ref, 0xFFFFFFFF, NULL, 0);
 
        r600_context_pipe_state_set(&rctx->ctx, &rstate);
        rctx->alpha_ref_dirty = false;
@@ -342,7 +349,7 @@ static void r600_spi_block_init(struct r600_pipe_context *rctx, struct r600_pipe
        rstate->nregs = 0;
        rstate->id = R600_PIPE_STATE_SPI;
        for (i = 0; i < 32; i++) {
-               r600_pipe_state_add_reg(rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, 0, 0xFFFFFFFF, NULL);
+               r600_pipe_state_add_reg(rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, 0, 0xFFFFFFFF, NULL, 0);
        }
 }
 
@@ -360,7 +367,7 @@ static void r600_spi_update(struct r600_pipe_context *rctx)
        for (i = 0; i < rshader->ninput; i++) {
                if (rshader->input[i].name == TGSI_SEMANTIC_POSITION ||
                    rshader->input[i].name == TGSI_SEMANTIC_FACE)
-                       if (rctx->family >= CHIP_CEDAR)
+                       if (rctx->chip_class >= EVERGREEN)
                                continue;
                        else
                                sid=0;
@@ -380,7 +387,7 @@ static void r600_spi_update(struct r600_pipe_context *rctx)
                        tmp |= S_028644_PT_SPRITE_TEX(1);
                }
 
-               if (rctx->family < CHIP_CEDAR) {
+               if (rctx->chip_class < EVERGREEN) {
                        if (rshader->input[i].centroid)
                                tmp |= S_028644_SEL_CENTROID(1);
 
@@ -391,6 +398,7 @@ static void r600_spi_update(struct r600_pipe_context *rctx)
                r600_pipe_state_mod_reg(rstate, tmp);
        }
 
+       rctx->spi_dirty = false;
        r600_context_pipe_state_set(&rctx->ctx, rstate);
 }
 
@@ -410,7 +418,6 @@ void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
        }
 
        r600_upload_const_buffer(rctx, &rbuffer, &offset);
-       offset += r600_bo_offset(rbuffer->r.bo);
 
        switch (shader) {
        case PIPE_SHADER_VERTEX:
@@ -418,26 +425,26 @@ void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
                r600_pipe_state_add_reg(&rctx->vs_const_buffer,
                                        R_028180_ALU_CONST_BUFFER_SIZE_VS_0,
                                        ALIGN_DIVUP(buffer->width0 >> 4, 16),
-                                       0xFFFFFFFF, NULL);
+                                       0xFFFFFFFF, NULL, 0);
                r600_pipe_state_add_reg(&rctx->vs_const_buffer,
                                        R_028980_ALU_CONST_CACHE_VS_0,
-                                       offset >> 8, 0xFFFFFFFF, rbuffer->r.bo);
+                                       offset >> 8, 0xFFFFFFFF, rbuffer->r.bo, RADEON_USAGE_READ);
                r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_const_buffer);
 
                rstate = &rctx->vs_const_buffer_resource[index];
                if (!rstate->id) {
-                       if (rctx->family >= CHIP_CEDAR) {
+                       if (rctx->chip_class >= EVERGREEN) {
                                evergreen_pipe_init_buffer_resource(rctx, rstate);
                        } else {
                                r600_pipe_init_buffer_resource(rctx, rstate);
                        }
                }
 
-               if (rctx->family >= CHIP_CEDAR) {
-                       evergreen_pipe_mod_buffer_resource(rstate, &rbuffer->r, offset, 16);
+               if (rctx->chip_class >= EVERGREEN) {
+                       evergreen_pipe_mod_buffer_resource(rstate, &rbuffer->r, offset, 16, RADEON_USAGE_READ);
                        evergreen_context_pipe_state_set_vs_resource(&rctx->ctx, rstate, index);
                } else {
-                       r600_pipe_mod_buffer_resource(rstate, &rbuffer->r, offset, 16);
+                       r600_pipe_mod_buffer_resource(rstate, &rbuffer->r, offset, 16, RADEON_USAGE_READ);
                        r600_context_pipe_state_set_vs_resource(&rctx->ctx, rstate, index);
                }
                break;
@@ -446,25 +453,25 @@ void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
                r600_pipe_state_add_reg(&rctx->ps_const_buffer,
                                        R_028140_ALU_CONST_BUFFER_SIZE_PS_0,
                                        ALIGN_DIVUP(buffer->width0 >> 4, 16),
-                                       0xFFFFFFFF, NULL);
+                                       0xFFFFFFFF, NULL, 0);
                r600_pipe_state_add_reg(&rctx->ps_const_buffer,
                                        R_028940_ALU_CONST_CACHE_PS_0,
-                                       offset >> 8, 0xFFFFFFFF, rbuffer->r.bo);
+                                       offset >> 8, 0xFFFFFFFF, rbuffer->r.bo, RADEON_USAGE_READ);
                r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_const_buffer);
 
                rstate = &rctx->ps_const_buffer_resource[index];
                if (!rstate->id) {
-                       if (rctx->family >= CHIP_CEDAR) {
+                       if (rctx->chip_class >= EVERGREEN) {
                                evergreen_pipe_init_buffer_resource(rctx, rstate);
                        } else {
                                r600_pipe_init_buffer_resource(rctx, rstate);
                        }
                }
-               if (rctx->family >= CHIP_CEDAR) {
-                       evergreen_pipe_mod_buffer_resource(rstate, &rbuffer->r, offset, 16);
+               if (rctx->chip_class >= EVERGREEN) {
+                       evergreen_pipe_mod_buffer_resource(rstate, &rbuffer->r, offset, 16, RADEON_USAGE_READ);
                        evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, rstate, index);
                } else {
-                       r600_pipe_mod_buffer_resource(rstate, &rbuffer->r, offset, 16);
+                       r600_pipe_mod_buffer_resource(rstate, &rbuffer->r, offset, 16, RADEON_USAGE_READ);
                        r600_context_pipe_state_set_ps_resource(&rctx->ctx, rstate, index);
                }
                break;
@@ -510,26 +517,41 @@ static void r600_vertex_buffer_update(struct r600_pipe_context *rctx)
                }
                if (vertex_buffer == NULL || rbuffer == NULL)
                        continue;
-               offset += vertex_buffer->buffer_offset + r600_bo_offset(rbuffer->bo);
+               offset += vertex_buffer->buffer_offset;
 
                if (!rstate->id) {
-                       if (rctx->family >= CHIP_CEDAR) {
+                       if (rctx->chip_class >= EVERGREEN) {
                                evergreen_pipe_init_buffer_resource(rctx, rstate);
                        } else {
                                r600_pipe_init_buffer_resource(rctx, rstate);
                        }
                }
 
-               if (rctx->family >= CHIP_CEDAR) {
-                       evergreen_pipe_mod_buffer_resource(rstate, rbuffer, offset, vertex_buffer->stride);
+               if (rctx->chip_class >= EVERGREEN) {
+                       evergreen_pipe_mod_buffer_resource(rstate, rbuffer, offset, vertex_buffer->stride, RADEON_USAGE_READ);
                        evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i);
                } else {
-                       r600_pipe_mod_buffer_resource(rstate, rbuffer, offset, vertex_buffer->stride);
+                       r600_pipe_mod_buffer_resource(rstate, rbuffer, offset, vertex_buffer->stride, RADEON_USAGE_READ);
                        r600_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i);
                }
        }
 }
 
+static int r600_shader_rebuild(struct pipe_context * ctx, struct r600_pipe_shader * shader)
+{
+       struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
+       int r;
+
+       r600_pipe_shader_destroy(ctx, shader);
+       r = r600_pipe_shader_create(ctx, shader);
+       if (r) {
+               return r;
+       }
+       r600_context_pipe_state_set(&rctx->ctx, &shader->rstate);
+
+       return 0;
+}
+
 void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 {
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
@@ -573,6 +595,17 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
        if (r600_conv_pipe_prim(draw.info.mode, &prim))
                return;
 
+       if (rctx->vs_shader->shader.clamp_color != rctx->clamp_vertex_color)
+               r600_shader_rebuild(ctx, rctx->vs_shader);
+
+       if ((rctx->ps_shader->shader.clamp_color != rctx->clamp_fragment_color) ||
+           ((rctx->chip_class >= EVERGREEN) && rctx->ps_shader->shader.fs_write_all &&
+            (rctx->ps_shader->shader.nr_cbufs != rctx->nr_cbufs)))
+               r600_shader_rebuild(ctx, rctx->ps_shader);
+
+       if (rctx->spi_dirty)
+               r600_spi_update(rctx);
+
        if (rctx->alpha_ref_dirty)
                r600_update_alpha_ref(rctx);
 
@@ -581,16 +614,16 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
        if (rctx->vgt.id != R600_PIPE_STATE_VGT) {
                rctx->vgt.id = R600_PIPE_STATE_VGT;
                rctx->vgt.nregs = 0;
-               r600_pipe_state_add_reg(&rctx->vgt, R_008958_VGT_PRIMITIVE_TYPE, prim, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(&rctx->vgt, R_028238_CB_TARGET_MASK, rctx->cb_target_mask & mask, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(&rctx->vgt, R_028400_VGT_MAX_VTX_INDX, draw.info.max_index, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(&rctx->vgt, R_028404_VGT_MIN_VTX_INDX, draw.info.min_index, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(&rctx->vgt, R_028408_VGT_INDX_OFFSET, draw.info.index_bias, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(&rctx->vgt, R_03CFF0_SQ_VTX_BASE_VTX_LOC, 0, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(&rctx->vgt, R_03CFF4_SQ_VTX_START_INST_LOC, draw.info.start_instance, 0xFFFFFFFF, NULL);
+               r600_pipe_state_add_reg(&rctx->vgt, R_008958_VGT_PRIMITIVE_TYPE, prim, 0xFFFFFFFF, NULL, 0);
+               r600_pipe_state_add_reg(&rctx->vgt, R_028238_CB_TARGET_MASK, rctx->cb_target_mask & mask, 0xFFFFFFFF, NULL, 0);
+               r600_pipe_state_add_reg(&rctx->vgt, R_028400_VGT_MAX_VTX_INDX, draw.info.max_index, 0xFFFFFFFF, NULL, 0);
+               r600_pipe_state_add_reg(&rctx->vgt, R_028404_VGT_MIN_VTX_INDX, draw.info.min_index, 0xFFFFFFFF, NULL, 0);
+               r600_pipe_state_add_reg(&rctx->vgt, R_028408_VGT_INDX_OFFSET, draw.info.index_bias, 0xFFFFFFFF, NULL, 0);
+               r600_pipe_state_add_reg(&rctx->vgt, R_03CFF0_SQ_VTX_BASE_VTX_LOC, 0, 0xFFFFFFFF, NULL, 0);
+               r600_pipe_state_add_reg(&rctx->vgt, R_03CFF4_SQ_VTX_START_INST_LOC, draw.info.start_instance, 0xFFFFFFFF, NULL, 0);
                r600_pipe_state_add_reg(&rctx->vgt, R_028814_PA_SU_SC_MODE_CNTL,
                                        0,
-                                       S_028814_PROVOKING_VTX_LAST(1), NULL);
+                                       S_028814_PROVOKING_VTX_LAST(1), NULL, 0);
 
        }
 
@@ -621,7 +654,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
                rdraw.indices_bo_offset = draw.index_buffer_offset;
        }
 
-       if (rctx->family >= CHIP_CEDAR) {
+       if (rctx->chip_class >= EVERGREEN) {
                evergreen_context_draw(&rctx->ctx, &rdraw);
        } else {
                r600_context_draw(&rctx->ctx, &rdraw);
@@ -642,11 +675,14 @@ void _r600_pipe_state_add_reg(struct r600_context *ctx,
                              struct r600_pipe_state *state,
                              u32 offset, u32 value, u32 mask,
                              u32 range_id, u32 block_id,
-                             struct r600_bo *bo)
+                             struct r600_bo *bo,
+                             enum radeon_bo_usage usage)
 {
        struct r600_range *range;
        struct r600_block *block;
 
+       if (bo) assert(usage);
+
        range = &ctx->range[range_id];
        block = range->blocks[block_id];
        state->regs[state->nregs].block = block;
@@ -655,6 +691,7 @@ void _r600_pipe_state_add_reg(struct r600_context *ctx,
        state->regs[state->nregs].value = value;
        state->regs[state->nregs].mask = mask;
        state->regs[state->nregs].bo = bo;
+       state->regs[state->nregs].bo_usage = usage;
 
        state->nregs++;
        assert(state->nregs < R600_BLOCK_MAX_REG);
@@ -662,13 +699,17 @@ void _r600_pipe_state_add_reg(struct r600_context *ctx,
 
 void r600_pipe_state_add_reg_noblock(struct r600_pipe_state *state,
                                     u32 offset, u32 value, u32 mask,
-                                    struct r600_bo *bo)
+                                    struct r600_bo *bo,
+                                    enum radeon_bo_usage usage)
 {
+       if (bo) assert(usage);
+
        state->regs[state->nregs].id = offset;
        state->regs[state->nregs].block = NULL;
        state->regs[state->nregs].value = value;
        state->regs[state->nregs].mask = mask;
        state->regs[state->nregs].bo = bo;
+       state->regs[state->nregs].bo_usage = usage;
 
        state->nregs++;
        assert(state->nregs < R600_BLOCK_MAX_REG);