summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2013-01-12 03:29:40 +0100
committerMarek Olšák <maraeo@gmail.com>2013-01-15 21:48:58 +0100
commitca2c28859eca83f8fbf1f43616f5ef861e95e8d6 (patch)
treece839793a720913a19cf69f1e6734fdab3e016ab
parent1dfe8eead95613a7db62dd17d3da56884b5a887e (diff)
r300g: implement MSAA compression and fast MSAA color clear
These are optimizations which make MSAA a lot faster. The MSAA work is complete with this commit. (except for enablement of AA optimizations for RGBA16F, for which a patch is ready and waiting until the kernel CS checker fix lands) MSAA can't be made any faster as far as hw programming is concerned. The catch is only one process and one colorbuffer can use the optimizations at a time. There usually is only one MSAA colorbuffer, so it shouldn't be an issue. Also, there is a limit on the size of MSAA colorbuffer resolution in terms of megapixels. If the limit is surpassed, the AA optimizations are disabled. The limit is: - 1 Mpix on low-end and some mid-level chipsets (1024x768 and 1280x720) - 2 Mpix on some mid-level chipsets (1600x1200 and 1920x1080) - 3 or 4 Mpix on high-end chipsets (2048x1536 or 2560x1600, respectively) It corresponds to the number of raster pipes (= GB pipes) available, each pipe can hold 1 Mpix of AA compression data. If it's enabled, the driver prints to stdout: radeon: Acquired access to AA optimizations.
-rw-r--r--src/gallium/drivers/r300/r300_blit.c68
-rw-r--r--src/gallium/drivers/r300/r300_chipset.h1
-rw-r--r--src/gallium/drivers/r300/r300_context.c4
-rw-r--r--src/gallium/drivers/r300/r300_context.h17
-rw-r--r--src/gallium/drivers/r300/r300_debug.c1
-rw-r--r--src/gallium/drivers/r300/r300_emit.c37
-rw-r--r--src/gallium/drivers/r300/r300_emit.h1
-rw-r--r--src/gallium/drivers/r300/r300_reg.h18
-rw-r--r--src/gallium/drivers/r300/r300_screen.c3
-rw-r--r--src/gallium/drivers/r300/r300_screen.h6
-rw-r--r--src/gallium/drivers/r300/r300_state.c9
-rw-r--r--src/gallium/drivers/r300/r300_texture.c9
-rw-r--r--src/gallium/drivers/r300/r300_texture_desc.c43
13 files changed, 211 insertions, 6 deletions
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index f8d3b1fd1d1..2bb6063846b 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -26,6 +26,7 @@
26#include "r300_reg.h" 26#include "r300_reg.h"
27 27
28#include "util/u_format.h" 28#include "util/u_format.h"
29#include "util/u_half.h"
29#include "util/u_pack_color.h" 30#include "util/u_pack_color.h"
30#include "util/u_surface.h" 31#include "util/u_surface.h"
31 32
@@ -176,6 +177,25 @@ static uint32_t r300_hiz_clear_value(double depth)
176 return r | (r << 8) | (r << 16) | (r << 24); 177 return r | (r << 8) | (r << 16) | (r << 24);
177} 178}
178 179
180static void r300_set_clear_color(struct r300_context *r300,
181 const union pipe_color_union *color)
182{
183 struct pipe_framebuffer_state *fb =
184 (struct pipe_framebuffer_state*)r300->fb_state.state;
185 union util_color uc;
186
187 memset(&uc, 0, sizeof(uc));
188 util_pack_color(color->f, fb->cbufs[0]->format, &uc);
189
190 if (fb->cbufs[0]->format == PIPE_FORMAT_R16G16B16A16_FLOAT) {
191 /* (0,1,2,3) maps to (B,G,R,A) */
192 r300->color_clear_value_gb = uc.h[0] | ((uint32_t)uc.h[1] << 16);
193 r300->color_clear_value_ar = uc.h[2] | ((uint32_t)uc.h[3] << 16);
194 } else {
195 r300->color_clear_value = uc.ui;
196 }
197}
198
179DEBUG_GET_ONCE_BOOL_OPTION(hyperz, "RADEON_HYPERZ", FALSE) 199DEBUG_GET_ONCE_BOOL_OPTION(hyperz, "RADEON_HYPERZ", FALSE)
180 200
181/* Clear currently bound buffers. */ 201/* Clear currently bound buffers. */
@@ -287,8 +307,44 @@ static void r300_clear(struct pipe_context* pipe,
287 } 307 }
288 } 308 }
289 309
310 /* Use fast color clear for an AA colorbuffer.
311 * The CMASK is shared between all colorbuffers, so we use it
312 * if there is only one colorbuffer bound. */
313 if ((buffers & PIPE_CLEAR_COLOR) && fb->nr_cbufs == 1 &&
314 r300_resource(fb->cbufs[0]->texture)->tex.cmask_dwords) {
315 /* Try to obtain the access to the CMASK if we don't have one. */
316 if (!r300->cmask_access) {
317 r300->cmask_access =
318 r300->rws->cs_request_feature(r300->cs,
319 RADEON_FID_R300_CMASK_ACCESS,
320 TRUE);
321 }
322
323 /* Setup the clear. */
324 if (r300->cmask_access) {
325 /* Pair the resource with the CMASK to avoid other resources
326 * accessing it. */
327 if (!r300->screen->cmask_resource) {
328 pipe_mutex_lock(r300->screen->cmask_mutex);
329 /* Double checking (first unlocked, then locked). */
330 if (!r300->screen->cmask_resource) {
331 /* Don't reference this, so that the texture can be
332 * destroyed while set in cmask_resource.
333 * Then in texture_destroy, we set cmask_resource to NULL. */
334 r300->screen->cmask_resource = fb->cbufs[0]->texture;
335 }
336 pipe_mutex_unlock(r300->screen->cmask_mutex);
337 }
338
339 if (r300->screen->cmask_resource == fb->cbufs[0]->texture) {
340 r300_set_clear_color(r300, color);
341 r300_mark_atom_dirty(r300, &r300->cmask_clear);
342 buffers &= ~PIPE_CLEAR_COLOR;
343 }
344 }
345 }
290 /* Enable CBZB clear. */ 346 /* Enable CBZB clear. */
291 if (r300_cbzb_clear_allowed(r300, buffers)) { 347 else if (r300_cbzb_clear_allowed(r300, buffers)) {
292 struct r300_surface *surf = r300_surface(fb->cbufs[0]); 348 struct r300_surface *surf = r300_surface(fb->cbufs[0]);
293 349
294 hyperz->zb_depthclearvalue = 350 hyperz->zb_depthclearvalue =
@@ -312,13 +368,16 @@ static void r300_clear(struct pipe_context* pipe,
312 fb->nr_cbufs, 368 fb->nr_cbufs,
313 buffers, cformat, color, depth, stencil); 369 buffers, cformat, color, depth, stencil);
314 r300_blitter_end(r300); 370 r300_blitter_end(r300);
315 } else if (r300->zmask_clear.dirty || r300->hiz_clear.dirty) { 371 } else if (r300->zmask_clear.dirty ||
372 r300->hiz_clear.dirty ||
373 r300->cmask_clear.dirty) {
316 /* Just clear zmask and hiz now, this does not use the standard draw 374 /* Just clear zmask and hiz now, this does not use the standard draw
317 * procedure. */ 375 * procedure. */
318 /* Calculate zmask_clear and hiz_clear atom sizes. */ 376 /* Calculate zmask_clear and hiz_clear atom sizes. */
319 unsigned dwords = 377 unsigned dwords =
320 (r300->zmask_clear.dirty ? r300->zmask_clear.size : 0) + 378 (r300->zmask_clear.dirty ? r300->zmask_clear.size : 0) +
321 (r300->hiz_clear.dirty ? r300->hiz_clear.size : 0) + 379 (r300->hiz_clear.dirty ? r300->hiz_clear.size : 0) +
380 (r300->cmask_clear.dirty ? r300->cmask_clear.size : 0) +
322 r300_get_num_cs_end_dwords(r300); 381 r300_get_num_cs_end_dwords(r300);
323 382
324 /* Reserve CS space. */ 383 /* Reserve CS space. */
@@ -337,6 +396,11 @@ static void r300_clear(struct pipe_context* pipe,
337 r300->hiz_clear.state); 396 r300->hiz_clear.state);
338 r300->hiz_clear.dirty = FALSE; 397 r300->hiz_clear.dirty = FALSE;
339 } 398 }
399 if (r300->cmask_clear.dirty) {
400 r300_emit_cmask_clear(r300, r300->cmask_clear.size,
401 r300->cmask_clear.state);
402 r300->cmask_clear.dirty = FALSE;
403 }
340 } else { 404 } else {
341 assert(0); 405 assert(0);
342 } 406 }
diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h
index f8b5d4e3d3e..996491e9431 100644
--- a/src/gallium/drivers/r300/r300_chipset.h
+++ b/src/gallium/drivers/r300/r300_chipset.h
@@ -30,6 +30,7 @@
30#define RV530_HIZ_LIMIT 15360 30#define RV530_HIZ_LIMIT 15360
31 31
32/* rv3xx have only one pipe */ 32/* rv3xx have only one pipe */
33#define PIPE_CMASK_SIZE 4096
33#define PIPE_ZMASK_SIZE 4096 34#define PIPE_ZMASK_SIZE 4096
34#define RV3xx_ZMASK_SIZE 5120 35#define RV3xx_ZMASK_SIZE 5120
35 36
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index c744fea10cf..a6fccc6e02c 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -75,6 +75,9 @@ static void r300_destroy_context(struct pipe_context* context)
75 if (r300->cs && r300->hyperz_enabled) { 75 if (r300->cs && r300->hyperz_enabled) {
76 r300->rws->cs_request_feature(r300->cs, RADEON_FID_R300_HYPERZ_ACCESS, FALSE); 76 r300->rws->cs_request_feature(r300->cs, RADEON_FID_R300_HYPERZ_ACCESS, FALSE);
77 } 77 }
78 if (r300->cs && r300->cmask_access) {
79 r300->rws->cs_request_feature(r300->cs, RADEON_FID_R300_CMASK_ACCESS, FALSE);
80 }
78 81
79 if (r300->blitter) 82 if (r300->blitter)
80 util_blitter_destroy(r300->blitter); 83 util_blitter_destroy(r300->blitter);
@@ -203,6 +206,7 @@ static boolean r300_setup_atoms(struct r300_context* r300)
203 /* Clear commands */ 206 /* Clear commands */
204 R300_INIT_ATOM(hiz_clear, r300->screen->caps.hiz_ram > 0 ? 6 : 0); 207 R300_INIT_ATOM(hiz_clear, r300->screen->caps.hiz_ram > 0 ? 6 : 0);
205 R300_INIT_ATOM(zmask_clear, r300->screen->caps.zmask_ram > 0 ? 6 : 0); 208 R300_INIT_ATOM(zmask_clear, r300->screen->caps.zmask_ram > 0 ? 6 : 0);
209 R300_INIT_ATOM(cmask_clear, 6);
206 /* ZB (unpipelined), SU. */ 210 /* ZB (unpipelined), SU. */
207 R300_INIT_ATOM(query_start, 4); 211 R300_INIT_ATOM(query_start, 4);
208 212
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 1b912c3eeee..33851519bd8 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -309,6 +309,7 @@ struct r300_surface {
309 uint32_t pitch; /* COLORPITCH or DEPTHPITCH. */ 309 uint32_t pitch; /* COLORPITCH or DEPTHPITCH. */
310 uint32_t pitch_zmask; /* ZMASK_PITCH */ 310 uint32_t pitch_zmask; /* ZMASK_PITCH */
311 uint32_t pitch_hiz; /* HIZ_PITCH */ 311 uint32_t pitch_hiz; /* HIZ_PITCH */
312 uint32_t pitch_cmask; /* CMASK_PITCH */
312 uint32_t format; /* US_OUT_FMT or ZB_FORMAT. */ 313 uint32_t format; /* US_OUT_FMT or ZB_FORMAT. */
313 314
314 /* Parameters dedicated to the CBZB clear. */ 315 /* Parameters dedicated to the CBZB clear. */
@@ -380,6 +381,10 @@ struct r300_texture_desc {
380 /* Zmask/HiZ strides for each miplevel. */ 381 /* Zmask/HiZ strides for each miplevel. */
381 unsigned zmask_stride_in_pixels[R300_MAX_TEXTURE_LEVELS]; 382 unsigned zmask_stride_in_pixels[R300_MAX_TEXTURE_LEVELS];
382 unsigned hiz_stride_in_pixels[R300_MAX_TEXTURE_LEVELS]; 383 unsigned hiz_stride_in_pixels[R300_MAX_TEXTURE_LEVELS];
384
385 /* CMASK info for AA buffers (no mipmapping). */
386 unsigned cmask_dwords;
387 unsigned cmask_stride_in_pixels;
383}; 388};
384 389
385struct r300_resource 390struct r300_resource
@@ -536,6 +541,8 @@ struct r300_context {
536 struct r300_atom hiz_clear; 541 struct r300_atom hiz_clear;
537 /* zmask clear */ 542 /* zmask clear */
538 struct r300_atom zmask_clear; 543 struct r300_atom zmask_clear;
544 /* cmask clear */
545 struct r300_atom cmask_clear;
539 /* Occlusion query. */ 546 /* Occlusion query. */
540 struct r300_atom query_start; 547 struct r300_atom query_start;
541 548
@@ -616,6 +623,13 @@ struct r300_context {
616 enum r300_hiz_func hiz_func; /* HiZ function. Can be either MIN or MAX. */ 623 enum r300_hiz_func hiz_func; /* HiZ function. Can be either MIN or MAX. */
617 uint32_t hiz_clear_value; /* HiZ clear value. */ 624 uint32_t hiz_clear_value; /* HiZ clear value. */
618 625
626 /* CMASK state. */
627 boolean cmask_access;
628 boolean cmask_in_use;
629 uint32_t color_clear_value; /* RGBA8 or RGBA1010102 */
630 uint32_t color_clear_value_ar; /* RGBA16F */
631 uint32_t color_clear_value_gb; /* RGBA16F */
632
619 /* Compiler state. */ 633 /* Compiler state. */
620 struct rc_regalloc_state fs_regalloc_state; /* Register allocator info for 634 struct rc_regalloc_state fs_regalloc_state; /* Register allocator info for
621 * fragment shaders. */ 635 * fragment shaders. */
@@ -722,7 +736,8 @@ void r300_blitter_draw_rectangle(struct blitter_context *blitter,
722enum r300_fb_state_change { 736enum r300_fb_state_change {
723 R300_CHANGED_FB_STATE = 0, 737 R300_CHANGED_FB_STATE = 0,
724 R300_CHANGED_HYPERZ_FLAG, 738 R300_CHANGED_HYPERZ_FLAG,
725 R300_CHANGED_MULTIWRITE 739 R300_CHANGED_MULTIWRITE,
740 R300_CHANGED_CMASK_ENABLE,
726}; 741};
727 742
728void r300_mark_fb_state_dirty(struct r300_context *r300, 743void r300_mark_fb_state_dirty(struct r300_context *r300,
diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c
index 5ec2cf9e4ae..ff1f16d913a 100644
--- a/src/gallium/drivers/r300/r300_debug.c
+++ b/src/gallium/drivers/r300/r300_debug.c
@@ -50,6 +50,7 @@ static const struct debug_named_value debug_options[] = {
50 { "nocbzb", DBG_NO_CBZB, "Disable fast color clear" }, 50 { "nocbzb", DBG_NO_CBZB, "Disable fast color clear" },
51 { "nozmask", DBG_NO_ZMASK, "Disable zbuffer compression" }, 51 { "nozmask", DBG_NO_ZMASK, "Disable zbuffer compression" },
52 { "nohiz", DBG_NO_HIZ, "Disable hierarchical zbuffer" }, 52 { "nohiz", DBG_NO_HIZ, "Disable hierarchical zbuffer" },
53 { "nocmask", DBG_NO_CMASK, "Disable AA compression and fast AA clear" },
53 54
54 /* must be last */ 55 /* must be last */
55 DEBUG_NAMED_VALUE_END 56 DEBUG_NAMED_VALUE_END
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index cb6c46e5e6c..9ea084fac2d 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -399,14 +399,17 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
399 399
400 BEGIN_CS(size); 400 BEGIN_CS(size);
401 401
402 /* NUM_MULTIWRITES replicates COLOR[0] to all colorbuffers, which is not
403 * what we usually want. */
404 if (r300->screen->caps.is_r500) { 402 if (r300->screen->caps.is_r500) {
405 rb3d_cctl = R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE; 403 rb3d_cctl = R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE;
406 } 404 }
405 /* NUM_MULTIWRITES replicates COLOR[0] to all colorbuffers. */
407 if (fb->nr_cbufs && r300->fb_multiwrite) { 406 if (fb->nr_cbufs && r300->fb_multiwrite) {
408 rb3d_cctl |= R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs); 407 rb3d_cctl |= R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs);
409 } 408 }
409 if (r300->cmask_in_use) {
410 rb3d_cctl |= R300_RB3D_CCTL_AA_COMPRESSION_ENABLE |
411 R300_RB3D_CCTL_CMASK_ENABLE;
412 }
410 413
411 OUT_CS_REG(R300_RB3D_CCTL, rb3d_cctl); 414 OUT_CS_REG(R300_RB3D_CCTL, rb3d_cctl);
412 415
@@ -419,6 +422,12 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
419 422
420 OUT_CS_REG(R300_RB3D_COLORPITCH0 + (4 * i), surf->pitch); 423 OUT_CS_REG(R300_RB3D_COLORPITCH0 + (4 * i), surf->pitch);
421 OUT_CS_RELOC(surf); 424 OUT_CS_RELOC(surf);
425
426 if (r300->cmask_in_use && i == 0) {
427 OUT_CS_REG(R300_RB3D_CMASK_OFFSET0, 0);
428 OUT_CS_REG(R300_RB3D_CMASK_PITCH0, surf->pitch_cmask);
429 OUT_CS_REG(R300_RB3D_COLOR_CLEAR_VALUE, r300->color_clear_value);
430 }
422 } 431 }
423 432
424 /* Set up the ZB part of the CBZB clear. */ 433 /* Set up the ZB part of the CBZB clear. */
@@ -1240,6 +1249,30 @@ void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state
1240 r300_mark_atom_dirty(r300, &r300->hyperz_state); 1249 r300_mark_atom_dirty(r300, &r300->hyperz_state);
1241} 1250}
1242 1251
1252void r300_emit_cmask_clear(struct r300_context *r300, unsigned size, void *state)
1253{
1254 struct pipe_framebuffer_state *fb =
1255 (struct pipe_framebuffer_state*)r300->fb_state.state;
1256 struct r300_resource *tex;
1257 CS_LOCALS(r300);
1258
1259 tex = r300_resource(fb->cbufs[0]->texture);
1260
1261 BEGIN_CS(size);
1262 OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT,
1263 R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS |
1264 R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
1265 OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_CMASK, 2);
1266 OUT_CS(0);
1267 OUT_CS(tex->tex.cmask_dwords);
1268 OUT_CS(0);
1269 END_CS;
1270
1271 /* Mark the current zbuffer's zmask as in use. */
1272 r300->cmask_in_use = TRUE;
1273 r300_mark_fb_state_dirty(r300, R300_CHANGED_CMASK_ENABLE);
1274}
1275
1243void r300_emit_ztop_state(struct r300_context* r300, 1276void r300_emit_ztop_state(struct r300_context* r300,
1244 unsigned size, void* state) 1277 unsigned size, void* state)
1245{ 1278{
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index a58ab857f56..eaa0a6c4ac0 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -117,6 +117,7 @@ void r300_emit_invariant_state(struct r300_context *r300,
117 117
118void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state); 118void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state);
119void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state); 119void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state);
120void r300_emit_cmask_clear(struct r300_context *r300, unsigned size, void *state);
120 121
121unsigned r300_get_num_dirty_dwords(struct r300_context *r300); 122unsigned r300_get_num_dirty_dwords(struct r300_context *r300);
122unsigned r300_get_num_cs_end_dwords(struct r300_context *r300); 123unsigned r300_get_num_cs_end_dwords(struct r300_context *r300);
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index 5e1d8101910..8342ef532d3 100644
--- a/src/gallium/drivers/r300/r300_reg.h
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -2390,7 +2390,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
2390 * Program this register with a 32-bit value in ARGB8888 or ARGB2101010 2390 * Program this register with a 32-bit value in ARGB8888 or ARGB2101010
2391 * formats, ignoring the fields. 2391 * formats, ignoring the fields.
2392 */ 2392 */
2393#define RB3D_COLOR_CLEAR_VALUE 0x4e14 2393#define R300_RB3D_COLOR_CLEAR_VALUE 0x4E14
2394/* For FP16 AA. */
2395#define R500_RB3D_COLOR_CLEAR_VALUE_AR 0x46C0
2396#define R500_RB3D_COLOR_CLEAR_VALUE_GB 0x46C4
2394 2397
2395/* gap */ 2398/* gap */
2396 2399
@@ -2485,6 +2488,18 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
2485# define R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT (2 << 2) 2488# define R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT (2 << 2)
2486/* reserved */ 2489/* reserved */
2487 2490
2491#define R300_RB3D_CMASK_OFFSET0 0x4E54
2492#define R300_RB3D_CMASK_OFFSET1 0x4E58
2493#define R300_RB3D_CMASK_OFFSET2 0x4E5C
2494#define R300_RB3D_CMASK_OFFSET3 0x4E60
2495#define R300_RB3D_CMASK_PITCH0 0x4E64
2496#define R300_RB3D_CMASK_PITCH1 0x4E68
2497#define R300_RB3D_CMASK_PITCH2 0x4E6C
2498#define R300_RB3D_CMASK_PITCH3 0x4E70
2499#define R300_RB3D_CMASK_WRINDEX 0x4E74
2500#define R300_RB3D_CMASK_DWORD 0x4E78
2501#define R300_RB3D_CMASK_RDINDEX 0x4E7C
2502
2488/* Resolve buffer destination address. The cache must be empty before changing 2503/* Resolve buffer destination address. The cache must be empty before changing
2489 * this register if the cb is in resolve mode. Unpipelined 2504 * this register if the cb is in resolve mode. Unpipelined
2490 */ 2505 */
@@ -3504,6 +3519,7 @@ enum {
3504 * 2. CLEAR_VALUE: Value to write into HIZ RAM. 3519 * 2. CLEAR_VALUE: Value to write into HIZ RAM.
3505 */ 3520 */
3506#define R300_PACKET3_3D_CLEAR_HIZ 0x00003700 3521#define R300_PACKET3_3D_CLEAR_HIZ 0x00003700
3522#define R300_PACKET3_3D_CLEAR_CMASK 0x00003800
3507 3523
3508/* Draws a set of primitives using vertex buffers pointed by the state data. 3524/* Draws a set of primitives using vertex buffers pointed by the state data.
3509 * At least 2 Parameters: 3525 * At least 2 Parameters:
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index 3af5774ea51..d0f00700f81 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -522,6 +522,8 @@ static void r300_destroy_screen(struct pipe_screen* pscreen)
522 struct r300_screen* r300screen = r300_screen(pscreen); 522 struct r300_screen* r300screen = r300_screen(pscreen);
523 struct radeon_winsys *rws = radeon_winsys(pscreen); 523 struct radeon_winsys *rws = radeon_winsys(pscreen);
524 524
525 pipe_mutex_destroy(r300screen->cmask_mutex);
526
525 if (rws) 527 if (rws)
526 rws->destroy(rws); 528 rws->destroy(rws);
527 529
@@ -612,6 +614,7 @@ struct pipe_screen* r300_screen_create(struct radeon_winsys *rws)
612 r300_init_screen_resource_functions(r300screen); 614 r300_init_screen_resource_functions(r300screen);
613 615
614 util_format_s3tc_init(); 616 util_format_s3tc_init();
617 pipe_mutex_init(r300screen->cmask_mutex);
615 618
616 return &r300screen->screen; 619 return &r300screen->screen;
617} 620}
diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h
index d2bed8d528e..e129cee57c7 100644
--- a/src/gallium/drivers/r300/r300_screen.h
+++ b/src/gallium/drivers/r300/r300_screen.h
@@ -28,6 +28,7 @@
28#include "../../winsys/radeon/drm/radeon_winsys.h" 28#include "../../winsys/radeon/drm/radeon_winsys.h"
29#include "pipe/p_screen.h" 29#include "pipe/p_screen.h"
30#include "util/u_slab.h" 30#include "util/u_slab.h"
31#include "os/os_thread.h"
31#include <stdio.h> 32#include <stdio.h>
32 33
33struct r300_screen { 34struct r300_screen {
@@ -42,6 +43,10 @@ struct r300_screen {
42 43
43 /** Combination of DBG_xxx flags */ 44 /** Combination of DBG_xxx flags */
44 unsigned debug; 45 unsigned debug;
46
47 /* The MSAA texture with CMASK access; */
48 struct pipe_resource *cmask_resource;
49 pipe_mutex cmask_mutex;
45}; 50};
46 51
47 52
@@ -92,6 +97,7 @@ radeon_winsys(struct pipe_screen *screen) {
92#define DBG_NO_CBZB (1 << 20) 97#define DBG_NO_CBZB (1 << 20)
93#define DBG_NO_ZMASK (1 << 21) 98#define DBG_NO_ZMASK (1 << 21)
94#define DBG_NO_HIZ (1 << 22) 99#define DBG_NO_HIZ (1 << 22)
100#define DBG_NO_CMASK (1 << 23)
95/* Statistics. */ 101/* Statistics. */
96#define DBG_P_STAT (1 << 25) 102#define DBG_P_STAT (1 << 25)
97/*@}*/ 103/*@}*/
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index 4a5a5a89b84..fa256aa2c55 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -825,6 +825,10 @@ void r300_mark_fb_state_dirty(struct r300_context *r300,
825 r300->fb_state.size += 8; 825 r300->fb_state.size += 8;
826 } 826 }
827 827
828 if (r300->cmask_in_use) {
829 r300->fb_state.size += 6;
830 }
831
828 /* The size of the rest of atoms stays the same. */ 832 /* The size of the rest of atoms stays the same. */
829} 833}
830 834
@@ -900,6 +904,11 @@ r300_set_framebuffer_state(struct pipe_context* pipe,
900 } 904 }
901 assert(state->zsbuf || (r300->locked_zbuffer && !unlock_zbuffer) || !r300->zmask_in_use); 905 assert(state->zsbuf || (r300->locked_zbuffer && !unlock_zbuffer) || !r300->zmask_in_use);
902 906
907 /* Set whether CMASK can be used. */
908 r300->cmask_in_use =
909 state->nr_cbufs == 1 &&
910 r300->screen->cmask_resource == state->cbufs[0]->texture;
911
903 /* Need to reset clamping or colormask. */ 912 /* Need to reset clamping or colormask. */
904 r300_mark_atom_dirty(r300, &r300->blend_state); 913 r300_mark_atom_dirty(r300, &r300->blend_state);
905 914
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 4be6d5067d2..6816fd01ab3 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -906,14 +906,23 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf)
906 surf->format = r300_translate_out_fmt(surf->base.format); 906 surf->format = r300_translate_out_fmt(surf->base.format);
907 surf->colormask_swizzle = 907 surf->colormask_swizzle =
908 r300_translate_colormask_swizzle(surf->base.format); 908 r300_translate_colormask_swizzle(surf->base.format);
909 surf->pitch_cmask = tex->tex.cmask_stride_in_pixels;
909 } 910 }
910} 911}
911 912
912static void r300_texture_destroy(struct pipe_screen *screen, 913static void r300_texture_destroy(struct pipe_screen *screen,
913 struct pipe_resource* texture) 914 struct pipe_resource* texture)
914{ 915{
916 struct r300_screen *rscreen = r300_screen(screen);
915 struct r300_resource* tex = (struct r300_resource*)texture; 917 struct r300_resource* tex = (struct r300_resource*)texture;
916 918
919 if (tex->tex.cmask_dwords) {
920 pipe_mutex_lock(rscreen->cmask_mutex);
921 if (texture == rscreen->cmask_resource) {
922 rscreen->cmask_resource = NULL;
923 }
924 pipe_mutex_unlock(rscreen->cmask_mutex);
925 }
917 pb_reference(&tex->buf, NULL); 926 pb_reference(&tex->buf, NULL);
918 FREE(tex); 927 FREE(tex);
919} 928}
diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c
index 8928f73f7cf..46f07e2c522 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.c
+++ b/src/gallium/drivers/r300/r300_texture_desc.c
@@ -409,6 +409,48 @@ static void r300_setup_hyperz_properties(struct r300_screen *screen,
409 } 409 }
410} 410}
411 411
412static void r300_setup_cmask_properties(struct r300_screen *screen,
413 struct r300_resource *tex)
414{
415 static unsigned cmask_align_x[4] = {16, 32, 48, 32};
416 static unsigned cmask_align_y[4] = {16, 16, 16, 32};
417 unsigned pipes, stride, cmask_num_dw;
418
419 /* We need an AA colorbuffer, no mipmaps. */
420 if (tex->b.b.nr_samples <= 1 ||
421 tex->b.b.last_level > 0 ||
422 util_format_is_depth_or_stencil(tex->b.b.format)) {
423 return;
424 }
425
426 if (tex->b.b.format == PIPE_FORMAT_R16G16B16A16_FLOAT) {
427 return;
428 }
429
430 if (SCREEN_DBG_ON(screen, DBG_NO_CMASK)) {
431 return;
432 }
433
434 /* CMASK is part of raster pipes. The number of Z pipes doesn't matter. */
435 pipes = screen->info.r300_num_gb_pipes;
436
437 stride = r300_stride_to_width(tex->b.b.format,
438 tex->tex.stride_in_bytes[0]);
439 stride = align(stride, 16);
440
441 /* Get the CMASK size in dwords. */
442 cmask_num_dw = r300_pixels_to_dwords(stride, tex->b.b.height0,
443 cmask_align_x[pipes-1],
444 cmask_align_y[pipes-1]);
445
446 /* Check the CMASK size against the CMASK memory limit. */
447 if (cmask_num_dw <= PIPE_CMASK_SIZE * pipes) {
448 tex->tex.cmask_dwords = cmask_num_dw;
449 tex->tex.cmask_stride_in_pixels =
450 util_align_npot(stride, cmask_align_x[pipes-1]);
451 }
452}
453
412static void r300_setup_tiling(struct r300_screen *screen, 454static void r300_setup_tiling(struct r300_screen *screen,
413 struct r300_resource *tex) 455 struct r300_resource *tex)
414{ 456{
@@ -532,6 +574,7 @@ void r300_texture_desc_init(struct r300_screen *rscreen,
532 } 574 }
533 575
534 r300_setup_hyperz_properties(rscreen, tex); 576 r300_setup_hyperz_properties(rscreen, tex);
577 r300_setup_cmask_properties(rscreen, tex);
535 578
536 if (SCREEN_DBG_ON(rscreen, DBG_TEX)) 579 if (SCREEN_DBG_ON(rscreen, DBG_TEX))
537 r300_tex_print_info(tex, "texture_desc_init"); 580 r300_tex_print_info(tex, "texture_desc_init");