From 6246b7be103416b86ba2f375cdbcefa810ebe1d6 Mon Sep 17 00:00:00 2001 From: Patrick Lerda Date: Mon, 1 Dec 2025 12:41:56 +0100 Subject: [PATCH] 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: 87a5b07f9013 ("gallium/radeon: add R600/Evergreen/Cayman support to common viewport code") Signed-off-by: Patrick Lerda Part-of: --- src/gallium/drivers/r600/evergreen_state.c | 19 ++++++++++++-- src/gallium/drivers/r600/meson.build | 1 + src/gallium/drivers/r600/r600_inline.h | 10 ++++++++ src/gallium/drivers/r600/r600_pipe_common.h | 4 +++ src/gallium/drivers/r600/r600_viewport.c | 28 +++++++++++++++++++++ 5 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 src/gallium/drivers/r600/r600_inline.h diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 5379bbe7ef8..229b1980b6e 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -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 */ diff --git a/src/gallium/drivers/r600/meson.build b/src/gallium/drivers/r600/meson.build index 5b8a9c5b882..f1696f59f48 100644 --- a/src/gallium/drivers/r600/meson.build +++ b/src/gallium/drivers/r600/meson.build @@ -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', diff --git a/src/gallium/drivers/r600/r600_inline.h b/src/gallium/drivers/r600/r600_inline.h new file mode 100644 index 00000000000..7db3924f00b --- /dev/null +++ b/src/gallium/drivers/r600/r600_inline.h @@ -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 diff --git a/src/gallium/drivers/r600/r600_pipe_common.h b/src/gallium/drivers/r600/r600_pipe_common.h index c60a4640e35..269dd9f5547 100644 --- a/src/gallium/drivers/r600/r600_pipe_common.h +++ b/src/gallium/drivers/r600/r600_pipe_common.h @@ -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); diff --git a/src/gallium/drivers/r600/r600_viewport.c b/src/gallium/drivers/r600/r600_viewport.c index 75a7686ea4c..552d8d77c22 100644 --- a/src/gallium/drivers/r600/r600_viewport.c +++ b/src/gallium/drivers/r600/r600_viewport.c @@ -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] */