From: Marek Olšák Date: Thu, 2 Aug 2012 20:31:22 +0000 (+0200) Subject: r600g: implement MSAA for r700 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8698a3b85dd89c5d2fa473e7942b7dc8d25f3c8f;p=mesa.git r600g: implement MSAA for r700 Reviewed-by: Jerome Glisse --- diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c index d0b453ac7c0..7b7b6b1ffac 100644 --- a/src/gallium/drivers/r600/r600_hw_context.c +++ b/src/gallium/drivers/r600/r600_hw_context.c @@ -240,6 +240,10 @@ int r600_context_add_block(struct r600_context *ctx, const struct r600_reg *reg, /* R600/R700 configuration */ static const struct r600_reg r600_config_reg_list[] = { {R_008958_VGT_PRIMITIVE_TYPE, 0, 0}, + {R_008B40_PA_SC_AA_SAMPLE_LOCS_2S, 0, 0}, + {R_008B44_PA_SC_AA_SAMPLE_LOCS_4S, 0, 0}, + {R_008B48_PA_SC_AA_SAMPLE_LOCS_8S_WD0, 0, 0}, + {R_008B4C_PA_SC_AA_SAMPLE_LOCS_8S_WD1, 0, 0}, {R_008C04_SQ_GPR_RESOURCE_MGMT_1, REG_FLAG_ENABLE_ALWAYS | REG_FLAG_FLUSH_CHANGE, 0}, }; @@ -260,6 +264,7 @@ static const struct r600_reg r600_context_reg_list[] = { {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_0280C0_CB_COLOR0_TILE, REG_FLAG_NEED_BO, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, + {R_028100_CB_COLOR0_MASK, 0, 0}, {R_028044_CB_COLOR1_BASE, REG_FLAG_NEED_BO|REG_FLAG_RV6XX_SBU, SURFACE_BASE_UPDATE_COLOR(1)}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_0280A4_CB_COLOR1_INFO, REG_FLAG_NEED_BO, 0}, @@ -269,6 +274,7 @@ static const struct r600_reg r600_context_reg_list[] = { {R_0280E4_CB_COLOR1_FRAG, REG_FLAG_NEED_BO, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_0280C4_CB_COLOR1_TILE, REG_FLAG_NEED_BO, 0}, + {R_028104_CB_COLOR1_MASK, 0, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_028048_CB_COLOR2_BASE, REG_FLAG_NEED_BO|REG_FLAG_RV6XX_SBU, SURFACE_BASE_UPDATE_COLOR(2)}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, @@ -279,6 +285,7 @@ static const struct r600_reg r600_context_reg_list[] = { {R_0280E8_CB_COLOR2_FRAG, REG_FLAG_NEED_BO, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_0280C8_CB_COLOR2_TILE, REG_FLAG_NEED_BO, 0}, + {R_028108_CB_COLOR2_MASK, 0, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_02804C_CB_COLOR3_BASE, REG_FLAG_NEED_BO|REG_FLAG_RV6XX_SBU, SURFACE_BASE_UPDATE_COLOR(3)}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, @@ -289,6 +296,7 @@ static const struct r600_reg r600_context_reg_list[] = { {R_0280EC_CB_COLOR3_FRAG, REG_FLAG_NEED_BO, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_0280CC_CB_COLOR3_TILE, REG_FLAG_NEED_BO, 0}, + {R_02810C_CB_COLOR3_MASK, 0, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_028050_CB_COLOR4_BASE, REG_FLAG_NEED_BO|REG_FLAG_RV6XX_SBU, SURFACE_BASE_UPDATE_COLOR(4)}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, @@ -299,6 +307,7 @@ static const struct r600_reg r600_context_reg_list[] = { {R_0280F0_CB_COLOR4_FRAG, REG_FLAG_NEED_BO, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_0280D0_CB_COLOR4_TILE, REG_FLAG_NEED_BO, 0}, + {R_028110_CB_COLOR4_MASK, 0, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_028054_CB_COLOR5_BASE, REG_FLAG_NEED_BO|REG_FLAG_RV6XX_SBU, SURFACE_BASE_UPDATE_COLOR(5)}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, @@ -309,6 +318,7 @@ static const struct r600_reg r600_context_reg_list[] = { {R_0280F4_CB_COLOR5_FRAG, REG_FLAG_NEED_BO, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_0280D4_CB_COLOR5_TILE, REG_FLAG_NEED_BO, 0}, + {R_028114_CB_COLOR5_MASK, 0, 0}, {R_028058_CB_COLOR6_BASE, REG_FLAG_NEED_BO|REG_FLAG_RV6XX_SBU, SURFACE_BASE_UPDATE_COLOR(6)}, {R_0280B8_CB_COLOR6_INFO, REG_FLAG_NEED_BO, 0}, {R_028078_CB_COLOR6_SIZE, 0, 0}, @@ -317,6 +327,7 @@ static const struct r600_reg r600_context_reg_list[] = { {R_0280F8_CB_COLOR6_FRAG, REG_FLAG_NEED_BO, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_0280D8_CB_COLOR6_TILE, REG_FLAG_NEED_BO, 0}, + {R_028118_CB_COLOR6_MASK, 0, 0}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, {R_02805C_CB_COLOR7_BASE, REG_FLAG_NEED_BO|REG_FLAG_RV6XX_SBU, SURFACE_BASE_UPDATE_COLOR(7)}, {GROUP_FORCE_NEW_BLOCK, 0, 0}, @@ -325,6 +336,7 @@ static const struct r600_reg r600_context_reg_list[] = { {R_02809C_CB_COLOR7_VIEW, 0, 0}, {R_0280FC_CB_COLOR7_FRAG, REG_FLAG_NEED_BO, 0}, {R_0280DC_CB_COLOR7_TILE, REG_FLAG_NEED_BO, 0}, + {R_02811C_CB_COLOR7_MASK, 0, 0}, {R_028120_CB_CLEAR_RED, 0, 0}, {R_028124_CB_CLEAR_GREEN, 0, 0}, {R_028128_CB_CLEAR_BLUE, 0, 0}, @@ -377,6 +389,8 @@ static const struct r600_reg r600_context_reg_list[] = { {R_028A04_PA_SU_POINT_MINMAX, 0, 0}, {R_028A08_PA_SU_LINE_CNTL, 0, 0}, {R_028A0C_PA_SC_LINE_STIPPLE, 0, 0}, + {R_028C00_PA_SC_LINE_CNTL, 0, 0}, + {R_028C04_PA_SC_AA_CONFIG, 0, 0}, {R_028C08_PA_SU_VTX_CNTL, 0, 0}, {R_028DF8_PA_SU_POLY_OFFSET_DB_FMT_CNTL, 0, 0}, {R_028DFC_PA_SU_POLY_OFFSET_CLAMP, 0, 0}, @@ -504,6 +518,8 @@ static const struct r600_reg r600_context_reg_list[] = { {R_028408_VGT_INDX_OFFSET, 0, 0}, {R_02840C_VGT_MULTI_PRIM_IB_RESET_INDX, 0, 0}, {R_028A94_VGT_MULTI_PRIM_IB_RESET_EN, 0, 0}, + {R_028C1C_PA_SC_AA_SAMPLE_LOCS_MCTX, 0, 0}, + {R_028C20_PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX, 0, 0}, }; static int r600_loop_const_init(struct r600_context *ctx, uint32_t offset) diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 0d489100dfb..34ba80b244f 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -250,6 +250,8 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void if (r600_context_init(rctx)) goto fail; rctx->custom_dsa_flush = r600_create_db_flush_dsa(rctx); + rctx->custom_blend_resolve = r600_create_resolve_blend(rctx); + rctx->custom_blend_decompress = r600_create_decompress_blend(rctx); rctx->has_vertex_cache = !(rctx->family == CHIP_RV610 || rctx->family == CHIP_RV620 || rctx->family == CHIP_RS780 || diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 65725b6da62..074eed432dc 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -550,6 +550,8 @@ void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shad void r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader *shader); void r600_fetch_shader(struct pipe_context *ctx, struct r600_vertex_element *ve); void *r600_create_db_flush_dsa(struct r600_context *rctx); +void *r600_create_resolve_blend(struct r600_context *rctx); +void *r600_create_decompress_blend(struct r600_context *rctx); void r600_polygon_offset_update(struct r600_context *rctx); void r600_adjust_gprs(struct r600_context *rctx); boolean r600_is_format_supported(struct pipe_screen *screen, diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h index dbb958e6925..da60d373c80 100644 --- a/src/gallium/drivers/r600/r600_resource.h +++ b/src/gallium/drivers/r600/r600_resource.h @@ -87,6 +87,7 @@ struct r600_surface { unsigned cb_color_fmask_slice; /* EG only */ unsigned cb_color_cmask; /* CB_COLORn_CMASK (EG) or CB_COLORn_TILE (r600) */ unsigned cb_color_cmask_slice; /* EG only */ + unsigned cb_color_mask; /* R600 only */ /* DB registers. */ unsigned db_depth_info; /* DB_Z_INFO (EG) or DB_DEPTH_INFO (r600) */ diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index cf7fa01ffdf..5b83f51f7c6 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -99,7 +99,7 @@ static uint32_t r600_translate_blend_factor(int blend_fact) return 0; } -static unsigned r600_tex_dim(unsigned dim) +static unsigned r600_tex_dim(unsigned dim, unsigned nr_samples) { switch (dim) { default: @@ -109,9 +109,11 @@ static unsigned r600_tex_dim(unsigned dim) return V_038000_SQ_TEX_DIM_1D_ARRAY; case PIPE_TEXTURE_2D: case PIPE_TEXTURE_RECT: - return V_038000_SQ_TEX_DIM_2D; + return nr_samples > 1 ? V_038000_SQ_TEX_DIM_2D_MSAA : + V_038000_SQ_TEX_DIM_2D; case PIPE_TEXTURE_2D_ARRAY: - return V_038000_SQ_TEX_DIM_2D_ARRAY; + return nr_samples > 1 ? V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA : + V_038000_SQ_TEX_DIM_2D_ARRAY; case PIPE_TEXTURE_3D: return V_038000_SQ_TEX_DIM_3D; case PIPE_TEXTURE_CUBE: @@ -570,6 +572,7 @@ boolean r600_is_format_supported(struct pipe_screen *screen, unsigned sample_count, unsigned usage) { + struct r600_screen *rscreen = (struct r600_screen*)screen; unsigned retval = 0; if (target >= PIPE_MAX_TEXTURE_TYPES) { @@ -580,9 +583,30 @@ boolean r600_is_format_supported(struct pipe_screen *screen, if (!util_format_is_supported(format, usage)) return FALSE; - /* Multisample */ - if (sample_count > 1) - return FALSE; + if (sample_count > 1) { + if (rscreen->info.drm_minor < 21) + return FALSE; + if (rscreen->chip_class != R700) + return FALSE; + + switch (sample_count) { + case 2: + case 4: + case 8: + break; + default: + return FALSE; + } + + /* require render-target support for multisample resources */ + if (util_format_is_depth_or_stencil(format)) { + usage |= PIPE_BIND_DEPTH_STENCIL; + } else if (util_format_is_pure_integer(format)) { + return FALSE; + } else { + usage |= PIPE_BIND_RENDER_TARGET; + } + } if ((usage & PIPE_BIND_SAMPLER_VIEW) && r600_is_sampler_format_supported(screen, format)) { @@ -669,13 +693,14 @@ void r600_polygon_offset_update(struct r600_context *rctx) } } -static void *r600_create_blend_state(struct pipe_context *ctx, - const struct pipe_blend_state *state) +static void *r600_create_blend_state_mode(struct pipe_context *ctx, + const struct pipe_blend_state *state, + int mode) { struct r600_context *rctx = (struct r600_context *)ctx; struct r600_pipe_blend *blend = CALLOC_STRUCT(r600_pipe_blend); struct r600_pipe_state *rstate; - uint32_t color_control = 0, target_mask; + uint32_t color_control = 0, target_mask = 0; if (blend == NULL) { return NULL; @@ -684,11 +709,10 @@ static void *r600_create_blend_state(struct pipe_context *ctx, rstate->id = R600_PIPE_STATE_BLEND; - target_mask = 0; - /* R600 does not support per-MRT blends */ if (rctx->family > CHIP_R600) color_control |= S_028808_PER_MRT_BLEND(1); + if (state->logicop_enable) { color_control |= (state->logicop_func << 16) | (state->logicop_func << 20); } else { @@ -712,7 +736,7 @@ static void *r600_create_blend_state(struct pipe_context *ctx, } if (target_mask) - color_control |= S_028808_SPECIAL_OP(V_028808_NORMAL); + color_control |= S_028808_SPECIAL_OP(mode); else color_control |= S_028808_SPECIAL_OP(V_028808_DISABLE); @@ -765,6 +789,13 @@ static void *r600_create_blend_state(struct pipe_context *ctx, return rstate; } + +static void *r600_create_blend_state(struct pipe_context *ctx, + const struct pipe_blend_state *state) +{ + return r600_create_blend_state_mode(ctx, state, V_028808_SPECIAL_NORMAL); +} + static void *r600_create_dsa_state(struct pipe_context *ctx, const struct pipe_depth_stencil_alpha_state *state) { @@ -897,12 +928,14 @@ static void *r600_create_rs_state(struct pipe_context *ctx, if (rctx->chip_class >= R700) { sc_mode_cntl = + S_028A4C_MSAA_ENABLE(state->multisample) | S_028A4C_FORCE_EOV_CNTDWN_ENABLE(1) | S_028A4C_FORCE_EOV_REZ_ENABLE(1) | S_028A4C_R700_ZMM_LINE_OFFSET(1) | S_028A4C_R700_VPORT_SCISSOR_ENABLE(state->scissor); } else { sc_mode_cntl = + S_028A4C_MSAA_ENABLE(state->multisample) | S_028A4C_WALK_ALIGN8_PRIM_FITS_ST(1) | S_028A4C_FORCE_EOV_CNTDWN_ENABLE(1); rs->scissor_enable = state->scissor; @@ -1051,7 +1084,7 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c } view->tex_resource = &tmp->resource; - view->tex_resource_words[0] = (S_038000_DIM(r600_tex_dim(texture->target)) | + view->tex_resource_words[0] = (S_038000_DIM(r600_tex_dim(texture->target, texture->nr_samples)) | S_038000_TILE_MODE(array_mode) | S_038000_TILE_TYPE(tile_type) | S_038000_PITCH((pitch / 8) - 1) | @@ -1070,9 +1103,14 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c S_038010_REQUEST_SIZE(1) | S_038010_ENDIAN_SWAP(endian) | S_038010_BASE_LEVEL(0)); - view->tex_resource_words[5] = (S_038014_LAST_LEVEL(last_level) | - S_038014_BASE_ARRAY(state->u.tex.first_layer) | + view->tex_resource_words[5] = (S_038014_BASE_ARRAY(state->u.tex.first_layer) | S_038014_LAST_ARRAY(state->u.tex.last_layer)); + if (texture->nr_samples > 1) { + /* LAST_LEVEL holds log2(nr_samples) for multisample textures */ + view->tex_resource_words[5] |= S_038014_LAST_LEVEL(util_logbase2(texture->nr_samples)); + } else { + view->tex_resource_words[5] |= S_038014_LAST_LEVEL(last_level); + } view->tex_resource_words[6] = (S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_TEXTURE) | S_038018_MAX_ANISO(4 /* max 16 samples */)); return &view->base; @@ -1329,9 +1367,25 @@ static void r600_init_color_surface(struct r600_context *rctx, } surf->cb_color_base = offset >> 8; - surf->cb_color_info = color_info; surf->cb_color_size = S_028060_PITCH_TILE_MAX(pitch) | S_028060_SLICE_TILE_MAX(slice); + surf->cb_color_fmask = surf->cb_color_base; + surf->cb_color_cmask = surf->cb_color_base; + + if (rtex->cmask_size) { + surf->cb_color_cmask = rtex->cmask_offset >> 8; + surf->cb_color_mask |= S_028100_CMASK_BLOCK_MAX(rtex->cmask_slice_tile_max); + + if (rtex->fmask_size) { + color_info |= S_0280A0_TILE_MODE(V_0280A0_FRAG_ENABLE); + surf->cb_color_fmask = rtex->fmask_offset >> 8; + surf->cb_color_mask |= S_028100_FMASK_TILE_MAX(slice); + } else { /* cmask only */ + color_info |= S_0280A0_TILE_MODE(V_0280A0_CLEAR_ENABLE); + } + } + surf->cb_color_info = color_info; + if (rtex->surface.level[level].mode < RADEON_SURF_MODE_1D) { surf->cb_color_view = 0; } else { @@ -1380,6 +1434,72 @@ static void r600_init_depth_surface(struct r600_context *rctx, surf->depth_initialized = true; } +#define FILL_SREG(s0x, s0y, s1x, s1y, s2x, s2y, s3x, s3y) \ + (((s0x) & 0xf) | (((s0y) & 0xf) << 4) | \ + (((s1x) & 0xf) << 8) | (((s1y) & 0xf) << 12) | \ + (((s2x) & 0xf) << 16) | (((s2y) & 0xf) << 20) | \ + (((s3x) & 0xf) << 24) | (((s3y) & 0xf) << 28)) + +static uint32_t r600_set_ms_pos(struct pipe_context *ctx, struct r600_pipe_state *rstate, int nsample) +{ + static uint32_t sample_locs_2x[] = { + FILL_SREG(-4, 4, 4, -4, -4, 4, 4, -4), + FILL_SREG(-4, 4, 4, -4, -4, 4, 4, -4), + }; + static unsigned max_dist_2x = 4; + static uint32_t sample_locs_4x[] = { + FILL_SREG(-2, -2, 2, 2, -6, 6, 6, -6), + FILL_SREG(-2, -2, 2, 2, -6, 6, 6, -6), + }; + static unsigned max_dist_4x = 6; + static uint32_t sample_locs_8x[] = { + FILL_SREG(-2, -5, 3, -4, -1, 5, -6, -2), + FILL_SREG( 6, 0, 0, 0, -5, 3, 4, 4), + }; + static unsigned max_dist_8x = 8; + struct r600_context *rctx = (struct r600_context *)ctx; + + if (rctx->family == CHIP_R600) { + switch (nsample) { + case 0: + case 1: + return 0; + case 2: + r600_pipe_state_add_reg(rstate, R_008B40_PA_SC_AA_SAMPLE_LOCS_2S, sample_locs_2x[0]); + return max_dist_2x; + case 4: + r600_pipe_state_add_reg(rstate, R_008B44_PA_SC_AA_SAMPLE_LOCS_4S, sample_locs_4x[0]); + return max_dist_4x; + case 8: + r600_pipe_state_add_reg(rstate, R_008B48_PA_SC_AA_SAMPLE_LOCS_8S_WD0, sample_locs_8x[0]); + r600_pipe_state_add_reg(rstate, R_008B4C_PA_SC_AA_SAMPLE_LOCS_8S_WD1, sample_locs_8x[1]); + return max_dist_8x; + } + } else { + switch (nsample) { + case 0: + case 1: + r600_pipe_state_add_reg(rstate, R_028C1C_PA_SC_AA_SAMPLE_LOCS_MCTX, 0); + r600_pipe_state_add_reg(rstate, R_028C20_PA_SC_AA_SAMPLE_LOCS_8D_WD1_MCTX, 0); + return 0; + case 2: + r600_pipe_state_add_reg(rstate, R_028C1C_PA_SC_AA_SAMPLE_LOCS_MCTX, sample_locs_2x[0]); + r600_pipe_state_add_reg(rstate, R_028C20_PA_SC_AA_SAMPLE_LOCS_8D_WD1_MCTX, sample_locs_2x[1]); + return max_dist_2x; + case 4: + r600_pipe_state_add_reg(rstate, R_028C1C_PA_SC_AA_SAMPLE_LOCS_MCTX, sample_locs_4x[0]); + r600_pipe_state_add_reg(rstate, R_028C20_PA_SC_AA_SAMPLE_LOCS_8D_WD1_MCTX, sample_locs_4x[1]); + return max_dist_4x; + case 8: + r600_pipe_state_add_reg(rstate, R_028C1C_PA_SC_AA_SAMPLE_LOCS_MCTX, sample_locs_8x[0]); + r600_pipe_state_add_reg(rstate, R_028C20_PA_SC_AA_SAMPLE_LOCS_8D_WD1_MCTX, sample_locs_8x[1]); + return max_dist_8x; + } + } + R600_ERR("Invalid nr_samples %i\n", nsample); + return 0; +} + static void r600_set_framebuffer_state(struct pipe_context *ctx, const struct pipe_framebuffer_state *state) { @@ -1387,7 +1507,8 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx, struct r600_pipe_state *rstate = CALLOC_STRUCT(r600_pipe_state); struct r600_surface *surf; struct r600_resource *res; - uint32_t tl, br, i; + struct r600_texture *rtex; + uint32_t tl, br, i, nr_samples, max_dist; if (rstate == NULL) return; @@ -1399,15 +1520,17 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx, util_copy_framebuffer_state(&rctx->framebuffer, state); - /* build states */ + /* Colorbuffers. */ rctx->export_16bpc = true; rctx->nr_cbufs = state->nr_cbufs; rctx->cb0_is_integer = state->nr_cbufs && util_format_is_pure_integer(state->cbufs[0]->format); + rctx->compressed_cb_mask = 0; for (i = 0; i < state->nr_cbufs; i++) { surf = (struct r600_surface*)state->cbufs[i]; res = (struct r600_resource*)surf->base.texture; + rtex = (struct r600_texture*)res; if (!surf->color_initialized) { r600_init_color_surface(rctx, surf); @@ -1429,6 +1552,12 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx, surf->cb_color_fmask, res, RADEON_USAGE_READWRITE); r600_pipe_state_add_reg_bo(rstate, R_0280C0_CB_COLOR0_TILE + i * 4, surf->cb_color_cmask, res, RADEON_USAGE_READWRITE); + r600_pipe_state_add_reg(rstate, R_028100_CB_COLOR0_MASK + i * 4, + surf->cb_color_mask); + + if (rtex->fmask_size && rtex->cmask_size) { + rctx->compressed_cb_mask |= 1 << i; + } } /* set CB_COLOR1_INFO for possible dual-src blending */ if (i == 1) { @@ -1450,6 +1579,7 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx, } } + /* ZS buffer. */ if (state->zsbuf) { surf = (struct r600_surface*)state->zsbuf; res = (struct r600_resource*)surf->base.texture; @@ -1467,6 +1597,7 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx, r600_pipe_state_add_reg(rstate, R_028D34_DB_PREFETCH_LIMIT, surf->db_prefetch_limit); } + /* Framebuffer dimensions. */ tl = S_028240_TL_X(0) | S_028240_TL_Y(0) | S_028240_WINDOW_OFFSET_DISABLE(1); br = S_028244_BR_X(state->width) | S_028244_BR_Y(state->height); @@ -1475,15 +1606,41 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx, r600_pipe_state_add_reg(rstate, R_028208_PA_SC_WINDOW_SCISSOR_BR, br); - /* Always enable the first colorbuffer in CB_SHADER_CONTROL. This - * will assure that the alpha-test will work even if there is - * no colorbuffer bound. */ - r600_pipe_state_add_reg(rstate, R_0287A0_CB_SHADER_CONTROL, - (1ull << MAX2(state->nr_cbufs, 1)) - 1); + /* If we're doing MSAA resolve... */ + if (state->nr_cbufs == 2 && + state->cbufs[0]->texture->nr_samples > 1 && + state->cbufs[1]->texture->nr_samples <= 1) { + r600_pipe_state_add_reg(rstate, R_0287A0_CB_SHADER_CONTROL, 1); + } else { + /* Always enable the first colorbuffer in CB_SHADER_CONTROL. This + * will assure that the alpha-test will work even if there is + * no colorbuffer bound. */ + r600_pipe_state_add_reg(rstate, R_0287A0_CB_SHADER_CONTROL, + (1ull << MAX2(state->nr_cbufs, 1)) - 1); + } + + /* Multisampling */ + if (state->nr_cbufs) + nr_samples = state->cbufs[0]->texture->nr_samples; + else if (state->zsbuf) + nr_samples = state->zsbuf->texture->nr_samples; + else + nr_samples = 0; - if (state->nr_cbufs == 0 && rctx->alphatest_state.bypass) { - rctx->alphatest_state.bypass = false; - r600_atom_dirty(rctx, &rctx->alphatest_state.atom); + max_dist = r600_set_ms_pos(ctx, rstate, nr_samples); + + if (nr_samples > 1) { + unsigned log_samples = util_logbase2(nr_samples); + + r600_pipe_state_add_reg(rstate, R_028C00_PA_SC_LINE_CNTL, + S_028C00_LAST_PIXEL(1) | + S_028C00_EXPAND_LINE_WIDTH(1)); + r600_pipe_state_add_reg(rstate, R_028C04_PA_SC_AA_CONFIG, + S_028C04_MSAA_NUM_SAMPLES(log_samples) | + S_028C04_MAX_SAMPLE_DIST(max_dist)); + } else { + r600_pipe_state_add_reg(rstate, R_028C00_PA_SC_LINE_CNTL, S_028C00_LAST_PIXEL(1)); + r600_pipe_state_add_reg(rstate, R_028C04_PA_SC_AA_CONFIG, 0); } free(rctx->states[R600_PIPE_STATE_FRAMEBUFFER]); @@ -1498,6 +1655,11 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx, rctx->cb_misc_state.nr_cbufs = state->nr_cbufs; r600_atom_dirty(rctx, &rctx->cb_misc_state.atom); } + + if (state->nr_cbufs == 0 && rctx->alphatest_state.bypass) { + rctx->alphatest_state.bypass = false; + r600_atom_dirty(rctx, &rctx->alphatest_state.atom); + } } static void r600_emit_cb_misc_state(struct r600_context *rctx, struct r600_atom *atom) @@ -1538,7 +1700,8 @@ static void r600_emit_db_misc_state(struct r600_context *rctx, struct r600_atom db_render_control |= S_028D0C_DEPTH_COPY_ENABLE(a->copy_depth) | S_028D0C_STENCIL_COPY_ENABLE(a->copy_stencil) | - S_028D0C_COPY_CENTROID(1); + S_028D0C_COPY_CENTROID(1) | + S_028D0C_COPY_SAMPLE(a->copy_sample); } r600_write_context_reg_seq(cs, R_028D0C_DB_RENDER_CONTROL, 2); @@ -1888,7 +2051,6 @@ void r600_init_atom_start_cs(struct r600_context *rctx) enum radeon_family family; struct r600_command_buffer *cb = &rctx->start_cs_cmd; uint32_t tmp; - unsigned i; r600_init_command_buffer(cb, 256, EMIT_EARLY); @@ -2141,17 +2303,11 @@ void r600_init_atom_start_cs(struct r600_context *rctx) r600_store_context_reg(cb, R_028820_PA_CL_NANINF_CNTL, 0); r600_store_context_reg(cb, R_028A48_PA_SC_MPASS_PS_CNTL, 0); - r600_store_context_reg_seq(cb, R_028C00_PA_SC_LINE_CNTL, 2); - r600_store_value(cb, 0x400); /* R_028C00_PA_SC_LINE_CNTL */ - r600_store_value(cb, 0); /* R_028C04_PA_SC_AA_CONFIG */ - - r600_store_context_reg_seq(cb, R_028C0C_PA_CL_GB_VERT_CLIP_ADJ, 6); + r600_store_context_reg_seq(cb, R_028C0C_PA_CL_GB_VERT_CLIP_ADJ, 4); r600_store_value(cb, 0x3F800000); /* R_028C0C_PA_CL_GB_VERT_CLIP_ADJ */ r600_store_value(cb, 0x3F800000); /* R_028C10_PA_CL_GB_VERT_DISC_ADJ */ r600_store_value(cb, 0x3F800000); /* R_028C14_PA_CL_GB_HORZ_CLIP_ADJ */ r600_store_value(cb, 0x3F800000); /* R_028C18_PA_CL_GB_HORZ_DISC_ADJ */ - r600_store_value(cb, 0); /* R_028C1C_PA_SC_AA_SAMPLE_LOCS_MCTX */ - r600_store_value(cb, 0); /* R_028C20_PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX */ r600_store_context_reg_seq(cb, R_0282D0_PA_SC_VPORT_ZMIN_0, 2); r600_store_value(cb, 0); /* R_0282D0_PA_SC_VPORT_ZMIN_0 */ @@ -2159,11 +2315,6 @@ void r600_init_atom_start_cs(struct r600_context *rctx) r600_store_context_reg(cb, R_028818_PA_CL_VTE_CNTL, 0x43F); - r600_store_context_reg_seq(cb, R_028100_CB_COLOR0_MASK, 8); - for (i = 0; i < 8; i++) { - r600_store_value(cb, 0); - } - r600_store_context_reg(cb, R_028200_PA_SC_WINDOW_OFFSET, 0); r600_store_context_reg(cb, R_02820C_PA_SC_CLIPRECT_RULE, 0xFFFF); @@ -2386,6 +2537,30 @@ void r600_fetch_shader(struct pipe_context *ctx, ve->fetch_shader, RADEON_USAGE_READ); } +void *r600_create_resolve_blend(struct r600_context *rctx) +{ + struct pipe_blend_state blend; + struct r600_pipe_state *rstate; + + memset(&blend, 0, sizeof(blend)); + blend.independent_blend_enable = true; + blend.rt[0].colormask = 0xf; + rstate = r600_create_blend_state_mode(&rctx->context, &blend, V_028808_SPECIAL_RESOLVE_BOX); + return rstate; +} + +void *r600_create_decompress_blend(struct r600_context *rctx) +{ + struct pipe_blend_state blend; + struct r600_pipe_state *rstate; + + memset(&blend, 0, sizeof(blend)); + blend.independent_blend_enable = true; + blend.rt[0].colormask = 0xf; + rstate = r600_create_blend_state_mode(&rctx->context, &blend, V_028808_SPECIAL_EXPAND_SAMPLES); + return rstate; +} + void *r600_create_db_flush_dsa(struct r600_context *rctx) { struct pipe_depth_stencil_alpha_state dsa; diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index acb77d5c4dd..0b2fdda53f7 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -282,6 +282,11 @@ static void r600_texture_allocate_fmask(struct r600_screen *rscreen, return; } + /* R600-R700 errata? Anyway, this fixes colorbuffer corruption. */ + if (rscreen->chip_class <= R700) { + fmask.bpe *= 2; + } + if (rscreen->chip_class >= EVERGREEN) { fmask.bankh = nr_samples <= 4 ? 4 : 1; } @@ -379,8 +384,8 @@ r600_texture_create_object(struct pipe_screen *screen, } if (base->nr_samples > 1 && !rtex->is_depth && alloc_bo) { - r600_texture_allocate_fmask(rscreen, rtex); r600_texture_allocate_cmask(rscreen, rtex); + r600_texture_allocate_fmask(rscreen, rtex); } if (!rtex->is_depth && base->nr_samples > 1 && diff --git a/src/gallium/drivers/r600/r600d.h b/src/gallium/drivers/r600/r600d.h index e99ed1dadd7..a6da0a2fbad 100644 --- a/src/gallium/drivers/r600/r600d.h +++ b/src/gallium/drivers/r600/r600d.h @@ -164,6 +164,10 @@ #define R_008964_VGT_STRMOUT_BUFFER_FILLED_SIZE_1 0x008964 /* read-only */ #define R_008968_VGT_STRMOUT_BUFFER_FILLED_SIZE_2 0x008968 /* read-only */ #define R_00896C_VGT_STRMOUT_BUFFER_FILLED_SIZE_3 0x00896C /* read-only */ +#define R_008B40_PA_SC_AA_SAMPLE_LOCS_2S 0x008B40 +#define R_008B44_PA_SC_AA_SAMPLE_LOCS_4S 0x008B44 +#define R_008B48_PA_SC_AA_SAMPLE_LOCS_8S_WD0 0x008B48 +#define R_008B4C_PA_SC_AA_SAMPLE_LOCS_8S_WD1 0x008B4C #define R_008C00_SQ_CONFIG 0x00008C00 #define S_008C00_VC_ENABLE(x) (((x) & 0x1) << 0) #define G_008C00_VC_ENABLE(x) (((x) >> 0) & 0x1) @@ -303,6 +307,9 @@ #define V_0280A0_SWAP_STD_REV 0x00000002 #define V_0280A0_SWAP_ALT_REV 0x00000003 #define S_0280A0_TILE_MODE(x) (((x) & 0x3) << 18) +#define V_0280A0_TILE_DISABLE 0 +#define V_0280A0_CLEAR_ENABLE 1 +#define V_0280A0_FRAG_ENABLE 2 #define G_0280A0_TILE_MODE(x) (((x) >> 18) & 0x3) #define C_0280A0_TILE_MODE 0xFFF3FFFF #define S_0280A0_BLEND_CLAMP(x) (((x) & 0x1) << 20) @@ -422,6 +429,14 @@ #define V_028808_DISABLE 1 #define G_028808_SPECIAL_OP(x) (((x) >> 4) & 0x7) #define C_028808_SPECIAL_OP 0xFFFFFF8F +#define V_028808_SPECIAL_NORMAL 0x00 +#define V_028808_SPECIAL_DISABLE 0x01 +#define V_028808_SPECIAL_FAST_CLEAR 0x02 +#define V_028808_SPECIAL_FORCE_CLEAR 0x03 +#define V_028808_SPECIAL_EXPAND_COLOR 0x04 +#define V_028808_SPECIAL_EXPAND_TEXTURE 0x05 +#define V_028808_SPECIAL_EXPAND_SAMPLES 0x06 +#define V_028808_SPECIAL_RESOLVE_BOX 0x07 #define S_028808_PER_MRT_BLEND(x) (((x) & 0x1) << 7) #define G_028808_PER_MRT_BLEND(x) (((x) >> 7) & 0x1) #define C_028808_PER_MRT_BLEND 0xFFFFFF7F @@ -1482,6 +1497,8 @@ #define R_0280B4_CB_COLOR5_INFO 0x0280B4 #define R_0280B8_CB_COLOR6_INFO 0x0280B8 #define R_0280BC_CB_COLOR7_INFO 0x0280BC +#define R_028C1C_PA_SC_AA_SAMPLE_LOCS_MCTX 0x028C1C +#define R_028C20_PA_SC_AA_SAMPLE_LOCS_8D_WD1_MCTX 0x028C20 #define R_028C30_CB_CLRCMP_CONTROL 0x028C30 #define S_028C30_CLRCMP_FCN_SRC(x) (((x) & 0x7) << 0) #define G_028C30_CLRCMP_FCN_SRC(x) (((x) >> 0) & 0x7) @@ -2166,6 +2183,9 @@ #define R_0286D4_SPI_INTERP_CONTROL_0 0x0286D4 #define R_028A48_PA_SC_MPASS_PS_CNTL 0x028A48 #define R_028C00_PA_SC_LINE_CNTL 0x028C00 +#define S_028C00_EXPAND_LINE_WIDTH(x) (((x) & 0x1) << 9) +#define G_028C00_EXPAND_LINE_WIDTH(x) (((x) >> 9) & 0x1) +#define C_028C00_EXPAND_LINE_WIDTH 0xFFFFFDFF #define S_028C00_LAST_PIXEL(x) (((x) & 0x1) << 10) #define G_028C00_LAST_PIXEL(x) (((x) >> 10) & 0x1) #define C_028C00_LAST_PIXEL 0xFFFFFBFF