mesa/src/amd/common/ac_guardband.c
Marek Olšák bfb6c41b64
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run
amd: remove unnecessary and transitive #includes
Reported by clang tools.
See: https://clangd.llvm.org/guides/include-cleaner

struct ac_cmdbuf had to be moved to ac_cmdbuf_base.h because we can't
include ac_cmdbuf.h->sid.h->amdgfxregs.h in radeon_winsys.h for r300.

Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41091>
2026-04-24 21:53:07 +00:00

108 lines
3.9 KiB
C

/*
* Copyright 2012 Advanced Micro Devices, Inc.
* Copyright 2026 Valve Corporation
*
* SPDX-License-Identifier: MIT
*/
#include "amd_family.h"
#include "ac_gpu_info.h"
#include "ac_guardband.h"
#include "util/macros.h"
void
ac_compute_guardband(const struct radeon_info *info, int minx, int miny,
int maxx, int maxy, enum ac_quant_mode quant_mode,
float clip_discard_distance, struct ac_guardband *guardband)
{
float left, top, right, bottom, max_range, guardband_x, guardband_y;
float scale[2], translate[2];
/* Determine the optimal hardware screen offset to center the viewport
* within the viewport range in order to maximize the guardband size.
*/
int hw_screen_offset_x = (maxx + minx) / 2;
int hw_screen_offset_y = (maxy + miny) / 2;
/* GFX6-GFX7 need to align the offset to an ubertile consisting of all SEs. */
const unsigned hw_screen_offset_alignment =
info->gfx_level >= GFX11 ? 32 :
info->gfx_level >= GFX8 ? 16 : MAX2(info->se_tile_repeat, 16);
const unsigned max_hw_screen_offset = info->gfx_level >= GFX12 ? 32768 : 8176;
/* Indexed by quantization modes */
static int max_viewport_size[] = {65536, 16384, 4096};
/* Ensure that the whole viewport stays representable in absolute
* coordinates.
*/
assert(maxx <= max_viewport_size[quant_mode] &&
maxy <= max_viewport_size[quant_mode]);
hw_screen_offset_x = CLAMP(hw_screen_offset_x, 0, max_hw_screen_offset);
hw_screen_offset_y = CLAMP(hw_screen_offset_y, 0, max_hw_screen_offset);
/* Align the screen offset by dropping the low bits. */
hw_screen_offset_x &= ~(hw_screen_offset_alignment - 1);
hw_screen_offset_y &= ~(hw_screen_offset_alignment - 1);
/* Apply the offset to center the viewport and maximize the guardband. */
minx -= hw_screen_offset_x;
maxx -= hw_screen_offset_x;
miny -= hw_screen_offset_y;
maxy -= hw_screen_offset_y;
/* Reconstruct the viewport transformation from the scissor. */
translate[0] = (minx + maxx) / 2.0;
translate[1] = (miny + maxy) / 2.0;
scale[0] = maxx - translate[0];
scale[1] = maxy - translate[1];
/* Treat a 0x0 viewport as 1x1 to prevent division by zero. */
if (minx == maxx)
scale[0] = 0.5;
if (miny == maxy)
scale[1] = 0.5;
/* Find the biggest guard band that is inside the supported viewport range.
* The guard band is specified as a horizontal and vertical distance from
* (0,0) in clip space.
*
* This is done by applying the inverse viewport transformation on the
* viewport limits to get those limits in clip space.
*
* The viewport range is [-max_viewport_size/2 - 1, max_viewport_size/2].
* (-1 to the min coord because max_viewport_size is odd and ViewportBounds
* Min/Max are -32768, 32767).
*/
assert(quant_mode < ARRAY_SIZE(max_viewport_size));
max_range = max_viewport_size[quant_mode] / 2;
left = (-max_range - 1 - translate[0]) / scale[0];
right = (max_range - translate[0]) / scale[0];
top = (-max_range - 1 - translate[1]) / scale[1];
bottom = (max_range - translate[1]) / scale[1];
assert(left <= -1 && top <= -1 && right >= 1 && bottom >= 1);
guardband_x = MIN2(-left, right);
guardband_y = MIN2(-top, bottom);
float discard_x = 1.0;
float discard_y = 1.0;
/* Add half the point size / line width */
discard_x += clip_discard_distance / (2.0 * scale[0]);
discard_y += clip_discard_distance / (2.0 * scale[1]);
/* Discard primitives that would lie entirely outside the viewport area. */
discard_x = MIN2(discard_x, guardband_x);
discard_y = MIN2(discard_y, guardband_y);
guardband->clip_x = guardband_x;
guardband->clip_y = guardband_y;
guardband->discard_x = discard_x;
guardband->discard_y = discard_y;
guardband->hw_screen_offset_x = hw_screen_offset_x;
guardband->hw_screen_offset_y = hw_screen_offset_y;
}