mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 21:50:12 +01:00
poly/asahi: Pull a bunch of vertex_id_for helpers into poly/prim.h
There's nothing really CL-specific about any of these. Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig@intel.com> Reviewed-by: Mary Guillemard <mary@mary.zone> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38404>
This commit is contained in:
parent
27b2290abe
commit
ddff3700a4
3 changed files with 152 additions and 275 deletions
|
|
@ -6,146 +6,11 @@
|
|||
|
||||
#include "compiler/libcl/libcl_vk.h"
|
||||
#include "poly/geometry.h"
|
||||
#include "poly/prim.h"
|
||||
#include "poly/tessellator.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
/* Swap the two non-provoking vertices in odd triangles. This generates a vertex
|
||||
* ID list with a consistent winding order.
|
||||
*
|
||||
* Holding prim and flatshade_first constant, the map : [0, 1, 2] -> [0, 1, 2]
|
||||
* is its own inverse. It is hence used both vertex fetch and transform
|
||||
* feedback.
|
||||
*/
|
||||
static uint
|
||||
map_vertex_in_tri_strip(uint prim, uint vert, bool flatshade_first)
|
||||
{
|
||||
unsigned pv = flatshade_first ? 0 : 2;
|
||||
|
||||
bool even = (prim & 1) == 0;
|
||||
bool provoking = vert == pv;
|
||||
|
||||
return (provoking || even) ? vert : ((3 - pv) - vert);
|
||||
}
|
||||
|
||||
static uint
|
||||
vertex_id_for_line_loop(uint prim, uint vert, uint num_prims)
|
||||
{
|
||||
/* (0, 1), (1, 2), (2, 0) */
|
||||
if (prim == (num_prims - 1) && vert == 1)
|
||||
return 0;
|
||||
else
|
||||
return prim + vert;
|
||||
}
|
||||
|
||||
static uint
|
||||
vertex_id_for_tri_fan(uint prim, uint vert, bool flatshade_first)
|
||||
{
|
||||
/* Vulkan spec section 20.1.7 gives (i + 1, i + 2, 0) for a provoking
|
||||
* first. OpenGL instead wants (0, i + 1, i + 2) with a provoking last.
|
||||
* Piglit clipflat expects us to switch between these orders depending on
|
||||
* provoking vertex, to avoid trivializing the fan.
|
||||
*
|
||||
* Rotate accordingly.
|
||||
*/
|
||||
if (flatshade_first) {
|
||||
vert = (vert == 2) ? 0 : (vert + 1);
|
||||
}
|
||||
|
||||
/* The simpler form assuming last is provoking. */
|
||||
return (vert == 0) ? 0 : prim + vert;
|
||||
}
|
||||
|
||||
static uint
|
||||
vertex_id_for_tri_strip_adj(uint prim, uint vert, uint num_prims,
|
||||
bool flatshade_first)
|
||||
{
|
||||
/* See Vulkan spec section 20.1.11 "Triangle Strips With Adjancency".
|
||||
*
|
||||
* There are different cases for first/middle/last/only primitives and for
|
||||
* odd/even primitives. Determine which case we're in.
|
||||
*/
|
||||
bool last = prim == (num_prims - 1);
|
||||
bool first = prim == 0;
|
||||
bool even = (prim & 1) == 0;
|
||||
bool even_or_first = even || first;
|
||||
|
||||
/* When the last vertex is provoking, we rotate the primitives
|
||||
* accordingly. This seems required for OpenGL.
|
||||
*/
|
||||
if (!flatshade_first && !even_or_first) {
|
||||
vert = (vert + 4u) % 6u;
|
||||
}
|
||||
|
||||
/* Offsets per the spec. The spec lists 6 cases with 6 offsets. Luckily,
|
||||
* there are lots of patterns we can exploit, avoiding a full 6x6 LUT.
|
||||
*
|
||||
* Here we assume the first vertex is provoking, the Vulkan default.
|
||||
*/
|
||||
uint offsets[6] = {
|
||||
0,
|
||||
first ? 1 : (even ? -2 : 3),
|
||||
even_or_first ? 2 : 4,
|
||||
last ? 5 : 6,
|
||||
even_or_first ? 4 : 2,
|
||||
even_or_first ? 3 : -2,
|
||||
};
|
||||
|
||||
/* Ensure NIR can see thru the local array */
|
||||
uint offset = 0;
|
||||
for (uint i = 1; i < 6; ++i) {
|
||||
if (i == vert)
|
||||
offset = offsets[i];
|
||||
}
|
||||
|
||||
/* Finally add to the base of the primitive */
|
||||
return (prim * 2) + offset;
|
||||
}
|
||||
|
||||
static uint
|
||||
vertex_id_for_topology(enum mesa_prim mode, bool flatshade_first, uint prim,
|
||||
uint vert, uint num_prims)
|
||||
{
|
||||
switch (mode) {
|
||||
case MESA_PRIM_POINTS:
|
||||
case MESA_PRIM_LINES:
|
||||
case MESA_PRIM_TRIANGLES:
|
||||
case MESA_PRIM_LINES_ADJACENCY:
|
||||
case MESA_PRIM_TRIANGLES_ADJACENCY:
|
||||
/* Regular primitive: every N vertices defines a primitive */
|
||||
return (prim * mesa_vertices_per_prim(mode)) + vert;
|
||||
|
||||
case MESA_PRIM_LINE_LOOP:
|
||||
return vertex_id_for_line_loop(prim, vert, num_prims);
|
||||
|
||||
case MESA_PRIM_LINE_STRIP:
|
||||
case MESA_PRIM_LINE_STRIP_ADJACENCY:
|
||||
/* (i, i + 1) or (i, ..., i + 3) */
|
||||
return prim + vert;
|
||||
|
||||
case MESA_PRIM_TRIANGLE_STRIP: {
|
||||
/* Order depends on the provoking vert.
|
||||
*
|
||||
* First: (0, 1, 2), (1, 3, 2), (2, 3, 4).
|
||||
* Last: (0, 1, 2), (2, 1, 3), (2, 3, 4).
|
||||
*
|
||||
* Pull the (maybe swapped) vert from the corresponding primitive
|
||||
*/
|
||||
return prim + map_vertex_in_tri_strip(prim, vert, flatshade_first);
|
||||
}
|
||||
|
||||
case MESA_PRIM_TRIANGLE_FAN:
|
||||
return vertex_id_for_tri_fan(prim, vert, flatshade_first);
|
||||
|
||||
case MESA_PRIM_TRIANGLE_STRIP_ADJACENCY:
|
||||
return vertex_id_for_tri_strip_adj(prim, vert, num_prims,
|
||||
flatshade_first);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
KERNEL(1)
|
||||
libagx_increment_ia(global uint32_t *ia_vertices,
|
||||
global uint32_t *ia_primitives,
|
||||
|
|
@ -321,7 +186,7 @@ libagx_unroll_restart(global struct poly_heap *heap, uint64_t index_buffer,
|
|||
for (uint i = tid; i < subprims; i += 1024) {
|
||||
for (uint vtx = 0; vtx < per_prim; ++vtx) {
|
||||
uint id =
|
||||
vertex_id_for_topology(mode, flatshade_first, i, vtx, subprims);
|
||||
poly_vertex_id_for_topology(mode, flatshade_first, i, vtx, subprims);
|
||||
uint offset = needle + id;
|
||||
|
||||
uint x = ((out_prims_base + i) * per_prim) + vtx;
|
||||
|
|
|
|||
|
|
@ -7,30 +7,13 @@
|
|||
|
||||
#include "compiler/libcl/libcl_vk.h"
|
||||
#include "poly/geometry.h"
|
||||
#include "poly/prim.h"
|
||||
#include "poly/tessellator.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
uint64_t nir_ro_to_rw_poly(uint64_t address);
|
||||
|
||||
/* Swap the two non-provoking vertices in odd triangles. This generates a vertex
|
||||
* ID list with a consistent winding order.
|
||||
*
|
||||
* Holding prim and flatshade_first constant, the map : [0, 1, 2] -> [0, 1, 2]
|
||||
* is its own inverse. It is hence used both vertex fetch and transform
|
||||
* feedback.
|
||||
*/
|
||||
static uint
|
||||
map_vertex_in_tri_strip(uint prim, uint vert, bool flatshade_first)
|
||||
{
|
||||
unsigned pv = flatshade_first ? 0 : 2;
|
||||
|
||||
bool even = (prim & 1) == 0;
|
||||
bool provoking = vert == pv;
|
||||
|
||||
return (provoking || even) ? vert : ((3 - pv) - vert);
|
||||
}
|
||||
|
||||
static inline uint
|
||||
xfb_prim(uint id, uint n, uint copy)
|
||||
{
|
||||
|
|
@ -60,7 +43,7 @@ poly_xfb_vertex_offset(uint n, uint invocation_base_prim, uint strip_base_prim,
|
|||
uint vert = vert_0 - copy;
|
||||
|
||||
if (n == 3) {
|
||||
vert = map_vertex_in_tri_strip(prim, vert, flatshade_first);
|
||||
vert = poly_map_vertex_in_tri_strip(prim, vert, flatshade_first);
|
||||
}
|
||||
|
||||
/* Tally up in the whole buffer */
|
||||
|
|
@ -78,16 +61,6 @@ poly_xfb_vertex_address(constant struct poly_geometry_params *p, uint index,
|
|||
return (uintptr_t)(p->xfb_base[buffer]) + xfb_offset;
|
||||
}
|
||||
|
||||
static uint
|
||||
vertex_id_for_line_loop(uint prim, uint vert, uint num_prims)
|
||||
{
|
||||
/* (0, 1), (1, 2), (2, 0) */
|
||||
if (prim == (num_prims - 1) && vert == 1)
|
||||
return 0;
|
||||
else
|
||||
return prim + vert;
|
||||
}
|
||||
|
||||
uint
|
||||
poly_vertex_id_for_line_class(enum mesa_prim mode, uint prim, uint vert,
|
||||
uint num_prims)
|
||||
|
|
@ -102,24 +75,6 @@ poly_vertex_id_for_line_class(enum mesa_prim mode, uint prim, uint vert,
|
|||
return prim + vert;
|
||||
}
|
||||
|
||||
static uint
|
||||
vertex_id_for_tri_fan(uint prim, uint vert, bool flatshade_first)
|
||||
{
|
||||
/* Vulkan spec section 20.1.7 gives (i + 1, i + 2, 0) for a provoking
|
||||
* first. OpenGL instead wants (0, i + 1, i + 2) with a provoking last.
|
||||
* Piglit clipflat expects us to switch between these orders depending on
|
||||
* provoking vertex, to avoid trivializing the fan.
|
||||
*
|
||||
* Rotate accordingly.
|
||||
*/
|
||||
if (flatshade_first) {
|
||||
vert = (vert == 2) ? 0 : (vert + 1);
|
||||
}
|
||||
|
||||
/* The simpler form assuming last is provoking. */
|
||||
return (vert == 0) ? 0 : prim + vert;
|
||||
}
|
||||
|
||||
uint
|
||||
poly_vertex_id_for_tri_class(enum mesa_prim mode, uint prim, uint vert,
|
||||
bool flatshade_first)
|
||||
|
|
@ -158,108 +113,18 @@ poly_vertex_id_for_line_adj_class(enum mesa_prim mode, uint prim, uint vert)
|
|||
return prim + vert;
|
||||
}
|
||||
|
||||
static uint
|
||||
vertex_id_for_tri_strip_adj(uint prim, uint vert, uint num_prims,
|
||||
bool flatshade_first)
|
||||
{
|
||||
/* See Vulkan spec section 20.1.11 "Triangle Strips With Adjancency".
|
||||
*
|
||||
* There are different cases for first/middle/last/only primitives and for
|
||||
* odd/even primitives. Determine which case we're in.
|
||||
*/
|
||||
bool last = prim == (num_prims - 1);
|
||||
bool first = prim == 0;
|
||||
bool even = (prim & 1) == 0;
|
||||
bool even_or_first = even || first;
|
||||
|
||||
/* When the last vertex is provoking, we rotate the primitives
|
||||
* accordingly. This seems required for OpenGL.
|
||||
*/
|
||||
if (!flatshade_first && !even_or_first) {
|
||||
vert = (vert + 4u) % 6u;
|
||||
}
|
||||
|
||||
/* Offsets per the spec. The spec lists 6 cases with 6 offsets. Luckily,
|
||||
* there are lots of patterns we can exploit, avoiding a full 6x6 LUT.
|
||||
*
|
||||
* Here we assume the first vertex is provoking, the Vulkan default.
|
||||
*/
|
||||
uint offsets[6] = {
|
||||
0,
|
||||
first ? 1 : (even ? -2 : 3),
|
||||
even_or_first ? 2 : 4,
|
||||
last ? 5 : 6,
|
||||
even_or_first ? 4 : 2,
|
||||
even_or_first ? 3 : -2,
|
||||
};
|
||||
|
||||
/* Ensure NIR can see thru the local array */
|
||||
uint offset = 0;
|
||||
for (uint i = 1; i < 6; ++i) {
|
||||
if (i == vert)
|
||||
offset = offsets[i];
|
||||
}
|
||||
|
||||
/* Finally add to the base of the primitive */
|
||||
return (prim * 2) + offset;
|
||||
}
|
||||
|
||||
uint
|
||||
poly_vertex_id_for_tri_adj_class(enum mesa_prim mode, uint prim, uint vert,
|
||||
uint nr, bool flatshade_first)
|
||||
{
|
||||
/* Tri adj list or tri adj strip */
|
||||
if (mode == MESA_PRIM_TRIANGLE_STRIP_ADJACENCY) {
|
||||
return vertex_id_for_tri_strip_adj(prim, vert, nr, flatshade_first);
|
||||
return poly_vertex_id_for_tri_strip_adj(prim, vert, nr, flatshade_first);
|
||||
} else {
|
||||
return (6 * prim) + vert;
|
||||
}
|
||||
}
|
||||
|
||||
static uint
|
||||
vertex_id_for_topology(enum mesa_prim mode, bool flatshade_first, uint prim,
|
||||
uint vert, uint num_prims)
|
||||
{
|
||||
switch (mode) {
|
||||
case MESA_PRIM_POINTS:
|
||||
case MESA_PRIM_LINES:
|
||||
case MESA_PRIM_TRIANGLES:
|
||||
case MESA_PRIM_LINES_ADJACENCY:
|
||||
case MESA_PRIM_TRIANGLES_ADJACENCY:
|
||||
/* Regular primitive: every N vertices defines a primitive */
|
||||
return (prim * mesa_vertices_per_prim(mode)) + vert;
|
||||
|
||||
case MESA_PRIM_LINE_LOOP:
|
||||
return vertex_id_for_line_loop(prim, vert, num_prims);
|
||||
|
||||
case MESA_PRIM_LINE_STRIP:
|
||||
case MESA_PRIM_LINE_STRIP_ADJACENCY:
|
||||
/* (i, i + 1) or (i, ..., i + 3) */
|
||||
return prim + vert;
|
||||
|
||||
case MESA_PRIM_TRIANGLE_STRIP: {
|
||||
/* Order depends on the provoking vert.
|
||||
*
|
||||
* First: (0, 1, 2), (1, 3, 2), (2, 3, 4).
|
||||
* Last: (0, 1, 2), (2, 1, 3), (2, 3, 4).
|
||||
*
|
||||
* Pull the (maybe swapped) vert from the corresponding primitive
|
||||
*/
|
||||
return prim + map_vertex_in_tri_strip(prim, vert, flatshade_first);
|
||||
}
|
||||
|
||||
case MESA_PRIM_TRIANGLE_FAN:
|
||||
return vertex_id_for_tri_fan(prim, vert, flatshade_first);
|
||||
|
||||
case MESA_PRIM_TRIANGLE_STRIP_ADJACENCY:
|
||||
return vertex_id_for_tri_strip_adj(prim, vert, num_prims,
|
||||
flatshade_first);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint
|
||||
poly_map_to_line_adj(uint id)
|
||||
{
|
||||
|
|
|
|||
147
src/poly/prim.h
Normal file
147
src/poly/prim.h
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright 2023 Alyssa Rosenzweig
|
||||
* Copyright 2023 Valve Corporation
|
||||
* Copyright 2025 Collabora Ltd.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "compiler/libcl/libcl.h"
|
||||
#include "compiler/shader_enums.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
/* Swap the two non-provoking vertices in odd triangles. This generates a vertex
|
||||
* ID list with a consistent winding order.
|
||||
*
|
||||
* Holding prim and flatshade_first constant, the map : [0, 1, 2] -> [0, 1, 2]
|
||||
* is its own inverse. It is hence used both vertex fetch and transform
|
||||
* feedback.
|
||||
*/
|
||||
static inline uint32_t
|
||||
poly_map_vertex_in_tri_strip(uint32_t prim, uint32_t vert, bool flatshade_first)
|
||||
{
|
||||
unsigned pv = flatshade_first ? 0 : 2;
|
||||
|
||||
bool even = (prim & 1) == 0;
|
||||
bool provoking = vert == pv;
|
||||
|
||||
return (provoking || even) ? vert : ((3 - pv) - vert);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
poly_vertex_id_for_line_loop(uint32_t prim, uint32_t vert, uint32_t num_prims)
|
||||
{
|
||||
/* (0, 1), (1, 2), (2, 0) */
|
||||
if (prim == (num_prims - 1) && vert == 1)
|
||||
return 0;
|
||||
else
|
||||
return prim + vert;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
poly_vertex_id_for_tri_fan(uint32_t prim, uint32_t vert, bool flatshade_first)
|
||||
{
|
||||
/* Vulkan spec section 20.1.7 gives (i + 1, i + 2, 0) for a provoking
|
||||
* first. OpenGL instead wants (0, i + 1, i + 2) with a provoking last.
|
||||
* Piglit clipflat expects us to switch between these orders depending on
|
||||
* provoking vertex, to avoid trivializing the fan.
|
||||
*
|
||||
* Rotate accordingly.
|
||||
*/
|
||||
if (flatshade_first) {
|
||||
vert = (vert == 2) ? 0 : (vert + 1);
|
||||
}
|
||||
|
||||
/* The simpler form assuming last is provoking. */
|
||||
return (vert == 0) ? 0 : prim + vert;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
poly_vertex_id_for_tri_strip_adj(uint32_t prim, uint32_t vert,
|
||||
uint32_t num_prims, bool flatshade_first)
|
||||
{
|
||||
/* See Vulkan spec section 20.1.11 "Triangle Strips With Adjancency".
|
||||
*
|
||||
* There are different cases for first/middle/last/only primitives and for
|
||||
* odd/even primitives. Determine which case we're in.
|
||||
*/
|
||||
bool last = prim == (num_prims - 1);
|
||||
bool first = prim == 0;
|
||||
bool even = (prim & 1) == 0;
|
||||
bool even_or_first = even || first;
|
||||
|
||||
/* When the last vertex is provoking, we rotate the primitives
|
||||
* accordingly. This seems required for OpenGL.
|
||||
*/
|
||||
if (!flatshade_first && !even_or_first) {
|
||||
vert = (vert + 4u) % 6u;
|
||||
}
|
||||
|
||||
/* Offsets per the spec. The spec lists 6 cases with 6 offsets. Luckily,
|
||||
* there are lots of patterns we can exploit, avoiding a full 6x6 LUT.
|
||||
*
|
||||
* Here we assume the first vertex is provoking, the Vulkan default.
|
||||
*/
|
||||
uint32_t offsets[6] = {
|
||||
0,
|
||||
first ? 1 : (even ? -2 : 3),
|
||||
even_or_first ? 2 : 4,
|
||||
last ? 5 : 6,
|
||||
even_or_first ? 4 : 2,
|
||||
even_or_first ? 3 : -2,
|
||||
};
|
||||
|
||||
/* Ensure NIR can see thru the local array */
|
||||
uint32_t offset = 0;
|
||||
for (uint32_t i = 1; i < 6; ++i) {
|
||||
if (i == vert)
|
||||
offset = offsets[i];
|
||||
}
|
||||
|
||||
/* Finally add to the base of the primitive */
|
||||
return (prim * 2) + offset;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
poly_vertex_id_for_topology(enum mesa_prim mode, bool flatshade_first,
|
||||
uint32_t prim, uint32_t vert, uint32_t num_prims)
|
||||
{
|
||||
switch (mode) {
|
||||
case MESA_PRIM_POINTS:
|
||||
case MESA_PRIM_LINES:
|
||||
case MESA_PRIM_TRIANGLES:
|
||||
case MESA_PRIM_LINES_ADJACENCY:
|
||||
case MESA_PRIM_TRIANGLES_ADJACENCY:
|
||||
/* Regular primitive: every N vertices defines a primitive */
|
||||
return (prim * mesa_vertices_per_prim(mode)) + vert;
|
||||
|
||||
case MESA_PRIM_LINE_LOOP:
|
||||
return poly_vertex_id_for_line_loop(prim, vert, num_prims);
|
||||
|
||||
case MESA_PRIM_LINE_STRIP:
|
||||
case MESA_PRIM_LINE_STRIP_ADJACENCY:
|
||||
/* (i, i + 1) or (i, ..., i + 3) */
|
||||
return prim + vert;
|
||||
|
||||
case MESA_PRIM_TRIANGLE_STRIP: {
|
||||
/* Order depends on the provoking vert.
|
||||
*
|
||||
* First: (0, 1, 2), (1, 3, 2), (2, 3, 4).
|
||||
* Last: (0, 1, 2), (2, 1, 3), (2, 3, 4).
|
||||
*
|
||||
* Pull the (maybe swapped) vert from the corresponding primitive
|
||||
*/
|
||||
return prim + poly_map_vertex_in_tri_strip(prim, vert, flatshade_first);
|
||||
}
|
||||
|
||||
case MESA_PRIM_TRIANGLE_FAN:
|
||||
return poly_vertex_id_for_tri_fan(prim, vert, flatshade_first);
|
||||
|
||||
case MESA_PRIM_TRIANGLE_STRIP_ADJACENCY:
|
||||
return poly_vertex_id_for_tri_strip_adj(prim, vert, num_prims,
|
||||
flatshade_first);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue