#include "util/u_format_s3tc.h"
#include "util/u_memory.h"
#include "util/u_pstipple.h"
+#include "util/u_resource.h"
/* Initialize an external atom (owned by ../radeon). */
static void
}
/* The old way. */
- switch (sscreen->b.tiling_info.num_banks) {
+ switch (sscreen->b.info.r600_num_banks) {
case 2:
return V_02803C_ADDR_SURF_2_BANK;
case 4:
/* This is probably broken for a lot of chips, but it's only used
* if the kernel cannot return the tile mode array for CIK. */
- switch (sscreen->b.info.r600_num_tile_pipes) {
+ switch (sscreen->b.info.num_tile_pipes) {
case 16:
return V_02803C_X_ADDR_SURF_P16_32X32_16X16;
case 8:
return V_02803C_X_ADDR_SURF_P8_32X32_16X16;
case 4:
default:
- if (sscreen->b.info.r600_num_backends == 4)
+ if (sscreen->b.info.num_render_backends == 4)
return V_02803C_X_ADDR_SURF_P4_16X16;
else
return V_02803C_X_ADDR_SURF_P4_8X16;
/*
* Inferred framebuffer and blender state.
*
- * One of the reasons this must be derived from the framebuffer state is that:
+ * One of the reasons CB_TARGET_MASK must be derived from the framebuffer state
+ * is that:
* - The blend state mask is 0xf most of the time.
* - The COLOR1 format isn't INVALID because of possible dual-source blending,
* so COLOR1 is enabled pretty much all the time.
*
* Another reason is to avoid a hang with dual source blending.
*/
-static void si_emit_cb_target_mask(struct si_context *sctx, struct r600_atom *atom)
+static void si_emit_cb_render_state(struct si_context *sctx, struct r600_atom *atom)
{
struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
struct si_state_blend *blend = sctx->queued.named.blend;
- uint32_t mask = 0, i;
+ uint32_t cb_target_mask = 0, i;
for (i = 0; i < sctx->framebuffer.state.nr_cbufs; i++)
if (sctx->framebuffer.state.cbufs[i])
- mask |= 0xf << (4*i);
+ cb_target_mask |= 0xf << (4*i);
if (blend)
- mask &= blend->cb_target_mask;
+ cb_target_mask &= blend->cb_target_mask;
/* Avoid a hang that happens when dual source blending is enabled
* but there is not enough color outputs. This is undefined behavior,
if (blend && blend->dual_src_blend &&
sctx->ps_shader.cso &&
(sctx->ps_shader.cso->info.colors_written & 0x3) != 0x3)
- mask = 0;
+ cb_target_mask = 0;
- radeon_set_context_reg(cs, R_028238_CB_TARGET_MASK, mask);
+ radeon_set_context_reg(cs, R_028238_CB_TARGET_MASK, cb_target_mask);
+
+ /* STONEY-specific register settings. */
+ if (sctx->b.family == CHIP_STONEY) {
+ unsigned spi_shader_col_format =
+ sctx->ps_shader.cso ?
+ sctx->ps_shader.current->key.ps.epilog.spi_shader_col_format : 0;
+ unsigned sx_ps_downconvert = 0;
+ unsigned sx_blend_opt_epsilon = 0;
+ unsigned sx_blend_opt_control = 0;
+
+ for (i = 0; i < sctx->framebuffer.state.nr_cbufs; i++) {
+ struct r600_surface *surf =
+ (struct r600_surface*)sctx->framebuffer.state.cbufs[i];
+ unsigned format, swap, spi_format, colormask;
+ bool has_alpha, has_rgb;
+
+ if (!surf)
+ continue;
+
+ format = G_028C70_FORMAT(surf->cb_color_info);
+ swap = G_028C70_COMP_SWAP(surf->cb_color_info);
+ spi_format = (spi_shader_col_format >> (i * 4)) & 0xf;
+ colormask = (cb_target_mask >> (i * 4)) & 0xf;
+
+ /* Set if RGB and A are present. */
+ has_alpha = !G_028C74_FORCE_DST_ALPHA_1(surf->cb_color_attrib);
+
+ if (format == V_028C70_COLOR_8 ||
+ format == V_028C70_COLOR_16 ||
+ format == V_028C70_COLOR_32)
+ has_rgb = !has_alpha;
+ else
+ has_rgb = true;
+
+ /* Check the colormask and export format. */
+ if (!(colormask & (PIPE_MASK_RGBA & ~PIPE_MASK_A)))
+ has_rgb = false;
+ if (!(colormask & PIPE_MASK_A))
+ has_alpha = false;
+
+ if (spi_format == V_028714_SPI_SHADER_ZERO) {
+ has_rgb = false;
+ has_alpha = false;
+ }
+
+ /* Disable value checking for disabled channels. */
+ if (!has_rgb)
+ sx_blend_opt_control |= S_02875C_MRT0_COLOR_OPT_DISABLE(1) << (i * 4);
+ if (!has_alpha)
+ sx_blend_opt_control |= S_02875C_MRT0_ALPHA_OPT_DISABLE(1) << (i * 4);
+
+ /* Enable down-conversion for 32bpp and smaller formats. */
+ switch (format) {
+ case V_028C70_COLOR_8:
+ case V_028C70_COLOR_8_8:
+ case V_028C70_COLOR_8_8_8_8:
+ /* For 1 and 2-channel formats, use the superset thereof. */
+ if (spi_format == V_028714_SPI_SHADER_FP16_ABGR ||
+ spi_format == V_028714_SPI_SHADER_UINT16_ABGR ||
+ spi_format == V_028714_SPI_SHADER_SINT16_ABGR) {
+ sx_ps_downconvert |= V_028754_SX_RT_EXPORT_8_8_8_8 << (i * 4);
+ sx_blend_opt_epsilon |= V_028758_8BIT_FORMAT << (i * 4);
+ }
+ break;
+
+ case V_028C70_COLOR_5_6_5:
+ if (spi_format == V_028714_SPI_SHADER_FP16_ABGR) {
+ sx_ps_downconvert |= V_028754_SX_RT_EXPORT_5_6_5 << (i * 4);
+ sx_blend_opt_epsilon |= V_028758_6BIT_FORMAT << (i * 4);
+ }
+ break;
+
+ case V_028C70_COLOR_1_5_5_5:
+ if (spi_format == V_028714_SPI_SHADER_FP16_ABGR) {
+ sx_ps_downconvert |= V_028754_SX_RT_EXPORT_1_5_5_5 << (i * 4);
+ sx_blend_opt_epsilon |= V_028758_5BIT_FORMAT << (i * 4);
+ }
+ break;
+
+ case V_028C70_COLOR_4_4_4_4:
+ if (spi_format == V_028714_SPI_SHADER_FP16_ABGR) {
+ sx_ps_downconvert |= V_028754_SX_RT_EXPORT_4_4_4_4 << (i * 4);
+ sx_blend_opt_epsilon |= V_028758_4BIT_FORMAT << (i * 4);
+ }
+ break;
+
+ case V_028C70_COLOR_32:
+ if (swap == V_0280A0_SWAP_STD &&
+ spi_format == V_028714_SPI_SHADER_32_R)
+ sx_ps_downconvert |= V_028754_SX_RT_EXPORT_32_R << (i * 4);
+ else if (swap == V_0280A0_SWAP_ALT_REV &&
+ spi_format == V_028714_SPI_SHADER_32_AR)
+ sx_ps_downconvert |= V_028754_SX_RT_EXPORT_32_A << (i * 4);
+ break;
+
+ case V_028C70_COLOR_16:
+ case V_028C70_COLOR_16_16:
+ /* For 1-channel formats, use the superset thereof. */
+ if (spi_format == V_028714_SPI_SHADER_UNORM16_ABGR ||
+ spi_format == V_028714_SPI_SHADER_SNORM16_ABGR ||
+ spi_format == V_028714_SPI_SHADER_UINT16_ABGR ||
+ spi_format == V_028714_SPI_SHADER_SINT16_ABGR) {
+ if (swap == V_0280A0_SWAP_STD ||
+ swap == V_0280A0_SWAP_STD_REV)
+ sx_ps_downconvert |= V_028754_SX_RT_EXPORT_16_16_GR << (i * 4);
+ else
+ sx_ps_downconvert |= V_028754_SX_RT_EXPORT_16_16_AR << (i * 4);
+ }
+ break;
+
+ case V_028C70_COLOR_10_11_11:
+ if (spi_format == V_028714_SPI_SHADER_FP16_ABGR) {
+ sx_ps_downconvert |= V_028754_SX_RT_EXPORT_10_11_11 << (i * 4);
+ sx_blend_opt_epsilon |= V_028758_11BIT_FORMAT << (i * 4);
+ }
+ break;
+
+ case V_028C70_COLOR_2_10_10_10:
+ if (spi_format == V_028714_SPI_SHADER_FP16_ABGR) {
+ sx_ps_downconvert |= V_028754_SX_RT_EXPORT_2_10_10_10 << (i * 4);
+ sx_blend_opt_epsilon |= V_028758_10BIT_FORMAT << (i * 4);
+ }
+ break;
+ }
+ }
+
+ if (sctx->screen->b.debug_flags & DBG_NO_RB_PLUS) {
+ sx_ps_downconvert = 0;
+ sx_blend_opt_epsilon = 0;
+ sx_blend_opt_control = 0;
+ }
+
+ radeon_set_context_reg_seq(cs, R_028754_SX_PS_DOWNCONVERT, 3);
+ radeon_emit(cs, sx_ps_downconvert); /* R_028754_SX_PS_DOWNCONVERT */
+ radeon_emit(cs, sx_blend_opt_epsilon); /* R_028758_SX_BLEND_OPT_EPSILON */
+ radeon_emit(cs, sx_blend_opt_control); /* R_02875C_SX_BLEND_OPT_CONTROL */
+ }
}
/*
}
}
+/**
+ * Get rid of DST in the blend factors by commuting the operands:
+ * func(src * DST, dst * 0) ---> func(src * 0, dst * SRC)
+ */
+static void si_blend_remove_dst(unsigned *func, unsigned *src_factor,
+ unsigned *dst_factor, unsigned expected_dst,
+ unsigned replacement_src)
+{
+ if (*src_factor == expected_dst &&
+ *dst_factor == PIPE_BLENDFACTOR_ZERO) {
+ *src_factor = PIPE_BLENDFACTOR_ZERO;
+ *dst_factor = replacement_src;
+
+ /* Commuting the operands requires reversing subtractions. */
+ if (*func == PIPE_BLEND_SUBTRACT)
+ *func = PIPE_BLEND_REVERSE_SUBTRACT;
+ else if (*func == PIPE_BLEND_REVERSE_SUBTRACT)
+ *func = PIPE_BLEND_SUBTRACT;
+ }
+}
+
+static bool si_blend_factor_uses_dst(unsigned factor)
+{
+ return factor == PIPE_BLENDFACTOR_DST_COLOR ||
+ factor == PIPE_BLENDFACTOR_DST_ALPHA ||
+ factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE ||
+ factor == PIPE_BLENDFACTOR_INV_DST_ALPHA ||
+ factor == PIPE_BLENDFACTOR_INV_DST_COLOR;
+}
+
static void *si_create_blend_state_mode(struct pipe_context *ctx,
const struct pipe_blend_state *state,
unsigned mode)
struct si_context *sctx = (struct si_context*)ctx;
struct si_state_blend *blend = CALLOC_STRUCT(si_state_blend);
struct si_pm4_state *pm4 = &blend->pm4;
-
+ uint32_t sx_mrt_blend_opt[8] = {0};
uint32_t color_control = 0;
if (!blend)
return NULL;
+ blend->alpha_to_coverage = state->alpha_to_coverage;
blend->alpha_to_one = state->alpha_to_one;
blend->dual_src_blend = util_blend_state_is_dual(state, 0);
S_028B70_ALPHA_TO_MASK_OFFSET2(2) |
S_028B70_ALPHA_TO_MASK_OFFSET3(2));
+ if (state->alpha_to_coverage)
+ blend->need_src_alpha_4bit |= 0xf;
+
blend->cb_target_mask = 0;
for (int i = 0; i < 8; i++) {
/* state->rt entries > 0 only written if independent blending */
unsigned srcA = state->rt[j].alpha_src_factor;
unsigned dstA = state->rt[j].alpha_dst_factor;
+ unsigned srcRGB_opt, dstRGB_opt, srcA_opt, dstA_opt;
unsigned blend_cntl = 0;
+ sx_mrt_blend_opt[i] =
+ S_028760_COLOR_COMB_FCN(V_028760_OPT_COMB_BLEND_DISABLED) |
+ S_028760_ALPHA_COMB_FCN(V_028760_OPT_COMB_BLEND_DISABLED);
+
if (!state->rt[j].colormask)
continue;
- /* we pretend 8 buffer are used, CB_SHADER_MASK will disable unused one */
+ /* cb_render_state will disable unused ones */
blend->cb_target_mask |= state->rt[j].colormask << (4 * i);
if (!state->rt[j].blend_enable) {
continue;
}
+ /* Blending optimizations for Stoney.
+ * These transformations don't change the behavior.
+ *
+ * First, get rid of DST in the blend factors:
+ * func(src * DST, dst * 0) ---> func(src * 0, dst * SRC)
+ */
+ si_blend_remove_dst(&eqRGB, &srcRGB, &dstRGB,
+ PIPE_BLENDFACTOR_DST_COLOR,
+ PIPE_BLENDFACTOR_SRC_COLOR);
+ si_blend_remove_dst(&eqA, &srcA, &dstA,
+ PIPE_BLENDFACTOR_DST_COLOR,
+ PIPE_BLENDFACTOR_SRC_COLOR);
+ si_blend_remove_dst(&eqA, &srcA, &dstA,
+ PIPE_BLENDFACTOR_DST_ALPHA,
+ PIPE_BLENDFACTOR_SRC_ALPHA);
+
+ /* Look up the ideal settings from tables. */
+ srcRGB_opt = si_translate_blend_opt_factor(srcRGB, false);
+ dstRGB_opt = si_translate_blend_opt_factor(dstRGB, false);
+ srcA_opt = si_translate_blend_opt_factor(srcA, true);
+ dstA_opt = si_translate_blend_opt_factor(dstA, true);
+
+ /* Handle interdependencies. */
+ if (si_blend_factor_uses_dst(srcRGB))
+ dstRGB_opt = V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_NONE;
+ if (si_blend_factor_uses_dst(srcA))
+ dstA_opt = V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_NONE;
+
+ if (srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE &&
+ (dstRGB == PIPE_BLENDFACTOR_ZERO ||
+ dstRGB == PIPE_BLENDFACTOR_SRC_ALPHA ||
+ dstRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE))
+ dstRGB_opt = V_028760_BLEND_OPT_PRESERVE_NONE_IGNORE_A0;
+
+ /* Set the final value. */
+ sx_mrt_blend_opt[i] =
+ S_028760_COLOR_SRC_OPT(srcRGB_opt) |
+ S_028760_COLOR_DST_OPT(dstRGB_opt) |
+ S_028760_COLOR_COMB_FCN(si_translate_blend_opt_function(eqRGB)) |
+ S_028760_ALPHA_SRC_OPT(srcA_opt) |
+ S_028760_ALPHA_DST_OPT(dstA_opt) |
+ S_028760_ALPHA_COMB_FCN(si_translate_blend_opt_function(eqA));
+
+ /* Set blend state. */
blend_cntl |= S_028780_ENABLE(1);
blend_cntl |= S_028780_COLOR_COMB_FCN(si_translate_blend_function(eqRGB));
blend_cntl |= S_028780_COLOR_SRCBLEND(si_translate_blend_factor(srcRGB));
blend_cntl |= S_028780_ALPHA_DESTBLEND(si_translate_blend_factor(dstA));
}
si_pm4_set_reg(pm4, R_028780_CB_BLEND0_CONTROL + i * 4, blend_cntl);
+
+ blend->blend_enable_4bit |= 0xf << (i * 4);
+
+ /* This is only important for formats without alpha. */
+ if (srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA ||
+ dstRGB == PIPE_BLENDFACTOR_SRC_ALPHA ||
+ srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE ||
+ dstRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE ||
+ srcRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA ||
+ dstRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA)
+ blend->need_src_alpha_4bit |= 0xf << (i * 4);
}
if (blend->cb_target_mask) {
}
if (sctx->b.family == CHIP_STONEY) {
- uint32_t sx_blend_opt_control = 0;
-
- for (int i = 0; i < 8; i++) {
- const int j = state->independent_blend_enable ? i : 0;
-
- /* TODO: We can also set this if the surface doesn't contain RGB. */
- if (!state->rt[j].blend_enable ||
- !(state->rt[j].colormask & (PIPE_MASK_R | PIPE_MASK_G | PIPE_MASK_B)))
- sx_blend_opt_control |= S_02875C_MRT0_COLOR_OPT_DISABLE(1) << (4 * i);
-
- /* TODO: We can also set this if the surface doesn't contain alpha. */
- if (!state->rt[j].blend_enable ||
- !(state->rt[j].colormask & PIPE_MASK_A))
- sx_blend_opt_control |= S_02875C_MRT0_ALPHA_OPT_DISABLE(1) << (4 * i);
-
- if (!state->rt[j].blend_enable) {
- si_pm4_set_reg(pm4, R_028760_SX_MRT0_BLEND_OPT + i * 4,
- S_028760_COLOR_COMB_FCN(V_028760_OPT_COMB_BLEND_DISABLED) |
- S_028760_ALPHA_COMB_FCN(V_028760_OPT_COMB_BLEND_DISABLED));
- continue;
- }
-
+ for (int i = 0; i < 8; i++)
si_pm4_set_reg(pm4, R_028760_SX_MRT0_BLEND_OPT + i * 4,
- S_028760_COLOR_SRC_OPT(si_translate_blend_opt_factor(state->rt[j].rgb_src_factor, false)) |
- S_028760_COLOR_DST_OPT(si_translate_blend_opt_factor(state->rt[j].rgb_dst_factor, false)) |
- S_028760_COLOR_COMB_FCN(si_translate_blend_opt_function(state->rt[j].rgb_func)) |
- S_028760_ALPHA_SRC_OPT(si_translate_blend_opt_factor(state->rt[j].alpha_src_factor, true)) |
- S_028760_ALPHA_DST_OPT(si_translate_blend_opt_factor(state->rt[j].alpha_dst_factor, true)) |
- S_028760_ALPHA_COMB_FCN(si_translate_blend_opt_function(state->rt[j].alpha_func)));
- }
-
- si_pm4_set_reg(pm4, R_02875C_SX_BLEND_OPT_CONTROL, sx_blend_opt_control);
+ sx_mrt_blend_opt[i]);
- /* RB+ doesn't work with dual source blending */
- if (blend->dual_src_blend)
+ /* RB+ doesn't work with dual source blending, logic op, and RESOLVE. */
+ if (blend->dual_src_blend || state->logicop_enable ||
+ mode == V_028808_CB_RESOLVE)
color_control |= S_028808_DISABLE_DUAL_QUAD(1);
}
{
struct si_context *sctx = (struct si_context *)ctx;
si_pm4_bind_state(sctx, blend, (struct si_state_blend *)state);
- si_mark_atom_dirty(sctx, &sctx->cb_target_mask);
+ si_mark_atom_dirty(sctx, &sctx->cb_render_state);
}
static void si_delete_blend_state(struct pipe_context *ctx, void *state)
sctx->ps_db_shader_control;
/* Bug workaround for smoothing (overrasterization) on SI. */
- if (sctx->b.chip_class == SI && sctx->smoothing_enabled)
+ if (sctx->b.chip_class == SI && sctx->smoothing_enabled) {
+ db_shader_control &= C_02880C_Z_ORDER;
db_shader_control |= S_02880C_Z_ORDER(V_02880C_LATE_Z);
- else
- db_shader_control |= S_02880C_Z_ORDER(V_02880C_EARLY_Z_THEN_LATE_Z);
+ }
/* Disable the gl_SampleMask fragment shader output if MSAA is disabled. */
if (sctx->framebuffer.nr_samples <= 1 || (rs && !rs->multisample_enable))
}
}
-/* Returns the size in bits of the widest component of a CB format */
-static unsigned si_colorformat_max_comp_size(uint32_t colorformat)
-{
- switch(colorformat) {
- case V_028C70_COLOR_4_4_4_4:
- return 4;
-
- case V_028C70_COLOR_1_5_5_5:
- case V_028C70_COLOR_5_5_5_1:
- return 5;
-
- case V_028C70_COLOR_5_6_5:
- return 6;
-
- case V_028C70_COLOR_8:
- case V_028C70_COLOR_8_8:
- case V_028C70_COLOR_8_8_8_8:
- return 8;
-
- case V_028C70_COLOR_10_10_10_2:
- case V_028C70_COLOR_2_10_10_10:
- return 10;
-
- case V_028C70_COLOR_10_11_11:
- case V_028C70_COLOR_11_11_10:
- return 11;
-
- case V_028C70_COLOR_16:
- case V_028C70_COLOR_16_16:
- case V_028C70_COLOR_16_16_16_16:
- return 16;
-
- case V_028C70_COLOR_8_24:
- case V_028C70_COLOR_24_8:
- return 24;
-
- case V_028C70_COLOR_32:
- case V_028C70_COLOR_32_32:
- case V_028C70_COLOR_32_32_32_32:
- case V_028C70_COLOR_X24_8_32_FLOAT:
- return 32;
- }
-
- assert(!"Unknown maximum component size");
- return 0;
-}
-
static uint32_t si_translate_dbformat(enum pipe_format format)
{
switch (format) {
}
}
+ if (desc->layout == UTIL_FORMAT_LAYOUT_ETC &&
+ sscreen->b.family >= CHIP_STONEY) {
+ switch (format) {
+ case PIPE_FORMAT_ETC1_RGB8:
+ case PIPE_FORMAT_ETC2_RGB8:
+ case PIPE_FORMAT_ETC2_SRGB8:
+ return V_008F14_IMG_DATA_FORMAT_ETC2_RGB;
+ case PIPE_FORMAT_ETC2_RGB8A1:
+ case PIPE_FORMAT_ETC2_SRGB8A1:
+ return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA1;
+ case PIPE_FORMAT_ETC2_RGBA8:
+ case PIPE_FORMAT_ETC2_SRGBA8:
+ return V_008F14_IMG_DATA_FORMAT_ETC2_RGBA;
+ case PIPE_FORMAT_ETC2_R11_UNORM:
+ case PIPE_FORMAT_ETC2_R11_SNORM:
+ return V_008F14_IMG_DATA_FORMAT_ETC2_R;
+ case PIPE_FORMAT_ETC2_RG11_UNORM:
+ case PIPE_FORMAT_ETC2_RG11_SNORM:
+ return V_008F14_IMG_DATA_FORMAT_ETC2_RG;
+ default:
+ goto out_unknown;
+ }
+ }
+
if (desc->layout == UTIL_FORMAT_LAYOUT_BPTC) {
if (!enable_compressed_formats)
goto out_unknown;
* framebuffer handling
*/
+static void si_choose_spi_color_formats(struct r600_surface *surf,
+ unsigned format, unsigned swap,
+ unsigned ntype, bool is_depth)
+{
+ /* Alpha is needed for alpha-to-coverage.
+ * Blending may be with or without alpha.
+ */
+ unsigned normal = 0; /* most optimal, may not support blending or export alpha */
+ unsigned alpha = 0; /* exports alpha, but may not support blending */
+ unsigned blend = 0; /* supports blending, but may not export alpha */
+ unsigned blend_alpha = 0; /* least optimal, supports blending and exports alpha */
+
+ /* Choose the SPI color formats. These are required values for Stoney/RB+.
+ * Other chips have multiple choices, though they are not necessarily better.
+ */
+ switch (format) {
+ case V_028C70_COLOR_5_6_5:
+ case V_028C70_COLOR_1_5_5_5:
+ case V_028C70_COLOR_5_5_5_1:
+ case V_028C70_COLOR_4_4_4_4:
+ case V_028C70_COLOR_10_11_11:
+ case V_028C70_COLOR_11_11_10:
+ case V_028C70_COLOR_8:
+ case V_028C70_COLOR_8_8:
+ case V_028C70_COLOR_8_8_8_8:
+ case V_028C70_COLOR_10_10_10_2:
+ case V_028C70_COLOR_2_10_10_10:
+ if (ntype == V_028C70_NUMBER_UINT)
+ alpha = blend = blend_alpha = normal = V_028714_SPI_SHADER_UINT16_ABGR;
+ else if (ntype == V_028C70_NUMBER_SINT)
+ alpha = blend = blend_alpha = normal = V_028714_SPI_SHADER_SINT16_ABGR;
+ else
+ alpha = blend = blend_alpha = normal = V_028714_SPI_SHADER_FP16_ABGR;
+ break;
+
+ case V_028C70_COLOR_16:
+ case V_028C70_COLOR_16_16:
+ case V_028C70_COLOR_16_16_16_16:
+ if (ntype == V_028C70_NUMBER_UNORM ||
+ ntype == V_028C70_NUMBER_SNORM) {
+ /* UNORM16 and SNORM16 don't support blending */
+ if (ntype == V_028C70_NUMBER_UNORM)
+ normal = alpha = V_028714_SPI_SHADER_UNORM16_ABGR;
+ else
+ normal = alpha = V_028714_SPI_SHADER_SNORM16_ABGR;
+
+ /* Use 32 bits per channel for blending. */
+ if (format == V_028C70_COLOR_16) {
+ if (swap == V_028C70_SWAP_STD) { /* R */
+ blend = V_028714_SPI_SHADER_32_R;
+ blend_alpha = V_028714_SPI_SHADER_32_AR;
+ } else if (swap == V_028C70_SWAP_ALT_REV) /* A */
+ blend = blend_alpha = V_028714_SPI_SHADER_32_AR;
+ else
+ assert(0);
+ } else if (format == V_028C70_COLOR_16_16) {
+ if (swap == V_028C70_SWAP_STD) { /* RG */
+ blend = V_028714_SPI_SHADER_32_GR;
+ blend_alpha = V_028714_SPI_SHADER_32_ABGR;
+ } else if (swap == V_028C70_SWAP_ALT) /* RA */
+ blend = blend_alpha = V_028714_SPI_SHADER_32_AR;
+ else
+ assert(0);
+ } else /* 16_16_16_16 */
+ blend = blend_alpha = V_028714_SPI_SHADER_32_ABGR;
+ } else if (ntype == V_028C70_NUMBER_UINT)
+ alpha = blend = blend_alpha = normal = V_028714_SPI_SHADER_UINT16_ABGR;
+ else if (ntype == V_028C70_NUMBER_SINT)
+ alpha = blend = blend_alpha = normal = V_028714_SPI_SHADER_SINT16_ABGR;
+ else if (ntype == V_028C70_NUMBER_FLOAT)
+ alpha = blend = blend_alpha = normal = V_028714_SPI_SHADER_FP16_ABGR;
+ else
+ assert(0);
+ break;
+
+ case V_028C70_COLOR_32:
+ if (swap == V_028C70_SWAP_STD) { /* R */
+ blend = normal = V_028714_SPI_SHADER_32_R;
+ alpha = blend_alpha = V_028714_SPI_SHADER_32_AR;
+ } else if (swap == V_028C70_SWAP_ALT_REV) /* A */
+ alpha = blend = blend_alpha = normal = V_028714_SPI_SHADER_32_AR;
+ else
+ assert(0);
+ break;
+
+ case V_028C70_COLOR_32_32:
+ if (swap == V_028C70_SWAP_STD) { /* RG */
+ blend = normal = V_028714_SPI_SHADER_32_GR;
+ alpha = blend_alpha = V_028714_SPI_SHADER_32_ABGR;
+ } else if (swap == V_028C70_SWAP_ALT) /* RA */
+ alpha = blend = blend_alpha = normal = V_028714_SPI_SHADER_32_AR;
+ else
+ assert(0);
+ break;
+
+ case V_028C70_COLOR_32_32_32_32:
+ case V_028C70_COLOR_8_24:
+ case V_028C70_COLOR_24_8:
+ case V_028C70_COLOR_X24_8_32_FLOAT:
+ alpha = blend = blend_alpha = normal = V_028714_SPI_SHADER_32_ABGR;
+ break;
+
+ default:
+ assert(0);
+ return;
+ }
+
+ /* The DB->CB copy needs 32_ABGR. */
+ if (is_depth)
+ alpha = blend = blend_alpha = normal = V_028714_SPI_SHADER_32_ABGR;
+
+ surf->spi_shader_col_format = normal;
+ surf->spi_shader_col_format_alpha = alpha;
+ surf->spi_shader_col_format_blend = blend;
+ surf->spi_shader_col_format_blend_alpha = blend_alpha;
+}
+
static void si_initialize_color_surface(struct si_context *sctx,
struct r600_surface *surf)
{
const struct util_format_description *desc;
int i;
unsigned blend_clamp = 0, blend_bypass = 0;
- unsigned max_comp_size;
/* Layered rendering doesn't work with LINEAR_GENERAL.
* (LINEAR_ALIGNED and others work) */
}
assert(format != V_028C70_COLOR_INVALID);
swap = r600_translate_colorswap(surf->base.format);
- if (rtex->resource.b.b.usage == PIPE_USAGE_STAGING) {
- endian = V_028C70_ENDIAN_NONE;
- } else {
- endian = si_colorformat_endian_swap(format);
- }
+ endian = si_colorformat_endian_swap(format);
/* blend clamp should be set for all NORM/SRGB types */
if (ntype == V_028C70_NUMBER_UNORM ||
blend_bypass = 1;
}
+ if ((ntype == V_028C70_NUMBER_UINT || ntype == V_028C70_NUMBER_SINT) &&
+ (format == V_028C70_COLOR_8 ||
+ format == V_028C70_COLOR_8_8 ||
+ format == V_028C70_COLOR_8_8_8_8))
+ surf->color_is_int8 = true;
+
color_info = S_028C70_FORMAT(format) |
S_028C70_COMP_SWAP(swap) |
S_028C70_BLEND_CLAMP(blend_clamp) |
color_pitch = S_028C64_TILE_MAX(pitch);
+ /* Intensity is implemented as Red, so treat it that way. */
color_attrib = S_028C74_TILE_MODE_INDEX(tile_mode_index) |
- S_028C74_FORCE_DST_ALPHA_1(desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_1);
+ S_028C74_FORCE_DST_ALPHA_1(desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_1 ||
+ util_format_is_intensity(surf->base.format));
if (rtex->resource.b.b.nr_samples > 1) {
unsigned log_samples = util_logbase2(rtex->resource.b.b.nr_samples);
surf->cb_color_info = color_info;
surf->cb_color_attrib = color_attrib;
- if (sctx->b.chip_class >= VI && rtex->dcc_buffer) {
+ if (sctx->b.chip_class >= VI && rtex->dcc_offset) {
unsigned max_uncompressed_block_size = 2;
- uint64_t dcc_offset = rtex->surface.level[level].dcc_offset;
if (rtex->surface.nsamples > 1) {
if (rtex->surface.bpe == 1)
surf->cb_dcc_control = S_028C78_MAX_UNCOMPRESSED_BLOCK_SIZE(max_uncompressed_block_size) |
S_028C78_INDEPENDENT_64B_BLOCKS(1);
- surf->cb_dcc_base = (rtex->dcc_buffer->gpu_address + dcc_offset) >> 8;
+ surf->cb_dcc_base = (rtex->resource.gpu_address +
+ rtex->dcc_offset +
+ rtex->surface.level[level].dcc_offset) >> 8;
}
if (rtex->fmask.size) {
}
/* Determine pixel shader export format */
- max_comp_size = si_colorformat_max_comp_size(format);
- if (ntype == V_028C70_NUMBER_SRGB ||
- ((ntype == V_028C70_NUMBER_UNORM || ntype == V_028C70_NUMBER_SNORM) &&
- max_comp_size <= 10) ||
- (ntype == V_028C70_NUMBER_FLOAT && max_comp_size <= 16)) {
- surf->export_16bpc = true;
- }
-
- if (sctx->b.family == CHIP_STONEY &&
- !(sctx->screen->b.debug_flags & DBG_NO_RB_PLUS)) {
- switch (desc->channel[0].size) {
- case 32:
- if (desc->nr_channels == 1) {
- if (swap == V_0280A0_SWAP_STD)
- surf->sx_ps_downconvert = V_028754_SX_RT_EXPORT_32_R;
- else if (swap == V_0280A0_SWAP_ALT_REV)
- surf->sx_ps_downconvert = V_028754_SX_RT_EXPORT_32_A;
- }
- break;
- case 16:
- /* For 1-channel formats, use the superset thereof. */
- if (desc->nr_channels <= 2) {
- if (swap == V_0280A0_SWAP_STD ||
- swap == V_0280A0_SWAP_STD_REV)
- surf->sx_ps_downconvert = V_028754_SX_RT_EXPORT_16_16_GR;
- else
- surf->sx_ps_downconvert = V_028754_SX_RT_EXPORT_16_16_AR;
- }
- break;
- case 11:
- if (desc->nr_channels == 3) {
- surf->sx_ps_downconvert = V_028754_SX_RT_EXPORT_10_11_11;
- surf->sx_blend_opt_epsilon = V_028758_11BIT_FORMAT;
- }
- break;
- case 10:
- if (desc->nr_channels == 4) {
- surf->sx_ps_downconvert = V_028754_SX_RT_EXPORT_2_10_10_10;
- surf->sx_blend_opt_epsilon = V_028758_10BIT_FORMAT;
- }
- break;
- case 8:
- /* For 1 and 2-channel formats, use the superset thereof. */
- surf->sx_ps_downconvert = V_028754_SX_RT_EXPORT_8_8_8_8;
- surf->sx_blend_opt_epsilon = V_028758_8BIT_FORMAT;
- break;
- case 5:
- if (desc->nr_channels == 3) {
- surf->sx_ps_downconvert = V_028754_SX_RT_EXPORT_5_6_5;
- surf->sx_blend_opt_epsilon = V_028758_6BIT_FORMAT;
- } else if (desc->nr_channels == 4) {
- surf->sx_ps_downconvert = V_028754_SX_RT_EXPORT_1_5_5_5;
- surf->sx_blend_opt_epsilon = V_028758_5BIT_FORMAT;
- }
- break;
- case 4:
- /* For 1 nad 2-channel formats, use the superset thereof. */
- surf->sx_ps_downconvert = V_028754_SX_RT_EXPORT_4_4_4_4;
- surf->sx_blend_opt_epsilon = V_028758_4BIT_FORMAT;
- break;
- }
- }
+ si_choose_spi_color_formats(surf, format, swap, ntype, rtex->is_depth);
surf->color_initialized = true;
}
util_copy_framebuffer_state(&sctx->framebuffer.state, state);
- sctx->framebuffer.export_16bpc = 0;
+ sctx->framebuffer.spi_shader_col_format = 0;
+ sctx->framebuffer.spi_shader_col_format_alpha = 0;
+ sctx->framebuffer.spi_shader_col_format_blend = 0;
+ sctx->framebuffer.spi_shader_col_format_blend_alpha = 0;
+ sctx->framebuffer.color_is_int8 = 0;
+
sctx->framebuffer.compressed_cb_mask = 0;
sctx->framebuffer.nr_samples = util_framebuffer_get_num_samples(state);
sctx->framebuffer.log_samples = util_logbase2(sctx->framebuffer.nr_samples);
si_initialize_color_surface(sctx, surf);
}
- if (surf->export_16bpc) {
- sctx->framebuffer.export_16bpc |= 1 << i;
- }
+ sctx->framebuffer.spi_shader_col_format |=
+ surf->spi_shader_col_format << (i * 4);
+ sctx->framebuffer.spi_shader_col_format_alpha |=
+ surf->spi_shader_col_format_alpha << (i * 4);
+ sctx->framebuffer.spi_shader_col_format_blend |=
+ surf->spi_shader_col_format_blend << (i * 4);
+ sctx->framebuffer.spi_shader_col_format_blend_alpha |=
+ surf->spi_shader_col_format_blend_alpha << (i * 4);
+
+ if (surf->color_is_int8)
+ sctx->framebuffer.color_is_int8 |= 1 << i;
if (rtex->fmask.size && rtex->cmask.size) {
sctx->framebuffer.compressed_cb_mask |= 1 << i;
}
r600_context_add_resource_size(ctx, surf->base.texture);
}
- /* Set the 16BPC export for possible dual-src blending. */
- if (i == 1 && surf && surf->export_16bpc) {
- sctx->framebuffer.export_16bpc |= 1 << 1;
+ /* Set the second SPI format for possible dual-src blending. */
+ if (i == 1 && surf) {
+ sctx->framebuffer.spi_shader_col_format |=
+ surf->spi_shader_col_format << (i * 4);
+ sctx->framebuffer.spi_shader_col_format_alpha |=
+ surf->spi_shader_col_format_alpha << (i * 4);
+ sctx->framebuffer.spi_shader_col_format_blend |=
+ surf->spi_shader_col_format_blend << (i * 4);
+ sctx->framebuffer.spi_shader_col_format_blend_alpha |=
+ surf->spi_shader_col_format_blend_alpha << (i * 4);
}
- assert(!(sctx->framebuffer.export_16bpc & ~0xff));
-
if (state->zsbuf) {
surf = (struct r600_surface*)state->zsbuf;
}
si_update_poly_offset_state(sctx);
- si_mark_atom_dirty(sctx, &sctx->cb_target_mask);
+ si_mark_atom_dirty(sctx, &sctx->cb_render_state);
si_mark_atom_dirty(sctx, &sctx->framebuffer.atom);
if (sctx->framebuffer.nr_samples != old_nr_samples) {
unsigned i, nr_cbufs = state->nr_cbufs;
struct r600_texture *tex = NULL;
struct r600_surface *cb = NULL;
- uint32_t sx_ps_downconvert = 0;
- uint32_t sx_blend_opt_epsilon = 0;
/* Colorbuffers. */
for (i = 0; i < nr_cbufs; i++) {
RADEON_PRIO_CMASK);
}
- if (tex->dcc_buffer && tex->dcc_buffer != &tex->resource) {
- radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx,
- tex->dcc_buffer, RADEON_USAGE_READWRITE,
- RADEON_PRIO_DCC);
- }
-
radeon_set_context_reg_seq(cs, R_028C60_CB_COLOR0_BASE + i * 0x3C,
sctx->b.chip_class >= VI ? 14 : 13);
radeon_emit(cs, cb->cb_color_base); /* R_028C60_CB_COLOR0_BASE */
if (sctx->b.chip_class >= VI)
radeon_emit(cs, cb->cb_dcc_base); /* R_028C94_CB_COLOR0_DCC_BASE */
-
- sx_ps_downconvert |= cb->sx_ps_downconvert << (4 * i);
- sx_blend_opt_epsilon |= cb->sx_blend_opt_epsilon << (4 * i);
}
/* set CB_COLOR1_INFO for possible dual-src blending */
if (i == 1 && state->cbufs[0] &&
sctx->framebuffer.dirty_cbufs & (1 << 0)) {
radeon_set_context_reg(cs, R_028C70_CB_COLOR0_INFO + 1 * 0x3C,
cb->cb_color_info | tex->cb_color_info);
- sx_ps_downconvert |= cb->sx_ps_downconvert << (4 * i);
- sx_blend_opt_epsilon |= cb->sx_blend_opt_epsilon << (4 * i);
i++;
}
for (; i < 8 ; i++)
if (sctx->framebuffer.dirty_cbufs & (1 << i))
radeon_set_context_reg(cs, R_028C70_CB_COLOR0_INFO + i * 0x3C, 0);
- if (sctx->b.family == CHIP_STONEY) {
- radeon_set_context_reg_seq(cs, R_028754_SX_PS_DOWNCONVERT, 2);
- radeon_emit(cs, sx_ps_downconvert); /* R_028754_SX_PS_DOWNCONVERT */
- radeon_emit(cs, sx_blend_opt_epsilon); /* R_028758_SX_BLEND_OPT_EPSILON */
- }
-
/* ZS buffer. */
if (state->zsbuf && sctx->framebuffer.dirty_zsbuf) {
struct r600_surface *zb = (struct r600_surface*)state->zsbuf;
*/
/**
- * Create a sampler view.
- *
- * @param ctx context
- * @param texture texture
- * @param state sampler view template
- * @param width0 width0 override (for compressed textures as int)
- * @param height0 height0 override (for compressed textures as int)
- * @param force_level set the base address to the level (for compressed textures)
+ * Build the sampler view descriptor for a buffer texture.
+ * @param state 256-bit descriptor; only the high 128 bits are filled in
*/
-struct pipe_sampler_view *
-si_create_sampler_view_custom(struct pipe_context *ctx,
- struct pipe_resource *texture,
- const struct pipe_sampler_view *state,
- unsigned width0, unsigned height0,
- unsigned force_level)
+void
+si_make_buffer_descriptor(struct si_screen *screen, struct r600_resource *buf,
+ enum pipe_format format,
+ unsigned first_element, unsigned last_element,
+ uint32_t *state)
{
- struct si_context *sctx = (struct si_context*)ctx;
- struct si_sampler_view *view = CALLOC_STRUCT(si_sampler_view);
- struct r600_texture *tmp = (struct r600_texture*)texture;
const struct util_format_description *desc;
- unsigned format, num_format, base_level, first_level, last_level;
- uint32_t pitch = 0;
- unsigned char state_swizzle[4], swizzle[4];
- unsigned height, depth, width;
- enum pipe_format pipe_format = state->format;
- struct radeon_surf_level *surflevel;
int first_non_void;
uint64_t va;
- unsigned last_layer = state->u.tex.last_layer;
-
- if (!view)
- return NULL;
-
- /* initialize base object */
- view->base = *state;
- view->base.texture = NULL;
- view->base.reference.count = 1;
- view->base.context = ctx;
-
- /* NULL resource, obey swizzle (only ZERO and ONE make sense). */
- if (!texture) {
- view->state[3] = S_008F1C_DST_SEL_X(si_map_swizzle(state->swizzle_r)) |
- S_008F1C_DST_SEL_Y(si_map_swizzle(state->swizzle_g)) |
- S_008F1C_DST_SEL_Z(si_map_swizzle(state->swizzle_b)) |
- S_008F1C_DST_SEL_W(si_map_swizzle(state->swizzle_a)) |
- S_008F1C_TYPE(V_008F1C_SQ_RSRC_IMG_1D);
- return &view->base;
- }
+ unsigned stride;
+ unsigned num_records;
+ unsigned num_format, data_format;
- pipe_resource_reference(&view->base.texture, texture);
- view->resource = &tmp->resource;
-
- if (state->format == PIPE_FORMAT_X24S8_UINT ||
- state->format == PIPE_FORMAT_S8X24_UINT ||
- state->format == PIPE_FORMAT_X32_S8X24_UINT ||
- state->format == PIPE_FORMAT_S8_UINT)
- view->is_stencil_sampler = true;
-
- /* Buffer resource. */
- if (texture->target == PIPE_BUFFER) {
- unsigned stride, num_records;
-
- desc = util_format_description(state->format);
- first_non_void = util_format_get_first_non_void_channel(state->format);
- stride = desc->block.bits / 8;
- va = tmp->resource.gpu_address + state->u.buf.first_element*stride;
- format = si_translate_buffer_dataformat(ctx->screen, desc, first_non_void);
- num_format = si_translate_buffer_numformat(ctx->screen, desc, first_non_void);
-
- num_records = state->u.buf.last_element + 1 - state->u.buf.first_element;
- num_records = MIN2(num_records, texture->width0 / stride);
+ desc = util_format_description(format);
+ first_non_void = util_format_get_first_non_void_channel(format);
+ stride = desc->block.bits / 8;
+ va = buf->gpu_address + first_element * stride;
+ num_format = si_translate_buffer_numformat(&screen->b.b, desc, first_non_void);
+ data_format = si_translate_buffer_dataformat(&screen->b.b, desc, first_non_void);
- if (sctx->b.chip_class >= VI)
- num_records *= stride;
-
- view->state[4] = va;
- view->state[5] = S_008F04_BASE_ADDRESS_HI(va >> 32) |
- S_008F04_STRIDE(stride);
- view->state[6] = num_records;
- view->state[7] = S_008F0C_DST_SEL_X(si_map_swizzle(desc->swizzle[0])) |
- S_008F0C_DST_SEL_Y(si_map_swizzle(desc->swizzle[1])) |
- S_008F0C_DST_SEL_Z(si_map_swizzle(desc->swizzle[2])) |
- S_008F0C_DST_SEL_W(si_map_swizzle(desc->swizzle[3])) |
- S_008F0C_NUM_FORMAT(num_format) |
- S_008F0C_DATA_FORMAT(format);
+ num_records = last_element + 1 - first_element;
+ num_records = MIN2(num_records, buf->b.b.width0 / stride);
- LIST_ADDTAIL(&view->list, &sctx->b.texture_buffers);
- return &view->base;
- }
+ if (screen->b.chip_class >= VI)
+ num_records *= stride;
- state_swizzle[0] = state->swizzle_r;
- state_swizzle[1] = state->swizzle_g;
- state_swizzle[2] = state->swizzle_b;
- state_swizzle[3] = state->swizzle_a;
+ state[4] = va;
+ state[5] = S_008F04_BASE_ADDRESS_HI(va >> 32) |
+ S_008F04_STRIDE(stride);
+ state[6] = num_records;
+ state[7] = S_008F0C_DST_SEL_X(si_map_swizzle(desc->swizzle[0])) |
+ S_008F0C_DST_SEL_Y(si_map_swizzle(desc->swizzle[1])) |
+ S_008F0C_DST_SEL_Z(si_map_swizzle(desc->swizzle[2])) |
+ S_008F0C_DST_SEL_W(si_map_swizzle(desc->swizzle[3])) |
+ S_008F0C_NUM_FORMAT(num_format) |
+ S_008F0C_DATA_FORMAT(data_format);
+}
- surflevel = tmp->surface.level;
+/**
+ * Build the sampler view descriptor for a texture.
+ */
+void
+si_make_texture_descriptor(struct si_screen *screen,
+ struct r600_texture *tex,
+ bool sampler,
+ enum pipe_texture_target target,
+ enum pipe_format pipe_format,
+ const unsigned char state_swizzle[4],
+ unsigned base_level, unsigned first_level, unsigned last_level,
+ unsigned first_layer, unsigned last_layer,
+ unsigned width, unsigned height, unsigned depth,
+ uint32_t *state,
+ uint32_t *fmask_state)
+{
+ struct pipe_resource *res = &tex->resource.b.b;
+ const struct radeon_surf_level *surflevel = tex->surface.level;
+ const struct util_format_description *desc;
+ unsigned char swizzle[4];
+ int first_non_void;
+ unsigned num_format, data_format, type;
+ uint32_t pitch;
+ uint64_t va;
/* Texturing with separate depth and stencil. */
- if (tmp->is_depth && !tmp->is_flushing_texture) {
+ if (tex->is_depth && !tex->is_flushing_texture) {
switch (pipe_format) {
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
pipe_format = PIPE_FORMAT_Z32_FLOAT;
case PIPE_FORMAT_S8X24_UINT:
case PIPE_FORMAT_X32_S8X24_UINT:
pipe_format = PIPE_FORMAT_S8_UINT;
- surflevel = tmp->surface.stencil_level;
+ surflevel = tex->surface.stencil_level;
break;
default:;
}
case PIPE_FORMAT_DXT3_SRGBA:
case PIPE_FORMAT_DXT5_SRGBA:
case PIPE_FORMAT_BPTC_SRGBA:
+ case PIPE_FORMAT_ETC2_SRGB8:
+ case PIPE_FORMAT_ETC2_SRGB8A1:
+ case PIPE_FORMAT_ETC2_SRGBA8:
num_format = V_008F14_IMG_NUM_FORMAT_SRGB;
break;
case PIPE_FORMAT_RGTC1_SNORM:
case PIPE_FORMAT_LATC1_SNORM:
case PIPE_FORMAT_RGTC2_SNORM:
case PIPE_FORMAT_LATC2_SNORM:
+ case PIPE_FORMAT_ETC2_R11_SNORM:
+ case PIPE_FORMAT_ETC2_RG11_SNORM:
/* implies float, so use SNORM/UNORM to determine
whether data is signed or not */
case PIPE_FORMAT_BPTC_RGB_FLOAT:
}
}
- format = si_translate_texformat(ctx->screen, pipe_format, desc, first_non_void);
- if (format == ~0) {
- format = 0;
+ data_format = si_translate_texformat(&screen->b.b, pipe_format, desc, first_non_void);
+ if (data_format == ~0) {
+ data_format = 0;
}
- base_level = 0;
- first_level = state->u.tex.first_level;
- last_level = state->u.tex.last_level;
- width = width0;
- height = height0;
- depth = texture->depth0;
+ if (!sampler &&
+ (res->target == PIPE_TEXTURE_CUBE ||
+ res->target == PIPE_TEXTURE_CUBE_ARRAY ||
+ 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
+ * caller to effectively disable mipmaps.
+ */
+ type = V_008F1C_SQ_RSRC_IMG_2D_ARRAY;
- if (force_level) {
- assert(force_level == first_level &&
- force_level == last_level);
- base_level = force_level;
- first_level = 0;
- last_level = 0;
- width = u_minify(width, force_level);
- height = u_minify(height, force_level);
- depth = u_minify(depth, force_level);
+ assert(res->target != PIPE_TEXTURE_3D || (first_level == 0 && last_level == 0));
+ } else {
+ type = si_tex_dim(res->target, target, res->nr_samples);
}
- pitch = surflevel[base_level].nblk_x * util_format_get_blockwidth(pipe_format);
-
- if (texture->target == PIPE_TEXTURE_1D_ARRAY) {
+ if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {
height = 1;
- depth = texture->array_size;
- } else if (texture->target == PIPE_TEXTURE_2D_ARRAY) {
- depth = texture->array_size;
- } else if (texture->target == PIPE_TEXTURE_CUBE_ARRAY)
- depth = texture->array_size / 6;
+ depth = res->array_size;
+ } else if (type == V_008F1C_SQ_RSRC_IMG_2D_ARRAY) {
+ if (sampler || res->target != PIPE_TEXTURE_3D)
+ depth = res->array_size;
+ } else if (type == V_008F1C_SQ_RSRC_IMG_CUBE)
+ depth = res->array_size / 6;
- /* This is not needed if state trackers set last_layer correctly. */
- if (state->target == PIPE_TEXTURE_1D ||
- state->target == PIPE_TEXTURE_2D ||
- state->target == PIPE_TEXTURE_RECT ||
- state->target == PIPE_TEXTURE_CUBE)
- last_layer = state->u.tex.first_layer;
-
- va = tmp->resource.gpu_address + surflevel[base_level].offset;
-
- view->state[0] = va >> 8;
- view->state[1] = (S_008F14_BASE_ADDRESS_HI(va >> 40) |
- S_008F14_DATA_FORMAT(format) |
- S_008F14_NUM_FORMAT(num_format));
- view->state[2] = (S_008F18_WIDTH(width - 1) |
- S_008F18_HEIGHT(height - 1));
- view->state[3] = (S_008F1C_DST_SEL_X(si_map_swizzle(swizzle[0])) |
- S_008F1C_DST_SEL_Y(si_map_swizzle(swizzle[1])) |
- S_008F1C_DST_SEL_Z(si_map_swizzle(swizzle[2])) |
- S_008F1C_DST_SEL_W(si_map_swizzle(swizzle[3])) |
- S_008F1C_BASE_LEVEL(texture->nr_samples > 1 ?
- 0 : first_level) |
- S_008F1C_LAST_LEVEL(texture->nr_samples > 1 ?
- util_logbase2(texture->nr_samples) :
- last_level) |
- S_008F1C_TILING_INDEX(si_tile_mode_index(tmp, base_level, false)) |
- S_008F1C_POW2_PAD(texture->last_level > 0) |
- S_008F1C_TYPE(si_tex_dim(texture->target, state->target,
- texture->nr_samples)));
- view->state[4] = (S_008F20_DEPTH(depth - 1) | S_008F20_PITCH(pitch - 1));
- view->state[5] = (S_008F24_BASE_ARRAY(state->u.tex.first_layer) |
- S_008F24_LAST_ARRAY(last_layer));
-
- if (tmp->dcc_buffer) {
- uint64_t dcc_offset = surflevel[base_level].dcc_offset;
+ pitch = surflevel[base_level].nblk_x * util_format_get_blockwidth(pipe_format);
+ va = tex->resource.gpu_address + surflevel[base_level].offset;
+
+ state[0] = va >> 8;
+ state[1] = (S_008F14_BASE_ADDRESS_HI(va >> 40) |
+ S_008F14_DATA_FORMAT(data_format) |
+ S_008F14_NUM_FORMAT(num_format));
+ state[2] = (S_008F18_WIDTH(width - 1) |
+ S_008F18_HEIGHT(height - 1));
+ state[3] = (S_008F1C_DST_SEL_X(si_map_swizzle(swizzle[0])) |
+ S_008F1C_DST_SEL_Y(si_map_swizzle(swizzle[1])) |
+ S_008F1C_DST_SEL_Z(si_map_swizzle(swizzle[2])) |
+ S_008F1C_DST_SEL_W(si_map_swizzle(swizzle[3])) |
+ S_008F1C_BASE_LEVEL(res->nr_samples > 1 ?
+ 0 : first_level) |
+ S_008F1C_LAST_LEVEL(res->nr_samples > 1 ?
+ util_logbase2(res->nr_samples) :
+ last_level) |
+ S_008F1C_TILING_INDEX(si_tile_mode_index(tex, base_level, false)) |
+ S_008F1C_POW2_PAD(res->last_level > 0) |
+ S_008F1C_TYPE(type));
+ state[4] = (S_008F20_DEPTH(depth - 1) | S_008F20_PITCH(pitch - 1));
+ state[5] = (S_008F24_BASE_ARRAY(first_layer) |
+ S_008F24_LAST_ARRAY(last_layer));
+
+ if (tex->dcc_offset) {
unsigned swap = r600_translate_colorswap(pipe_format);
- view->state[6] = S_008F28_COMPRESSION_EN(1) | S_008F28_ALPHA_IS_ON_MSB(swap <= 1);
- view->state[7] = (tmp->dcc_buffer->gpu_address + dcc_offset) >> 8;
- view->dcc_buffer = tmp->dcc_buffer;
+ state[6] = S_008F28_COMPRESSION_EN(1) | S_008F28_ALPHA_IS_ON_MSB(swap <= 1);
+ state[7] = (tex->resource.gpu_address +
+ tex->dcc_offset +
+ surflevel[base_level].dcc_offset) >> 8;
} else {
- view->state[6] = 0;
- view->state[7] = 0;
+ state[6] = 0;
+ state[7] = 0;
}
/* Initialize the sampler view for FMASK. */
- if (tmp->fmask.size) {
- uint64_t va = tmp->resource.gpu_address + tmp->fmask.offset;
+ if (tex->fmask.size) {
uint32_t fmask_format;
- switch (texture->nr_samples) {
+ va = tex->resource.gpu_address + tex->fmask.offset;
+
+ switch (res->nr_samples) {
case 2:
fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S2_F2;
break;
fmask_format = V_008F14_IMG_DATA_FORMAT_INVALID;
}
- view->fmask_state[0] = va >> 8;
- view->fmask_state[1] = S_008F14_BASE_ADDRESS_HI(va >> 40) |
- S_008F14_DATA_FORMAT(fmask_format) |
- S_008F14_NUM_FORMAT(V_008F14_IMG_NUM_FORMAT_UINT);
- view->fmask_state[2] = S_008F18_WIDTH(width - 1) |
- S_008F18_HEIGHT(height - 1);
- view->fmask_state[3] = S_008F1C_DST_SEL_X(V_008F1C_SQ_SEL_X) |
- 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_TILING_INDEX(tmp->fmask.tile_mode_index) |
- S_008F1C_TYPE(si_tex_dim(texture->target,
- state->target, 0));
- view->fmask_state[4] = S_008F20_DEPTH(depth - 1) |
- S_008F20_PITCH(tmp->fmask.pitch_in_pixels - 1);
- view->fmask_state[5] = S_008F24_BASE_ARRAY(state->u.tex.first_layer) |
- S_008F24_LAST_ARRAY(last_layer);
- view->fmask_state[6] = 0;
- view->fmask_state[7] = 0;
+ fmask_state[0] = va >> 8;
+ fmask_state[1] = S_008F14_BASE_ADDRESS_HI(va >> 40) |
+ S_008F14_DATA_FORMAT(fmask_format) |
+ S_008F14_NUM_FORMAT(V_008F14_IMG_NUM_FORMAT_UINT);
+ fmask_state[2] = S_008F18_WIDTH(width - 1) |
+ S_008F18_HEIGHT(height - 1);
+ fmask_state[3] = S_008F1C_DST_SEL_X(V_008F1C_SQ_SEL_X) |
+ 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_TILING_INDEX(tex->fmask.tile_mode_index) |
+ S_008F1C_TYPE(si_tex_dim(res->target, target, 0));
+ fmask_state[4] = S_008F20_DEPTH(depth - 1) |
+ S_008F20_PITCH(tex->fmask.pitch_in_pixels - 1);
+ fmask_state[5] = S_008F24_BASE_ARRAY(first_layer) |
+ S_008F24_LAST_ARRAY(last_layer);
+ fmask_state[6] = 0;
+ fmask_state[7] = 0;
+ }
+}
+
+/**
+ * Create a sampler view.
+ *
+ * @param ctx context
+ * @param texture texture
+ * @param state sampler view template
+ * @param width0 width0 override (for compressed textures as int)
+ * @param height0 height0 override (for compressed textures as int)
+ * @param force_level set the base address to the level (for compressed textures)
+ */
+struct pipe_sampler_view *
+si_create_sampler_view_custom(struct pipe_context *ctx,
+ struct pipe_resource *texture,
+ const struct pipe_sampler_view *state,
+ unsigned width0, unsigned height0,
+ unsigned force_level)
+{
+ struct si_context *sctx = (struct si_context*)ctx;
+ struct si_sampler_view *view = CALLOC_STRUCT(si_sampler_view);
+ struct r600_texture *tmp = (struct r600_texture*)texture;
+ unsigned base_level, first_level, last_level;
+ unsigned char state_swizzle[4];
+ unsigned height, depth, width;
+ unsigned last_layer = state->u.tex.last_layer;
+
+ if (!view)
+ return NULL;
+
+ /* initialize base object */
+ view->base = *state;
+ view->base.texture = NULL;
+ view->base.reference.count = 1;
+ view->base.context = ctx;
+
+ /* NULL resource, obey swizzle (only ZERO and ONE make sense). */
+ if (!texture) {
+ view->state[3] = S_008F1C_DST_SEL_X(si_map_swizzle(state->swizzle_r)) |
+ S_008F1C_DST_SEL_Y(si_map_swizzle(state->swizzle_g)) |
+ S_008F1C_DST_SEL_Z(si_map_swizzle(state->swizzle_b)) |
+ S_008F1C_DST_SEL_W(si_map_swizzle(state->swizzle_a)) |
+ S_008F1C_TYPE(V_008F1C_SQ_RSRC_IMG_1D);
+ return &view->base;
+ }
+
+ pipe_resource_reference(&view->base.texture, texture);
+
+ if (state->format == PIPE_FORMAT_X24S8_UINT ||
+ state->format == PIPE_FORMAT_S8X24_UINT ||
+ state->format == PIPE_FORMAT_X32_S8X24_UINT ||
+ state->format == PIPE_FORMAT_S8_UINT)
+ view->is_stencil_sampler = true;
+
+ /* Buffer resource. */
+ if (texture->target == PIPE_BUFFER) {
+ si_make_buffer_descriptor(sctx->screen,
+ (struct r600_resource *)texture,
+ state->format,
+ state->u.buf.first_element,
+ state->u.buf.last_element,
+ view->state);
+
+ LIST_ADDTAIL(&view->list, &sctx->b.texture_buffers);
+ return &view->base;
}
+ state_swizzle[0] = state->swizzle_r;
+ state_swizzle[1] = state->swizzle_g;
+ state_swizzle[2] = state->swizzle_b;
+ state_swizzle[3] = state->swizzle_a;
+
+ base_level = 0;
+ first_level = state->u.tex.first_level;
+ last_level = state->u.tex.last_level;
+ width = width0;
+ height = height0;
+ depth = texture->depth0;
+
+ if (force_level) {
+ assert(force_level == first_level &&
+ force_level == last_level);
+ base_level = force_level;
+ first_level = 0;
+ last_level = 0;
+ width = u_minify(width, force_level);
+ height = u_minify(height, force_level);
+ depth = u_minify(depth, force_level);
+ }
+
+ /* This is not needed if state trackers set last_layer correctly. */
+ if (state->target == PIPE_TEXTURE_1D ||
+ state->target == PIPE_TEXTURE_2D ||
+ state->target == PIPE_TEXTURE_RECT ||
+ state->target == PIPE_TEXTURE_CUBE)
+ last_layer = state->u.tex.first_layer;
+
+ si_make_texture_descriptor(sctx->screen, tmp, true, state->target,
+ state->format, state_swizzle,
+ base_level, first_level, last_level,
+ state->u.tex.first_layer, last_layer,
+ width, height, depth,
+ view->state, view->fmask_state);
+
return &view->base;
}
{
struct si_sampler_view *view = (struct si_sampler_view *)state;
- if (view->resource && view->resource->b.b.target == PIPE_BUFFER)
+ if (state->texture && state->texture->target == PIPE_BUFFER)
LIST_DELINIT(&view->list);
pipe_resource_reference(&state->texture, NULL);
SI_CONTEXT_FLUSH_AND_INV_CB;
}
+static void si_memory_barrier(struct pipe_context *ctx, unsigned flags)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+
+ /* Subsequent commands must wait for all shader invocations to
+ * complete. */
+ sctx->b.flags |= SI_CONTEXT_PS_PARTIAL_FLUSH;
+
+ if (flags & PIPE_BARRIER_CONSTANT_BUFFER)
+ sctx->b.flags |= SI_CONTEXT_INV_SMEM_L1 |
+ SI_CONTEXT_INV_VMEM_L1;
+
+ if (flags & (PIPE_BARRIER_VERTEX_BUFFER |
+ PIPE_BARRIER_SHADER_BUFFER |
+ PIPE_BARRIER_TEXTURE |
+ PIPE_BARRIER_IMAGE)) {
+ /* As far as I can tell, L1 contents are written back to L2
+ * automatically at end of shader, but the contents of other
+ * L1 caches might still be stale. */
+ sctx->b.flags |= SI_CONTEXT_INV_VMEM_L1;
+ }
+
+ if (flags & PIPE_BARRIER_FRAMEBUFFER)
+ sctx->b.flags |= SI_CONTEXT_FLUSH_AND_INV_FRAMEBUFFER;
+
+ if (flags & (PIPE_BARRIER_MAPPED_BUFFER |
+ PIPE_BARRIER_FRAMEBUFFER)) {
+ /* Not sure if INV_GLOBAL_L2 is the best thing here.
+ *
+ * We need to make sure that TC L1 & L2 are written back to
+ * memory, because neither CPU accesses nor CB fetches consider
+ * TC, but there's no need to invalidate any TC cache lines. */
+ sctx->b.flags |= SI_CONTEXT_INV_GLOBAL_L2;
+ }
+}
+
static void *si_create_blend_custom(struct si_context *sctx, unsigned mode)
{
struct pipe_blend_state blend;
si_init_atom(sctx, &sctx->db_render_state, &sctx->atoms.s.db_render_state, si_emit_db_render_state);
si_init_atom(sctx, &sctx->msaa_config, &sctx->atoms.s.msaa_config, si_emit_msaa_config);
si_init_atom(sctx, &sctx->sample_mask.atom, &sctx->atoms.s.sample_mask, si_emit_sample_mask);
- si_init_atom(sctx, &sctx->cb_target_mask, &sctx->atoms.s.cb_target_mask, si_emit_cb_target_mask);
+ si_init_atom(sctx, &sctx->cb_render_state, &sctx->atoms.s.cb_render_state, si_emit_cb_render_state);
si_init_atom(sctx, &sctx->blend_color.atom, &sctx->atoms.s.blend_color, si_emit_blend_color);
si_init_atom(sctx, &sctx->clip_regs, &sctx->atoms.s.clip_regs, si_emit_clip_regs);
si_init_atom(sctx, &sctx->clip_state.atom, &sctx->atoms.s.clip_state, si_emit_clip_state);
sctx->custom_blend_resolve = si_create_blend_custom(sctx, V_028808_CB_RESOLVE);
sctx->custom_blend_decompress = si_create_blend_custom(sctx, V_028808_CB_FMASK_DECOMPRESS);
sctx->custom_blend_fastclear = si_create_blend_custom(sctx, V_028808_CB_ELIMINATE_FAST_CLEAR);
+ sctx->custom_blend_dcc_decompress = si_create_blend_custom(sctx, V_028808_CB_DCC_DECOMPRESS);
sctx->b.b.set_clip_state = si_set_clip_state;
sctx->b.b.set_scissor_states = si_set_scissor_states;
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;
sctx->b.b.set_polygon_stipple = si_set_polygon_stipple;
sctx->b.b.set_min_samples = si_set_min_samples;
sctx->b.b.set_tess_state = si_set_tess_state;
si_init_config(sctx);
}
+static void si_query_opaque_metadata(struct r600_common_screen *rscreen,
+ struct r600_texture *rtex,
+ struct radeon_bo_metadata *md)
+{
+ struct si_screen *sscreen = (struct si_screen*)rscreen;
+ struct pipe_resource *res = &rtex->resource.b.b;
+ static const unsigned char swizzle[] = {
+ PIPE_SWIZZLE_RED,
+ PIPE_SWIZZLE_GREEN,
+ PIPE_SWIZZLE_BLUE,
+ PIPE_SWIZZLE_ALPHA
+ };
+ uint32_t desc[8], i;
+ bool is_array = util_resource_is_array_texture(res);
+
+ /* DRM 2.x.x doesn't support this. */
+ if (rscreen->info.drm_major != 3)
+ return;
+
+ assert(rtex->fmask.size == 0);
+
+ /* Metadata image format format version 1:
+ * [0] = 1 (metadata format identifier)
+ * [1] = (VENDOR_ID << 16) | PCI_ID
+ * [2:9] = image descriptor for the whole resource
+ * [2] is always 0, because the base address is cleared
+ * [9] is the DCC offset bits [39:8] from the beginning of
+ * the buffer
+ * [10:10+LAST_LEVEL] = mipmap level offset bits [39:8] for each level
+ */
+
+ md->metadata[0] = 1; /* metadata image format version 1 */
+
+ /* TILE_MODE_INDEX is ambiguous without a PCI ID. */
+ md->metadata[1] = (ATI_VENDOR_ID << 16) | rscreen->info.pci_id;
+
+ si_make_texture_descriptor(sscreen, rtex, true,
+ res->target, res->format,
+ swizzle, 0, 0, res->last_level, 0,
+ is_array ? res->array_size - 1 : 0,
+ res->width0, res->height0, res->depth0,
+ desc, NULL);
+
+ /* Clear the base address and set the relative DCC offset. */
+ desc[0] = 0;
+ desc[1] &= C_008F14_BASE_ADDRESS_HI;
+ desc[7] = rtex->dcc_offset >> 8;
+
+ /* Dwords [2:9] contain the image descriptor. */
+ memcpy(&md->metadata[2], desc, sizeof(desc));
+
+ /* Dwords [10:..] contain the mipmap level offsets. */
+ for (i = 0; i <= res->last_level; i++)
+ md->metadata[10+i] = rtex->surface.level[i].offset >> 8;
+
+ md->size_metadata = (11 + res->last_level) * 4;
+}
+
+void si_init_screen_state_functions(struct si_screen *sscreen)
+{
+ sscreen->b.query_opaque_metadata = si_query_opaque_metadata;
+}
+
static void
si_write_harvested_raster_configs(struct si_context *sctx,
struct si_pm4_state *pm4,
{
unsigned sh_per_se = MAX2(sctx->screen->b.info.max_sh_per_se, 1);
unsigned num_se = MAX2(sctx->screen->b.info.max_se, 1);
- unsigned rb_mask = sctx->screen->b.info.si_backend_enabled_mask;
- unsigned num_rb = MIN2(sctx->screen->b.info.r600_num_backends, 16);
+ unsigned rb_mask = sctx->screen->b.info.enabled_rb_mask;
+ unsigned num_rb = MIN2(sctx->screen->b.info.num_render_backends, 16);
unsigned rb_per_pkr = MIN2(num_rb / num_se / sh_per_se, 2);
unsigned rb_per_se = num_rb / num_se;
unsigned se_mask[4];
static void si_init_config(struct si_context *sctx)
{
struct si_screen *sscreen = sctx->screen;
- unsigned num_rb = MIN2(sctx->screen->b.info.r600_num_backends, 16);
- unsigned rb_mask = sctx->screen->b.info.si_backend_enabled_mask;
+ unsigned num_rb = MIN2(sctx->screen->b.info.num_render_backends, 16);
+ unsigned rb_mask = sctx->screen->b.info.enabled_rb_mask;
unsigned raster_config, raster_config_1;
uint64_t border_color_va = sctx->border_color_buffer->gpu_address;
struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state);
si_pm4_set_reg(pm4, R_028408_VGT_INDX_OFFSET, 0);
if (sctx->b.chip_class >= CIK) {
- si_pm4_set_reg(pm4, R_00B51C_SPI_SHADER_PGM_RSRC3_LS, S_00B51C_CU_EN(0xfffc));
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(0xfffe));
+ si_pm4_set_reg(pm4, R_00B31C_SPI_SHADER_PGM_RSRC3_ES, S_00B31C_CU_EN(0xffff));
si_pm4_set_reg(pm4, R_00B21C_SPI_SHADER_PGM_RSRC3_GS, S_00B21C_CU_EN(0xffff));
- si_pm4_set_reg(pm4, R_00B118_SPI_SHADER_PGM_RSRC3_VS, S_00B118_CU_EN(0xffff));
- si_pm4_set_reg(pm4, R_00B11C_SPI_SHADER_LATE_ALLOC_VS, S_00B11C_LIMIT(0));
+
+ if (sscreen->b.info.num_good_compute_units /
+ (sscreen->b.info.max_se * sscreen->b.info.max_sh_per_se) <= 4) {
+ /* Too few available compute units per SH. Disallowing
+ * VS to run on CU0 could hurt us more than late VS
+ * allocation would help.
+ *
+ * LATE_ALLOC_VS = 2 is the highest safe number.
+ */
+ si_pm4_set_reg(pm4, R_00B51C_SPI_SHADER_PGM_RSRC3_LS, S_00B51C_CU_EN(0xffff));
+ si_pm4_set_reg(pm4, R_00B118_SPI_SHADER_PGM_RSRC3_VS, S_00B118_CU_EN(0xffff));
+ si_pm4_set_reg(pm4, R_00B11C_SPI_SHADER_LATE_ALLOC_VS, S_00B11C_LIMIT(2));
+ } else {
+ /* Set LATE_ALLOC_VS == 31. It should be less than
+ * the number of scratch waves. Limitations:
+ * - VS can't execute on CU0.
+ * - If HS writes outputs to LDS, LS can't execute on CU0.
+ */
+ si_pm4_set_reg(pm4, R_00B51C_SPI_SHADER_PGM_RSRC3_LS, S_00B51C_CU_EN(0xfffe));
+ si_pm4_set_reg(pm4, R_00B118_SPI_SHADER_PGM_RSRC3_VS, S_00B118_CU_EN(0xfffe));
+ si_pm4_set_reg(pm4, R_00B11C_SPI_SHADER_LATE_ALLOC_VS, S_00B11C_LIMIT(31));
+ }
+
si_pm4_set_reg(pm4, R_00B01C_SPI_SHADER_PGM_RSRC3_PS, S_00B01C_CU_EN(0xffff));
}