vc4: Add support for 16-bit signed/unsigned norm/scaled vertex attrs.
[mesa.git] / src / gallium / drivers / r600 / r600_state_common.c
index d29e137d511a6b08fce1e668cdd8726b49700736..09d8952844fa5b9c6351b3ec9fd6ec83b83a1a6d 100644 (file)
@@ -28,7 +28,6 @@
 #include "r600_shader.h"
 #include "r600d.h"
 
-#include "util/u_draw_quad.h"
 #include "util/u_format_s3tc.h"
 #include "util/u_index_modify.h"
 #include "util/u_memory.h"
@@ -36,8 +35,6 @@
 #include "util/u_math.h"
 #include "tgsi/tgsi_parse.h"
 
-#define R600_PRIM_RECTANGLE_LIST PIPE_PRIM_MAX
-
 void r600_init_command_buffer(struct r600_command_buffer *cb, unsigned num_dw)
 {
        assert(!cb->buf);
@@ -161,8 +158,10 @@ static void r600_bind_blend_state(struct pipe_context *ctx, void *state)
        struct r600_context *rctx = (struct r600_context *)ctx;
        struct r600_blend_state *blend = (struct r600_blend_state *)state;
 
-       if (blend == NULL)
+       if (blend == NULL) {
+               r600_set_cso_state_with_cb(&rctx->blend_state, NULL, NULL);
                return;
+       }
 
        r600_bind_blend_state_internal(rctx, blend, rctx->force_blend_disable);
 }
@@ -450,8 +449,13 @@ static void r600_delete_sampler_state(struct pipe_context *ctx, void *state)
 
 static void r600_delete_blend_state(struct pipe_context *ctx, void *state)
 {
+       struct r600_context *rctx = (struct r600_context *)ctx;
        struct r600_blend_state *blend = (struct r600_blend_state*)state;
 
+       if (rctx->blend_state.cso == state) {
+               ctx->bind_blend_state(ctx, NULL);
+       }
+
        r600_release_command_buffer(&blend->buffer);
        r600_release_command_buffer(&blend->buffer_no_blend);
        FREE(blend);
@@ -645,7 +649,6 @@ static void r600_set_sampler_views(struct pipe_context *pipe, unsigned shader,
        dst->views.dirty_mask |= new_mask;
        dst->views.compressed_depthtex_mask &= dst->views.enabled_mask;
        dst->views.compressed_colortex_mask &= dst->views.enabled_mask;
-       dst->views.dirty_txq_constants = TRUE;
        dst->views.dirty_buffer_constants = TRUE;
        r600_sampler_views_dirty(rctx, &dst->views);
 
@@ -980,6 +983,7 @@ static void r600_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask
  * then in the shader, we AND the 4 components with 0xffffffff or 0,
  * then OR the alpha with the value given here.
  * We use a 6th constant to store the txq buffer size in
+ * we use 7th slot for number of cube layers in a cube map array.
  */
 static void r600_setup_buffer_constants(struct r600_context *rctx, int shader_type)
 {
@@ -1018,6 +1022,7 @@ static void r600_setup_buffer_constants(struct r600_context *rctx, int shader_ty
                                samplers->buffer_constants[offset + 4] = 0;
 
                        samplers->buffer_constants[offset + 5] = samplers->views.views[i]->base.texture->width0 / util_format_get_blocksize(samplers->views.views[i]->base.format);
+                       samplers->buffer_constants[offset + 6] = samplers->views.views[i]->base.texture->array_size / 6;
                }
        }
 
@@ -1029,7 +1034,10 @@ static void r600_setup_buffer_constants(struct r600_context *rctx, int shader_ty
        pipe_resource_reference(&cb.buffer, NULL);
 }
 
-/* On evergreen we only need to store the buffer size for TXQ */
+/* On evergreen we store two values
+ * 1. buffer size for TXQ
+ * 2. number of cube layers in a cube map array.
+ */
 static void eg_setup_buffer_constants(struct r600_context *rctx, int shader_type)
 {
        struct r600_textures_info *samplers = &rctx->samplers[shader_type];
@@ -1044,12 +1052,16 @@ static void eg_setup_buffer_constants(struct r600_context *rctx, int shader_type
        samplers->views.dirty_buffer_constants = FALSE;
 
        bits = util_last_bit(samplers->views.enabled_mask);
-       array_size = bits * sizeof(uint32_t) * 4;
+       array_size = bits * 2 * sizeof(uint32_t) * 4;
        samplers->buffer_constants = realloc(samplers->buffer_constants, array_size);
        memset(samplers->buffer_constants, 0, array_size);
-       for (i = 0; i < bits; i++)
-               if (samplers->views.enabled_mask & (1 << i))
-                  samplers->buffer_constants[i] = samplers->views.views[i]->base.texture->width0 / util_format_get_blocksize(samplers->views.views[i]->base.format);
+       for (i = 0; i < bits; i++) {
+               if (samplers->views.enabled_mask & (1 << i)) {
+                       uint32_t offset = i * 2;
+                       samplers->buffer_constants[offset] = samplers->views.views[i]->base.texture->width0 / util_format_get_blocksize(samplers->views.views[i]->base.format);
+                       samplers->buffer_constants[offset + 1] = samplers->views.views[i]->base.texture->array_size / 6;
+               }
+       }
 
        cb.buffer = NULL;
        cb.user_buffer = samplers->buffer_constants;
@@ -1059,33 +1071,27 @@ static void eg_setup_buffer_constants(struct r600_context *rctx, int shader_type
        pipe_resource_reference(&cb.buffer, NULL);
 }
 
-static void r600_setup_txq_cube_array_constants(struct r600_context *rctx, int shader_type)
+/* set sample xy locations as array of fragment shader constants */
+void r600_set_sample_locations_constant_buffer(struct r600_context *rctx)
 {
-       struct r600_textures_info *samplers = &rctx->samplers[shader_type];
-       int bits;
-       uint32_t array_size;
-       struct pipe_constant_buffer cb;
+       struct pipe_constant_buffer constbuf = {0};
+       float values[4*16] = {0.0f};
        int i;
+       struct pipe_context *ctx = &rctx->b.b;
 
-       if (!samplers->views.dirty_txq_constants)
-               return;
-
-       samplers->views.dirty_txq_constants = FALSE;
-
-       bits = util_last_bit(samplers->views.enabled_mask);
-       array_size = bits * sizeof(uint32_t) * 4;
-       samplers->txq_constants = realloc(samplers->txq_constants, array_size);
-       memset(samplers->txq_constants, 0, array_size);
-       for (i = 0; i < bits; i++)
-               if (samplers->views.enabled_mask & (1 << i))
-                       samplers->txq_constants[i] = samplers->views.views[i]->base.texture->array_size / 6;
+       assert(rctx->framebuffer.nr_samples <= Elements(values)/4);
+       for (i = 0; i < rctx->framebuffer.nr_samples; i++) {
+               ctx->get_sample_position(ctx, rctx->framebuffer.nr_samples, i, &values[4*i]);
+               /* Also fill in center-zeroed positions used for interpolateAtSample */
+               values[4*i + 2] = values[4*i + 0] - 0.5f;
+               values[4*i + 3] = values[4*i + 1] - 0.5f;
+       }
 
-       cb.buffer = NULL;
-       cb.user_buffer = samplers->txq_constants;
-       cb.buffer_offset = 0;
-       cb.buffer_size = array_size;
-       rctx->b.b.set_constant_buffer(&rctx->b.b, shader_type, R600_TXQ_CONST_BUFFER, &cb);
-       pipe_resource_reference(&cb.buffer, NULL);
+       constbuf.user_buffer = values;
+       constbuf.buffer_size = rctx->framebuffer.nr_samples * 4 * 4;
+       ctx->set_constant_buffer(ctx, PIPE_SHADER_FRAGMENT,
+               R600_SAMPLE_POSITIONS_CONST_BUFFER, &constbuf);
+       pipe_resource_reference(&constbuf.buffer, NULL);
 }
 
 static void update_shader_atom(struct pipe_context *ctx,
@@ -1148,7 +1154,7 @@ static bool r600_update_derived_state(struct r600_context *rctx)
        struct pipe_context * ctx = (struct pipe_context*)rctx;
        bool ps_dirty = false, vs_dirty = false, gs_dirty = false;
        bool blend_disable;
-
+       bool need_buf_const;
        if (!rctx->blitter->running) {
                unsigned i;
 
@@ -1230,7 +1236,9 @@ static bool r600_update_derived_state(struct r600_context *rctx)
        if (unlikely(!rctx->ps_shader->current))
                return false;
 
-       if (unlikely(ps_dirty || rctx->pixel_shader.shader != rctx->ps_shader->current)) {
+       if (unlikely(ps_dirty || rctx->pixel_shader.shader != rctx->ps_shader->current ||
+               rctx->rasterizer->sprite_coord_enable != rctx->ps_shader->current->sprite_coord_enable ||
+               rctx->rasterizer->flatshade != rctx->ps_shader->current->flatshade)) {
 
                if (rctx->cb_misc_state.nr_ps_color_outputs != rctx->ps_shader->current->nr_ps_color_outputs) {
                        rctx->cb_misc_state.nr_ps_color_outputs = rctx->ps_shader->current->nr_ps_color_outputs;
@@ -1246,12 +1254,6 @@ static bool r600_update_derived_state(struct r600_context *rctx)
                        }
                }
 
-               if (rctx->b.chip_class >= EVERGREEN) {
-                       evergreen_update_db_shader_control(rctx);
-               } else {
-                       r600_update_db_shader_control(rctx);
-               }
-
                if (unlikely(!ps_dirty && rctx->ps_shader && rctx->rasterizer &&
                                ((rctx->rasterizer->sprite_coord_enable != rctx->ps_shader->current->sprite_coord_enable) ||
                                                (rctx->rasterizer->flatshade != rctx->ps_shader->current->flatshade)))) {
@@ -1265,31 +1267,43 @@ static bool r600_update_derived_state(struct r600_context *rctx)
                update_shader_atom(ctx, &rctx->pixel_shader, rctx->ps_shader->current);
        }
 
+       if (rctx->b.chip_class >= EVERGREEN) {
+               evergreen_update_db_shader_control(rctx);
+       } else {
+               r600_update_db_shader_control(rctx);
+       }
+
        /* on R600 we stuff masks + txq info into one constant buffer */
        /* on evergreen we only need a txq info one */
-       if (rctx->b.chip_class < EVERGREEN) {
-               if (rctx->ps_shader && rctx->ps_shader->current->shader.uses_tex_buffers)
-                       r600_setup_buffer_constants(rctx, PIPE_SHADER_FRAGMENT);
-               if (rctx->vs_shader && rctx->vs_shader->current->shader.uses_tex_buffers)
-                       r600_setup_buffer_constants(rctx, PIPE_SHADER_VERTEX);
-               if (rctx->gs_shader && rctx->gs_shader->current->shader.uses_tex_buffers)
-                       r600_setup_buffer_constants(rctx, PIPE_SHADER_GEOMETRY);
-       } else {
-               if (rctx->ps_shader && rctx->ps_shader->current->shader.uses_tex_buffers)
-                       eg_setup_buffer_constants(rctx, PIPE_SHADER_FRAGMENT);
-               if (rctx->vs_shader && rctx->vs_shader->current->shader.uses_tex_buffers)
-                       eg_setup_buffer_constants(rctx, PIPE_SHADER_VERTEX);
-               if (rctx->gs_shader && rctx->gs_shader->current->shader.uses_tex_buffers)
-                       eg_setup_buffer_constants(rctx, PIPE_SHADER_GEOMETRY);
+       if (rctx->ps_shader) {
+               need_buf_const = rctx->ps_shader->current->shader.uses_tex_buffers || rctx->ps_shader->current->shader.has_txq_cube_array_z_comp;
+               if (need_buf_const) {
+                       if (rctx->b.chip_class < EVERGREEN)
+                               r600_setup_buffer_constants(rctx, PIPE_SHADER_FRAGMENT);
+                       else
+                               eg_setup_buffer_constants(rctx, PIPE_SHADER_FRAGMENT);
+               }
        }
 
+       if (rctx->vs_shader) {
+               need_buf_const = rctx->vs_shader->current->shader.uses_tex_buffers || rctx->vs_shader->current->shader.has_txq_cube_array_z_comp;
+               if (need_buf_const) {
+                       if (rctx->b.chip_class < EVERGREEN)
+                               r600_setup_buffer_constants(rctx, PIPE_SHADER_VERTEX);
+                       else
+                               eg_setup_buffer_constants(rctx, PIPE_SHADER_VERTEX);
+               }
+       }
 
-       if (rctx->ps_shader && rctx->ps_shader->current->shader.has_txq_cube_array_z_comp)
-               r600_setup_txq_cube_array_constants(rctx, PIPE_SHADER_FRAGMENT);
-       if (rctx->vs_shader && rctx->vs_shader->current->shader.has_txq_cube_array_z_comp)
-               r600_setup_txq_cube_array_constants(rctx, PIPE_SHADER_VERTEX);
-       if (rctx->gs_shader && rctx->gs_shader->current->shader.has_txq_cube_array_z_comp)
-               r600_setup_txq_cube_array_constants(rctx, PIPE_SHADER_GEOMETRY);
+       if (rctx->gs_shader) {
+               need_buf_const = rctx->gs_shader->current->shader.uses_tex_buffers || rctx->gs_shader->current->shader.has_txq_cube_array_z_comp;
+               if (need_buf_const) {
+                       if (rctx->b.chip_class < EVERGREEN)
+                               r600_setup_buffer_constants(rctx, PIPE_SHADER_GEOMETRY);
+                       else
+                               eg_setup_buffer_constants(rctx, PIPE_SHADER_GEOMETRY);
+               }
+       }
 
        if (rctx->b.chip_class < EVERGREEN && rctx->ps_shader && rctx->vs_shader) {
                if (!r600_adjust_gprs(rctx)) {
@@ -1421,6 +1435,30 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
                r600_emit_atom(rctx, rctx->atoms[i]);
        }
 
+       if (rctx->b.chip_class == CAYMAN) {
+               /* Copied from radeonsi. */
+               unsigned primgroup_size = 128; /* recommended without a GS */
+               bool ia_switch_on_eop = false;
+               bool partial_vs_wave = false;
+
+               if (rctx->gs_shader)
+                       primgroup_size = 64; /* recommended with a GS */
+
+               if ((rctx->rasterizer && rctx->rasterizer->pa_sc_line_stipple) ||
+                   (rctx->b.screen->debug_flags & DBG_SWITCH_ON_EOP)) {
+                       ia_switch_on_eop = true;
+               }
+
+               if (rctx->b.streamout.streamout_enabled ||
+                   rctx->b.streamout.prims_gen_query_enabled)
+                       partial_vs_wave = true;
+
+               r600_write_context_reg(cs, CM_R_028AA8_IA_MULTI_VGT_PARAM,
+                                      S_028AA8_SWITCH_ON_EOP(ia_switch_on_eop) |
+                                      S_028AA8_PARTIAL_VS_WAVE_ON(partial_vs_wave) |
+                                      S_028AA8_PRIMGROUP_SIZE(primgroup_size - 1));
+       }
+
        /* On R6xx, CULL_FRONT=1 culls all points, lines, and rectangles,
         * even though it should have no effect on those. */
        if (rctx->b.chip_class == R600 && rctx->rasterizer) {
@@ -1550,67 +1588,6 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
        rctx->b.num_draw_calls++;
 }
 
-void r600_draw_rectangle(struct blitter_context *blitter,
-                        int x1, int y1, int x2, int y2, float depth,
-                        enum blitter_attrib_type type, const union pipe_color_union *attrib)
-{
-       struct r600_context *rctx = (struct r600_context*)util_blitter_get_pipe(blitter);
-       struct pipe_viewport_state viewport;
-       struct pipe_resource *buf = NULL;
-       unsigned offset = 0;
-       float *vb;
-
-       if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) {
-               util_blitter_draw_rectangle(blitter, x1, y1, x2, y2, depth, type, attrib);
-               return;
-       }
-
-       /* Some operations (like color resolve on r6xx) don't work
-        * with the conventional primitive types.
-        * One that works is PT_RECTLIST, which we use here. */
-
-       /* setup viewport */
-       viewport.scale[0] = 1.0f;
-       viewport.scale[1] = 1.0f;
-       viewport.scale[2] = 1.0f;
-       viewport.scale[3] = 1.0f;
-       viewport.translate[0] = 0.0f;
-       viewport.translate[1] = 0.0f;
-       viewport.translate[2] = 0.0f;
-       viewport.translate[3] = 0.0f;
-       rctx->b.b.set_viewport_states(&rctx->b.b, 0, 1, &viewport);
-
-       /* Upload vertices. The hw rectangle has only 3 vertices,
-        * I guess the 4th one is derived from the first 3.
-        * The vertex specification should match u_blitter's vertex element state. */
-       u_upload_alloc(rctx->b.uploader, 0, sizeof(float) * 24, &offset, &buf, (void**)&vb);
-       vb[0] = x1;
-       vb[1] = y1;
-       vb[2] = depth;
-       vb[3] = 1;
-
-       vb[8] = x1;
-       vb[9] = y2;
-       vb[10] = depth;
-       vb[11] = 1;
-
-       vb[16] = x2;
-       vb[17] = y1;
-       vb[18] = depth;
-       vb[19] = 1;
-
-       if (attrib) {
-               memcpy(vb+4, attrib->f, sizeof(float)*4);
-               memcpy(vb+12, attrib->f, sizeof(float)*4);
-               memcpy(vb+20, attrib->f, sizeof(float)*4);
-       }
-
-       /* draw */
-       util_draw_vertex_buffer(&rctx->b.b, NULL, buf, rctx->blitter->vb_slot, offset,
-                               R600_PRIM_RECTANGLE_LIST, 3, 2);
-       pipe_resource_reference(&buf, NULL);
-}
-
 uint32_t r600_translate_stencil_op(int s_op)
 {
        switch (s_op) {