anv: rewrite internal shaders using OpenCL

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26797>
This commit is contained in:
Lionel Landwerlin
2023-11-06 13:12:25 +02:00
committed by Marge Bot
parent da391650f5
commit b52e25d3a8
26 changed files with 911 additions and 1133 deletions
+206
View File
@@ -0,0 +1,206 @@
/* Copyright © 2023 Intel Corporation
* SPDX-License-Identifier: MIT
*/
#include "libintel_shaders.h"
void genX(write_3DSTATE_VERTEX_BUFFERS)(global void *dst_ptr,
uint32_t buffer_count)
{
struct GENX(3DSTATE_VERTEX_BUFFERS) v = {
GENX(3DSTATE_VERTEX_BUFFERS_header),
};
v.DWordLength = 1 + (buffer_count * 4) -
GENX(3DSTATE_VERTEX_BUFFERS_length_bias);
GENX(3DSTATE_VERTEX_BUFFERS_pack)(dst_ptr, &v);
}
void genX(write_VERTEX_BUFFER_STATE)(global void *dst_ptr,
uint32_t mocs,
uint32_t buffer_idx,
uint64_t address,
uint32_t size,
uint32_t stride)
{
bool buffer_null = address == 0;
struct GENX(VERTEX_BUFFER_STATE) v = {
.BufferPitch = stride,
.NullVertexBuffer = address == 0,
.AddressModifyEnable = true,
.MOCS = mocs,
#if GFX_VER >= 12
.L3BypassDisable = true,
#endif
.VertexBufferIndex = buffer_idx,
.BufferStartingAddress = address,
.BufferSize = size,
};
GENX(VERTEX_BUFFER_STATE_pack)(dst_ptr, &v);
}
#if GFX_VER == 9
void genX(write_3DPRIMITIVE)(global void *dst_ptr,
bool is_predicated,
bool is_indexed,
bool uses_tbimr,
uint32_t vertex_count_per_instance,
uint32_t start_vertex_location,
uint32_t instance_count,
uint32_t start_instance_location,
uint32_t base_vertex_location)
{
struct GENX(3DPRIMITIVE) v = {
GENX(3DPRIMITIVE_header),
#if GFX_VERx10 >= 125
.TBIMREnable = uses_tbimr,
#endif
.PredicateEnable = is_predicated,
.VertexAccessType = is_indexed ? RANDOM : SEQUENTIAL,
.VertexCountPerInstance = vertex_count_per_instance,
.StartVertexLocation = start_vertex_location,
.InstanceCount = instance_count,
.StartInstanceLocation = start_instance_location,
.BaseVertexLocation = base_vertex_location,
};
GENX(3DPRIMITIVE_pack)(dst_ptr, &v);
}
#endif
#if GFX_VER >= 11
void genX(write_3DPRIMITIVE_EXTENDED)(global void *dst_ptr,
bool is_predicated,
bool is_indexed,
bool uses_tbimr,
uint32_t vertex_count_per_instance,
uint32_t start_vertex_location,
uint32_t instance_count,
uint32_t start_instance_location,
uint32_t base_vertex_location,
uint32_t param_base_vertex,
uint32_t param_base_instance,
uint32_t param_draw_id)
{
struct GENX(3DPRIMITIVE_EXTENDED) v = {
GENX(3DPRIMITIVE_EXTENDED_header),
#if GFX_VERx10 >= 125
.TBIMREnable = uses_tbimr,
#endif
.PredicateEnable = is_predicated,
.VertexAccessType = is_indexed ? RANDOM : SEQUENTIAL,
.VertexCountPerInstance = vertex_count_per_instance,
.StartVertexLocation = start_vertex_location,
.InstanceCount = instance_count,
.StartInstanceLocation = start_instance_location,
.BaseVertexLocation = base_vertex_location,
.ExtendedParameter0 = param_base_vertex,
.ExtendedParameter1 = param_base_instance,
.ExtendedParameter2 = param_draw_id,
};
GENX(3DPRIMITIVE_EXTENDED_pack)(dst_ptr, &v);
}
#endif
void genX(write_MI_BATCH_BUFFER_START)(global void *dst_ptr, uint64_t addr)
{
struct GENX(MI_BATCH_BUFFER_START) v = {
GENX(MI_BATCH_BUFFER_START_header),
.AddressSpaceIndicator = ASI_PPGTT,
.BatchBufferStartAddress = addr,
};
GENX(MI_BATCH_BUFFER_START_pack)(dst_ptr, &v);
}
void genX(write_draw)(global uint32_t *dst_ptr,
global void *indirect_ptr,
global uint32_t *draw_id_ptr,
uint32_t draw_id,
uint32_t instance_multiplier,
bool is_indexed,
bool is_predicated,
bool uses_tbimr,
bool uses_base,
bool uses_drawid,
uint32_t mocs)
{
#if GFX_VER == 9
if (uses_base || uses_drawid) {
uint32_t vertex_buffer_count =
(uses_base ? 1 : 0) + (uses_drawid ? 1 : 0);
genX(write_3DSTATE_VERTEX_BUFFERS)(dst_ptr, vertex_buffer_count);
dst_ptr += 1; /* GENX(3DSTATE_VERTEX_BUFFERS_length); */
if (uses_base) {
uint64_t base_addr = (uint64_t)indirect_ptr + (is_indexed ? 12 : 8);
genX(write_VERTEX_BUFFER_STATE)(dst_ptr, mocs, 31, base_addr, 8, 0);
dst_ptr += GENX(VERTEX_BUFFER_STATE_length);
}
if (uses_drawid) {
*draw_id_ptr = draw_id;
genX(write_VERTEX_BUFFER_STATE)(dst_ptr, mocs, 32,
(uint64_t)draw_id_ptr, 4, 0);
dst_ptr += GENX(VERTEX_BUFFER_STATE_length);
}
}
if (is_indexed) {
VkDrawIndexedIndirectCommand data =
*((global VkDrawIndexedIndirectCommand *)indirect_ptr);
genX(write_3DPRIMITIVE)(dst_ptr,
is_predicated,
is_indexed,
uses_tbimr,
data.indexCount,
data.firstIndex,
data.instanceCount * instance_multiplier,
data.firstInstance,
data.vertexOffset);
} else {
VkDrawIndirectCommand data =
*((global VkDrawIndirectCommand *)indirect_ptr);
genX(write_3DPRIMITIVE)(dst_ptr,
is_predicated,
is_indexed,
uses_tbimr,
data.vertexCount,
data.firstVertex,
data.instanceCount * instance_multiplier,
data.firstInstance,
0 /* base_vertex_location */);
}
#else
if (is_indexed) {
VkDrawIndexedIndirectCommand data =
*((global VkDrawIndexedIndirectCommand *)indirect_ptr);
genX(write_3DPRIMITIVE_EXTENDED)(dst_ptr,
is_predicated,
is_indexed,
uses_tbimr,
data.indexCount,
data.firstIndex,
data.instanceCount * instance_multiplier,
data.firstInstance,
data.vertexOffset,
data.vertexOffset,
data.firstInstance,
draw_id);
} else {
VkDrawIndirectCommand data =
*((global VkDrawIndirectCommand *)indirect_ptr);
genX(write_3DPRIMITIVE_EXTENDED)(dst_ptr,
is_predicated,
is_indexed,
uses_tbimr,
data.vertexCount,
data.firstVertex,
data.instanceCount * instance_multiplier,
data.firstInstance,
0 /* base_vertex_location */,
data.firstVertex,
data.firstInstance,
draw_id);
}
#endif
}
+77
View File
@@ -0,0 +1,77 @@
/* Copyright © 2023 Intel Corporation
* SPDX-License-Identifier: MIT
*/
#include "libintel_shaders.h"
static void end_generated_draws(global void *dst_ptr,
uint32_t item_idx,
uint32_t draw_id, uint32_t draw_count,
uint32_t ring_count, uint32_t max_draw_count,
uint32_t flags,
uint64_t gen_addr, uint64_t end_addr)
{
uint32_t _3dprim_size_B = ((flags >> 16) & 0xff) * 4;
bool indirect_count = (flags & ANV_GENERATED_FLAG_COUNT) != 0;
bool ring_mode = (flags & ANV_GENERATED_FLAG_RING_MODE) != 0;
/* We can have an indirect draw count = 0. */
uint32_t last_draw_id = draw_count == 0 ? 0 : (min(draw_count, max_draw_count) - 1);
global void *jump_dst = draw_count == 0 ? dst_ptr : (dst_ptr + _3dprim_size_B);
if (ring_mode) {
if (draw_id == last_draw_id) {
/* Exit the ring buffer to the next user commands */
genX(write_MI_BATCH_BUFFER_START)(jump_dst, end_addr);
} else if (item_idx == (ring_count - 1)) {
/* Jump back to the generation shader to generate mode draws */
genX(write_MI_BATCH_BUFFER_START)(jump_dst, gen_addr);
}
} else {
if (draw_id == last_draw_id && draw_count < max_draw_count) {
/* Skip forward to the end of the generated draws */
genX(write_MI_BATCH_BUFFER_START)(jump_dst, end_addr);
}
}
}
void
genX(libanv_write_draw)(global void *dst_base,
global void *indirect_base,
global void *draw_id_base,
uint32_t indirect_stride,
global uint32_t *_draw_count,
uint32_t draw_base,
uint32_t instance_multiplier,
uint32_t max_draw_count,
uint32_t flags,
uint32_t ring_count,
uint64_t gen_addr,
uint64_t end_addr,
uint32_t item_idx)
{
uint32_t _3dprim_size_B = ((flags >> 16) & 0xff) * 4;
uint32_t draw_id = draw_base + item_idx;
uint32_t draw_count = *_draw_count;
global void *dst_ptr = dst_base + item_idx * _3dprim_size_B;
global void *indirect_ptr = indirect_base + draw_id * indirect_stride;
global void *draw_id_ptr = draw_id_base + item_idx * 4;
if (draw_id < min(draw_count, max_draw_count)) {
bool is_indexed = (flags & ANV_GENERATED_FLAG_INDEXED) != 0;
bool is_predicated = (flags & ANV_GENERATED_FLAG_PREDICATED) != 0;
bool uses_tbimr = (flags & ANV_GENERATED_FLAG_TBIMR) != 0;
bool uses_base = (flags & ANV_GENERATED_FLAG_BASE) != 0;
bool uses_drawid = (flags & ANV_GENERATED_FLAG_DRAWID) != 0;
uint32_t mocs = (flags >> 8) & 0xff;
genX(write_draw)(dst_ptr, indirect_ptr, draw_id_ptr,
draw_id, instance_multiplier,
is_indexed, is_predicated,
uses_tbimr, uses_base, uses_drawid,
mocs);
}
end_generated_draws(dst_ptr, item_idx, draw_id, draw_count,
ring_count, max_draw_count, flags,
gen_addr, end_addr);
}
+127
View File
@@ -0,0 +1,127 @@
/* Copyright © 2023 Intel Corporation
* SPDX-License-Identifier: MIT
*/
#ifndef _LIBANV_SHADERS_H_
#define _LIBANV_SHADERS_H_
/* Define stdint types compatible between the CPU and GPU for shared headers */
#ifndef __OPENCL_VERSION__
#include <stdint.h>
#include "util/macros.h"
#else
#define BITFIELD_BIT(i) (1u << i)
typedef ulong uint64_t;
typedef uint uint32_t;
typedef ushort uint16_t;
typedef uchar uint8_t;
typedef long int64_t;
typedef int int32_t;
typedef short int16_t;
typedef char int8_t;
typedef struct VkDrawIndexedIndirectCommand {
uint32_t indexCount;
uint32_t instanceCount;
uint32_t firstIndex;
int32_t vertexOffset;
uint32_t firstInstance;
} VkDrawIndexedIndirectCommand __attribute__((aligned(4)));
typedef struct VkDrawIndirectCommand {
uint32_t vertexCount;
uint32_t instanceCount;
uint32_t firstVertex;
uint32_t firstInstance;
} VkDrawIndirectCommand __attribute__((aligned(4)));
#include "genxml/gen_macros.h"
#include "genxml/genX_cl_pack.h"
#endif
/**
* Flags for generated_draws.cl
*/
#define ANV_GENERATED_FLAG_INDEXED BITFIELD_BIT(0)
#define ANV_GENERATED_FLAG_PREDICATED BITFIELD_BIT(1)
/* Only used on Gfx9, means the pipeline is using gl_DrawID */
#define ANV_GENERATED_FLAG_DRAWID BITFIELD_BIT(2)
/* Only used on Gfx9, means the pipeline is using gl_BaseVertex or
* gl_BaseInstance
*/
#define ANV_GENERATED_FLAG_BASE BITFIELD_BIT(3)
/* Whether the count is indirect */
#define ANV_GENERATED_FLAG_COUNT BITFIELD_BIT(4)
/* Whether the generation shader writes to the ring buffer */
#define ANV_GENERATED_FLAG_RING_MODE BITFIELD_BIT(5)
/* Whether TBIMR tile-based rendering shall be enabled. */
#define ANV_GENERATED_FLAG_TBIMR BITFIELD_BIT(6)
/**
* Flags for query_copy.cl
*/
#define ANV_COPY_QUERY_FLAG_RESULT64 BITFIELD_BIT(0)
#define ANV_COPY_QUERY_FLAG_AVAILABLE BITFIELD_BIT(1)
#define ANV_COPY_QUERY_FLAG_DELTA BITFIELD_BIT(2)
#define ANV_COPY_QUERY_FLAG_PARTIAL BITFIELD_BIT(3)
#ifdef __OPENCL_VERSION__
void genX(write_3DSTATE_VERTEX_BUFFERS)(global void *dst_ptr,
uint32_t buffer_count);
void genX(write_VERTEX_BUFFER_STATE)(global void *dst_ptr,
uint32_t mocs,
uint32_t buffer_idx,
uint64_t address,
uint32_t size,
uint32_t stride);
#if GFX_VER == 9
void genX(write_3DPRIMITIVE)(global void *dst_ptr,
bool is_predicated,
bool is_indexed,
bool use_tbimr,
uint32_t vertex_count_per_instance,
uint32_t start_vertex_location,
uint32_t instance_count,
uint32_t start_instance_location,
uint32_t base_vertex_location);
#endif
#if GFX_VER >= 11
void genX(write_3DPRIMITIVE_EXTENDED)(global void *dst_ptr,
bool is_predicated,
bool is_indexed,
bool use_tbimr,
uint32_t vertex_count_per_instance,
uint32_t start_vertex_location,
uint32_t instance_count,
uint32_t start_instance_location,
uint32_t base_vertex_location,
uint32_t param_base_vertex,
uint32_t param_base_instance,
uint32_t param_draw_id);
#endif
void genX(write_MI_BATCH_BUFFER_START)(global void *dst_ptr, uint64_t addr);
void genX(write_draw)(global uint32_t *dst_ptr,
global void *indirect_ptr,
global uint32_t *draw_id_ptr,
uint32_t draw_id,
uint32_t instance_multiplier,
bool is_indexed,
bool is_predicated,
bool uses_tbimr,
bool uses_base,
bool uses_draw_id,
uint32_t mocs);
#endif /* __OPENCL_VERSION__ */
#endif /* _LIBANV_SHADERS_H_ */
+23
View File
@@ -0,0 +1,23 @@
/* Copyright © 2023 Intel Corporation
* SPDX-License-Identifier: MIT
*/
void
genX(libanv_memcpy)(global void *dst_base,
global void *src_base,
uint num_dwords,
uint dword_offset)
{
global void *dst = dst_base + 4 * dword_offset;
global void *src = src_base + 4 * dword_offset;
if (dword_offset + 4 <= num_dwords) {
*(global uint4 *)(dst) = *(global uint4 *)(src);
} else if (dword_offset + 3 <= num_dwords) {
*(global uint3 *)(dst) = *(global uint3 *)(src);
} else if (dword_offset + 2 <= num_dwords) {
*(global uint2 *)(dst) = *(global uint2 *)(src);
} else if (dword_offset + 1 <= num_dwords) {
*(global uint *)(dst) = *(global uint *)(src);
}
}
+63
View File
@@ -0,0 +1,63 @@
# Copyright © 2023 Intel Corporation
# SPDX-License-Identifier: MIT
intel_float64_spv_h = custom_target(
'float64_spv.h',
input : [glsl2spirv, float64_glsl_file],
output : 'float64_spv.h',
command : [
prog_python, '@INPUT@', '@OUTPUT@',
prog_glslang,
'--create-entry', 'main',
'--vn', 'float64_spv_source',
'--glsl-version', '450',
'-Olib',
]
)
intel_shader_files = files(
'libintel_shaders.h',
'generate.cl',
'generate_draws.cl',
'memcpy.cl',
'query_copy.cl',
)
prepended_input_args = []
foreach input_arg : intel_shader_files
prepended_input_args += ['--in', input_arg]
endforeach
intel_shaders_gens = [ [ 90, 9],
[110, 11],
[120, 12],
[125, 125],
[200, 20] ]
intel_shaders = []
foreach gen : intel_shaders_gens
intel_shaders += custom_target(
'intel_gfx@0@_shaders_code.h'.format(gen[1]),
input : intel_shader_files,
output : 'intel_gfx@0@_shaders_code.h'.format(gen[1]),
command : [
prog_intel_clc, '--nir',
'--prefix', 'gfx@0@_intel_shaders'.format(gen[1]),
prepended_input_args, '-o', '@OUTPUT@', '--',
'-cl-std=cl2.0', '-D__OPENCL_VERSION__=200',
'-DGFX_VERx10=@0@'.format(gen[0]),
'-I' + join_paths(meson.current_source_dir(), '.'),
'-I' + join_paths(meson.source_root(), 'src'),
'-I' + join_paths(meson.source_root(), 'src/intel'),
'-I' + join_paths(meson.build_root(), 'src/intel'),
'-I' + join_paths(meson.source_root(), 'src/intel/genxml'),
'-include', 'opencl-c.h',
],
env: ['MESA_SHADER_CACHE_DISABLE=true'],
depends : [dep_prog_intel_clc, gen_cl_xml_pack],
)
endforeach
idep_intel_shaders = declare_dependency(
sources : intel_shaders,
include_directories : include_directories('.'),
)
+72
View File
@@ -0,0 +1,72 @@
/* Copyright © 2023 Intel Corporation
* SPDX-License-Identifier: MIT
*/
void
genX(libanv_query_copy)(global void *destination_base,
uint32_t destination_stride,
global void *query_data,
uint32_t first_query,
uint32_t num_queries,
uint32_t query_data_offset,
uint32_t query_stride,
uint32_t num_query_items,
uint32_t copy_flags,
uint32_t copy_item_idx)
{
if (copy_item_idx >= num_queries)
return;
bool is_result64 = (copy_flags & ANV_COPY_QUERY_FLAG_RESULT64) != 0;
bool write_available = (copy_flags & ANV_COPY_QUERY_FLAG_AVAILABLE) != 0;
bool compute_delta = (copy_flags & ANV_COPY_QUERY_FLAG_DELTA) != 0;
bool partial_result = (copy_flags & ANV_COPY_QUERY_FLAG_PARTIAL) != 0;
uint query_byte = (first_query + copy_item_idx) * query_stride;
uint query_data_byte = query_byte + query_data_offset;
global uint64_t *query = query_data + (first_query + copy_item_idx) * query_stride;
global uint64_t *dest64 = destination_base + copy_item_idx * destination_stride;
global uint32_t *dest32 = destination_base + copy_item_idx * destination_stride;
uint64_t availability = *(global uint32_t *)(query_data + query_byte);
if (write_available) {
if (is_result64)
dest64[num_query_items] = availability;
else
dest32[num_query_items] = availability;
}
for (uint32_t i = 0; i < num_query_items; i++) {
uint32_t qw_offset = 1 + i * 2;
uint64_t v;
if (compute_delta) {
struct delta64 {
uint64_t v0;
uint64_t v1;
} data = *((global struct delta64 *)&query[qw_offset]);
v = data.v1 - data.v0;
} else {
v = query[qw_offset + 0];
}
/* vkCmdCopyQueryPoolResults:
*
* "If VK_QUERY_RESULT_PARTIAL_BIT is set, then for any query that is
* unavailable, an intermediate result between zero and the final
* result value is written for that query."
*
* We write 0 as the values not being written yet, we can't really make
* provide any sensible value.
*/
if (partial_result && availability == 0)
v = 0;
if (is_result64)
dest64[i] = v;
else
dest32[i] = v;
}
}