#include "util/u_memory.h"
#include "util/u_framebuffer.h"
#include "util/u_blitter.h"
+#include "util/u_helpers.h"
+#include "util/u_math.h"
#include "util/u_pack_color.h"
+#include "util/u_upload_mgr.h"
+#include "util/u_format_s3tc.h"
#include "tgsi/tgsi_parse.h"
#include "radeonsi_pipe.h"
+#include "radeonsi_shader.h"
#include "si_state.h"
#include "sid.h"
*/
static void si_update_fb_blend_state(struct r600_context *rctx)
{
- struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state);
+ struct si_pm4_state *pm4;
struct si_state_blend *blend = rctx->queued.named.blend;
uint32_t mask;
- if (pm4 == NULL || blend == NULL)
+ if (blend == NULL)
+ return;
+
+ pm4 = CALLOC_STRUCT(si_pm4_state);
+ if (pm4 == NULL)
return;
mask = (1ULL << ((unsigned)rctx->framebuffer.nr_cbufs * 4)) - 1;
{
struct r600_context *rctx = (struct r600_context *)ctx;
struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state);
+ struct pipe_constant_buffer cb;
if (pm4 == NULL)
return;
fui(state->ucp[i][3]));
}
+ cb.buffer = NULL;
+ cb.user_buffer = state->ucp;
+ cb.buffer_offset = 0;
+ cb.buffer_size = 4*4*8;
+ ctx->set_constant_buffer(ctx, PIPE_SHADER_VERTEX, 1, &cb);
+ pipe_resource_reference(&cb.buffer, NULL);
+
si_pm4_set_state(rctx, clip, pm4);
}
-static void si_set_scissor_state(struct pipe_context *ctx,
- const struct pipe_scissor_state *state)
+static void si_set_scissor_states(struct pipe_context *ctx,
+ unsigned start_slot,
+ unsigned num_scissors,
+ const struct pipe_scissor_state *state)
{
struct r600_context *rctx = (struct r600_context *)ctx;
struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state);
si_pm4_set_state(rctx, scissor, pm4);
}
-static void si_set_viewport_state(struct pipe_context *ctx,
- const struct pipe_viewport_state *state)
+static void si_set_viewport_states(struct pipe_context *ctx,
+ unsigned start_slot,
+ unsigned num_viewports,
+ const struct pipe_viewport_state *state)
{
struct r600_context *rctx = (struct r600_context *)ctx;
struct si_state_viewport *viewport = CALLOC_STRUCT(si_state_viewport);
viewport->viewport = *state;
si_pm4_set_reg(pm4, R_0282D0_PA_SC_VPORT_ZMIN_0, 0x00000000);
si_pm4_set_reg(pm4, R_0282D4_PA_SC_VPORT_ZMAX_0, 0x3F800000);
- si_pm4_set_reg(pm4, R_028350_PA_SC_RASTER_CONFIG, 0x00000000);
si_pm4_set_reg(pm4, R_02843C_PA_CL_VPORT_XSCALE_0, fui(state->scale[0]));
si_pm4_set_reg(pm4, R_028440_PA_CL_VPORT_XOFFSET_0, fui(state->translate[0]));
si_pm4_set_reg(pm4, R_028444_PA_CL_VPORT_YSCALE_0, fui(state->scale[1]));
static void si_update_fb_rs_state(struct r600_context *rctx)
{
struct si_state_rasterizer *rs = rctx->queued.named.rasterizer;
- struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state);
+ struct si_pm4_state *pm4;
unsigned offset_db_fmt_cntl = 0, depth;
float offset_units;
- if (!rs || !rctx->framebuffer.zsbuf) {
- FREE(pm4);
+ if (!rs || !rctx->framebuffer.zsbuf)
return;
- }
offset_units = rctx->queued.named.rasterizer->offset_units;
switch (rctx->framebuffer.zsbuf->texture->format) {
+ case PIPE_FORMAT_S8_UINT_Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
depth = -24;
return;
}
+ pm4 = CALLOC_STRUCT(si_pm4_state);
/* FIXME some of those reg can be computed with cso */
offset_db_fmt_cntl |= S_028B78_POLY_OFFSET_NEG_NUM_DB_BITS(depth);
si_pm4_set_reg(pm4, R_028B80_PA_SU_POLY_OFFSET_FRONT_SCALE,
return NULL;
}
+ rs->two_side = state->light_twoside;
+ rs->clip_plane_enable = state->clip_plane_enable;
+
polygon_dual_mode = (state->fill_front != PIPE_POLYGON_MODE_FILL ||
state->fill_back != PIPE_POLYGON_MODE_FILL);
S_028810_ZCLIP_NEAR_DISABLE(!state->depth_clip) |
S_028810_ZCLIP_FAR_DISABLE(!state->depth_clip) |
S_028810_DX_LINEAR_ATTR_CLIP_ENA(1);
- rs->pa_cl_vs_out_cntl =
- S_02881C_USE_VTX_POINT_SIZE(state->point_size_per_vertex) |
- S_02881C_VS_OUT_MISC_VEC_ENA(state->point_size_per_vertex);
clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
rs->offset_units = state->offset_units;
rs->offset_scale = state->offset_scale * 12.0f;
- /* XXX: Flat shading hangs the GPU */
- tmp = S_0286D4_FLAT_SHADE_ENA(0);
+ tmp = S_0286D4_FLAT_SHADE_ENA(1);
if (state->sprite_coord_enable) {
tmp |= S_0286D4_PNT_SPRITE_ENA(1) |
S_0286D4_PNT_SPRITE_OVRD_X(V_0286D4_SPI_PNT_SPRITE_SEL_S) |
si_pm4_set_reg(pm4, R_028BDC_PA_SC_LINE_CNTL, 0x00000400);
si_pm4_set_reg(pm4, R_028BE4_PA_SU_VTX_CNTL,
- S_028BE4_PIX_CENTER(state->gl_rasterization_rules));
+ S_028BE4_PIX_CENTER(state->half_pixel_center));
si_pm4_set_reg(pm4, R_028BE8_PA_CL_GB_VERT_CLIP_ADJ, 0x3F800000);
si_pm4_set_reg(pm4, R_028BEC_PA_CL_GB_VERT_DISC_ADJ, 0x3F800000);
si_pm4_set_reg(pm4, R_028BF0_PA_CL_GB_HORZ_CLIP_ADJ, 0x3F800000);
rctx->sprite_coord_enable = rs->sprite_coord_enable;
rctx->pa_sc_line_stipple = rs->pa_sc_line_stipple;
rctx->pa_su_sc_mode_cntl = rs->pa_su_sc_mode_cntl;
- rctx->pa_cl_clip_cntl = rs->pa_cl_clip_cntl;
- rctx->pa_cl_vs_out_cntl = rs->pa_cl_vs_out_cntl;
si_pm4_bind_state(rctx, rasterizer, rs);
si_update_fb_rs_state(rctx);
si_pm4_set_reg(pm4, R_028430_DB_STENCILREFMASK,
S_028430_STENCILTESTVAL(ref->ref_value[0]) |
S_028430_STENCILMASK(dsa->valuemask[0]) |
- S_028430_STENCILWRITEMASK(dsa->writemask[0]));
+ S_028430_STENCILWRITEMASK(dsa->writemask[0]) |
+ S_028430_STENCILOPVAL(1));
si_pm4_set_reg(pm4, R_028434_DB_STENCILREFMASK_BF,
S_028434_STENCILTESTVAL_BF(ref->ref_value[1]) |
S_028434_STENCILMASK_BF(dsa->valuemask[1]) |
- S_028434_STENCILWRITEMASK_BF(dsa->writemask[1]));
+ S_028434_STENCILWRITEMASK_BF(dsa->writemask[1]) |
+ S_028434_STENCILOPVAL_BF(1));
si_pm4_set_state(rctx, dsa_stencil_ref, pm4);
}
* DSA
*/
-/* transnates straight */
-static uint32_t si_translate_ds_func(int func)
+static uint32_t si_translate_stencil_op(int s_op)
{
- return func;
+ switch (s_op) {
+ case PIPE_STENCIL_OP_KEEP:
+ return V_02842C_STENCIL_KEEP;
+ case PIPE_STENCIL_OP_ZERO:
+ return V_02842C_STENCIL_ZERO;
+ case PIPE_STENCIL_OP_REPLACE:
+ return V_02842C_STENCIL_REPLACE_TEST;
+ case PIPE_STENCIL_OP_INCR:
+ return V_02842C_STENCIL_ADD_CLAMP;
+ case PIPE_STENCIL_OP_DECR:
+ return V_02842C_STENCIL_SUB_CLAMP;
+ case PIPE_STENCIL_OP_INCR_WRAP:
+ return V_02842C_STENCIL_ADD_WRAP;
+ case PIPE_STENCIL_OP_DECR_WRAP:
+ return V_02842C_STENCIL_SUB_WRAP;
+ case PIPE_STENCIL_OP_INVERT:
+ return V_02842C_STENCIL_INVERT;
+ default:
+ R600_ERR("Unknown stencil op %d", s_op);
+ assert(0);
+ break;
+ }
+ return 0;
}
static void *si_create_dsa_state(struct pipe_context *ctx,
{
struct si_state_dsa *dsa = CALLOC_STRUCT(si_state_dsa);
struct si_pm4_state *pm4 = &dsa->pm4;
- unsigned db_depth_control, /* alpha_test_control, */ alpha_ref;
+ unsigned db_depth_control;
unsigned db_render_override, db_render_control;
+ uint32_t db_stencil_control = 0;
if (dsa == NULL) {
return NULL;
/* stencil */
if (state->stencil[0].enabled) {
db_depth_control |= S_028800_STENCIL_ENABLE(1);
- db_depth_control |= S_028800_STENCILFUNC(si_translate_ds_func(state->stencil[0].func));
- //db_depth_control |= S_028800_STENCILFAIL(r600_translate_stencil_op(state->stencil[0].fail_op));
- //db_depth_control |= S_028800_STENCILZPASS(r600_translate_stencil_op(state->stencil[0].zpass_op));
- //db_depth_control |= S_028800_STENCILZFAIL(r600_translate_stencil_op(state->stencil[0].zfail_op));
+ db_depth_control |= S_028800_STENCILFUNC(state->stencil[0].func);
+ db_stencil_control |= S_02842C_STENCILFAIL(si_translate_stencil_op(state->stencil[0].fail_op));
+ db_stencil_control |= S_02842C_STENCILZPASS(si_translate_stencil_op(state->stencil[0].zpass_op));
+ db_stencil_control |= S_02842C_STENCILZFAIL(si_translate_stencil_op(state->stencil[0].zfail_op));
if (state->stencil[1].enabled) {
db_depth_control |= S_028800_BACKFACE_ENABLE(1);
- db_depth_control |= S_028800_STENCILFUNC_BF(si_translate_ds_func(state->stencil[1].func));
- //db_depth_control |= S_028800_STENCILFAIL_BF(r600_translate_stencil_op(state->stencil[1].fail_op));
- //db_depth_control |= S_028800_STENCILZPASS_BF(r600_translate_stencil_op(state->stencil[1].zpass_op));
- //db_depth_control |= S_028800_STENCILZFAIL_BF(r600_translate_stencil_op(state->stencil[1].zfail_op));
+ db_depth_control |= S_028800_STENCILFUNC_BF(state->stencil[1].func);
+ db_stencil_control |= S_02842C_STENCILFAIL_BF(si_translate_stencil_op(state->stencil[1].fail_op));
+ db_stencil_control |= S_02842C_STENCILZPASS_BF(si_translate_stencil_op(state->stencil[1].zpass_op));
+ db_stencil_control |= S_02842C_STENCILZFAIL_BF(si_translate_stencil_op(state->stencil[1].zfail_op));
}
}
/* alpha */
- //alpha_test_control = 0;
- alpha_ref = 0;
if (state->alpha.enabled) {
- //alpha_test_control = S_028410_ALPHA_FUNC(state->alpha.func);
- //alpha_test_control |= S_028410_ALPHA_TEST_ENABLE(1);
- alpha_ref = fui(state->alpha.ref_value);
+ dsa->alpha_func = state->alpha.func;
+ dsa->alpha_ref = state->alpha.ref_value;
+ } else {
+ dsa->alpha_func = PIPE_FUNC_ALWAYS;
}
- dsa->alpha_ref = alpha_ref;
/* misc */
db_render_control = 0;
si_pm4_set_reg(pm4, R_028800_DB_DEPTH_CONTROL, db_depth_control);
si_pm4_set_reg(pm4, R_028000_DB_RENDER_CONTROL, db_render_control);
si_pm4_set_reg(pm4, R_02800C_DB_RENDER_OVERRIDE, db_render_override);
+ si_pm4_set_reg(pm4, R_02842C_DB_STENCIL_CONTROL, db_stencil_control);
si_pm4_set_reg(pm4, R_028AC0_DB_SRESULTS_COMPARE_STATE0, 0x0);
si_pm4_set_reg(pm4, R_028AC4_DB_SRESULTS_COMPARE_STATE1, 0x0);
si_pm4_set_reg(pm4, R_028AC8_DB_PRELOAD_CONTROL, 0x0);
si_pm4_bind_state(rctx, dsa, dsa);
si_update_dsa_stencil_ref(rctx);
-
- // TODO
- rctx->alpha_ref = dsa->alpha_ref;
- rctx->alpha_ref_dirty = true;
}
static void si_delete_dsa_state(struct pipe_context *ctx, void *state)
si_pm4_delete_state(rctx, dsa, (struct si_state_dsa *)state);
}
-static void *si_create_db_flush_dsa(struct r600_context *rctx)
+static void *si_create_db_flush_dsa(struct r600_context *rctx, bool copy_depth,
+ bool copy_stencil)
{
struct pipe_depth_stencil_alpha_state dsa;
struct si_state_dsa *state;
memset(&dsa, 0, sizeof(dsa));
state = rctx->context.create_depth_stencil_alpha_state(&rctx->context, &dsa);
- si_pm4_set_reg(&state->pm4, R_028000_DB_RENDER_CONTROL,
- S_028000_DEPTH_COPY(1) |
- S_028000_STENCIL_COPY(1) |
- S_028000_COPY_CENTROID(1));
+ if (copy_depth || copy_stencil) {
+ si_pm4_set_reg(&state->pm4, R_028000_DB_RENDER_CONTROL,
+ S_028000_DEPTH_COPY(copy_depth) |
+ S_028000_STENCIL_COPY(copy_stencil) |
+ S_028000_COPY_CENTROID(1));
+ } else {
+ si_pm4_set_reg(&state->pm4, R_028000_DB_RENDER_CONTROL,
+ S_028000_DEPTH_COMPRESS_DISABLE(1) |
+ S_028000_STENCIL_COMPRESS_DISABLE(1));
+ si_pm4_set_reg(&state->pm4, R_02800C_DB_RENDER_OVERRIDE,
+ S_02800C_FORCE_HIZ_ENABLE(V_02800C_FORCE_DISABLE) |
+ S_02800C_FORCE_HIS_ENABLE0(V_02800C_FORCE_DISABLE) |
+ S_02800C_FORCE_HIS_ENABLE1(V_02800C_FORCE_DISABLE) |
+ S_02800C_DISABLE_TILE_RATE_TILES(1));
+ }
+
return state;
}
switch (format) {
/* 8-bit buffers. */
case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_A8_SNORM:
case PIPE_FORMAT_A8_UINT:
case PIPE_FORMAT_A8_SINT:
case PIPE_FORMAT_I8_UNORM:
+ case PIPE_FORMAT_I8_SNORM:
case PIPE_FORMAT_I8_UINT:
case PIPE_FORMAT_I8_SINT:
case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_L8_SNORM:
case PIPE_FORMAT_L8_UINT:
case PIPE_FORMAT_L8_SINT:
case PIPE_FORMAT_L8_SRGB:
return V_028C70_COLOR_4_4_4_4;
case PIPE_FORMAT_L8A8_UNORM:
+ case PIPE_FORMAT_L8A8_SNORM:
case PIPE_FORMAT_L8A8_UINT:
case PIPE_FORMAT_L8A8_SINT:
- case PIPE_FORMAT_L8A8_SRGB:
+ case PIPE_FORMAT_R8G8_SNORM:
case PIPE_FORMAT_R8G8_UNORM:
case PIPE_FORMAT_R8G8_UINT:
case PIPE_FORMAT_R8G8_SINT:
case PIPE_FORMAT_Z16_UNORM:
case PIPE_FORMAT_R16_UNORM:
+ case PIPE_FORMAT_R16_SNORM:
case PIPE_FORMAT_R16_UINT:
case PIPE_FORMAT_R16_SINT:
case PIPE_FORMAT_R16_FLOAT:
- case PIPE_FORMAT_R16G16_FLOAT:
+ case PIPE_FORMAT_L16_UNORM:
+ case PIPE_FORMAT_L16_SNORM:
+ case PIPE_FORMAT_L16_FLOAT:
+ case PIPE_FORMAT_I16_UNORM:
+ case PIPE_FORMAT_I16_SNORM:
+ case PIPE_FORMAT_I16_FLOAT:
+ case PIPE_FORMAT_A16_UNORM:
+ case PIPE_FORMAT_A16_SNORM:
+ case PIPE_FORMAT_A16_FLOAT:
return V_028C70_COLOR_16;
/* 32-bit buffers. */
case PIPE_FORMAT_R8G8B8A8_SNORM:
case PIPE_FORMAT_R8G8B8A8_UNORM:
case PIPE_FORMAT_R8G8B8X8_UNORM:
+ case PIPE_FORMAT_R8G8B8X8_SNORM:
+ case PIPE_FORMAT_R8G8B8X8_SRGB:
+ case PIPE_FORMAT_R8G8B8X8_UINT:
+ case PIPE_FORMAT_R8G8B8X8_SINT:
case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
case PIPE_FORMAT_X8B8G8R8_UNORM:
case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_R8G8B8_UNORM:
case PIPE_FORMAT_R8G8B8A8_SSCALED:
case PIPE_FORMAT_R8G8B8A8_USCALED:
case PIPE_FORMAT_R8G8B8A8_SINT:
case PIPE_FORMAT_R10G10B10X2_SNORM:
case PIPE_FORMAT_B10G10R10A2_UNORM:
case PIPE_FORMAT_B10G10R10A2_UINT:
+ case PIPE_FORMAT_B10G10R10X2_UNORM:
case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
return V_028C70_COLOR_2_10_10_10;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
return V_028C70_COLOR_8_24;
+ case PIPE_FORMAT_S8X24_UINT:
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
return V_028C70_COLOR_24_8;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
return V_028C70_COLOR_X24_8_32_FLOAT;
+ case PIPE_FORMAT_I32_FLOAT:
+ case PIPE_FORMAT_L32_FLOAT:
case PIPE_FORMAT_R32_FLOAT:
+ case PIPE_FORMAT_A32_FLOAT:
case PIPE_FORMAT_Z32_FLOAT:
return V_028C70_COLOR_32;
+ case PIPE_FORMAT_L16A16_UNORM:
+ case PIPE_FORMAT_L16A16_SNORM:
+ case PIPE_FORMAT_L16A16_FLOAT:
case PIPE_FORMAT_R16G16_SSCALED:
case PIPE_FORMAT_R16G16_UNORM:
+ case PIPE_FORMAT_R16G16_SNORM:
case PIPE_FORMAT_R16G16_UINT:
case PIPE_FORMAT_R16G16_SINT:
+ case PIPE_FORMAT_R16G16_FLOAT:
return V_028C70_COLOR_16_16;
case PIPE_FORMAT_R11G11B10_FLOAT:
return V_028C70_COLOR_10_11_11;
/* 64-bit buffers. */
- case PIPE_FORMAT_R16G16B16_USCALED:
- case PIPE_FORMAT_R16G16B16_SSCALED:
case PIPE_FORMAT_R16G16B16A16_UINT:
case PIPE_FORMAT_R16G16B16A16_SINT:
case PIPE_FORMAT_R16G16B16A16_USCALED:
case PIPE_FORMAT_R16G16B16A16_SSCALED:
case PIPE_FORMAT_R16G16B16A16_UNORM:
case PIPE_FORMAT_R16G16B16A16_SNORM:
- case PIPE_FORMAT_R16G16B16_FLOAT:
case PIPE_FORMAT_R16G16B16A16_FLOAT:
+ case PIPE_FORMAT_R16G16B16X16_UNORM:
+ case PIPE_FORMAT_R16G16B16X16_SNORM:
+ case PIPE_FORMAT_R16G16B16X16_FLOAT:
+ case PIPE_FORMAT_R16G16B16X16_UINT:
+ case PIPE_FORMAT_R16G16B16X16_SINT:
return V_028C70_COLOR_16_16_16_16;
+ case PIPE_FORMAT_L32A32_FLOAT:
+ case PIPE_FORMAT_L32A32_UINT:
+ case PIPE_FORMAT_L32A32_SINT:
case PIPE_FORMAT_R32G32_FLOAT:
case PIPE_FORMAT_R32G32_USCALED:
case PIPE_FORMAT_R32G32_SSCALED:
case PIPE_FORMAT_R32G32B32A32_SINT:
case PIPE_FORMAT_R32G32B32A32_UINT:
case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ case PIPE_FORMAT_R32G32B32X32_FLOAT:
+ case PIPE_FORMAT_R32G32B32X32_UINT:
+ case PIPE_FORMAT_R32G32B32X32_SINT:
return V_028C70_COLOR_32_32_32_32;
/* YUV buffers. */
case PIPE_FORMAT_R4A4_UNORM:
case PIPE_FORMAT_A4R4_UNORM:
default:
- return ~0U; /* Unsupported. */
+ return V_028C70_COLOR_INVALID; /* Unsupported. */
}
}
return V_028C70_SWAP_ALT;
case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_A8_SNORM:
case PIPE_FORMAT_A8_UINT:
case PIPE_FORMAT_A8_SINT:
case PIPE_FORMAT_R4A4_UNORM:
return V_028C70_SWAP_ALT_REV;
case PIPE_FORMAT_I8_UNORM:
+ case PIPE_FORMAT_I8_SNORM:
case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_L8_SNORM:
case PIPE_FORMAT_I8_UINT:
case PIPE_FORMAT_I8_SINT:
case PIPE_FORMAT_L8_UINT:
return V_028C70_SWAP_STD;
case PIPE_FORMAT_L8A8_UNORM:
+ case PIPE_FORMAT_L8A8_SNORM:
case PIPE_FORMAT_L8A8_UINT:
case PIPE_FORMAT_L8A8_SINT:
- case PIPE_FORMAT_L8A8_SRGB:
return V_028C70_SWAP_ALT;
+ case PIPE_FORMAT_R8G8_SNORM:
case PIPE_FORMAT_R8G8_UNORM:
case PIPE_FORMAT_R8G8_UINT:
case PIPE_FORMAT_R8G8_SINT:
return V_028C70_SWAP_STD;
+ case PIPE_FORMAT_I16_UNORM:
+ case PIPE_FORMAT_I16_SNORM:
+ case PIPE_FORMAT_I16_FLOAT:
+ case PIPE_FORMAT_L16_UNORM:
+ case PIPE_FORMAT_L16_SNORM:
+ case PIPE_FORMAT_L16_FLOAT:
case PIPE_FORMAT_R16_UNORM:
+ case PIPE_FORMAT_R16_SNORM:
case PIPE_FORMAT_R16_UINT:
case PIPE_FORMAT_R16_SINT:
case PIPE_FORMAT_R16_FLOAT:
return V_028C70_SWAP_STD;
+ case PIPE_FORMAT_A16_UNORM:
+ case PIPE_FORMAT_A16_SNORM:
+ case PIPE_FORMAT_A16_FLOAT:
+ return V_028C70_SWAP_ALT_REV;
+
/* 32-bit buffers. */
case PIPE_FORMAT_A8B8G8R8_SRGB:
return V_028C70_SWAP_STD_REV;
case PIPE_FORMAT_R8G8B8A8_SINT:
case PIPE_FORMAT_R8G8B8A8_UINT:
case PIPE_FORMAT_R8G8B8X8_UNORM:
+ case PIPE_FORMAT_R8G8B8X8_SNORM:
+ case PIPE_FORMAT_R8G8B8X8_SRGB:
+ case PIPE_FORMAT_R8G8B8X8_UINT:
+ case PIPE_FORMAT_R8G8B8X8_SINT:
return V_028C70_SWAP_STD;
case PIPE_FORMAT_A8B8G8R8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
return V_028C70_SWAP_STD;
+ case PIPE_FORMAT_S8X24_UINT:
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
- return V_028C70_SWAP_STD;
+ return V_028C70_SWAP_STD_REV;
case PIPE_FORMAT_R10G10B10A2_UNORM:
case PIPE_FORMAT_R10G10B10X2_SNORM:
case PIPE_FORMAT_B10G10R10A2_UNORM:
case PIPE_FORMAT_B10G10R10A2_UINT:
+ case PIPE_FORMAT_B10G10R10X2_UNORM:
return V_028C70_SWAP_ALT;
case PIPE_FORMAT_R11G11B10_FLOAT:
+ case PIPE_FORMAT_I32_FLOAT:
+ case PIPE_FORMAT_L32_FLOAT:
case PIPE_FORMAT_R32_FLOAT:
case PIPE_FORMAT_R32_UINT:
case PIPE_FORMAT_R32_SINT:
case PIPE_FORMAT_Z32_FLOAT:
case PIPE_FORMAT_R16G16_FLOAT:
case PIPE_FORMAT_R16G16_UNORM:
+ case PIPE_FORMAT_R16G16_SNORM:
case PIPE_FORMAT_R16G16_UINT:
case PIPE_FORMAT_R16G16_SINT:
return V_028C70_SWAP_STD;
+ case PIPE_FORMAT_L16A16_UNORM:
+ case PIPE_FORMAT_L16A16_SNORM:
+ case PIPE_FORMAT_L16A16_FLOAT:
+ return V_028C70_SWAP_ALT;
+
+ case PIPE_FORMAT_A32_FLOAT:
+ return V_028C70_SWAP_ALT_REV;
+
/* 64-bit buffers. */
case PIPE_FORMAT_R32G32_FLOAT:
case PIPE_FORMAT_R32G32_UINT:
case PIPE_FORMAT_R16G16B16A16_UINT:
case PIPE_FORMAT_R16G16B16A16_SINT:
case PIPE_FORMAT_R16G16B16A16_FLOAT:
+ case PIPE_FORMAT_R16G16B16X16_UNORM:
+ case PIPE_FORMAT_R16G16B16X16_SNORM:
+ case PIPE_FORMAT_R16G16B16X16_FLOAT:
+ case PIPE_FORMAT_R16G16B16X16_UINT:
+ case PIPE_FORMAT_R16G16B16X16_SINT:
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+ return V_028C70_SWAP_STD;
+
+ case PIPE_FORMAT_L32A32_FLOAT:
+ case PIPE_FORMAT_L32A32_UINT:
+ case PIPE_FORMAT_L32A32_SINT:
+ return V_028C70_SWAP_ALT;
/* 128-bit buffers. */
case PIPE_FORMAT_R32G32B32A32_FLOAT:
case PIPE_FORMAT_R32G32B32A32_USCALED:
case PIPE_FORMAT_R32G32B32A32_SINT:
case PIPE_FORMAT_R32G32B32A32_UINT:
+ case PIPE_FORMAT_R32G32B32X32_FLOAT:
+ case PIPE_FORMAT_R32G32B32X32_UINT:
+ case PIPE_FORMAT_R32G32B32X32_SINT:
return V_028C70_SWAP_STD;
default:
R600_ERR("unsupported colorswap format %d\n", format);
}
}
+/* 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) {
case PIPE_FORMAT_Z16_UNORM:
return V_028040_Z_16;
+ case PIPE_FORMAT_S8_UINT_Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
- return V_028040_Z_24; /* XXX no longer supported on SI */
+ return V_028040_Z_24; /* deprecated on SI */
case PIPE_FORMAT_Z32_FLOAT:
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
return V_028040_Z_32_FLOAT;
default:
- return ~0U;
+ return V_028040_Z_INVALID;
}
}
const struct util_format_description *desc,
int first_non_void)
{
+ struct r600_screen *rscreen = (struct r600_screen*)screen;
+ bool enable_s3tc = rscreen->info.drm_minor >= 31;
boolean uniform = TRUE;
int i;
case PIPE_FORMAT_X24S8_UINT:
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
- return V_008F14_IMG_DATA_FORMAT_24_8;
- case PIPE_FORMAT_S8X24_UINT:
+ return V_008F14_IMG_DATA_FORMAT_8_24;
case PIPE_FORMAT_X8Z24_UNORM:
+ case PIPE_FORMAT_S8X24_UINT:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
- return V_008F14_IMG_DATA_FORMAT_8_24;
+ return V_008F14_IMG_DATA_FORMAT_24_8;
case PIPE_FORMAT_S8_UINT:
return V_008F14_IMG_DATA_FORMAT_8;
case PIPE_FORMAT_Z32_FLOAT:
return V_008F14_IMG_DATA_FORMAT_32;
+ case PIPE_FORMAT_X32_S8X24_UINT:
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
return V_008F14_IMG_DATA_FORMAT_X24_8_32;
default:
goto out_unknown; /* TODO */
case UTIL_FORMAT_COLORSPACE_SRGB:
+ if (desc->nr_channels != 4 && desc->nr_channels != 1)
+ goto out_unknown;
break;
default:
break;
}
- /* TODO compressed formats */
+ if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
+ if (!enable_s3tc)
+ goto out_unknown;
+
+ switch (format) {
+ case PIPE_FORMAT_RGTC1_SNORM:
+ case PIPE_FORMAT_LATC1_SNORM:
+ case PIPE_FORMAT_RGTC1_UNORM:
+ case PIPE_FORMAT_LATC1_UNORM:
+ return V_008F14_IMG_DATA_FORMAT_BC4;
+ case PIPE_FORMAT_RGTC2_SNORM:
+ case PIPE_FORMAT_LATC2_SNORM:
+ case PIPE_FORMAT_RGTC2_UNORM:
+ case PIPE_FORMAT_LATC2_UNORM:
+ return V_008F14_IMG_DATA_FORMAT_BC5;
+ default:
+ goto out_unknown;
+ }
+ }
+
+ if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
+
+ if (!enable_s3tc)
+ goto out_unknown;
+
+ if (!util_format_s3tc_enabled) {
+ goto out_unknown;
+ }
+
+ switch (format) {
+ case PIPE_FORMAT_DXT1_RGB:
+ case PIPE_FORMAT_DXT1_RGBA:
+ case PIPE_FORMAT_DXT1_SRGB:
+ case PIPE_FORMAT_DXT1_SRGBA:
+ return V_008F14_IMG_DATA_FORMAT_BC1;
+ case PIPE_FORMAT_DXT3_RGBA:
+ case PIPE_FORMAT_DXT3_SRGBA:
+ return V_008F14_IMG_DATA_FORMAT_BC2;
+ case PIPE_FORMAT_DXT5_RGBA:
+ case PIPE_FORMAT_DXT5_SRGBA:
+ return V_008F14_IMG_DATA_FORMAT_BC3;
+ default:
+ goto out_unknown;
+ }
+ }
if (format == PIPE_FORMAT_R9G9B9E5_FLOAT) {
return V_008F14_IMG_DATA_FORMAT_5_9_9_9;
switch (desc->channel[first_non_void].size) {
case 4:
switch (desc->nr_channels) {
+#if 0 /* Not supported for render targets */
case 2:
return V_008F14_IMG_DATA_FORMAT_4_4;
+#endif
case 4:
return V_008F14_IMG_DATA_FORMAT_4_4_4_4;
}
return V_008F14_IMG_DATA_FORMAT_32;
case 2:
return V_008F14_IMG_DATA_FORMAT_32_32;
+#if 0 /* Not supported for render targets */
case 3:
return V_008F14_IMG_DATA_FORMAT_32_32_32;
+#endif
case 4:
return V_008F14_IMG_DATA_FORMAT_32_32_32_32;
}
const struct util_format_description *desc,
int first_non_void)
{
- uint32_t result;
+ unsigned type = desc->channel[first_non_void].type;
+ int i;
+
+ if (type == UTIL_FORMAT_TYPE_FIXED)
+ return V_008F0C_BUF_DATA_FORMAT_INVALID;
+
+ /* See whether the components are of the same size. */
+ for (i = 0; i < desc->nr_channels; i++) {
+ if (desc->channel[first_non_void].size != desc->channel[i].size)
+ return V_008F0C_BUF_DATA_FORMAT_INVALID;
+ }
- if (desc->channel[first_non_void].type == UTIL_FORMAT_TYPE_FIXED)
- return ~0;
+ switch (desc->channel[first_non_void].size) {
+ case 8:
+ switch (desc->nr_channels) {
+ case 1:
+ return V_008F0C_BUF_DATA_FORMAT_8;
+ case 2:
+ return V_008F0C_BUF_DATA_FORMAT_8_8;
+ case 3:
+ case 4:
+ return V_008F0C_BUF_DATA_FORMAT_8_8_8_8;
+ }
+ break;
+ case 16:
+ switch (desc->nr_channels) {
+ case 1:
+ return V_008F0C_BUF_DATA_FORMAT_16;
+ case 2:
+ return V_008F0C_BUF_DATA_FORMAT_16_16;
+ case 3:
+ case 4:
+ return V_008F0C_BUF_DATA_FORMAT_16_16_16_16;
+ }
+ break;
+ case 32:
+ if (type != UTIL_FORMAT_TYPE_FLOAT)
+ return V_008F0C_BUF_DATA_FORMAT_INVALID;
- result = si_translate_texformat(screen, format, desc, first_non_void);
- if (result == V_008F0C_BUF_DATA_FORMAT_INVALID ||
- result > V_008F0C_BUF_DATA_FORMAT_32_32_32_32)
- result = ~0;
+ switch (desc->nr_channels) {
+ case 1:
+ return V_008F0C_BUF_DATA_FORMAT_32;
+ case 2:
+ return V_008F0C_BUF_DATA_FORMAT_32_32;
+ case 3:
+ return V_008F0C_BUF_DATA_FORMAT_32_32_32;
+ case 4:
+ return V_008F0C_BUF_DATA_FORMAT_32_32_32_32;
+ }
+ break;
+ }
- return result;
+ return V_008F0C_BUF_DATA_FORMAT_INVALID;
}
static bool si_is_vertex_format_supported(struct pipe_screen *screen, enum pipe_format format)
{
- return si_translate_vertexformat(screen, format, util_format_description(format),
- util_format_get_first_non_void_channel(format)) != ~0U;
+ const struct util_format_description *desc;
+ int first_non_void;
+ unsigned data_format;
+
+ desc = util_format_description(format);
+ first_non_void = util_format_get_first_non_void_channel(format);
+ data_format = si_translate_vertexformat(screen, format, desc, first_non_void);
+ return data_format != V_008F0C_BUF_DATA_FORMAT_INVALID;
}
static bool si_is_colorbuffer_format_supported(enum pipe_format format)
{
- return si_translate_colorformat(format) != ~0U &&
+ return si_translate_colorformat(format) != V_028C70_COLOR_INVALID &&
si_translate_colorswap(format) != ~0U;
}
static bool si_is_zs_format_supported(enum pipe_format format)
{
- return si_translate_dbformat(format) != ~0U;
+ return si_translate_dbformat(format) != V_028040_Z_INVALID;
}
-bool si_is_format_supported(struct pipe_screen *screen,
- enum pipe_format format,
- enum pipe_texture_target target,
- unsigned sample_count,
- unsigned usage)
+boolean si_is_format_supported(struct pipe_screen *screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned sample_count,
+ unsigned usage)
{
unsigned retval = 0;
return retval == usage;
}
+static unsigned si_tile_mode_index(struct r600_resource_texture *rtex, unsigned level, bool stencil)
+{
+ unsigned tile_mode_index = 0;
+
+ if (stencil) {
+ tile_mode_index = rtex->surface.stencil_tiling_index[level];
+ } else {
+ tile_mode_index = rtex->surface.tiling_index[level];
+ }
+ return tile_mode_index;
+}
+
/*
* framebuffer handling
*/
unsigned level = state->cbufs[cb]->u.tex.level;
unsigned pitch, slice;
unsigned color_info, color_attrib;
+ unsigned tile_mode_index;
unsigned format, swap, ntype, endian;
uint64_t offset;
- unsigned blocksize;
const struct util_format_description *desc;
int i;
unsigned blend_clamp = 0, blend_bypass = 0;
+ unsigned max_comp_size;
surf = (struct r600_surface *)state->cbufs[cb];
rtex = (struct r600_resource_texture*)state->cbufs[cb]->texture;
- blocksize = util_format_get_blocksize(rtex->real_format);
-
- if (rtex->depth)
- rctx->have_depth_fb = TRUE;
-
- if (rtex->depth && !rtex->is_flushing_texture) {
- r600_texture_depth_flush(&rctx->context, state->cbufs[cb]->texture, TRUE);
- rtex = rtex->flushed_depth_texture;
- }
offset = rtex->surface.level[level].offset;
if (rtex->surface.level[level].mode < RADEON_SURF_MODE_1D) {
slice = slice - 1;
}
- color_attrib = S_028C74_TILE_MODE_INDEX(8);
- switch (rtex->surface.level[level].mode) {
- case RADEON_SURF_MODE_LINEAR_ALIGNED:
- color_attrib = S_028C74_TILE_MODE_INDEX(8);
- break;
- case RADEON_SURF_MODE_1D:
- color_attrib = S_028C74_TILE_MODE_INDEX(9);
- break;
- case RADEON_SURF_MODE_2D:
- if (rtex->resource.b.b.bind & PIPE_BIND_SCANOUT) {
- switch (blocksize) {
- case 1:
- color_attrib = S_028C74_TILE_MODE_INDEX(10);
- break;
- case 2:
- color_attrib = S_028C74_TILE_MODE_INDEX(11);
- break;
- case 4:
- color_attrib = S_028C74_TILE_MODE_INDEX(12);
- break;
- }
- break;
- } else switch (blocksize) {
- case 1:
- color_attrib = S_028C74_TILE_MODE_INDEX(14);
- break;
- case 2:
- color_attrib = S_028C74_TILE_MODE_INDEX(15);
- break;
- case 4:
- color_attrib = S_028C74_TILE_MODE_INDEX(16);
- break;
- case 8:
- color_attrib = S_028C74_TILE_MODE_INDEX(17);
- break;
- default:
- color_attrib = S_028C74_TILE_MODE_INDEX(13);
- }
- break;
- }
+ tile_mode_index = si_tile_mode_index(rtex, level, false);
desc = util_format_description(surf->base.format);
for (i = 0; i < 4; i++) {
break;
}
}
- if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT) {
+ if (i == 4 || desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT) {
ntype = V_028C70_NUMBER_FLOAT;
} else {
ntype = V_028C70_NUMBER_UNORM;
if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
ntype = V_028C70_NUMBER_SRGB;
else if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
- if (desc->channel[i].normalized)
- ntype = V_028C70_NUMBER_SNORM;
- else if (desc->channel[i].pure_integer)
+ if (desc->channel[i].pure_integer) {
ntype = V_028C70_NUMBER_SINT;
+ } else {
+ assert(desc->channel[i].normalized);
+ ntype = V_028C70_NUMBER_SNORM;
+ }
} else if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) {
- if (desc->channel[i].normalized)
- ntype = V_028C70_NUMBER_UNORM;
- else if (desc->channel[i].pure_integer)
+ if (desc->channel[i].pure_integer) {
ntype = V_028C70_NUMBER_UINT;
+ } else {
+ assert(desc->channel[i].normalized);
+ ntype = V_028C70_NUMBER_UNORM;
+ }
}
}
format = si_translate_colorformat(surf->base.format);
+ if (format == V_028C70_COLOR_INVALID) {
+ R600_ERR("Invalid CB format: %d, disabling CB.\n", surf->base.format);
+ }
+ assert(format != V_028C70_COLOR_INVALID);
swap = si_translate_colorswap(surf->base.format);
if (rtex->resource.b.b.usage == PIPE_USAGE_STAGING) {
endian = V_028C70_ENDIAN_NONE;
S_028C70_NUMBER_TYPE(ntype) |
S_028C70_ENDIAN(endian);
- rctx->alpha_ref_dirty = true;
+ color_attrib = S_028C74_TILE_MODE_INDEX(tile_mode_index) |
+ S_028C74_FORCE_DST_ALPHA_1(desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_1);
offset += r600_resource_va(rctx->context.screen, state->cbufs[cb]->texture);
offset >>= 8;
}
si_pm4_set_reg(pm4, R_028C70_CB_COLOR0_INFO + cb * 0x3C, color_info);
si_pm4_set_reg(pm4, R_028C74_CB_COLOR0_ATTRIB + cb * 0x3C, color_attrib);
+
+ /* set CB_COLOR1_INFO for possible dual-src blending */
+ if (state->nr_cbufs == 1) {
+ assert(cb == 0);
+ si_pm4_set_reg(pm4, R_028C70_CB_COLOR0_INFO + 1 * 0x3C, color_info);
+ }
+
+ /* 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)) {
+ rctx->export_16bpc |= 1 << cb;
+ /* set SPI_SHADER_COL_FORMAT for possible dual-src blending */
+ if (state->nr_cbufs == 1)
+ rctx->export_16bpc |= 1 << 1;
+ }
}
static void si_db(struct r600_context *rctx, struct si_pm4_state *pm4,
{
struct r600_resource_texture *rtex;
struct r600_surface *surf;
- unsigned level, first_layer, pitch, slice, format;
- uint32_t db_z_info, stencil_info;
- uint64_t offset;
+ unsigned level, pitch, slice, format, tile_mode_index;
+ uint32_t z_info, s_info;
+ uint64_t z_offs, s_offs;
if (state->zsbuf == NULL) {
- si_pm4_set_reg(pm4, R_028040_DB_Z_INFO, 0);
- si_pm4_set_reg(pm4, R_028044_DB_STENCIL_INFO, 0);
+ si_pm4_set_reg(pm4, R_028040_DB_Z_INFO, S_028040_FORMAT(V_028040_Z_INVALID));
+ si_pm4_set_reg(pm4, R_028044_DB_STENCIL_INFO, S_028044_FORMAT(V_028044_STENCIL_INVALID));
return;
}
level = surf->base.u.tex.level;
rtex = (struct r600_resource_texture*)surf->base.texture;
- first_layer = surf->base.u.tex.first_layer;
format = si_translate_dbformat(rtex->real_format);
- offset = r600_resource_va(rctx->context.screen, surf->base.texture);
- offset += rtex->surface.level[level].offset;
+ if (format == V_028040_Z_INVALID) {
+ R600_ERR("Invalid DB format: %d, disabling DB.\n", rtex->real_format);
+ }
+ assert(format != V_028040_Z_INVALID);
+
+ s_offs = z_offs = r600_resource_va(rctx->context.screen, surf->base.texture);
+ z_offs += rtex->surface.level[level].offset;
+ s_offs += rtex->surface.stencil_level[level].offset;
+
+ z_offs >>= 8;
+ s_offs >>= 8;
+
pitch = (rtex->surface.level[level].nblk_x / 8) - 1;
slice = (rtex->surface.level[level].nblk_x * rtex->surface.level[level].nblk_y) / 64;
if (slice) {
slice = slice - 1;
}
- offset >>= 8;
- si_pm4_add_bo(pm4, &rtex->resource, RADEON_USAGE_READWRITE);
- si_pm4_set_reg(pm4, R_028048_DB_Z_READ_BASE, offset);
- si_pm4_set_reg(pm4, R_028050_DB_Z_WRITE_BASE, offset);
+ z_info = S_028040_FORMAT(format);
+ if (rtex->surface.flags & RADEON_SURF_SBUFFER)
+ s_info = S_028044_FORMAT(V_028044_STENCIL_8);
+ else
+ s_info = S_028044_FORMAT(V_028044_STENCIL_INVALID);
+
+ tile_mode_index = si_tile_mode_index(rtex, level, false);
+ z_info |= S_028040_TILE_MODE_INDEX(tile_mode_index);
+ tile_mode_index = si_tile_mode_index(rtex, level, true);
+ s_info |= S_028044_TILE_MODE_INDEX(tile_mode_index);
+
si_pm4_set_reg(pm4, R_028008_DB_DEPTH_VIEW,
S_028008_SLICE_START(state->zsbuf->u.tex.first_layer) |
S_028008_SLICE_MAX(state->zsbuf->u.tex.last_layer));
- db_z_info = S_028040_FORMAT(format);
- stencil_info = S_028044_FORMAT(rtex->stencil != 0);
+ si_pm4_set_reg(pm4, R_02803C_DB_DEPTH_INFO, S_02803C_ADDR5_SWIZZLE_MASK(1));
+ si_pm4_set_reg(pm4, R_028040_DB_Z_INFO, z_info);
+ si_pm4_set_reg(pm4, R_028044_DB_STENCIL_INFO, s_info);
- switch (format) {
- case V_028040_Z_16:
- db_z_info |= S_028040_TILE_MODE_INDEX(5);
- stencil_info |= S_028044_TILE_MODE_INDEX(5);
- break;
- case V_028040_Z_24:
- case V_028040_Z_32_FLOAT:
- db_z_info |= S_028040_TILE_MODE_INDEX(6);
- stencil_info |= S_028044_TILE_MODE_INDEX(6);
- break;
- default:
- db_z_info |= S_028040_TILE_MODE_INDEX(7);
- stencil_info |= S_028044_TILE_MODE_INDEX(7);
- }
-
- if (rtex->stencil) {
- uint64_t stencil_offset =
- r600_texture_get_offset(rtex->stencil, level, first_layer);
-
- stencil_offset += r600_resource_va(rctx->context.screen, (void*)rtex->stencil);
- stencil_offset >>= 8;
-
- si_pm4_add_bo(pm4, &rtex->stencil->resource, RADEON_USAGE_READWRITE);
- si_pm4_set_reg(pm4, R_02804C_DB_STENCIL_READ_BASE, stencil_offset);
- si_pm4_set_reg(pm4, R_028054_DB_STENCIL_WRITE_BASE, stencil_offset);
- si_pm4_set_reg(pm4, R_028044_DB_STENCIL_INFO, stencil_info);
- } else {
- si_pm4_set_reg(pm4, R_028044_DB_STENCIL_INFO, 0);
- }
-
- if (format != ~0U) {
- si_pm4_set_reg(pm4, R_02803C_DB_DEPTH_INFO, 0x1);
- si_pm4_set_reg(pm4, R_028040_DB_Z_INFO, db_z_info);
- si_pm4_set_reg(pm4, R_028058_DB_DEPTH_SIZE, S_028058_PITCH_TILE_MAX(pitch));
- si_pm4_set_reg(pm4, R_02805C_DB_DEPTH_SLICE, S_02805C_SLICE_TILE_MAX(slice));
+ si_pm4_add_bo(pm4, &rtex->resource, RADEON_USAGE_READWRITE);
+ si_pm4_set_reg(pm4, R_028048_DB_Z_READ_BASE, z_offs);
+ si_pm4_set_reg(pm4, R_02804C_DB_STENCIL_READ_BASE, s_offs);
+ si_pm4_set_reg(pm4, R_028050_DB_Z_WRITE_BASE, z_offs);
+ si_pm4_set_reg(pm4, R_028054_DB_STENCIL_WRITE_BASE, s_offs);
- } else {
- si_pm4_set_reg(pm4, R_028040_DB_Z_INFO, 0);
- }
+ si_pm4_set_reg(pm4, R_028058_DB_DEPTH_SIZE, S_028058_PITCH_TILE_MAX(pitch));
+ si_pm4_set_reg(pm4, R_02805C_DB_DEPTH_SLICE, S_02805C_SLICE_TILE_MAX(slice));
}
static void si_set_framebuffer_state(struct pipe_context *ctx,
{
struct r600_context *rctx = (struct r600_context *)ctx;
struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state);
- uint32_t shader_mask, tl, br;
+ uint32_t tl, br;
int tl_x, tl_y, br_x, br_y;
if (pm4 == NULL)
util_copy_framebuffer_state(&rctx->framebuffer, state);
/* build states */
- rctx->have_depth_fb = 0;
+ rctx->export_16bpc = 0;
for (int i = 0; i < state->nr_cbufs; i++) {
si_cb(rctx, pm4, state, i);
}
+ assert(!(rctx->export_16bpc & ~0xff));
si_db(rctx, pm4, state);
- shader_mask = 0;
- for (int i = 0; i < state->nr_cbufs; i++) {
- shader_mask |= 0xf << (i * 4);
- }
tl_x = 0;
tl_y = 0;
br_x = state->width;
br_y = state->height;
-#if 0 /* These shouldn't be necessary on SI, see PA_SC_ENHANCE register */
- /* EG hw workaround */
- if (br_x == 0)
- tl_x = 1;
- if (br_y == 0)
- tl_y = 1;
- /* cayman hw workaround */
- if (rctx->chip_class == CAYMAN) {
- if (br_x == 1 && br_y == 1)
- br_x = 2;
- }
-#endif
+
tl = S_028240_TL_X(tl_x) | S_028240_TL_Y(tl_y);
br = S_028244_BR_X(br_x) | S_028244_BR_Y(br_y);
si_pm4_set_reg(pm4, R_028208_PA_SC_WINDOW_SCISSOR_BR, br);
si_pm4_set_reg(pm4, R_028200_PA_SC_WINDOW_OFFSET, 0x00000000);
si_pm4_set_reg(pm4, R_028230_PA_SC_EDGERULE, 0xAAAAAAAA);
- si_pm4_set_reg(pm4, R_02823C_CB_SHADER_MASK, shader_mask);
si_pm4_set_reg(pm4, R_028BE0_PA_SC_AA_CONFIG, 0x00000000);
si_pm4_set_state(rctx, framebuffer, pm4);
* shaders
*/
+/* Compute the key for the hw shader variant */
+static INLINE void si_shader_selector_key(struct pipe_context *ctx,
+ struct si_pipe_shader_selector *sel,
+ union si_shader_key *key)
+{
+ struct r600_context *rctx = (struct r600_context *)ctx;
+ memset(key, 0, sizeof(*key));
+
+ if (sel->type == PIPE_SHADER_VERTEX) {
+ unsigned i;
+ if (!rctx->vertex_elements)
+ return;
+
+ for (i = 0; i < rctx->vertex_elements->count; ++i)
+ key->vs.instance_divisors[i] = rctx->vertex_elements->elements[i].instance_divisor;
+
+ } else if (sel->type == PIPE_SHADER_FRAGMENT) {
+ if (sel->fs_write_all)
+ key->ps.nr_cbufs = rctx->framebuffer.nr_cbufs;
+ key->ps.export_16bpc = rctx->export_16bpc;
+ if (rctx->queued.named.rasterizer) {
+ key->ps.color_two_side = rctx->queued.named.rasterizer->two_side;
+ key->ps.flatshade = rctx->queued.named.rasterizer->flatshade;
+ }
+ if (rctx->queued.named.dsa) {
+ key->ps.alpha_func = rctx->queued.named.dsa->alpha_func;
+ key->ps.alpha_ref = rctx->queued.named.dsa->alpha_ref;
+ } else {
+ key->ps.alpha_func = PIPE_FUNC_ALWAYS;
+ }
+ }
+}
+
+/* Select the hw shader variant depending on the current state.
+ * (*dirty) is set to 1 if current variant was changed */
+int si_shader_select(struct pipe_context *ctx,
+ struct si_pipe_shader_selector *sel,
+ unsigned *dirty)
+{
+ union si_shader_key key;
+ struct si_pipe_shader * shader = NULL;
+ int r;
+
+ si_shader_selector_key(ctx, sel, &key);
+
+ /* Check if we don't need to change anything.
+ * This path is also used for most shaders that don't need multiple
+ * variants, it will cost just a computation of the key and this
+ * test. */
+ if (likely(sel->current && memcmp(&sel->current->key, &key, sizeof(key)) == 0)) {
+ return 0;
+ }
+
+ /* lookup if we have other variants in the list */
+ if (sel->num_shaders > 1) {
+ struct si_pipe_shader *p = sel->current, *c = p->next_variant;
+
+ while (c && memcmp(&c->key, &key, sizeof(key)) != 0) {
+ p = c;
+ c = c->next_variant;
+ }
+
+ if (c) {
+ p->next_variant = c->next_variant;
+ shader = c;
+ }
+ }
+
+ if (unlikely(!shader)) {
+ shader = CALLOC(1, sizeof(struct si_pipe_shader));
+ shader->selector = sel;
+ shader->key = key;
+
+ r = si_pipe_shader_create(ctx, shader);
+ if (unlikely(r)) {
+ R600_ERR("Failed to build shader variant (type=%u) %d\n",
+ sel->type, r);
+ sel->current = NULL;
+ FREE(shader);
+ return r;
+ }
+
+ /* We don't know the value of fs_write_all property until we built
+ * at least one variant, so we may need to recompute the key (include
+ * rctx->framebuffer.nr_cbufs) after building first variant. */
+ if (sel->type == PIPE_SHADER_FRAGMENT &&
+ sel->num_shaders == 0 &&
+ shader->shader.fs_write_all) {
+ sel->fs_write_all = 1;
+ si_shader_selector_key(ctx, sel, &shader->key);
+ }
+
+ sel->num_shaders++;
+ }
+
+ if (dirty)
+ *dirty = 1;
+
+ shader->next_variant = sel->current;
+ sel->current = shader;
+
+ return 0;
+}
+
static void *si_create_shader_state(struct pipe_context *ctx,
- const struct pipe_shader_state *state)
+ const struct pipe_shader_state *state,
+ unsigned pipe_shader_type)
{
- struct si_pipe_shader *shader = CALLOC_STRUCT(si_pipe_shader);
+ struct si_pipe_shader_selector *sel = CALLOC_STRUCT(si_pipe_shader_selector);
+ int r;
+
+ sel->type = pipe_shader_type;
+ sel->tokens = tgsi_dup_tokens(state->tokens);
+ sel->so = state->stream_output;
- shader->tokens = tgsi_dup_tokens(state->tokens);
- shader->so = state->stream_output;
+ r = si_shader_select(ctx, sel, NULL);
+ if (r) {
+ free(sel);
+ return NULL;
+ }
+
+ return sel;
+}
- return shader;
+static void *si_create_fs_state(struct pipe_context *ctx,
+ const struct pipe_shader_state *state)
+{
+ return si_create_shader_state(ctx, state, PIPE_SHADER_FRAGMENT);
+}
+
+static void *si_create_vs_state(struct pipe_context *ctx,
+ const struct pipe_shader_state *state)
+{
+ return si_create_shader_state(ctx, state, PIPE_SHADER_VERTEX);
}
static void si_bind_vs_shader(struct pipe_context *ctx, void *state)
{
struct r600_context *rctx = (struct r600_context *)ctx;
- struct si_pipe_shader *shader = state;
+ struct si_pipe_shader_selector *sel = state;
- if (rctx->vs_shader == state)
+ if (rctx->vs_shader == sel)
return;
- rctx->shader_dirty = true;
- rctx->vs_shader = shader;
- si_pm4_bind_state(rctx, vs, shader->pm4);
+ rctx->vs_shader = sel;
+
+ if (sel && sel->current)
+ si_pm4_bind_state(rctx, vs, sel->current->pm4);
+ else
+ si_pm4_bind_state(rctx, vs, rctx->dummy_pixel_shader->pm4);
}
static void si_bind_ps_shader(struct pipe_context *ctx, void *state)
{
struct r600_context *rctx = (struct r600_context *)ctx;
- struct si_pipe_shader *shader = state;
+ struct si_pipe_shader_selector *sel = state;
- if (rctx->ps_shader == state)
+ if (rctx->ps_shader == sel)
return;
- rctx->shader_dirty = true;
- rctx->ps_shader = shader;
- si_pm4_bind_state(rctx, ps, shader->pm4);
+ rctx->ps_shader = sel;
+
+ if (sel && sel->current)
+ si_pm4_bind_state(rctx, ps, sel->current->pm4);
+ else
+ si_pm4_bind_state(rctx, ps, rctx->dummy_pixel_shader->pm4);
}
+static void si_delete_shader_selector(struct pipe_context *ctx,
+ struct si_pipe_shader_selector *sel)
+{
+ struct r600_context *rctx = (struct r600_context *)ctx;
+ struct si_pipe_shader *p = sel->current, *c;
+
+ while (p) {
+ c = p->next_variant;
+ si_pm4_delete_state(rctx, vs, p->pm4);
+ si_pipe_shader_destroy(ctx, p);
+ free(p);
+ p = c;
+ }
+
+ free(sel->tokens);
+ free(sel);
+ }
+
static void si_delete_vs_shader(struct pipe_context *ctx, void *state)
{
struct r600_context *rctx = (struct r600_context *)ctx;
- struct si_pipe_shader *shader = (struct si_pipe_shader *)state;
+ struct si_pipe_shader_selector *sel = (struct si_pipe_shader_selector *)state;
- if (rctx->vs_shader == shader) {
+ if (rctx->vs_shader == sel) {
rctx->vs_shader = NULL;
}
- si_pm4_delete_state(rctx, vs, shader->pm4);
- free(shader->tokens);
- si_pipe_shader_destroy(ctx, shader);
- free(shader);
+ si_delete_shader_selector(ctx, sel);
}
static void si_delete_ps_shader(struct pipe_context *ctx, void *state)
{
struct r600_context *rctx = (struct r600_context *)ctx;
- struct si_pipe_shader *shader = (struct si_pipe_shader *)state;
+ struct si_pipe_shader_selector *sel = (struct si_pipe_shader_selector *)state;
- if (rctx->ps_shader == shader) {
+ if (rctx->ps_shader == sel) {
rctx->ps_shader = NULL;
}
- si_pm4_delete_state(rctx, ps, shader->pm4);
- free(shader->tokens);
- si_pipe_shader_destroy(ctx, shader);
- free(shader);
+ si_delete_shader_selector(ctx, sel);
}
/*
{
struct si_pipe_sampler_view *view = CALLOC_STRUCT(si_pipe_sampler_view);
struct r600_resource_texture *tmp = (struct r600_resource_texture*)texture;
- const struct util_format_description *desc = util_format_description(state->format);
- unsigned blocksize = util_format_get_blocksize(tmp->real_format);
- unsigned format, num_format, /*endian,*/ tiling_index;
+ const struct util_format_description *desc;
+ unsigned format, num_format;
uint32_t pitch = 0;
unsigned char state_swizzle[4], swizzle[4];
unsigned height, depth, width;
+ enum pipe_format pipe_format = state->format;
+ struct radeon_surface_level *surflevel;
int first_non_void;
uint64_t va;
state_swizzle[1] = state->swizzle_g;
state_swizzle[2] = state->swizzle_b;
state_swizzle[3] = state->swizzle_a;
- util_format_compose_swizzles(desc->swizzle, state_swizzle, swizzle);
- first_non_void = util_format_get_first_non_void_channel(state->format);
- switch (desc->channel[first_non_void].type) {
- case UTIL_FORMAT_TYPE_FLOAT:
- num_format = V_008F14_IMG_NUM_FORMAT_FLOAT;
- break;
- case UTIL_FORMAT_TYPE_SIGNED:
- num_format = V_008F14_IMG_NUM_FORMAT_SNORM;
+ surflevel = tmp->surface.level;
+
+ /* Texturing with separate depth and stencil. */
+ if (tmp->is_depth && !tmp->is_flushing_texture) {
+ switch (pipe_format) {
+ case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+ pipe_format = PIPE_FORMAT_Z32_FLOAT;
+ break;
+ case PIPE_FORMAT_X8Z24_UNORM:
+ case PIPE_FORMAT_S8_UINT_Z24_UNORM:
+ /* Z24 is always stored like this. */
+ pipe_format = PIPE_FORMAT_Z24X8_UNORM;
+ break;
+ case PIPE_FORMAT_X24S8_UINT:
+ case PIPE_FORMAT_S8X24_UINT:
+ case PIPE_FORMAT_X32_S8X24_UINT:
+ pipe_format = PIPE_FORMAT_S8_UINT;
+ surflevel = tmp->surface.stencil_level;
+ break;
+ default:;
+ }
+ }
+
+ desc = util_format_description(pipe_format);
+
+ if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
+ const unsigned char swizzle_xxxx[4] = {0, 0, 0, 0};
+ const unsigned char swizzle_yyyy[4] = {1, 1, 1, 1};
+
+ switch (pipe_format) {
+ case PIPE_FORMAT_S8_UINT_Z24_UNORM:
+ case PIPE_FORMAT_X24S8_UINT:
+ case PIPE_FORMAT_X32_S8X24_UINT:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ util_format_compose_swizzles(swizzle_yyyy, state_swizzle, swizzle);
+ break;
+ default:
+ util_format_compose_swizzles(swizzle_xxxx, state_swizzle, swizzle);
+ }
+ } else {
+ util_format_compose_swizzles(desc->swizzle, state_swizzle, swizzle);
+ }
+
+ first_non_void = util_format_get_first_non_void_channel(pipe_format);
+
+ switch (pipe_format) {
+ case PIPE_FORMAT_S8_UINT_Z24_UNORM:
+ num_format = V_008F14_IMG_NUM_FORMAT_UNORM;
break;
- case UTIL_FORMAT_TYPE_UNSIGNED:
default:
- num_format = V_008F14_IMG_NUM_FORMAT_UNORM;
+ if (first_non_void < 0) {
+ if (util_format_is_compressed(pipe_format)) {
+ switch (pipe_format) {
+ case PIPE_FORMAT_DXT1_SRGB:
+ case PIPE_FORMAT_DXT1_SRGBA:
+ case PIPE_FORMAT_DXT3_SRGBA:
+ case PIPE_FORMAT_DXT5_SRGBA:
+ 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:
+ num_format = V_008F14_IMG_NUM_FORMAT_SNORM;
+ break;
+ default:
+ num_format = V_008F14_IMG_NUM_FORMAT_UNORM;
+ break;
+ }
+ } else {
+ num_format = V_008F14_IMG_NUM_FORMAT_FLOAT;
+ }
+ } else if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
+ num_format = V_008F14_IMG_NUM_FORMAT_SRGB;
+ } else {
+ num_format = V_008F14_IMG_NUM_FORMAT_UNORM;
+
+ switch (desc->channel[first_non_void].type) {
+ case UTIL_FORMAT_TYPE_FLOAT:
+ num_format = V_008F14_IMG_NUM_FORMAT_FLOAT;
+ break;
+ case UTIL_FORMAT_TYPE_SIGNED:
+ if (desc->channel[first_non_void].normalized)
+ num_format = V_008F14_IMG_NUM_FORMAT_SNORM;
+ else if (desc->channel[first_non_void].pure_integer)
+ num_format = V_008F14_IMG_NUM_FORMAT_SINT;
+ else
+ num_format = V_008F14_IMG_NUM_FORMAT_SSCALED;
+ break;
+ case UTIL_FORMAT_TYPE_UNSIGNED:
+ if (desc->channel[first_non_void].normalized)
+ num_format = V_008F14_IMG_NUM_FORMAT_UNORM;
+ else if (desc->channel[first_non_void].pure_integer)
+ num_format = V_008F14_IMG_NUM_FORMAT_UINT;
+ else
+ num_format = V_008F14_IMG_NUM_FORMAT_USCALED;
+ }
+ }
}
- format = si_translate_texformat(ctx->screen, state->format, desc, first_non_void);
+ format = si_translate_texformat(ctx->screen, pipe_format, desc, first_non_void);
if (format == ~0) {
format = 0;
}
- if (tmp->depth && !tmp->is_flushing_texture) {
- r600_texture_depth_flush(ctx, texture, TRUE);
- tmp = tmp->flushed_depth_texture;
- }
+ view->resource = &tmp->resource;
/* not supported any more */
//endian = si_colorformat_endian_swap(format);
- height = texture->height0;
- depth = texture->depth0;
- width = texture->width0;
- pitch = align(tmp->pitch_in_blocks[0] *
- util_format_get_blockwidth(state->format), 8);
+ width = surflevel[0].npix_x;
+ height = surflevel[0].npix_y;
+ depth = surflevel[0].npix_z;
+ pitch = surflevel[0].nblk_x * util_format_get_blockwidth(pipe_format);
if (texture->target == PIPE_TEXTURE_1D_ARRAY) {
height = 1;
depth = texture->array_size;
}
- tiling_index = 8;
- switch (tmp->surface.level[state->u.tex.first_level].mode) {
- case RADEON_SURF_MODE_LINEAR_ALIGNED:
- tiling_index = 8;
- break;
- case RADEON_SURF_MODE_1D:
- tiling_index = 9;
- break;
- case RADEON_SURF_MODE_2D:
- if (tmp->resource.b.b.bind & PIPE_BIND_SCANOUT) {
- switch (blocksize) {
- case 1:
- tiling_index = 10;
- break;
- case 2:
- tiling_index = 11;
- break;
- case 4:
- tiling_index = 12;
- break;
- }
- break;
- } else switch (blocksize) {
- case 1:
- tiling_index = 14;
- break;
- case 2:
- tiling_index = 15;
- break;
- case 4:
- tiling_index = 16;
- break;
- case 8:
- tiling_index = 17;
- break;
- default:
- tiling_index = 13;
- }
- break;
- }
-
va = r600_resource_va(ctx->screen, texture);
- if (state->u.tex.last_level) {
- view->state[0] = (va + tmp->offset[1]) >> 8;
- } else {
- view->state[0] = (va + tmp->offset[0]) >> 8;
- }
- view->state[1] = (S_008F14_BASE_ADDRESS_HI((va + tmp->offset[0]) >> 40) |
+ va += surflevel[0].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_008F1C_DST_SEL_W(si_map_swizzle(swizzle[3])) |
S_008F1C_BASE_LEVEL(state->u.tex.first_level) |
S_008F1C_LAST_LEVEL(state->u.tex.last_level) |
- S_008F1C_TILING_INDEX(tiling_index) |
+ S_008F1C_TILING_INDEX(si_tile_mode_index(tmp, 0, false)) |
+ S_008F1C_POW2_PAD(texture->last_level > 0) |
S_008F1C_TYPE(si_tex_dim(texture->target)));
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) |
FREE(resource);
}
+static bool wrap_mode_uses_border_color(unsigned wrap, bool linear_filter)
+{
+ return wrap == PIPE_TEX_WRAP_CLAMP_TO_BORDER ||
+ wrap == PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER ||
+ (linear_filter &&
+ (wrap == PIPE_TEX_WRAP_CLAMP ||
+ wrap == PIPE_TEX_WRAP_MIRROR_CLAMP));
+}
+
+static bool sampler_state_needs_border_color(const struct pipe_sampler_state *state)
+{
+ bool linear_filter = state->min_img_filter != PIPE_TEX_FILTER_NEAREST ||
+ state->mag_img_filter != PIPE_TEX_FILTER_NEAREST;
+
+ return (state->border_color.ui[0] || state->border_color.ui[1] ||
+ state->border_color.ui[2] || state->border_color.ui[3]) &&
+ (wrap_mode_uses_border_color(state->wrap_s, linear_filter) ||
+ wrap_mode_uses_border_color(state->wrap_t, linear_filter) ||
+ wrap_mode_uses_border_color(state->wrap_r, linear_filter));
+}
+
static void *si_create_sampler_state(struct pipe_context *ctx,
const struct pipe_sampler_state *state)
{
struct si_pipe_sampler_state *rstate = CALLOC_STRUCT(si_pipe_sampler_state);
- union util_color uc;
unsigned aniso_flag_offset = state->max_anisotropy > 1 ? 2 : 0;
unsigned border_color_type;
return NULL;
}
- util_pack_color(state->border_color.f, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
- switch (uc.ui) {
- case 0x000000FF:
- border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_BLACK;
- break;
- case 0x00000000:
- border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK;
- break;
- case 0xFFFFFFFF:
- border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_WHITE;
- break;
- default: /* Use border color pointer */
+ if (sampler_state_needs_border_color(state))
border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER;
- }
+ else
+ border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK;
rstate->val[0] = (S_008F30_CLAMP_X(si_tex_wrap(state->wrap_s)) |
S_008F30_CLAMP_Y(si_tex_wrap(state->wrap_t)) |
S_008F38_MIP_FILTER(si_tex_mipfilter(state->min_mip_filter)));
rstate->val[3] = S_008F3C_BORDER_COLOR_TYPE(border_color_type);
-#if 0
- if (border_color_type == 3) {
- si_pm4_set_reg(pm4, R_00A404_TD_PS_SAMPLER0_BORDER_RED, fui(state->border_color.f[0]));
- si_pm4_set_reg(pm4, R_00A408_TD_PS_SAMPLER0_BORDER_GREEN, fui(state->border_color.f[1]));
- si_pm4_set_reg(pm4, R_00A40C_TD_PS_SAMPLER0_BORDER_BLUE, fui(state->border_color.f[2]));
- si_pm4_set_reg(pm4, R_00A410_TD_PS_SAMPLER0_BORDER_ALPHA, fui(state->border_color.f[3]));
+ if (border_color_type == V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER) {
+ memcpy(rstate->border_color, state->border_color.ui,
+ sizeof(rstate->border_color));
}
-#endif
+
return rstate;
}
-static void si_set_vs_sampler_view(struct pipe_context *ctx, unsigned count,
- struct pipe_sampler_view **views)
+static struct si_pm4_state *si_set_sampler_view(struct r600_context *rctx,
+ unsigned count,
+ struct pipe_sampler_view **views,
+ struct r600_textures_info *samplers,
+ unsigned user_data_reg)
{
- assert(count == 0);
-}
-
-static void si_set_ps_sampler_view(struct pipe_context *ctx, unsigned count,
- struct pipe_sampler_view **views)
-{
- struct r600_context *rctx = (struct r600_context *)ctx;
struct si_pipe_sampler_view **resource = (struct si_pipe_sampler_view **)views;
struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state);
- struct si_resource *bo;
- int i;
- int has_depth = 0;
- uint64_t va;
- char *ptr;
+ int i, j;
if (!count)
goto out;
si_pm4_inval_texture_cache(pm4);
- bo = si_resource_create_custom(ctx->screen, PIPE_USAGE_IMMUTABLE,
- count * sizeof(resource[0]->state));
- ptr = rctx->ws->buffer_map(bo->cs_buf, rctx->cs, PIPE_TRANSFER_WRITE);
-
- for (i = 0; i < count; i++, ptr += sizeof(resource[0]->state)) {
- struct r600_resource_texture *tex = (void *)resource[i]->base.texture;
-
+ si_pm4_sh_data_begin(pm4);
+ for (i = 0; i < count; i++) {
pipe_sampler_view_reference(
- (struct pipe_sampler_view **)&rctx->ps_samplers.views[i],
+ (struct pipe_sampler_view **)&samplers->views[i],
views[i]);
- si_pm4_add_bo(pm4, &tex->resource, RADEON_USAGE_READ);
+ if (views[i]) {
+ struct r600_resource_texture *rtex =
+ (struct r600_resource_texture*)views[i]->texture;
- if (resource[i]) {
- if (tex->depth)
- has_depth = 1;
+ if (rtex->is_depth && !rtex->is_flushing_texture) {
+ samplers->depth_texture_mask |= 1 << i;
+ } else {
+ samplers->depth_texture_mask &= ~(1 << i);
+ }
- memcpy(ptr, resource[i]->state, sizeof(resource[0]->state));
- } else
- memset(ptr, 0, sizeof(resource[0]->state));
- }
+ si_pm4_add_bo(pm4, resource[i]->resource, RADEON_USAGE_READ);
+ } else {
+ samplers->depth_texture_mask &= ~(1 << i);
+ }
- rctx->ws->buffer_unmap(bo->cs_buf);
+ for (j = 0; j < Elements(resource[i]->state); ++j) {
+ si_pm4_sh_data_add(pm4, resource[i] ? resource[i]->state[j] : 0);
+ }
+ }
for (i = count; i < NUM_TEX_UNITS; i++) {
- if (rctx->ps_samplers.views[i])
- pipe_sampler_view_reference((struct pipe_sampler_view **)&rctx->ps_samplers.views[i], NULL);
+ if (samplers->views[i])
+ pipe_sampler_view_reference((struct pipe_sampler_view **)&samplers->views[i], NULL);
}
- va = r600_resource_va(ctx->screen, (void *)bo);
- si_pm4_add_bo(pm4, bo, RADEON_USAGE_READ);
- si_pm4_set_reg(pm4, R_00B040_SPI_SHADER_USER_DATA_PS_4, va);
- si_pm4_set_reg(pm4, R_00B044_SPI_SHADER_USER_DATA_PS_5, va >> 32);
+ si_pm4_sh_data_end(pm4, user_data_reg, SI_SGPR_RESOURCE);
out:
- si_pm4_set_state(rctx, ps_sampler_views, pm4);
- rctx->have_depth_texture = has_depth;
rctx->ps_samplers.n_views = count;
+ return pm4;
}
-static void si_bind_vs_sampler(struct pipe_context *ctx, unsigned count, void **states)
+static void si_set_vs_sampler_view(struct pipe_context *ctx, unsigned count,
+ struct pipe_sampler_view **views)
{
- assert(0);
+ struct r600_context *rctx = (struct r600_context *)ctx;
+ struct si_pm4_state *pm4;
+
+ pm4 = si_set_sampler_view(rctx, count, views, &rctx->vs_samplers,
+ R_00B130_SPI_SHADER_USER_DATA_VS_0);
+ si_pm4_set_state(rctx, vs_sampler_views, pm4);
}
-static void si_bind_ps_sampler(struct pipe_context *ctx, unsigned count, void **states)
+static void si_set_ps_sampler_view(struct pipe_context *ctx, unsigned count,
+ struct pipe_sampler_view **views)
{
struct r600_context *rctx = (struct r600_context *)ctx;
+ struct si_pm4_state *pm4;
+
+ pm4 = si_set_sampler_view(rctx, count, views, &rctx->ps_samplers,
+ R_00B030_SPI_SHADER_USER_DATA_PS_0);
+ si_pm4_set_state(rctx, ps_sampler_views, pm4);
+}
+
+static struct si_pm4_state *si_bind_sampler(struct r600_context *rctx, unsigned count,
+ void **states,
+ struct r600_textures_info *samplers,
+ unsigned user_data_reg)
+{
struct si_pipe_sampler_state **rstates = (struct si_pipe_sampler_state **)states;
struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state);
- struct si_resource *bo;
- uint64_t va;
- char *ptr;
- int i;
+ uint32_t *border_color_table = NULL;
+ int i, j;
if (!count)
goto out;
si_pm4_inval_texture_cache(pm4);
- bo = si_resource_create_custom(ctx->screen, PIPE_USAGE_IMMUTABLE,
- count * sizeof(rstates[0]->val));
- ptr = rctx->ws->buffer_map(bo->cs_buf, rctx->cs, PIPE_TRANSFER_WRITE);
+ si_pm4_sh_data_begin(pm4);
+ for (i = 0; i < count; i++) {
+ if (rstates[i] &&
+ G_008F3C_BORDER_COLOR_TYPE(rstates[i]->val[3]) ==
+ V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER) {
+ if (!rctx->border_color_table ||
+ ((rctx->border_color_offset + count - i) &
+ C_008F3C_BORDER_COLOR_PTR)) {
+ si_resource_reference(&rctx->border_color_table, NULL);
+ rctx->border_color_offset = 0;
+
+ rctx->border_color_table =
+ si_resource_create_custom(&rctx->screen->screen,
+ PIPE_USAGE_STAGING,
+ 4096 * 4 * 4);
+ }
+
+ if (!border_color_table) {
+ border_color_table =
+ rctx->ws->buffer_map(rctx->border_color_table->cs_buf,
+ rctx->cs,
+ PIPE_TRANSFER_WRITE |
+ PIPE_TRANSFER_UNSYNCHRONIZED);
+ }
+
+ for (j = 0; j < 4; j++) {
+ border_color_table[4 * rctx->border_color_offset + j] =
+ util_le32_to_cpu(rstates[i]->border_color[j]);
+ }
+
+ rstates[i]->val[3] &= C_008F3C_BORDER_COLOR_PTR;
+ rstates[i]->val[3] |= S_008F3C_BORDER_COLOR_PTR(rctx->border_color_offset++);
+ }
- for (i = 0; i < count; i++, ptr += sizeof(rstates[0]->val)) {
- memcpy(ptr, rstates[i]->val, sizeof(rstates[0]->val));
+ for (j = 0; j < Elements(rstates[i]->val); ++j) {
+ si_pm4_sh_data_add(pm4, rstates[i] ? rstates[i]->val[j] : 0);
+ }
}
+ si_pm4_sh_data_end(pm4, user_data_reg, SI_SGPR_SAMPLER);
- rctx->ws->buffer_unmap(bo->cs_buf);
+ if (border_color_table) {
+ uint64_t va_offset =
+ r600_resource_va(&rctx->screen->screen,
+ (void*)rctx->border_color_table);
- memcpy(rctx->ps_samplers.samplers, states, sizeof(void*) * count);
+ si_pm4_set_reg(pm4, R_028080_TA_BC_BASE_ADDR, va_offset >> 8);
+ rctx->ws->buffer_unmap(rctx->border_color_table->cs_buf);
+ si_pm4_add_bo(pm4, rctx->border_color_table, RADEON_USAGE_READ);
+ }
- va = r600_resource_va(ctx->screen, (void *)bo);
- si_pm4_add_bo(pm4, bo, RADEON_USAGE_READ);
- si_pm4_set_reg(pm4, R_00B038_SPI_SHADER_USER_DATA_PS_2, va);
- si_pm4_set_reg(pm4, R_00B03C_SPI_SHADER_USER_DATA_PS_3, va >> 32);
+ memcpy(samplers->samplers, states, sizeof(void*) * count);
out:
+ samplers->n_samplers = count;
+ return pm4;
+}
+
+static void si_bind_vs_sampler(struct pipe_context *ctx, unsigned count, void **states)
+{
+ struct r600_context *rctx = (struct r600_context *)ctx;
+ struct si_pm4_state *pm4;
+
+ pm4 = si_bind_sampler(rctx, count, states, &rctx->vs_samplers,
+ R_00B130_SPI_SHADER_USER_DATA_VS_0);
+ si_pm4_set_state(rctx, vs_sampler, pm4);
+}
+
+static void si_bind_ps_sampler(struct pipe_context *ctx, unsigned count, void **states)
+{
+ struct r600_context *rctx = (struct r600_context *)ctx;
+ struct si_pm4_state *pm4;
+
+ pm4 = si_bind_sampler(rctx, count, states, &rctx->ps_samplers,
+ R_00B030_SPI_SHADER_USER_DATA_PS_0);
si_pm4_set_state(rctx, ps_sampler, pm4);
- rctx->ps_samplers.n_samplers = count;
}
static void si_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
* Constants
*/
static void si_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
- struct pipe_constant_buffer *cb)
+ struct pipe_constant_buffer *input)
{
struct r600_context *rctx = (struct r600_context *)ctx;
- struct si_resource *rbuffer = cb ? si_resource(cb->buffer) : NULL;
- struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state);
- uint64_t va_offset;
- uint32_t offset;
+ struct r600_constbuf_state *state = &rctx->constbuf_state[shader];
+ struct pipe_constant_buffer *cb;
+ const uint8_t *ptr;
/* Note that the state tracker can unbind constant buffers by
* passing NULL here.
*/
- if (cb == NULL) {
- FREE(pm4);
+ if (unlikely(!input || (!input->buffer && !input->user_buffer))) {
+ state->enabled_mask &= ~(1 << index);
+ state->dirty_mask &= ~(1 << index);
+ pipe_resource_reference(&state->cb[index].buffer, NULL);
return;
}
- si_pm4_inval_shader_cache(pm4);
-
- if (cb->user_buffer)
- r600_upload_const_buffer(rctx, &rbuffer, cb->user_buffer, cb->buffer_size, &offset);
- else
- offset = 0;
- va_offset = r600_resource_va(ctx->screen, (void*)rbuffer);
- va_offset += offset;
+ cb = &state->cb[index];
+ cb->buffer_size = input->buffer_size;
- si_pm4_add_bo(pm4, rbuffer, RADEON_USAGE_READ);
+ ptr = input->user_buffer;
- switch (shader) {
- case PIPE_SHADER_VERTEX:
- si_pm4_set_reg(pm4, R_00B130_SPI_SHADER_USER_DATA_VS_0, va_offset);
- si_pm4_set_reg(pm4, R_00B134_SPI_SHADER_USER_DATA_VS_1, va_offset >> 32);
- si_pm4_set_state(rctx, vs_const, pm4);
- break;
-
- case PIPE_SHADER_FRAGMENT:
- si_pm4_set_reg(pm4, R_00B030_SPI_SHADER_USER_DATA_PS_0, va_offset);
- si_pm4_set_reg(pm4, R_00B034_SPI_SHADER_USER_DATA_PS_1, va_offset >> 32);
- si_pm4_set_state(rctx, ps_const, pm4);
- break;
-
- default:
- R600_ERR("unsupported %d\n", shader);
- return;
+ if (ptr) {
+ r600_upload_const_buffer(rctx,
+ (struct si_resource**)&cb->buffer, ptr,
+ cb->buffer_size, &cb->buffer_offset);
+ } else {
+ /* Setup the hw buffer. */
+ cb->buffer_offset = input->buffer_offset;
+ pipe_resource_reference(&cb->buffer, input->buffer);
}
- if (cb->buffer != &rbuffer->b.b)
- si_resource_reference(&rbuffer, NULL);
+ state->enabled_mask |= 1 << index;
+ state->dirty_mask |= 1 << index;
}
/*
num_format = V_008F0C_BUF_NUM_FORMAT_USCALED; /* XXX */
break;
case UTIL_FORMAT_TYPE_SIGNED:
- num_format = V_008F0C_BUF_NUM_FORMAT_SNORM;
+ if (desc->channel[first_non_void].normalized)
+ num_format = V_008F0C_BUF_NUM_FORMAT_SNORM;
+ else if (desc->channel[first_non_void].pure_integer)
+ num_format = V_008F0C_BUF_NUM_FORMAT_SINT;
+ else
+ num_format = V_008F0C_BUF_NUM_FORMAT_SSCALED;
break;
case UTIL_FORMAT_TYPE_UNSIGNED:
- num_format = V_008F0C_BUF_NUM_FORMAT_UNORM;
+ if (desc->channel[first_non_void].normalized)
+ num_format = V_008F0C_BUF_NUM_FORMAT_UNORM;
+ else if (desc->channel[first_non_void].pure_integer)
+ num_format = V_008F0C_BUF_NUM_FORMAT_UINT;
+ else
+ num_format = V_008F0C_BUF_NUM_FORMAT_USCALED;
break;
case UTIL_FORMAT_TYPE_FLOAT:
default:
FREE(state);
}
-static void si_set_vertex_buffers(struct pipe_context *ctx, unsigned count,
+static void si_set_vertex_buffers(struct pipe_context *ctx, unsigned start_slot, unsigned count,
const struct pipe_vertex_buffer *buffers)
{
struct r600_context *rctx = (struct r600_context *)ctx;
- util_copy_vertex_buffers(rctx->vertex_buffer, &rctx->nr_vertex_buffers, buffers, count);
+ util_set_vertex_buffers_count(rctx->vertex_buffer, &rctx->nr_vertex_buffers, buffers, start_slot, count);
}
static void si_set_index_buffer(struct pipe_context *ctx,
}
}
-/*
- * Stream out
- */
-
-static struct pipe_stream_output_target *
-si_create_so_target(struct pipe_context *ctx,
- struct pipe_resource *buffer,
- unsigned buffer_offset,
- unsigned buffer_size)
-{
- struct r600_context *rctx = (struct r600_context *)ctx;
- struct r600_so_target *t;
- void *ptr;
-
- t = CALLOC_STRUCT(r600_so_target);
- if (!t) {
- return NULL;
- }
-
- t->b.reference.count = 1;
- t->b.context = ctx;
- pipe_resource_reference(&t->b.buffer, buffer);
- t->b.buffer_offset = buffer_offset;
- t->b.buffer_size = buffer_size;
-
- t->filled_size = si_resource_create_custom(ctx->screen, PIPE_USAGE_STATIC, 4);
- ptr = rctx->ws->buffer_map(t->filled_size->cs_buf, rctx->cs, PIPE_TRANSFER_WRITE);
- memset(ptr, 0, t->filled_size->buf->size);
- rctx->ws->buffer_unmap(t->filled_size->cs_buf);
-
- return &t->b;
-}
-
-static void si_so_target_destroy(struct pipe_context *ctx,
- struct pipe_stream_output_target *target)
-{
- struct r600_so_target *t = (struct r600_so_target*)target;
- pipe_resource_reference(&t->b.buffer, NULL);
- si_resource_reference(&t->filled_size, NULL);
- FREE(t);
-}
-
-static void si_set_so_targets(struct pipe_context *ctx,
- unsigned num_targets,
- struct pipe_stream_output_target **targets,
- unsigned append_bitmask)
-{
- struct r600_context *rctx = (struct r600_context *)ctx;
- unsigned i;
-
- /* Stop streamout. */
- if (rctx->num_so_targets) {
- r600_context_streamout_end(rctx);
- }
-
- /* Set the new targets. */
- for (i = 0; i < num_targets; i++) {
- pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->so_targets[i], targets[i]);
- }
- for (; i < rctx->num_so_targets; i++) {
- pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->so_targets[i], NULL);
- }
-
- rctx->num_so_targets = num_targets;
- rctx->streamout_start = num_targets != 0;
- rctx->streamout_append_bitmask = append_bitmask;
-}
-
/*
* Misc
*/
-#if 0
-static uint32_t r600_translate_stencil_op(int s_op)
-{
- switch (s_op) {
- case PIPE_STENCIL_OP_KEEP:
- return V_028800_STENCIL_KEEP;
- case PIPE_STENCIL_OP_ZERO:
- return V_028800_STENCIL_ZERO;
- case PIPE_STENCIL_OP_REPLACE:
- return V_028800_STENCIL_REPLACE;
- case PIPE_STENCIL_OP_INCR:
- return V_028800_STENCIL_INCR;
- case PIPE_STENCIL_OP_DECR:
- return V_028800_STENCIL_DECR;
- case PIPE_STENCIL_OP_INCR_WRAP:
- return V_028800_STENCIL_INCR_WRAP;
- case PIPE_STENCIL_OP_DECR_WRAP:
- return V_028800_STENCIL_DECR_WRAP;
- case PIPE_STENCIL_OP_INVERT:
- return V_028800_STENCIL_INVERT;
- default:
- R600_ERR("Unknown stencil op %d", s_op);
- assert(0);
- break;
- }
- return 0;
-}
-#endif
-
static void si_set_polygon_stipple(struct pipe_context *ctx,
const struct pipe_poly_stipple *state)
{
rctx->context.create_depth_stencil_alpha_state = si_create_dsa_state;
rctx->context.bind_depth_stencil_alpha_state = si_bind_dsa_state;
rctx->context.delete_depth_stencil_alpha_state = si_delete_dsa_state;
- rctx->custom_dsa_flush = si_create_db_flush_dsa(rctx);
+ rctx->custom_dsa_flush_depth_stencil = si_create_db_flush_dsa(rctx, true, true);
+ rctx->custom_dsa_flush_depth = si_create_db_flush_dsa(rctx, true, false);
+ rctx->custom_dsa_flush_stencil = si_create_db_flush_dsa(rctx, false, true);
+ rctx->custom_dsa_flush_inplace = si_create_db_flush_dsa(rctx, false, false);
rctx->context.set_clip_state = si_set_clip_state;
- rctx->context.set_scissor_state = si_set_scissor_state;
- rctx->context.set_viewport_state = si_set_viewport_state;
+ rctx->context.set_scissor_states = si_set_scissor_states;
+ rctx->context.set_viewport_states = si_set_viewport_states;
rctx->context.set_stencil_ref = si_set_pipe_stencil_ref;
rctx->context.set_framebuffer_state = si_set_framebuffer_state;
- rctx->context.create_vs_state = si_create_shader_state;
- rctx->context.create_fs_state = si_create_shader_state;
+ rctx->context.create_vs_state = si_create_vs_state;
+ rctx->context.create_fs_state = si_create_fs_state;
rctx->context.bind_vs_state = si_bind_vs_shader;
rctx->context.bind_fs_state = si_bind_ps_shader;
rctx->context.delete_vs_state = si_delete_vs_shader;
{
struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state);
+ si_cmd_context_control(pm4);
+
si_pm4_set_reg(pm4, R_028A4C_PA_SC_MODE_CNTL_1, 0x0);
si_pm4_set_reg(pm4, R_028A10_VGT_OUTPUT_PATH_CNTL, 0x0);
S_028AA8_PRIMGROUP_SIZE(63));
si_pm4_set_reg(pm4, R_028AB4_VGT_REUSE_OFF, 0x00000000);
si_pm4_set_reg(pm4, R_028AB8_VGT_VTX_CNT_EN, 0x0);
- si_pm4_set_reg(pm4, R_008A14_PA_CL_ENHANCE, (3 << 1) | 1);
+ si_pm4_set_reg(pm4, R_008A14_PA_CL_ENHANCE, S_008A14_NUM_CLIP_SEQ(3) |
+ S_008A14_CLIP_VTX_REORDER_ENA(1));
si_pm4_set_reg(pm4, R_028B54_VGT_SHADER_STAGES_EN, 0);
si_pm4_set_reg(pm4, R_028BD4_PA_SC_CENTROID_PRIORITY_0, 0x76543210);
si_pm4_set_reg(pm4, R_028804_DB_EQAA, 0x110000);
+ si_pm4_set_reg(pm4, R_02882C_PA_SU_PRIM_FILTER_CNTL, 0);
+
+ switch (rctx->screen->family) {
+ case CHIP_TAHITI:
+ case CHIP_PITCAIRN:
+ si_pm4_set_reg(pm4, R_028350_PA_SC_RASTER_CONFIG, 0x2a00126a);
+ break;
+ case CHIP_VERDE:
+ si_pm4_set_reg(pm4, R_028350_PA_SC_RASTER_CONFIG, 0x0000124a);
+ break;
+ case CHIP_OLAND:
+ si_pm4_set_reg(pm4, R_028350_PA_SC_RASTER_CONFIG, 0x00000082);
+ break;
+ case CHIP_HAINAN:
+ si_pm4_set_reg(pm4, R_028350_PA_SC_RASTER_CONFIG, 0x00000000);
+ break;
+ default:
+ si_pm4_set_reg(pm4, R_028350_PA_SC_RASTER_CONFIG, 0x00000000);
+ break;
+ }
+
si_pm4_set_state(rctx, init, pm4);
}