radeon_set_context_reg(cs, R_028238_CB_TARGET_MASK, cb_target_mask);
+ /* GFX9: Flush DFSM when CB_TARGET_MASK changes.
+ * I think we don't have to do anything between IBs.
+ */
+ if (sctx->b.chip_class >= GFX9 &&
+ sctx->last_cb_target_mask != cb_target_mask) {
+ sctx->last_cb_target_mask = cb_target_mask;
+
+ radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0));
+ radeon_emit(cs, EVENT_TYPE(V_028A90_FLUSH_DFSM) | EVENT_INDEX(0));
+ }
+
/* RB+ register settings. */
if (sctx->screen->b.rbplus_allowed) {
unsigned spi_shader_col_format =
ucp_mask |
S_028810_CLIP_DISABLE(window_space));
- /* reuse needs to be set off if we write oViewport */
- radeon_set_context_reg(cs, R_028AB4_VGT_REUSE_OFF,
- S_028AB4_REUSE_OFF(info->writes_viewport_index));
+ if (sctx->b.chip_class <= VI) {
+ /* reuse needs to be set off if we write oViewport */
+ radeon_set_context_reg(cs, R_028AB4_VGT_REUSE_OFF,
+ S_028AB4_REUSE_OFF(info->writes_viewport_index));
+ }
}
/*
rs->uses_poly_offset = state->offset_point || state->offset_line ||
state->offset_tri;
rs->clamp_fragment_color = state->clamp_fragment_color;
+ rs->clamp_vertex_color = state->clamp_vertex_color;
rs->flatshade = state->flatshade;
rs->sprite_coord_enable = state->sprite_coord_enable;
rs->rasterizer_discard = state->rasterizer_discard;
state->fill_back != PIPE_POLYGON_MODE_FILL) |
S_028814_POLYMODE_FRONT_PTYPE(si_translate_fill(state->fill_front)) |
S_028814_POLYMODE_BACK_PTYPE(si_translate_fill(state->fill_back)));
- si_pm4_set_reg(pm4, R_00B130_SPI_SHADER_USER_DATA_VS_0 +
- SI_SGPR_VS_STATE_BITS * 4, state->clamp_vertex_color);
/* Precalculate polygon offset states for 16-bit, 24-bit, and 32-bit zbuffers. */
for (i = 0; i < 3; i++) {
si_mark_atom_dirty(sctx, &sctx->db_render_state);
/* Update the small primitive filter workaround if necessary. */
- if (sctx->b.family >= CHIP_POLARIS10 &&
+ if (sctx->screen->has_msaa_sample_loc_bug &&
sctx->framebuffer.nr_samples > 1)
si_mark_atom_dirty(sctx, &sctx->msaa_sample_locs.atom);
}
+ sctx->current_vs_state &= C_VS_STATE_CLAMP_VERTEX_COLOR;
+ sctx->current_vs_state |= S_VS_STATE_CLAMP_VERTEX_COLOR(rs->clamp_vertex_color);
+
r600_viewport_set_rast_deps(&sctx->b, rs->scissor_enable, rs->clip_halfz);
si_pm4_bind_state(sctx, rasterizer, rs);
}
}
-static unsigned si_tex_dim(unsigned res_target, unsigned view_target,
- unsigned nr_samples)
+static unsigned si_tex_dim(struct si_screen *sscreen, struct r600_texture *rtex,
+ unsigned view_target, unsigned nr_samples)
{
+ unsigned res_target = rtex->resource.b.b.target;
+
if (view_target == PIPE_TEXTURE_CUBE ||
view_target == PIPE_TEXTURE_CUBE_ARRAY)
res_target = view_target;
res_target == PIPE_TEXTURE_CUBE_ARRAY)
res_target = PIPE_TEXTURE_2D_ARRAY;
+ /* GFX9 allocates 1D textures as 2D. */
+ if ((res_target == PIPE_TEXTURE_1D ||
+ res_target == PIPE_TEXTURE_1D_ARRAY) &&
+ sscreen->b.chip_class >= GFX9 &&
+ rtex->surface.u.gfx9.resource_type == RADEON_RESOURCE_2D) {
+ if (res_target == PIPE_TEXTURE_1D)
+ res_target = PIPE_TEXTURE_2D;
+ else
+ res_target = PIPE_TEXTURE_2D_ARRAY;
+ }
+
switch (res_target) {
default:
case PIPE_TEXTURE_1D:
if (sctx->b.chip_class >= GFX9) {
unsigned mip0_depth = util_max_layer(&rtex->resource.b.b, 0);
- unsigned type;
-
- switch (rtex->resource.b.b.target) {
- case PIPE_TEXTURE_1D:
- case PIPE_TEXTURE_1D_ARRAY:
- type = V_028C74_1D;
- break;
- default:
- type = V_028C74_2D;
- break;
- case PIPE_TEXTURE_3D:
- type = V_028C74_3D;
- break;
- }
surf->cb_color_view |= S_028C6C_MIP_LEVEL(surf->base.u.tex.level);
surf->cb_color_attrib |= S_028C74_MIP0_DEPTH(mip0_depth) |
- S_028C74_RESOURCE_TYPE(type);
- surf->cb_color_attrib2 = S_028C68_MIP0_WIDTH(rtex->resource.b.b.width0 - 1) |
- S_028C68_MIP0_HEIGHT(rtex->resource.b.b.height0 - 1) |
+ S_028C74_RESOURCE_TYPE(rtex->surface.u.gfx9.resource_type);
+ surf->cb_color_attrib2 = S_028C68_MIP0_WIDTH(surf->width0 - 1) |
+ S_028C68_MIP0_HEIGHT(surf->height0 - 1) |
S_028C68_MAX_MIP(rtex->resource.b.b.last_level);
}
surf->db_htile_surface = 0;
if (sctx->b.chip_class >= GFX9) {
+ assert(rtex->surface.u.gfx9.surf_offset == 0);
surf->db_depth_base = rtex->resource.gpu_address >> 8;
surf->db_stencil_base = (rtex->resource.gpu_address +
rtex->surface.u.gfx9.stencil_offset) >> 8;
struct r600_texture *rtex;
bool old_any_dst_linear = sctx->framebuffer.any_dst_linear;
unsigned old_nr_samples = sctx->framebuffer.nr_samples;
+ bool unbound = false;
int i;
for (i = 0; i < sctx->framebuffer.state.nr_cbufs; i++) {
vi_separate_dcc_stop_query(ctx, rtex);
}
+ /* Disable DCC if the formats are incompatible. */
+ for (i = 0; i < state->nr_cbufs; i++) {
+ if (!state->cbufs[i])
+ continue;
+
+ surf = (struct r600_surface*)state->cbufs[i];
+ rtex = (struct r600_texture*)surf->base.texture;
+
+ if (!surf->dcc_incompatible)
+ continue;
+
+ /* Since the DCC decompression calls back into set_framebuffer-
+ * _state, we need to unbind the framebuffer, so that
+ * vi_separate_dcc_stop_query isn't called twice with the same
+ * color buffer.
+ */
+ if (!unbound) {
+ util_copy_framebuffer_state(&sctx->framebuffer.state, NULL);
+ unbound = true;
+ }
+
+ if (vi_dcc_enabled(rtex, surf->base.u.tex.level))
+ if (!r600_texture_disable_dcc(&sctx->b, rtex))
+ sctx->b.decompress_dcc(ctx, rtex);
+
+ surf->dcc_incompatible = false;
+ }
+
/* Only flush TC when changing the framebuffer state, because
* the only client not using TC that can change textures is
* the framebuffer.
cb_color_fmask = (tex->resource.gpu_address + tex->fmask.offset) >> 8;
/* Set up DCC. */
- if (tex->dcc_offset && cb->base.u.tex.level < tex->surface.num_dcc_levels) {
+ if (vi_dcc_enabled(tex, cb->base.u.tex.level)) {
bool is_msaa_resolve_dst = state->cbufs[0] &&
state->cbufs[0]->texture->nr_samples > 1 &&
state->cbufs[1] == &cb->base &&
meta = tex->surface.u.gfx9.cmask;
/* Set mutable surface parameters. */
+ cb_color_base += tex->surface.u.gfx9.surf_offset >> 8;
cb_color_attrib |= S_028C74_COLOR_SW_MODE(tex->surface.u.gfx9.surf.swizzle_mode) |
S_028C74_FMASK_SW_MODE(tex->surface.u.gfx9.fmask.swizzle_mode) |
S_028C74_RB_ALIGNED(meta.rb_aligned) |
radeon_set_context_reg(cs, R_028208_PA_SC_WINDOW_SCISSOR_BR,
S_028208_BR_X(state->width) | S_028208_BR_Y(state->height));
+ if (sctx->b.chip_class >= GFX9) {
+ radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0));
+ radeon_emit(cs, EVENT_TYPE(V_028A90_BREAK_BATCH) | EVENT_INDEX(0));
+ }
+
sctx->framebuffer.dirty_cbufs = 0;
sctx->framebuffer.dirty_zsbuf = false;
}
{
struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
unsigned nr_samples = sctx->framebuffer.nr_samples;
+ bool has_msaa_sample_loc_bug = sctx->screen->has_msaa_sample_loc_bug;
/* Smoothing (only possible with nr_samples == 1) uses the same
* sample locations as the MSAA it simulates.
/* On Polaris, the small primitive filter uses the sample locations
* even when MSAA is off, so we need to make sure they're set to 0.
*/
- if (sctx->b.family >= CHIP_POLARIS10)
+ if (has_msaa_sample_loc_bug)
nr_samples = MAX2(nr_samples, 1);
if (nr_samples >= 1 &&
struct si_state_rasterizer *rs = sctx->queued.named.rasterizer;
unsigned small_prim_filter_cntl =
S_028830_SMALL_PRIM_FILTER_ENABLE(1) |
- S_028830_LINE_FILTER_DISABLE(sctx->b.chip_class == VI); /* line bug */
+ /* line bug */
+ S_028830_LINE_FILTER_DISABLE(sctx->b.family <= CHIP_POLARIS12);
/* The alternative of setting sample locations to 0 would
* require a DB flush to avoid Z errors, see
* https://bugs.freedesktop.org/show_bug.cgi?id=96908
*/
- if (sctx->framebuffer.nr_samples > 1 && rs && !rs->multisample_enable)
+ if (has_msaa_sample_loc_bug &&
+ sctx->framebuffer.nr_samples > 1 &&
+ rs && !rs->multisample_enable)
small_prim_filter_cntl &= C_028830_SMALL_PRIM_FILTER_ENABLE;
radeon_set_context_reg(cs, R_028830_PA_SU_SMALL_PRIM_FILTER_CNTL,
sctx->ps_iter_samples,
sctx->smoothing_enabled ? SI_NUM_SMOOTH_AA_SAMPLES : 0,
sc_mode_cntl_1);
+
+ /* GFX9: Flush DFSM when the AA mode changes. */
+ if (sctx->b.chip_class >= GFX9) {
+ radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0));
+ radeon_emit(cs, EVENT_TYPE(V_028A90_FLUSH_DFSM) | EVENT_INDEX(0));
+ }
}
static void si_set_min_samples(struct pipe_context *ctx, unsigned min_samples)
num_records = size / stride;
num_records = MIN2(num_records, (buf->b.b.width0 - offset) / stride);
- if (screen->b.chip_class == VI)
+ /* The NUM_RECORDS field has a different meaning depending on the chip,
+ * instruction type, STRIDE, and SWIZZLE_ENABLE.
+ *
+ * SI-CIK:
+ * - If STRIDE == 0, it's in byte units.
+ * - If STRIDE != 0, it's in units of STRIDE, used with inst.IDXEN.
+ *
+ * VI:
+ * - For SMEM and STRIDE == 0, it's in byte units.
+ * - For SMEM and STRIDE != 0, it's in units of STRIDE.
+ * - For VMEM and STRIDE == 0 or SWIZZLE_ENABLE == 0, it's in byte units.
+ * - For VMEM and STRIDE != 0 and SWIZZLE_ENABLE == 1, it's in units of STRIDE.
+ * NOTE: There is incompatibility between VMEM and SMEM opcodes due to SWIZZLE_-
+ * ENABLE. The workaround is to set STRIDE = 0 if SWIZZLE_ENABLE == 0 when
+ * using SMEM. This can be done in the shader by clearing STRIDE with s_and.
+ * That way the same descriptor can be used by both SMEM and VMEM.
+ *
+ * GFX9:
+ * - For SMEM and STRIDE == 0, it's in byte units.
+ * - For SMEM and STRIDE != 0, it's in units of STRIDE.
+ * - For VMEM and inst.IDXEN == 0 or STRIDE == 0, it's in byte units.
+ * - For VMEM and inst.IDXEN == 1 and STRIDE != 0, it's in units of STRIDE.
+ */
+ if (screen->b.chip_class >= GFX9)
+ /* When vindex == 0, LLVM sets IDXEN = 0, thus changing units
+ * from STRIDE to bytes. This works around it by setting
+ * NUM_RECORDS to at least the size of one element, so that
+ * the first element is readable when IDXEN == 0.
+ *
+ * TODO: Fix this in LLVM, but do we need a new intrinsic where
+ * IDXEN is enforced?
+ */
+ num_records = num_records ? MAX2(num_records, stride) : 0;
+ else if (screen->b.chip_class == VI)
num_records *= stride;
state[4] = 0;
if (!sampler &&
(res->target == PIPE_TEXTURE_CUBE ||
res->target == PIPE_TEXTURE_CUBE_ARRAY ||
- res->target == PIPE_TEXTURE_3D)) {
+ (screen->b.chip_class <= VI &&
+ res->target == PIPE_TEXTURE_3D))) {
/* For the purpose of shader images, treat cube maps and 3D
* textures as 2D arrays. For 3D textures, the address
* calculations for mipmaps are different, so we rely on the
assert(res->target != PIPE_TEXTURE_3D || (first_level == 0 && last_level == 0));
} else {
- type = si_tex_dim(res->target, target, res->nr_samples);
+ type = si_tex_dim(screen, tex, target, res->nr_samples);
}
if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {
num_format = V_008F14_IMG_FMASK_32_8_8;
break;
default:
- assert(0);
+ unreachable("invalid nr_samples");
}
} else {
switch (res->nr_samples) {
data_format = V_008F14_IMG_DATA_FORMAT_FMASK32_S8_F8;
break;
default:
- assert(0);
+ unreachable("invalid nr_samples");
}
num_format = V_008F14_IMG_NUM_FORMAT_UINT;
}
S_008F1C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |
S_008F1C_DST_SEL_Z(V_008F1C_SQ_SEL_X) |
S_008F1C_DST_SEL_W(V_008F1C_SQ_SEL_X) |
- S_008F1C_TYPE(si_tex_dim(res->target, target, 0));
+ S_008F1C_TYPE(si_tex_dim(screen, tex, target, 0));
fmask_state[4] = 0;
fmask_state[5] = S_008F24_BASE_ARRAY(first_layer);
fmask_state[6] = 0;
height = height0;
depth = texture->depth0;
- if (force_level) {
+ if (sctx->b.chip_class <= VI && force_level) {
assert(force_level == first_level &&
force_level == last_level);
base_level = force_level;
}
}
- vi_dcc_disable_if_incompatible_format(&sctx->b, texture,
- state->u.tex.first_level,
- state->format);
+ view->dcc_incompatible =
+ vi_dcc_formats_are_incompatible(texture,
+ state->u.tex.first_level,
+ state->format);
si_make_texture_descriptor(sctx->screen, tmp, true,
state->target, pipe_format, state_swizzle,
const struct pipe_vertex_buffer *src = buffers + i;
struct pipe_vertex_buffer *dsti = dst + i;
- if (unlikely(src->user_buffer)) {
+ if (unlikely(src->is_user_buffer)) {
/* Zero-stride attribs only. */
assert(src->stride == 0);
* Use const_uploader to upload into VRAM directly.
*/
u_upload_data(sctx->b.b.const_uploader, 0, 32, 32,
- src->user_buffer,
+ src->buffer.user,
&dsti->buffer_offset,
- &dsti->buffer);
+ &dsti->buffer.resource);
dsti->stride = 0;
} else {
- struct pipe_resource *buf = src->buffer;
+ struct pipe_resource *buf = src->buffer.resource;
- pipe_resource_reference(&dsti->buffer, buf);
+ pipe_resource_reference(&dsti->buffer.resource, buf);
dsti->buffer_offset = src->buffer_offset;
dsti->stride = src->stride;
r600_context_add_resource_size(ctx, buf);
}
} else {
for (i = 0; i < count; i++) {
- pipe_resource_reference(&dst[i].buffer, NULL);
+ pipe_resource_reference(&dst[i].buffer.resource, NULL);
}
}
sctx->vertex_buffers_dirty = true;
}
-static void si_set_index_buffer(struct pipe_context *ctx,
- const struct pipe_index_buffer *ib)
-{
- struct si_context *sctx = (struct si_context *)ctx;
-
- if (ib) {
- struct pipe_resource *buf = ib->buffer;
-
- pipe_resource_reference(&sctx->index_buffer.buffer, buf);
- memcpy(&sctx->index_buffer, ib, sizeof(*ib));
- r600_context_add_resource_size(ctx, buf);
- if (buf)
- r600_resource(buf)->bind_history |= PIPE_BIND_INDEX_BUFFER;
- } else {
- pipe_resource_reference(&sctx->index_buffer.buffer, NULL);
- }
-}
-
/*
* Misc
*/
sctx->b.b.bind_vertex_elements_state = si_bind_vertex_elements;
sctx->b.b.delete_vertex_elements_state = si_delete_vertex_element;
sctx->b.b.set_vertex_buffers = si_set_vertex_buffers;
- sctx->b.b.set_index_buffer = si_set_index_buffer;
sctx->b.b.texture_barrier = si_texture_barrier;
sctx->b.b.memory_barrier = si_memory_barrier;
/* Dwords [2:9] contain the image descriptor. */
memcpy(&md->metadata[2], desc, sizeof(desc));
+ md->size_metadata = 10 * 4;
/* Dwords [10:..] contain the mipmap level offsets. */
- for (i = 0; i <= res->last_level; i++)
- md->metadata[10+i] = rtex->surface.u.legacy.level[i].offset >> 8;
+ if (rscreen->chip_class <= VI) {
+ for (i = 0; i <= res->last_level; i++)
+ md->metadata[10+i] = rtex->surface.u.legacy.level[i].offset >> 8;
- md->size_metadata = (11 + res->last_level) * 4;
+ md->size_metadata += (1 + res->last_level) * 4;
+ }
}
static void si_apply_opaque_metadata(struct r600_common_screen *rscreen,
si_pm4_set_reg(pm4, R_028A1C_VGT_HOS_MIN_TESS_LEVEL, fui(0));
/* FIXME calculate these values somehow ??? */
- si_pm4_set_reg(pm4, R_028A54_VGT_GS_PER_ES, SI_GS_PER_ES);
- si_pm4_set_reg(pm4, R_028A58_VGT_ES_PER_GS, 0x40);
+ if (sctx->b.chip_class <= VI) {
+ si_pm4_set_reg(pm4, R_028A54_VGT_GS_PER_ES, SI_GS_PER_ES);
+ si_pm4_set_reg(pm4, R_028A58_VGT_ES_PER_GS, 0x40);
+ }
si_pm4_set_reg(pm4, R_028A5C_VGT_GS_PER_VS, 0x2);
si_pm4_set_reg(pm4, R_028A8C_VGT_PRIMITIVEID_RESET, 0x0);
si_pm4_set_reg(pm4, R_028B28_VGT_STRMOUT_DRAW_OPAQUE_OFFSET, 0);
si_pm4_set_reg(pm4, R_028B98_VGT_STRMOUT_BUFFER_CONFIG, 0x0);
+ si_pm4_set_reg(pm4, R_028AA0_VGT_INSTANCE_STEP_RATE_0, 1);
+ if (sctx->b.chip_class >= GFX9)
+ si_pm4_set_reg(pm4, R_028AB4_VGT_REUSE_OFF, 0);
si_pm4_set_reg(pm4, R_028AB8_VGT_VTX_CNT_EN, 0x0);
if (sctx->b.chip_class < CIK)
si_pm4_set_reg(pm4, R_008A14_PA_CL_ENHANCE, S_008A14_NUM_CLIP_SEQ(3) |
}
if (sctx->b.chip_class >= CIK) {
- /* If this is 0, Bonaire can hang even if GS isn't being used.
- * Other chips are unaffected. These are suboptimal values,
- * but we don't use on-chip GS.
- */
- si_pm4_set_reg(pm4, R_028A44_VGT_GS_ONCHIP_CNTL,
- S_028A44_ES_VERTS_PER_SUBGRP(64) |
- S_028A44_GS_PRIMS_PER_SUBGRP(4));
-
if (sctx->b.chip_class >= GFX9) {
si_pm4_set_reg(pm4, R_00B41C_SPI_SHADER_PGM_RSRC3_HS, S_00B41C_CU_EN(0xffff));
} else {
si_pm4_set_reg(pm4, R_00B51C_SPI_SHADER_PGM_RSRC3_LS, S_00B51C_CU_EN(0xffff));
si_pm4_set_reg(pm4, R_00B41C_SPI_SHADER_PGM_RSRC3_HS, 0);
si_pm4_set_reg(pm4, R_00B31C_SPI_SHADER_PGM_RSRC3_ES, S_00B31C_CU_EN(0xffff));
+
+ /* If this is 0, Bonaire can hang even if GS isn't being used.
+ * Other chips are unaffected. These are suboptimal values,
+ * but we don't use on-chip GS.
+ */
+ si_pm4_set_reg(pm4, R_028A44_VGT_GS_ONCHIP_CNTL,
+ S_028A44_ES_VERTS_PER_SUBGRP(64) |
+ S_028A44_GS_PRIMS_PER_SUBGRP(4));
}
si_pm4_set_reg(pm4, R_00B21C_SPI_SHADER_PGM_RSRC3_GS, S_00B21C_CU_EN(0xffff));
RADEON_PRIO_BORDER_COLORS);
if (sctx->b.chip_class >= GFX9) {
- si_pm4_set_reg(pm4, R_028060_DB_DFSM_CONTROL, 0);
+ unsigned num_se = sscreen->b.info.max_se;
+ unsigned pc_lines = 0;
+
+ switch (sctx->b.family) {
+ case CHIP_VEGA10:
+ pc_lines = 4096;
+ break;
+ default:
+ assert(0);
+ }
+
+ si_pm4_set_reg(pm4, R_028060_DB_DFSM_CONTROL,
+ S_028060_PUNCHOUT_MODE(V_028060_FORCE_OFF));
si_pm4_set_reg(pm4, R_028064_DB_RENDER_FILTER, 0);
/* TODO: We can use this to disable RBs for rendering to GART: */
si_pm4_set_reg(pm4, R_02835C_PA_SC_TILE_STEERING_OVERRIDE, 0);
si_pm4_set_reg(pm4, R_02883C_PA_SU_OVER_RASTERIZATION_CNTL, 0);
/* TODO: Enable the binner: */
si_pm4_set_reg(pm4, R_028C44_PA_SC_BINNER_CNTL_0,
- S_028C44_BINNING_MODE(V_028C44_DISABLE_BINNING_USE_LEGACY_SC));
- si_pm4_set_reg(pm4, R_028C48_PA_SC_BINNER_CNTL_1, 0);
+ S_028C44_BINNING_MODE(V_028C44_DISABLE_BINNING_USE_LEGACY_SC) |
+ S_028C44_DISABLE_START_OF_PRIM(1));
+ si_pm4_set_reg(pm4, R_028C48_PA_SC_BINNER_CNTL_1,
+ S_028C48_MAX_ALLOC_COUNT(MIN2(128, pc_lines / (4 * num_se))) |
+ S_028C48_MAX_PRIM_PER_BATCH(1023));
si_pm4_set_reg(pm4, R_028C4C_PA_SC_CONSERVATIVE_RASTERIZATION_CNTL,
S_028C4C_NULL_SQUAD_AA_MASK_ENABLE(1));
si_pm4_set_reg(pm4, R_030968_VGT_INSTANCE_BASE_ID, 0);