From c5b6a65f81445553c023f7e3f253c8afebf27dd0 Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Tue, 6 Jun 2023 10:39:37 +0200 Subject: [PATCH] v3d,v3dv: fix viewport offset for negative viewport center MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit If the viewport center is not positive we can't express it through the fine coordinates, which are unsigned, and we need to use the coarse coordinates too. Fixes new crashes in Vulkan CTS 1.3.6.0: dEQP-VK.draw.renderpass.offscreen_viewport.*negative* Reviewed-by: Alejandro Piñeiro Part-of: --- src/broadcom/vulkan/v3dvx_cmd_buffer.c | 24 ++++++++++++++++++++++-- src/gallium/drivers/v3d/v3dx_emit.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c b/src/broadcom/vulkan/v3dvx_cmd_buffer.c index 024decb..f182b79 100644 --- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c @@ -1103,8 +1103,28 @@ v3dX(cmd_buffer_emit_viewport)(struct v3dv_cmd_buffer *cmd_buffer) } cl_emit(&job->bcl, VIEWPORT_OFFSET, vp) { - vp.fine_x = vptranslate[0]; - vp.fine_y = vptranslate[1]; + float vp_fine_x = vptranslate[0]; + float vp_fine_y = vptranslate[1]; + int32_t vp_coarse_x = 0; + int32_t vp_coarse_y = 0; + + /* The fine coordinates must be unsigned, but coarse can be signed */ + if (unlikely(vp_fine_x < 0)) { + int32_t blocks_64 = DIV_ROUND_UP(fabsf(vp_fine_x), 64); + vp_fine_x += 64.0f * blocks_64; + vp_coarse_x -= blocks_64; + } + + if (unlikely(vp_fine_y < 0)) { + int32_t blocks_64 = DIV_ROUND_UP(fabsf(vp_fine_y), 64); + vp_fine_y += 64.0f * blocks_64; + vp_coarse_y -= blocks_64; + } + + vp.fine_x = vp_fine_x; + vp.fine_y = vp_fine_y; + vp.coarse_x = vp_coarse_x; + vp.coarse_y = vp_coarse_y; } cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_VIEWPORT; diff --git a/src/gallium/drivers/v3d/v3dx_emit.c b/src/gallium/drivers/v3d/v3dx_emit.c index 5303eaf..0ad3fb6 100644 --- a/src/gallium/drivers/v3d/v3dx_emit.c +++ b/src/gallium/drivers/v3d/v3dx_emit.c @@ -593,8 +593,32 @@ v3dX(emit_state)(struct pipe_context *pctx) vp.viewport_centre_y_coordinate = v3d->viewport.translate[1]; #else - vp.fine_x = v3d->viewport.translate[0]; - vp.fine_y = v3d->viewport.translate[1]; + float vp_fine_x = v3d->viewport.translate[0]; + float vp_fine_y = v3d->viewport.translate[1]; + int32_t vp_coarse_x = 0; + int32_t vp_coarse_y = 0; + + /* The fine coordinates must be unsigned, but coarse + * can be signed. + */ + if (unlikely(vp_fine_x < 0)) { + int32_t blocks_64 = + DIV_ROUND_UP(fabsf(vp_fine_x), 64); + vp_fine_x += 64.0f * blocks_64; + vp_coarse_x -= blocks_64; + } + + if (unlikely(vp_fine_y < 0)) { + int32_t blocks_64 = + DIV_ROUND_UP(fabsf(vp_fine_y), 64); + vp_fine_y += 64.0f * blocks_64; + vp_coarse_y -= blocks_64; + } + + vp.fine_x = vp_fine_x; + vp.fine_y = vp_fine_y; + vp.coarse_x = vp_coarse_x; + vp.coarse_y = vp_coarse_y; #endif } } -- 2.7.4