r300g: optimize blending by discarding pixels that don't change the colorbuffer

Let's get some performance out of the blender.
This commit is contained in:
Marek Olšák 2009-12-20 18:19:03 +01:00 committed by Corbin Simpson
parent 717c28055a
commit 6b9b3213c5
2 changed files with 162 additions and 3 deletions

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
* Copyright 2009 Marek Olšák <maraeo@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -41,6 +42,120 @@
/* r300_state: Functions used to intialize state context by translating
* Gallium state objects into semi-native r300 state objects. */
static boolean blend_discard_if_src_alpha_0(unsigned srcRGB, unsigned srcA,
unsigned dstRGB, unsigned dstA)
{
/* If the blend equation is ADD or REVERSE_SUBTRACT,
* SRC_ALPHA == 0, and the following state is set, the colorbuffer
* will not be changed.
* Notice that the dst factors are the src factors inverted. */
return (srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA ||
srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE ||
srcRGB == PIPE_BLENDFACTOR_ZERO) &&
(srcA == PIPE_BLENDFACTOR_SRC_COLOR ||
srcA == PIPE_BLENDFACTOR_SRC_ALPHA ||
srcA == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE ||
srcA == PIPE_BLENDFACTOR_ZERO) &&
(dstRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA ||
dstRGB == PIPE_BLENDFACTOR_ONE) &&
(dstA == PIPE_BLENDFACTOR_INV_SRC_COLOR ||
dstA == PIPE_BLENDFACTOR_INV_SRC_ALPHA ||
dstA == PIPE_BLENDFACTOR_ONE);
}
static boolean blend_discard_if_src_alpha_1(unsigned srcRGB, unsigned srcA,
unsigned dstRGB, unsigned dstA)
{
/* If the blend equation is ADD or REVERSE_SUBTRACT,
* SRC_ALPHA == 1, and the following state is set, the colorbuffer
* will not be changed.
* Notice that the dst factors are the src factors inverted. */
return (srcRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA ||
srcRGB == PIPE_BLENDFACTOR_ZERO) &&
(srcA == PIPE_BLENDFACTOR_INV_SRC_COLOR ||
srcA == PIPE_BLENDFACTOR_INV_SRC_ALPHA ||
srcA == PIPE_BLENDFACTOR_ZERO) &&
(dstRGB == PIPE_BLENDFACTOR_SRC_ALPHA ||
dstRGB == PIPE_BLENDFACTOR_ONE) &&
(dstA == PIPE_BLENDFACTOR_SRC_COLOR ||
dstA == PIPE_BLENDFACTOR_SRC_ALPHA ||
dstA == PIPE_BLENDFACTOR_ONE);
}
static boolean blend_discard_if_src_color_0(unsigned srcRGB, unsigned srcA,
unsigned dstRGB, unsigned dstA)
{
/* If the blend equation is ADD or REVERSE_SUBTRACT,
* SRC_COLOR == (0,0,0), and the following state is set, the colorbuffer
* will not be changed.
* Notice that the dst factors are the src factors inverted. */
return (srcRGB == PIPE_BLENDFACTOR_SRC_COLOR ||
srcRGB == PIPE_BLENDFACTOR_ZERO) &&
(srcA == PIPE_BLENDFACTOR_ZERO) &&
(dstRGB == PIPE_BLENDFACTOR_INV_SRC_COLOR ||
dstRGB == PIPE_BLENDFACTOR_ONE) &&
(dstA == PIPE_BLENDFACTOR_ONE);
}
static boolean blend_discard_if_src_color_1(unsigned srcRGB, unsigned srcA,
unsigned dstRGB, unsigned dstA)
{
/* If the blend equation is ADD or REVERSE_SUBTRACT,
* SRC_COLOR == (1,1,1), and the following state is set, the colorbuffer
* will not be changed.
* Notice that the dst factors are the src factors inverted. */
return (srcRGB == PIPE_BLENDFACTOR_INV_SRC_COLOR ||
srcRGB == PIPE_BLENDFACTOR_ZERO) &&
(srcA == PIPE_BLENDFACTOR_ZERO) &&
(dstRGB == PIPE_BLENDFACTOR_SRC_COLOR ||
dstRGB == PIPE_BLENDFACTOR_ONE) &&
(dstA == PIPE_BLENDFACTOR_ONE);
}
static boolean blend_discard_if_src_alpha_color_0(unsigned srcRGB, unsigned srcA,
unsigned dstRGB, unsigned dstA)
{
/* If the blend equation is ADD or REVERSE_SUBTRACT,
* SRC_ALPHA_COLOR == (0,0,0,0), and the following state is set,
* the colorbuffer will not be changed.
* Notice that the dst factors are the src factors inverted. */
return (srcRGB == PIPE_BLENDFACTOR_SRC_COLOR ||
srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA ||
srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE ||
srcRGB == PIPE_BLENDFACTOR_ZERO) &&
(srcA == PIPE_BLENDFACTOR_SRC_COLOR ||
srcA == PIPE_BLENDFACTOR_SRC_ALPHA ||
srcA == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE ||
srcA == PIPE_BLENDFACTOR_ZERO) &&
(dstRGB == PIPE_BLENDFACTOR_INV_SRC_COLOR ||
dstRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA ||
dstRGB == PIPE_BLENDFACTOR_ONE) &&
(dstA == PIPE_BLENDFACTOR_INV_SRC_COLOR ||
dstA == PIPE_BLENDFACTOR_INV_SRC_ALPHA ||
dstA == PIPE_BLENDFACTOR_ONE);
}
static boolean blend_discard_if_src_alpha_color_1(unsigned srcRGB, unsigned srcA,
unsigned dstRGB, unsigned dstA)
{
/* If the blend equation is ADD or REVERSE_SUBTRACT,
* SRC_ALPHA_COLOR == (1,1,1,1), and the following state is set,
* the colorbuffer will not be changed.
* Notice that the dst factors are the src factors inverted. */
return (srcRGB == PIPE_BLENDFACTOR_INV_SRC_COLOR ||
srcRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA ||
srcRGB == PIPE_BLENDFACTOR_ZERO) &&
(srcA == PIPE_BLENDFACTOR_INV_SRC_COLOR ||
srcA == PIPE_BLENDFACTOR_INV_SRC_ALPHA ||
srcA == PIPE_BLENDFACTOR_ZERO) &&
(dstRGB == PIPE_BLENDFACTOR_SRC_COLOR ||
dstRGB == PIPE_BLENDFACTOR_SRC_ALPHA ||
dstRGB == PIPE_BLENDFACTOR_ONE) &&
(dstA == PIPE_BLENDFACTOR_SRC_COLOR ||
dstA == PIPE_BLENDFACTOR_SRC_ALPHA ||
dstA == PIPE_BLENDFACTOR_ONE);
}
/* Create a new blend state based on the CSO blend state.
*
* This encompasses alpha blending, logic/raster ops, and blend dithering. */
@ -86,7 +201,51 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE)
blend->blend_control |= R300_READ_ENABLE;
/* XXX implement the optimization with DISCARD_SRC_PIXELS*/
/* Optimization: discard pixels which don't change the colorbuffer.
*
* The code below is non-trivial and some math is involved.
*
* Discarding pixels must be disabled when FP16 AA is enabled.
* This is a hardware bug. Also, this implementation wouldn't work
* with FP blending enabled and equation clamping disabled.
*
* Equations other than ADD are rarely used and therefore won't be
* optimized. */
if ((eqRGB == PIPE_BLEND_ADD || eqRGB == PIPE_BLEND_REVERSE_SUBTRACT) &&
(eqA == PIPE_BLEND_ADD || eqA == PIPE_BLEND_REVERSE_SUBTRACT)) {
/* ADD: X+Y
* REVERSE_SUBTRACT: Y-X
*
* The idea is:
* If X = src*srcFactor = 0 and Y = dst*dstFactor = 1,
* then CB will not be changed.
*
* Given the srcFactor and dstFactor variables, we can derive
* what src and dst should be equal to and discard appropriate
* pixels.
*/
if (blend_discard_if_src_alpha_0(srcRGB, srcA, dstRGB, dstA)) {
blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_0;
} else if (blend_discard_if_src_alpha_1(srcRGB, srcA,
dstRGB, dstA)) {
blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_1;
} else if (blend_discard_if_src_color_0(srcRGB, srcA,
dstRGB, dstA)) {
blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_0;
} else if (blend_discard_if_src_color_1(srcRGB, srcA,
dstRGB, dstA)) {
blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_1;
} else if (blend_discard_if_src_alpha_color_0(srcRGB, srcA,
dstRGB, dstA)) {
blend->blend_control |=
R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_0;
} else if (blend_discard_if_src_alpha_color_1(srcRGB, srcA,
dstRGB, dstA)) {
blend->blend_control |=
R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_1;
}
}
/* XXX implement the optimization with SRC_ALPHA_?_NO_READ */
/* separate alpha */

View File

@ -118,8 +118,8 @@ void r300_emit_invariant_state(struct r300_context* r300)
OUT_CS_REG(R300_SC_EDGERULE, 0x2DA49525);
OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0x00000000);
if (caps->is_r500) {
OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x00000000);
OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFFFFFFFF);
OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101);
OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE);
}
OUT_CS_REG(R300_ZB_BW_CNTL, 0x00000000);
OUT_CS_REG(R300_ZB_DEPTHCLEARVALUE, 0x00000000);