radeon_set_context_reg(cs, R_028438_SX_ALPHA_REF, alpha_ref);
}
+static void r600_memory_barrier(struct pipe_context *ctx, unsigned flags)
+{
+ struct r600_context *rctx = (struct r600_context *)ctx;
+ if (flags & PIPE_BARRIER_CONSTANT_BUFFER)
+ rctx->b.flags |= R600_CONTEXT_INV_CONST_CACHE;
+
+ if (flags & (PIPE_BARRIER_VERTEX_BUFFER |
+ PIPE_BARRIER_SHADER_BUFFER |
+ PIPE_BARRIER_TEXTURE |
+ PIPE_BARRIER_IMAGE |
+ PIPE_BARRIER_STREAMOUT_BUFFER |
+ PIPE_BARRIER_GLOBAL_BUFFER)) {
+ rctx->b.flags |= R600_CONTEXT_INV_VERTEX_CACHE|
+ R600_CONTEXT_INV_TEX_CACHE;
+ }
+
+ if (flags & (PIPE_BARRIER_FRAMEBUFFER|
+ PIPE_BARRIER_IMAGE))
+ rctx->b.flags |= R600_CONTEXT_FLUSH_AND_INV;
+
+ rctx->b.flags |= R600_CONTEXT_WAIT_3D_IDLE;
+}
+
static void r600_texture_barrier(struct pipe_context *ctx, unsigned flags)
{
struct r600_context *rctx = (struct r600_context *)ctx;
}
}
+static int r600_get_hw_atomic_count(const struct pipe_context *ctx,
+ enum pipe_shader_type shader)
+{
+ const struct r600_context *rctx = (struct r600_context *)ctx;
+ int value = 0;
+ switch (shader) {
+ case PIPE_SHADER_FRAGMENT:
+ case PIPE_SHADER_COMPUTE:
+ default:
+ break;
+ case PIPE_SHADER_VERTEX:
+ value = rctx->ps_shader->info.file_count[TGSI_FILE_HW_ATOMIC];
+ break;
+ case PIPE_SHADER_GEOMETRY:
+ value = rctx->ps_shader->info.file_count[TGSI_FILE_HW_ATOMIC] +
+ rctx->vs_shader->info.file_count[TGSI_FILE_HW_ATOMIC];
+ break;
+ case PIPE_SHADER_TESS_EVAL:
+ value = rctx->ps_shader->info.file_count[TGSI_FILE_HW_ATOMIC] +
+ rctx->vs_shader->info.file_count[TGSI_FILE_HW_ATOMIC] +
+ (rctx->gs_shader ? rctx->gs_shader->info.file_count[TGSI_FILE_HW_ATOMIC] : 0);
+ break;
+ case PIPE_SHADER_TESS_CTRL:
+ value = rctx->ps_shader->info.file_count[TGSI_FILE_HW_ATOMIC] +
+ rctx->vs_shader->info.file_count[TGSI_FILE_HW_ATOMIC] +
+ (rctx->gs_shader ? rctx->gs_shader->info.file_count[TGSI_FILE_HW_ATOMIC] : 0) +
+ rctx->tes_shader->info.file_count[TGSI_FILE_HW_ATOMIC];
+ break;
+ }
+ return value;
+}
+
+static void r600_update_compressed_colortex_mask_images(struct r600_image_state *images)
+{
+ uint32_t mask = images->enabled_mask;
+
+ while (mask) {
+ unsigned i = u_bit_scan(&mask);
+ struct pipe_resource *res = images->views[i].base.resource;
+
+ if (res && res->target != PIPE_BUFFER) {
+ struct r600_texture *rtex = (struct r600_texture *)res;
+
+ if (rtex->cmask.size) {
+ images->compressed_colortex_mask |= 1 << i;
+ } else {
+ images->compressed_colortex_mask &= ~(1 << i);
+ }
+ }
+ }
+}
+
/* Compute the key for the hw shader variant */
static inline void r600_shader_selector_key(const struct pipe_context *ctx,
const struct r600_pipe_shader_selector *sel,
key->vs.as_gs_a = true;
key->vs.prim_id_out = rctx->ps_shader->current->shader.input[rctx->ps_shader->current->shader.ps_prim_id_input].spi_sid;
}
+ key->vs.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_VERTEX);
break;
}
case PIPE_SHADER_GEOMETRY:
+ key->gs.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_GEOMETRY);
+ key->gs.tri_strip_adj_fix = rctx->gs_tri_strip_adj_fix;
break;
case PIPE_SHADER_FRAGMENT: {
+ if (rctx->ps_shader->info.images_declared)
+ key->ps.image_size_const_offset = util_last_bit(rctx->samplers[PIPE_SHADER_FRAGMENT].views.enabled_mask);
+ key->ps.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_FRAGMENT);
key->ps.color_two_side = rctx->rasterizer && rctx->rasterizer->two_side;
key->ps.alpha_to_one = rctx->alpha_to_one &&
rctx->rasterizer && rctx->rasterizer->multisample_enable &&
}
case PIPE_SHADER_TESS_EVAL:
key->tes.as_es = (rctx->gs_shader != NULL);
+ key->tes.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_TESS_EVAL);
break;
case PIPE_SHADER_TESS_CTRL:
key->tcs.prim_mode = rctx->tes_shader->info.properties[TGSI_PROPERTY_TES_PRIM_MODE];
+ key->tcs.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_TESS_CTRL);
break;
default:
assert(0);
case TGSI_SEMANTIC_TESSOUTER:
case TGSI_SEMANTIC_PATCH:
sel->lds_patch_outputs_written_mask |=
- 1llu << r600_get_lds_unique_index(name, index);
+ 1ull << r600_get_lds_unique_index(name, index);
break;
default:
sel->lds_outputs_written_mask |=
- 1llu << r600_get_lds_unique_index(name, index);
+ 1ull << r600_get_lds_unique_index(name, index);
}
}
break;
static void eg_setup_buffer_constants(struct r600_context *rctx, int shader_type)
{
struct r600_textures_info *samplers = &rctx->samplers[shader_type];
- int bits;
+ struct r600_image_state *images = NULL;
+ struct r600_image_state *buffers = NULL;
+ int bits, sview_bits, img_bits;
uint32_t array_size;
int i;
uint32_t *constants;
uint32_t base_offset;
- if (!samplers->views.dirty_buffer_constants)
+
+ if (shader_type == PIPE_SHADER_FRAGMENT) {
+ images = &rctx->fragment_images;
+ buffers = &rctx->fragment_buffers;
+ }
+
+ if (!samplers->views.dirty_buffer_constants &&
+ (images && !images->dirty_buffer_constants) &&
+ (buffers && !buffers->dirty_buffer_constants))
return;
+ if (images)
+ images->dirty_buffer_constants = FALSE;
+ if (buffers)
+ buffers->dirty_buffer_constants = FALSE;
samplers->views.dirty_buffer_constants = FALSE;
- bits = util_last_bit(samplers->views.enabled_mask);
+ bits = sview_bits = util_last_bit(samplers->views.enabled_mask);
+ if (images)
+ bits += util_last_bit(images->enabled_mask);
+ img_bits = bits;
+ if (buffers)
+ bits += util_last_bit(buffers->enabled_mask);
array_size = bits * 2 * sizeof(uint32_t) * 4;
constants = r600_alloc_buf_consts(rctx, shader_type, array_size,
&base_offset);
- for (i = 0; i < bits; i++) {
+ for (i = 0; i < sview_bits; i++) {
if (samplers->views.enabled_mask & (1 << i)) {
uint32_t offset = (base_offset / 4) + i * 2;
constants[offset] = samplers->views.views[i]->base.texture->width0 / util_format_get_blocksize(samplers->views.views[i]->base.format);
constants[offset + 1] = samplers->views.views[i]->base.texture->array_size / 6;
}
}
+ if (images) {
+ for (i = sview_bits; i < img_bits; i++) {
+ int idx = i - sview_bits;
+ if (images->enabled_mask & (1 << idx)) {
+ uint32_t offset = (base_offset / 4) + i * 2;
+ constants[offset] = images->views[i].base.resource->width0 / util_format_get_blocksize(images->views[i].base.format);
+ constants[offset + 1] = images->views[i].base.resource->array_size / 6;
+ }
+ }
+ }
+ if (buffers) {
+ for (i = img_bits; i < bits; i++) {
+ int idx = i - img_bits;
+ if (buffers->enabled_mask & (1 << idx)) {
+ uint32_t offset = (base_offset / 4) + i * 2;
+ constants[offset] = buffers->views[i].base.resource->width0 / util_format_get_blocksize(buffers->views[i].base.format);
+ constants[offset + 1] = 0;
+ }
+ }
+ }
}
/* set sample xy locations as array of fragment shader constants */
{
if (current->pa_cl_vs_out_cntl != rctx->clip_misc_state.pa_cl_vs_out_cntl ||
current->shader.clip_dist_write != rctx->clip_misc_state.clip_dist_write ||
+ current->shader.cull_dist_write != rctx->clip_misc_state.cull_dist_write ||
current->shader.vs_position_window_space != rctx->clip_misc_state.clip_disable ||
current->shader.vs_out_viewport != rctx->clip_misc_state.vs_out_viewport) {
rctx->clip_misc_state.pa_cl_vs_out_cntl = current->pa_cl_vs_out_cntl;
rctx->clip_misc_state.clip_dist_write = current->shader.clip_dist_write;
+ rctx->clip_misc_state.cull_dist_write = current->shader.cull_dist_write;
rctx->clip_misc_state.clip_disable = current->shader.vs_position_window_space;
rctx->clip_misc_state.vs_out_viewport = current->shader.vs_out_viewport;
r600_mark_atom_dirty(rctx, &rctx->clip_misc_state.atom);
ureg_create_shader_and_destroy(ureg, &rctx->b.b);
}
+static void r600_update_compressed_resource_state(struct r600_context *rctx)
+{
+ unsigned i;
+ unsigned counter;
+
+ counter = p_atomic_read(&rctx->screen->b.compressed_colortex_counter);
+ if (counter != rctx->b.last_compressed_colortex_counter) {
+ rctx->b.last_compressed_colortex_counter = counter;
+
+ for (i = 0; i < PIPE_SHADER_TYPES; ++i) {
+ r600_update_compressed_colortex_mask(&rctx->samplers[i].views);
+ }
+ r600_update_compressed_colortex_mask_images(&rctx->fragment_images);
+ }
+
+ /* Decompress textures if needed. */
+ for (i = 0; i < PIPE_SHADER_TYPES; i++) {
+ struct r600_samplerview_state *views = &rctx->samplers[i].views;
+ if (views->compressed_depthtex_mask) {
+ r600_decompress_depth_textures(rctx, views);
+ }
+ if (views->compressed_colortex_mask) {
+ r600_decompress_color_textures(rctx, views);
+ }
+ }
+
+ {
+ struct r600_image_state *istate;
+ istate = &rctx->fragment_images;
+ if (istate->compressed_depthtex_mask)
+ r600_decompress_depth_images(rctx, istate);
+ if (istate->compressed_colortex_mask)
+ r600_decompress_color_images(rctx, istate);
+ }
+}
+
#define SELECT_SHADER_OR_FAIL(x) do { \
r600_shader_select(ctx, rctx->x##_shader, &x##_dirty); \
if (unlikely(!rctx->x##_shader->current)) \
bool need_buf_const;
struct r600_pipe_shader *clip_so_current = NULL;
- if (!rctx->blitter->running) {
- unsigned i;
- unsigned counter;
-
- counter = p_atomic_read(&rctx->screen->b.compressed_colortex_counter);
- if (counter != rctx->b.last_compressed_colortex_counter) {
- rctx->b.last_compressed_colortex_counter = counter;
-
- for (i = 0; i < PIPE_SHADER_TYPES; ++i) {
- r600_update_compressed_colortex_mask(&rctx->samplers[i].views);
- }
- }
-
- /* Decompress textures if needed. */
- for (i = 0; i < PIPE_SHADER_TYPES; i++) {
- struct r600_samplerview_state *views = &rctx->samplers[i].views;
- if (views->compressed_depthtex_mask) {
- r600_decompress_depth_textures(rctx, views);
- }
- if (views->compressed_colortex_mask) {
- r600_decompress_color_textures(rctx, views);
- }
- }
- }
+ if (!rctx->blitter->running)
+ r600_update_compressed_resource_state(rctx);
SELECT_SHADER_OR_FAIL(ps);
S_028810_CLIP_DISABLE(state->clip_disable));
radeon_set_context_reg(cs, R_02881C_PA_CL_VS_OUT_CNTL,
state->pa_cl_vs_out_cntl |
- (state->clip_plane_enable & state->clip_dist_write));
+ (state->clip_plane_enable & state->clip_dist_write) |
+ (state->cull_dist_write << 8));
/* reuse needs to be set off if we write oViewport */
if (rctx->b.chip_class >= EVERGREEN)
radeon_set_context_reg(cs, R_028AB4_VGT_REUSE_OFF,
unsigned num_patches, dirty_tex_counter, index_offset = 0;
unsigned index_size = info->index_size;
int index_bias;
+ struct r600_shader_atomic combined_atomics[8];
+ uint8_t atomic_used_mask;
if (!info->indirect && !info->count && (index_size || !info->count_from_stream_output)) {
return;
/* make sure that the gfx ring is only one active */
if (radeon_emitted(rctx->b.dma.cs, 0)) {
- rctx->b.dma.flush(rctx, RADEON_FLUSH_ASYNC, NULL);
+ rctx->b.dma.flush(rctx, PIPE_FLUSH_ASYNC, NULL);
}
/* Re-emit the framebuffer state if needed. */
rctx->framebuffer.do_update_surf_dirtiness = true;
}
+ if (rctx->gs_shader) {
+ /* Determine whether the GS triangle strip adjacency fix should
+ * be applied. Rotate every other triangle if
+ * - triangle strips with adjacency are fed to the GS and
+ * - primitive restart is disabled (the rotation doesn't help
+ * when the restart occurs after an odd number of triangles).
+ */
+ bool gs_tri_strip_adj_fix =
+ !rctx->tes_shader &&
+ info->mode == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY &&
+ !info->primitive_restart;
+ if (gs_tri_strip_adj_fix != rctx->gs_tri_strip_adj_fix)
+ rctx->gs_tri_strip_adj_fix = gs_tri_strip_adj_fix;
+ }
if (!r600_update_derived_state(rctx)) {
/* useless to render because current rendering command
* can't be achieved
: (rctx->tes_shader)? rctx->tes_shader->info.properties[TGSI_PROPERTY_TES_PRIM_MODE]
: info->mode;
+ if (rctx->b.chip_class >= EVERGREEN)
+ evergreen_emit_atomic_buffer_setup(rctx, combined_atomics, &atomic_used_mask);
+
if (index_size) {
index_offset += info->start * index_size;
radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_SQ_NON_EVENT));
}
+
+ if (rctx->b.chip_class >= EVERGREEN)
+ evergreen_emit_atomic_buffer_save(rctx, combined_atomics, &atomic_used_mask);
+
+ if (rctx->trace_buf)
+ eg_trace_emit(rctx);
+
if (rctx->framebuffer.do_update_surf_dirtiness) {
/* Set the depth buffer as dirty. */
if (rctx->framebuffer.state.zsbuf) {
rtex->dirty_level_mask |= 1 << surf->u.tex.level;
- if (rtex->surface.flags & RADEON_SURF_SBUFFER)
+ if (rtex->surface.has_stencil)
rtex->stencil_dirty_level_mask |= 1 << surf->u.tex.level;
}
if (rctx->framebuffer.compressed_cb_mask) {
format = PIPE_FORMAT_A4R4_UNORM;
desc = util_format_description(format);
+ if (!desc)
+ goto out_unknown;
/* Depth and stencil swizzling is handled separately. */
if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) {
}
if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
- if (!util_format_s3tc_enabled) {
- goto out_unknown;
- }
-
switch (format) {
case PIPE_FORMAT_DXT1_RGB:
case PIPE_FORMAT_DXT1_RGBA:
const struct util_format_description *desc = util_format_description(format);
int channel = util_format_get_first_non_void_channel(format);
bool is_float;
+ if (!desc)
+ return ~0U;
#define HAS_SIZE(x,y,z,w) \
(desc->channel[0].size == (x) && desc->channel[1].size == (y) && \
r600_sampler_views_dirty(rctx, state);
}
}
+
+ /* SSBOs */
+ struct r600_image_state *istate = &rctx->fragment_buffers;
+ {
+ uint32_t mask = istate->enabled_mask;
+ bool found = false;
+ while (mask) {
+ unsigned i = u_bit_scan(&mask);
+ if (istate->views[i].base.resource == &rbuffer->b.b) {
+ found = true;
+ istate->dirty_mask |= 1 << i;
+ }
+ }
+ if (found) {
+ r600_mark_atom_dirty(rctx, &istate->atom);
+ }
+ }
+
}
static void r600_set_active_query_state(struct pipe_context *ctx, boolean enable)
}
}
-static void r600_set_occlusion_query_state(struct pipe_context *ctx, bool enable)
-{
- struct r600_context *rctx = (struct r600_context*)ctx;
-
- r600_mark_atom_dirty(rctx, &rctx->db_misc_state.atom);
-}
-
static void r600_need_gfx_cs_space(struct pipe_context *ctx, unsigned num_dw,
bool include_draw_vbo)
{
rctx->b.b.set_vertex_buffers = r600_set_vertex_buffers;
rctx->b.b.set_sampler_views = r600_set_sampler_views;
rctx->b.b.sampler_view_destroy = r600_sampler_view_destroy;
+ rctx->b.b.memory_barrier = r600_memory_barrier;
rctx->b.b.texture_barrier = r600_texture_barrier;
rctx->b.b.set_stream_output_targets = r600_set_streamout_targets;
rctx->b.b.set_active_query_state = r600_set_active_query_state;
rctx->b.b.draw_vbo = r600_draw_vbo;
rctx->b.invalidate_buffer = r600_invalidate_buffer;
- rctx->b.set_occlusion_query_state = r600_set_occlusion_query_state;
rctx->b.need_gfx_cs_space = r600_need_gfx_cs_space;
}