r600: implement EXT_window_rectangles

This is a backport of 0ca8294ece ("radeonsi:
implement EXT_window_rectangles")

This change was tested and passes the piglit tests (20/20)
on rv770, palm and cayman.

Signed-off-by: Patrick Lerda <patrick9876@free.fr>
Acked-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34295>
This commit is contained in:
Patrick Lerda 2025-03-28 13:21:32 +01:00 committed by Marge Bot
parent c1ce2dcc66
commit 6fab29d37e
8 changed files with 117 additions and 1 deletions

View file

@ -4670,6 +4670,7 @@ void evergreen_init_state_functions(struct r600_context *rctx)
r600_add_atom(rctx, &rctx->b.render_cond_atom, id++); r600_add_atom(rctx, &rctx->b.render_cond_atom, id++);
r600_add_atom(rctx, &rctx->b.streamout.begin_atom, id++); r600_add_atom(rctx, &rctx->b.streamout.begin_atom, id++);
r600_add_atom(rctx, &rctx->b.streamout.enable_atom, id++); r600_add_atom(rctx, &rctx->b.streamout.enable_atom, id++);
r600_add_atom(rctx, &rctx->b.window_rectangles.atom, id++);
for (i = 0; i < EG_NUM_HW_STAGES; i++) for (i = 0; i < EG_NUM_HW_STAGES; i++)
r600_init_atom(rctx, &rctx->hw_shader_stages[i].atom, id++, r600_emit_shader, 0); r600_init_atom(rctx, &rctx->hw_shader_stages[i].atom, id++, r600_emit_shader, 0);
r600_init_atom(rctx, &rctx->shader_stages.atom, id++, evergreen_emit_shader_stages, 15); r600_init_atom(rctx, &rctx->shader_stages.atom, id++, evergreen_emit_shader_stages, 15);

View file

@ -65,6 +65,9 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op
util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->dsa_state.cso); util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->dsa_state.cso);
util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref.pipe_state); util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref.pipe_state);
util_blitter_save_sample_mask(rctx->blitter, rctx->sample_mask.sample_mask, rctx->ps_iter_samples); util_blitter_save_sample_mask(rctx->blitter, rctx->sample_mask.sample_mask, rctx->ps_iter_samples);
util_blitter_save_window_rectangles(rctx->blitter, rctx->b.window_rectangles.include,
rctx->b.window_rectangles.number,
rctx->b.window_rectangles.states);
} }
if (op & R600_SAVE_CONST_BUF0) { if (op & R600_SAVE_CONST_BUF0) {

View file

@ -475,6 +475,7 @@ static void r600_init_screen_caps(struct r600_screen *rscreen)
caps->two_sided_color = false; caps->two_sided_color = false;
caps->cull_distance = true; caps->cull_distance = true;
caps->max_window_rectangles = R600_MAX_WINDOW_RECTANGLES;
caps->shader_buffer_offset_alignment = family >= CHIP_CEDAR ? 256 : 0; caps->shader_buffer_offset_alignment = family >= CHIP_CEDAR ? 256 : 0;
caps->max_shader_patch_varyings = family >= CHIP_CEDAR ? 30 : 0; caps->max_shader_patch_varyings = family >= CHIP_CEDAR ? 30 : 0;

View file

@ -20,7 +20,7 @@
#include "tgsi/tgsi_scan.h" #include "tgsi/tgsi_scan.h"
#define R600_NUM_ATOMS 56 #define R600_NUM_ATOMS 57
#define R600_MAX_IMAGES 8 #define R600_MAX_IMAGES 8
/* /*

View file

@ -446,6 +446,16 @@ struct r600_viewports {
struct r600_signed_scissor as_scissor[R600_MAX_VIEWPORTS]; struct r600_signed_scissor as_scissor[R600_MAX_VIEWPORTS];
}; };
/* EXT_window_rectangles */
#define R600_MAX_WINDOW_RECTANGLES 4
struct r600_window_rectangles {
unsigned number;
bool include;
struct pipe_scissor_state states[R600_MAX_WINDOW_RECTANGLES];
struct r600_atom atom;
};
struct r600_ring { struct r600_ring {
struct radeon_cmdbuf cs; struct radeon_cmdbuf cs;
void (*flush)(void *ctx, unsigned flags, void (*flush)(void *ctx, unsigned flags,
@ -493,6 +503,7 @@ struct r600_common_context {
struct r600_streamout streamout; struct r600_streamout streamout;
struct r600_scissors scissors; struct r600_scissors scissors;
struct r600_viewports viewports; struct r600_viewports viewports;
struct r600_window_rectangles window_rectangles;
bool scissor_enabled; bool scissor_enabled;
bool clip_halfz; bool clip_halfz;
bool vs_writes_viewport_index; bool vs_writes_viewport_index;

View file

@ -3104,6 +3104,7 @@ void r600_init_state_functions(struct r600_context *rctx)
r600_add_atom(rctx, &rctx->b.render_cond_atom, id++); r600_add_atom(rctx, &rctx->b.render_cond_atom, id++);
r600_add_atom(rctx, &rctx->b.streamout.begin_atom, id++); r600_add_atom(rctx, &rctx->b.streamout.begin_atom, id++);
r600_add_atom(rctx, &rctx->b.streamout.enable_atom, id++); r600_add_atom(rctx, &rctx->b.streamout.enable_atom, id++);
r600_add_atom(rctx, &rctx->b.window_rectangles.atom, id++);
for (i = 0; i < R600_NUM_HW_STAGES; i++) for (i = 0; i < R600_NUM_HW_STAGES; i++)
r600_init_atom(rctx, &rctx->hw_shader_stages[i].atom, id++, r600_emit_shader, 0); r600_init_atom(rctx, &rctx->hw_shader_stages[i].atom, id++, r600_emit_shader, 0);
r600_init_atom(rctx, &rctx->shader_stages.atom, id++, r600_emit_shader_stages, 0); r600_init_atom(rctx, &rctx->shader_stages.atom, id++, r600_emit_shader_stages, 0);

View file

@ -6,6 +6,7 @@
#include "r600_cs.h" #include "r600_cs.h"
#include "util/u_viewport.h" #include "util/u_viewport.h"
#include "tgsi/tgsi_scan.h" #include "tgsi/tgsi_scan.h"
#include "r600d.h"
#define R600_R_028C0C_PA_CL_GB_VERT_CLIP_ADJ 0x028C0C #define R600_R_028C0C_PA_CL_GB_VERT_CLIP_ADJ 0x028C0C
#define CM_R_028BE8_PA_CL_GB_VERT_CLIP_ADJ 0x28be8 #define CM_R_028BE8_PA_CL_GB_VERT_CLIP_ADJ 0x28be8
@ -425,14 +426,96 @@ void r600_update_vs_writes_viewport_index(struct r600_common_context *rctx,
rctx->set_atom_dirty(rctx, &rctx->viewports.atom, true); rctx->set_atom_dirty(rctx, &rctx->viewports.atom, true);
} }
static void r600_emit_window_rectangles(struct r600_common_context *rctx,
struct r600_atom *atom)
{
/* There are four clipping rectangles. Their corner coordinates are inclusive.
* Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
* on whether the pixel is inside cliprects 0-3, respectively. For example,
* if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
* the number 3 (binary 0011).
*
* If CLIPRECT_RULE & (1 << number), the pixel is rasterized.
*/
struct radeon_cmdbuf *cs = &rctx->gfx.cs;
static const unsigned outside[4] = {
/* outside rectangle 0 */
V_02820C_OUT |
V_02820C_IN_1 |
V_02820C_IN_2 |
V_02820C_IN_21 |
V_02820C_IN_3 |
V_02820C_IN_31 |
V_02820C_IN_32 |
V_02820C_IN_321,
/* outside rectangles 0, 1 */
V_02820C_OUT |
V_02820C_IN_2 |
V_02820C_IN_3 |
V_02820C_IN_32,
/* outside rectangles 0, 1, 2 */
V_02820C_OUT |
V_02820C_IN_3,
/* outside rectangles 0, 1, 2, 3 */
V_02820C_OUT,
};
const unsigned disabled = 0xffff; /* all inside and outside cases */
unsigned num_rectangles = rctx->window_rectangles.number;
struct pipe_scissor_state *rects = rctx->window_rectangles.states;
unsigned rule;
assert(num_rectangles <= R600_MAX_WINDOW_RECTANGLES);
if (num_rectangles == 0)
rule = disabled;
else if (rctx->window_rectangles.include)
rule = ~outside[num_rectangles - 1];
else
rule = outside[num_rectangles - 1];
radeon_set_context_reg_seq(cs, R_02820C_PA_SC_CLIPRECT_RULE, 1);
radeon_emit(cs, rule);
if (num_rectangles == 0)
return;
radeon_set_context_reg_seq(cs, R_028210_PA_SC_CLIPRECT_0_TL,
num_rectangles * 2);
for (unsigned i = 0; i < num_rectangles; i++) {
radeon_emit(cs, S_028210_TL_X(rects[i].minx) |
S_028210_TL_Y(rects[i].miny));
radeon_emit(cs, S_028214_BR_X(rects[i].maxx) |
S_028214_BR_Y(rects[i].maxy));
}
}
static void r600_set_window_rectangles(struct pipe_context *ctx,
bool include,
unsigned num_rectangles,
const struct pipe_scissor_state *rects)
{
struct r600_common_context *rctx = (struct r600_common_context *)ctx;
rctx->window_rectangles.number = num_rectangles;
rctx->window_rectangles.include = include;
if (num_rectangles)
memcpy(rctx->window_rectangles.states, rects,
sizeof(*rects) * num_rectangles);
rctx->set_atom_dirty(rctx, &rctx->window_rectangles.atom, true);
}
void r600_init_viewport_functions(struct r600_common_context *rctx) void r600_init_viewport_functions(struct r600_common_context *rctx)
{ {
rctx->scissors.atom.emit = r600_emit_scissors; rctx->scissors.atom.emit = r600_emit_scissors;
rctx->viewports.atom.emit = r600_emit_viewport_states; rctx->viewports.atom.emit = r600_emit_viewport_states;
rctx->window_rectangles.atom.emit = r600_emit_window_rectangles;
rctx->scissors.atom.num_dw = (2 + 16 * 2) + 6; rctx->scissors.atom.num_dw = (2 + 16 * 2) + 6;
rctx->viewports.atom.num_dw = 2 + 16 * 6; rctx->viewports.atom.num_dw = 2 + 16 * 6;
rctx->b.set_scissor_states = r600_set_scissor_states; rctx->b.set_scissor_states = r600_set_scissor_states;
rctx->b.set_viewport_states = r600_set_viewport_states; rctx->b.set_viewport_states = r600_set_viewport_states;
rctx->b.set_window_rectangles = r600_set_window_rectangles;
} }

View file

@ -2849,6 +2849,22 @@
#define S_02820C_CLIP_RULE(x) (((unsigned)(x) & 0xFFFF) << 0) #define S_02820C_CLIP_RULE(x) (((unsigned)(x) & 0xFFFF) << 0)
#define G_02820C_CLIP_RULE(x) (((x) >> 0) & 0xFFFF) #define G_02820C_CLIP_RULE(x) (((x) >> 0) & 0xFFFF)
#define C_02820C_CLIP_RULE 0xFFFF0000 #define C_02820C_CLIP_RULE 0xFFFF0000
#define V_02820C_OUT 0x0001
#define V_02820C_IN_0 0x0002
#define V_02820C_IN_1 0x0004
#define V_02820C_IN_10 0x0008
#define V_02820C_IN_2 0x0010
#define V_02820C_IN_20 0x0020
#define V_02820C_IN_21 0x0040
#define V_02820C_IN_210 0x0080
#define V_02820C_IN_3 0x0100
#define V_02820C_IN_30 0x0200
#define V_02820C_IN_31 0x0400
#define V_02820C_IN_310 0x0800
#define V_02820C_IN_32 0x1000
#define V_02820C_IN_320 0x2000
#define V_02820C_IN_321 0x4000
#define V_02820C_IN_3210 0x8000
#define R_028210_PA_SC_CLIPRECT_0_TL 0x028210 #define R_028210_PA_SC_CLIPRECT_0_TL 0x028210
#define S_028210_TL_X(x) (((unsigned)(x) & 0x3FFF) << 0) #define S_028210_TL_X(x) (((unsigned)(x) & 0x3FFF) << 0)
#define G_028210_TL_X(x) (((x) >> 0) & 0x3FFF) #define G_028210_TL_X(x) (((x) >> 0) & 0x3FFF)