r600: improve cayman scissor 1x1 workaround

This change improves evergreen_apply_scissor_bug_workaround().
It provides a fully functional workaround for cayman.

Note: this was the last functionality which was working
properly on evergreen but not on cayman.

Here are the tests fixed:
spec/arb_framebuffer_no_attachments/arb_framebuffer_no_attachments-atomic/glscissor: fail pass
spec/arb_framebuffer_no_attachments/arb_framebuffer_no_attachments-query/glscissor: fail pass
deqp-gles31/functional/fbo/no_attachments/interaction/1x1ms0_default_2048x2048ms4: fail pass
deqp-gles31/functional/fbo/no_attachments/npot_size/1x1: fail pass

Fixes: 87a5b07f90 ("gallium/radeon: add R600/Evergreen/Cayman support to common viewport code")
Signed-off-by: Patrick Lerda <patrick9876@free.fr>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38743>
This commit is contained in:
Patrick Lerda
2025-12-01 12:41:56 +01:00
committed by Marge Bot
parent 7f6bd8b003
commit 6246b7be10
5 changed files with 60 additions and 2 deletions

View File

@@ -8,6 +8,7 @@
#include "r600_query.h"
#include "r600d_common.h"
#include "evergreend.h"
#include "r600_inline.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_endian.h"
@@ -2063,8 +2064,22 @@ static void evergreen_emit_framebuffer_state(struct r600_context *rctx, struct r
radeon_emit(cs, S_028044_FORMAT(V_028044_STENCIL_INVALID)); /* R_028044_DB_STENCIL_INFO */
}
/* Framebuffer dimensions. */
evergreen_get_scissor_rect(rctx, 0, 0, state->width, state->height, &tl, &br);
if (unlikely(rctx->b.gfx_level == CAYMAN &&
state->width == 1 && state->height == 1 &&
!rctx->b.window_rectangles.number)) {
tl = S_028240_TL_X(0) | S_028240_TL_Y(0);
br = S_028244_BR_X(2) | S_028244_BR_Y(1);
cayman_apply_scissor_workaround_1x1(&rctx->b, cs);
rctx->b.window_rectangles.fbo_cayman_workaround = true;
} else {
if (unlikely(rctx->b.window_rectangles.fbo_cayman_workaround &&
!rctx->b.window_rectangles.number)) {
r600_disable_cliprect_rule(cs);
rctx->b.window_rectangles.fbo_cayman_workaround = false;
}
/* Framebuffer dimensions. */
evergreen_get_scissor_rect(rctx, 0, 0, state->width, state->height, &tl, &br);
}
radeon_set_context_reg_seq(cs, R_028204_PA_SC_WINDOW_SCISSOR_TL, 2);
radeon_emit(cs, tl); /* R_028204_PA_SC_WINDOW_SCISSOR_TL */

View File

@@ -23,6 +23,7 @@ files_r600 = files(
'r600_dump.h',
'r600_formats.h',
'r600_hw_context.c',
'r600_inline.h',
'r600_isa.c',
'r600_isa.h',
'r600_opcodes.h',

View File

@@ -0,0 +1,10 @@
#ifndef R600_INLINE_H
#define R600_INLINE_H
static inline void r600_disable_cliprect_rule(struct radeon_cmdbuf *const cs)
{
radeon_set_context_reg_seq(cs, R_02820C_PA_SC_CLIPRECT_RULE, 1);
radeon_emit(cs, 0xffff);
}
#endif

View File

@@ -477,6 +477,8 @@ struct r600_viewports {
struct r600_window_rectangles {
unsigned number;
bool include;
bool fbo_cayman_workaround;
bool viewport_cayman_workaround;
struct pipe_scissor_state states[R600_MAX_WINDOW_RECTANGLES];
struct r600_atom atom;
};
@@ -849,6 +851,8 @@ void r600_texture_transfer_unmap(struct pipe_context *ctx,
/* r600_viewport.c */
void evergreen_apply_scissor_bug_workaround(struct r600_common_context *rctx,
struct pipe_scissor_state *scissor);
void cayman_apply_scissor_workaround_1x1(struct r600_common_context *rctx,
struct radeon_cmdbuf *cs);
void r600_update_vs_writes_viewport_index(struct r600_common_context *rctx,
struct tgsi_shader_info *info);
void r600_init_viewport_functions(struct r600_common_context *rctx);

View File

@@ -7,6 +7,7 @@
#include "util/u_viewport.h"
#include "tgsi/tgsi_scan.h"
#include "r600d.h"
#include "r600_inline.h"
#define R600_R_028C0C_PA_CL_GB_VERT_CLIP_ADJ 0x028C0C
#define CM_R_028BE8_PA_CL_GB_VERT_CLIP_ADJ 0x28be8
@@ -136,6 +137,18 @@ void evergreen_apply_scissor_bug_workaround(struct r600_common_context *rctx,
}
}
void cayman_apply_scissor_workaround_1x1(struct r600_common_context *rctx,
struct radeon_cmdbuf *cs)
{
radeon_set_context_reg_seq(cs, R_02820C_PA_SC_CLIPRECT_RULE, 1);
radeon_emit(cs, 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);
radeon_set_context_reg_seq(cs, R_028210_PA_SC_CLIPRECT_0_TL, 2);
radeon_emit(cs, S_028240_TL_X(1) | S_028240_TL_Y(0));
radeon_emit(cs, S_028244_BR_X(2) | S_028244_BR_Y(1));
}
static void r600_emit_one_scissor(struct r600_common_context *rctx,
struct radeon_cmdbuf *cs,
struct r600_signed_scissor *vp_scissor,
@@ -153,6 +166,12 @@ static void r600_emit_one_scissor(struct r600_common_context *rctx,
if (scissor)
r600_clip_scissor(&final, scissor);
const bool cayman_1x1_workaround = rctx->gfx_level == CAYMAN &&
!rctx->window_rectangles.fbo_cayman_workaround &&
final.minx == 0 && final.miny == 0 &&
final.maxx == 1 && final.maxy == 1 &&
!rctx->window_rectangles.number;
evergreen_apply_scissor_bug_workaround(rctx, &final);
radeon_emit(cs, S_028250_TL_X(final.minx) |
@@ -160,6 +179,15 @@ static void r600_emit_one_scissor(struct r600_common_context *rctx,
S_028250_WINDOW_OFFSET_DISABLE(1));
radeon_emit(cs, S_028254_BR_X(final.maxx) |
S_028254_BR_Y(final.maxy));
if (unlikely(cayman_1x1_workaround)) {
cayman_apply_scissor_workaround_1x1(rctx, cs);
rctx->window_rectangles.viewport_cayman_workaround = true;
} else if (unlikely(rctx->window_rectangles.viewport_cayman_workaround &&
!rctx->window_rectangles.number)) {
r600_disable_cliprect_rule(cs);
rctx->window_rectangles.viewport_cayman_workaround = false;
}
}
/* the range is [-MAX, MAX] */