dzn: Add KHR_draw_indirect_count support

Unfortunately it's not as simple as passing the indirect draw count
buffer to ExecuteIndirect. The compute job that populate the execute
buffer also needs to know the number of entries that need to be
patched. Instead of transitioning the indirect count buffer from
GENERIC_READ to INDIRECT_ARGUMENT we just keep at as a read-only
resource and copy the draw_count value to the exec buffer in the
compute job.

Acked-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15914>
This commit is contained in:
Boris Brezillon
2022-04-07 06:49:00 -07:00
committed by Marge Bot
parent ece5e27a7f
commit e018311b35
6 changed files with 177 additions and 34 deletions
+8
View File
@@ -874,6 +874,14 @@ dEQP-VK.api.copy_and_blit.dedicated_allocation.blit_image.all_formats.depth_sten
dEQP-VK.api.copy_and_blit.dedicated_allocation.blit_image.all_formats.depth_stencil.2d.d32_sfloat_s8_uint_d32_sfloat_s8_uint_separate_layouts.general_optimal_nearest,Fail
dEQP-VK.api.copy_and_blit.dedicated_allocation.blit_image.all_formats.depth_stencil.2d.d32_sfloat_s8_uint_d32_sfloat_s8_uint_separate_layouts.optimal_general_nearest,Fail
dEQP-VK.api.copy_and_blit.dedicated_allocation.blit_image.all_formats.depth_stencil.2d.d32_sfloat_s8_uint_d32_sfloat_s8_uint_separate_layouts.optimal_optimal_nearest,Fail
dEQP-VK.draw.dynamic_rendering.basic_draw.draw_indexed_indirect.triangle_fan.45_multi_command,Fail
dEQP-VK.draw.dynamic_rendering.basic_draw.draw_indirect.triangle_fan.45_multi_command,Fail
dEQP-VK.draw.renderpass.basic_draw.draw_indexed_indirect.triangle_fan.17_multi_command,Fail
dEQP-VK.draw.renderpass.basic_draw.draw_indexed_indirect.triangle_fan.3_multi_command,Fail
dEQP-VK.draw.renderpass.basic_draw.draw_indexed_indirect.triangle_fan.45_multi_command,Fail
dEQP-VK.draw.renderpass.basic_draw.draw_indirect.triangle_fan.17_multi_command,Fail
dEQP-VK.draw.renderpass.basic_draw.draw_indirect.triangle_fan.3_multi_command,Fail
dEQP-VK.draw.renderpass.basic_draw.draw_indirect.triangle_fan.45_multi_command,Fail
dEQP-VK.draw.renderpass.multiple_interpolation.separate.no_sample_decoration.4_samples,Fail
dEQP-VK.draw.renderpass.multiple_interpolation.separate.with_sample_decoration.4_samples,Fail
dEQP-VK.draw.renderpass.multiple_interpolation.structured.no_sample_decoration.4_samples,Fail
+104 -27
View File
@@ -2547,7 +2547,9 @@ static void
dzn_cmd_buffer_indirect_draw(struct dzn_cmd_buffer *cmdbuf,
struct dzn_buffer *draw_buf,
size_t draw_buf_offset,
uint32_t draw_count,
struct dzn_buffer *count_buf,
size_t count_buf_offset,
uint32_t max_draw_count,
uint32_t draw_buf_stride,
bool indexed)
{
@@ -2574,9 +2576,19 @@ dzn_cmd_buffer_indirect_draw(struct dzn_cmd_buffer *cmdbuf,
sizeof(struct dzn_indirect_draw_exec_params);
uint32_t triangle_fan_exec_buf_stride =
sizeof(struct dzn_indirect_triangle_fan_rewrite_index_exec_params);
uint32_t exec_buf_size = max_draw_count * exec_buf_stride;
uint32_t exec_buf_draw_offset = 0;
// We reserve the first slot for the draw_count value when indirect count is
// involved.
if (count_buf != NULL) {
exec_buf_size += exec_buf_stride;
exec_buf_draw_offset = exec_buf_stride;
}
ID3D12Resource *exec_buf;
VkResult result =
dzn_cmd_buffer_alloc_internal_buf(cmdbuf, draw_count * exec_buf_stride,
dzn_cmd_buffer_alloc_internal_buf(cmdbuf, exec_buf_size,
D3D12_HEAP_TYPE_DEFAULT,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
&exec_buf);
@@ -2591,7 +2603,7 @@ dzn_cmd_buffer_indirect_draw(struct dzn_cmd_buffer *cmdbuf,
if (triangle_fan_index_buf_stride) {
result =
dzn_cmd_buffer_alloc_internal_buf(cmdbuf,
draw_count * triangle_fan_index_buf_stride,
max_draw_count * triangle_fan_index_buf_stride,
D3D12_HEAP_TYPE_DEFAULT,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
&triangle_fan_index_buf);
@@ -2600,7 +2612,7 @@ dzn_cmd_buffer_indirect_draw(struct dzn_cmd_buffer *cmdbuf,
result =
dzn_cmd_buffer_alloc_internal_buf(cmdbuf,
draw_count * triangle_fan_exec_buf_stride,
max_draw_count * triangle_fan_exec_buf_stride,
D3D12_HEAP_TYPE_DEFAULT,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
&triangle_fan_exec_buf);
@@ -2622,29 +2634,50 @@ dzn_cmd_buffer_indirect_draw(struct dzn_cmd_buffer *cmdbuf,
enum dzn_indirect_draw_type draw_type;
if (indexed && triangle_fan_index_buf_stride > 0)
draw_type = DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN;
else if (!indexed && triangle_fan_index_buf_stride > 0)
draw_type = DZN_INDIRECT_DRAW_TRIANGLE_FAN;
else if (indexed)
draw_type = DZN_INDIRECT_INDEXED_DRAW;
else
draw_type = DZN_INDIRECT_DRAW;
if (indexed && triangle_fan_index_buf_stride > 0) {
draw_type = count_buf ?
DZN_INDIRECT_INDEXED_DRAW_COUNT_TRIANGLE_FAN :
DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN;
} else if (!indexed && triangle_fan_index_buf_stride > 0) {
draw_type = count_buf ?
DZN_INDIRECT_DRAW_COUNT_TRIANGLE_FAN :
DZN_INDIRECT_DRAW_TRIANGLE_FAN;
} else if (indexed) {
draw_type = count_buf ?
DZN_INDIRECT_INDEXED_DRAW_COUNT :
DZN_INDIRECT_INDEXED_DRAW;
} else {
draw_type = count_buf ? DZN_INDIRECT_DRAW_COUNT : DZN_INDIRECT_DRAW;
}
struct dzn_meta_indirect_draw *indirect_draw = &device->indirect_draws[draw_type];
const struct dzn_pipeline *compute_pipeline =
cmdbuf->state.bindpoint[VK_PIPELINE_BIND_POINT_COMPUTE].pipeline;
uint32_t root_param_idx = 0;
ID3D12GraphicsCommandList1_SetComputeRootSignature(cmdbuf->cmdlist, indirect_draw->root_sig);
ID3D12GraphicsCommandList1_SetPipelineState(cmdbuf->cmdlist, indirect_draw->pipeline_state);
ID3D12GraphicsCommandList1_SetComputeRoot32BitConstants(cmdbuf->cmdlist, 0, params_size / 4, &params, 0);
ID3D12GraphicsCommandList1_SetComputeRootShaderResourceView(cmdbuf->cmdlist, 1, draw_buf_gpu);
ID3D12GraphicsCommandList1_SetComputeRootUnorderedAccessView(cmdbuf->cmdlist, 2, ID3D12Resource_GetGPUVirtualAddress(exec_buf));
if (triangle_fan_exec_buf)
ID3D12GraphicsCommandList1_SetComputeRootUnorderedAccessView(cmdbuf->cmdlist, 3, ID3D12Resource_GetGPUVirtualAddress(triangle_fan_exec_buf));
ID3D12GraphicsCommandList1_SetComputeRoot32BitConstants(cmdbuf->cmdlist, root_param_idx++,
params_size / 4, (const void *)&params, 0);
ID3D12GraphicsCommandList1_SetComputeRootShaderResourceView(cmdbuf->cmdlist, root_param_idx++,
draw_buf_gpu);
ID3D12GraphicsCommandList1_SetComputeRootUnorderedAccessView(cmdbuf->cmdlist, root_param_idx++,
ID3D12Resource_GetGPUVirtualAddress(exec_buf));
if (count_buf) {
ID3D12GraphicsCommandList1_SetComputeRootShaderResourceView(cmdbuf->cmdlist,
root_param_idx++,
ID3D12Resource_GetGPUVirtualAddress(count_buf->res) +
count_buf_offset);
}
ID3D12GraphicsCommandList1_Dispatch(cmdbuf->cmdlist, draw_count, 1, 1);
if (triangle_fan_exec_buf) {
ID3D12GraphicsCommandList1_SetComputeRootUnorderedAccessView(cmdbuf->cmdlist,
root_param_idx++,
ID3D12Resource_GetGPUVirtualAddress(triangle_fan_exec_buf));
}
ID3D12GraphicsCommandList1_Dispatch(cmdbuf->cmdlist, max_draw_count, 1, 1);
D3D12_RESOURCE_BARRIER post_barriers[] = {
{
@@ -2697,16 +2730,22 @@ dzn_cmd_buffer_indirect_draw(struct dzn_cmd_buffer *cmdbuf,
ID3D12GraphicsCommandList1_SetComputeRootSignature(cmdbuf->cmdlist, rewrite_index->root_sig);
ID3D12GraphicsCommandList1_SetPipelineState(cmdbuf->cmdlist, rewrite_index->pipeline_state);
ID3D12GraphicsCommandList1_SetComputeRootUnorderedAccessView(cmdbuf->cmdlist, 0, ID3D12Resource_GetGPUVirtualAddress(triangle_fan_index_buf));
ID3D12GraphicsCommandList1_SetComputeRoot32BitConstants(cmdbuf->cmdlist, 1, sizeof(rewrite_index_params) / 4,
root_param_idx = 0;
ID3D12GraphicsCommandList1_SetComputeRootUnorderedAccessView(cmdbuf->cmdlist, root_param_idx++,
ID3D12Resource_GetGPUVirtualAddress(triangle_fan_index_buf));
ID3D12GraphicsCommandList1_SetComputeRoot32BitConstants(cmdbuf->cmdlist, root_param_idx++,
sizeof(rewrite_index_params) / 4,
(const void *)&rewrite_index_params, 0);
if (indexed)
ID3D12GraphicsCommandList1_SetComputeRootShaderResourceView(cmdbuf->cmdlist, 2, cmdbuf->state.ib.view.BufferLocation);
if (indexed) {
ID3D12GraphicsCommandList1_SetComputeRootShaderResourceView(cmdbuf->cmdlist,
root_param_idx++,
cmdbuf->state.ib.view.BufferLocation);
}
ID3D12GraphicsCommandList1_ExecuteIndirect(cmdbuf->cmdlist, rewrite_index->cmd_sig,
draw_count, triangle_fan_exec_buf,
0, NULL, 0);
max_draw_count, triangle_fan_exec_buf, 0,
count_buf ? exec_buf : NULL, 0);
D3D12_RESOURCE_BARRIER index_buf_barriers[] = {
{
@@ -2771,7 +2810,9 @@ dzn_cmd_buffer_indirect_draw(struct dzn_cmd_buffer *cmdbuf,
}
ID3D12GraphicsCommandList1_ExecuteIndirect(cmdbuf->cmdlist, cmdsig,
draw_count, exec_buf, 0, NULL, 0);
max_draw_count,
exec_buf, exec_buf_draw_offset,
count_buf ? exec_buf : NULL, 0);
}
static void
@@ -3729,7 +3770,7 @@ dzn_CmdDrawIndirect(VkCommandBuffer commandBuffer,
VK_FROM_HANDLE(dzn_cmd_buffer, cmdbuf, commandBuffer);
VK_FROM_HANDLE(dzn_buffer, buf, buffer);
dzn_cmd_buffer_indirect_draw(cmdbuf, buf, offset, drawCount, stride, false);
dzn_cmd_buffer_indirect_draw(cmdbuf, buf, offset, NULL, 0, drawCount, stride, false);
}
VKAPI_ATTR void VKAPI_CALL
@@ -3742,7 +3783,43 @@ dzn_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,
VK_FROM_HANDLE(dzn_cmd_buffer, cmdbuf, commandBuffer);
VK_FROM_HANDLE(dzn_buffer, buf, buffer);
dzn_cmd_buffer_indirect_draw(cmdbuf, buf, offset, drawCount, stride, true);
dzn_cmd_buffer_indirect_draw(cmdbuf, buf, offset, NULL, 0, drawCount, stride, true);
}
VKAPI_ATTR void VKAPI_CALL
dzn_CmdDrawIndirectCount(VkCommandBuffer commandBuffer,
VkBuffer buffer,
VkDeviceSize offset,
VkBuffer countBuffer,
VkDeviceSize countBufferOffset,
uint32_t maxDrawCount,
uint32_t stride)
{
VK_FROM_HANDLE(dzn_cmd_buffer, cmdbuf, commandBuffer);
VK_FROM_HANDLE(dzn_buffer, buf, buffer);
VK_FROM_HANDLE(dzn_buffer, count_buf, countBuffer);
dzn_cmd_buffer_indirect_draw(cmdbuf, buf, offset,
count_buf, countBufferOffset,
maxDrawCount, stride, false);
}
VKAPI_ATTR void VKAPI_CALL
dzn_CmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer,
VkBuffer buffer,
VkDeviceSize offset,
VkBuffer countBuffer,
VkDeviceSize countBufferOffset,
uint32_t maxDrawCount,
uint32_t stride)
{
VK_FROM_HANDLE(dzn_cmd_buffer, cmdbuf, commandBuffer);
VK_FROM_HANDLE(dzn_buffer, buf, buffer);
VK_FROM_HANDLE(dzn_buffer, count_buf, countBuffer);
dzn_cmd_buffer_indirect_draw(cmdbuf, buf, offset,
count_buf, countBufferOffset,
maxDrawCount, stride, true);
}
VKAPI_ATTR void VKAPI_CALL
+1
View File
@@ -78,6 +78,7 @@ dzn_physical_device_get_extensions(struct dzn_physical_device *pdev)
{
pdev->vk.supported_extensions = (struct vk_device_extension_table) {
.KHR_descriptor_update_template = true,
.KHR_draw_indirect_count = true,
.KHR_dynamic_rendering = true,
.KHR_shader_draw_parameters = true,
#ifdef DZN_USE_WSI_PLATFORM
+21 -3
View File
@@ -87,7 +87,7 @@ dzn_meta_compile_shader(struct dzn_device *device, nir_shader *nir,
slot->BytecodeLength = size;
}
#define DZN_META_INDIRECT_DRAW_MAX_PARAM_COUNT 4
#define DZN_META_INDIRECT_DRAW_MAX_PARAM_COUNT 5
static void
dzn_meta_indirect_draw_finish(struct dzn_device *device, enum dzn_indirect_draw_type type)
@@ -114,7 +114,13 @@ dzn_meta_indirect_draw_init(struct dzn_device *device,
nir_shader *nir = dzn_nir_indirect_draw_shader(type);
bool triangle_fan = type == DZN_INDIRECT_DRAW_TRIANGLE_FAN ||
type == DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN;
type == DZN_INDIRECT_DRAW_COUNT_TRIANGLE_FAN ||
type == DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN ||
type == DZN_INDIRECT_INDEXED_DRAW_COUNT_TRIANGLE_FAN;
bool indirect_count = type == DZN_INDIRECT_DRAW_COUNT ||
type == DZN_INDIRECT_INDEXED_DRAW_COUNT ||
type == DZN_INDIRECT_DRAW_COUNT_TRIANGLE_FAN ||
type == DZN_INDIRECT_INDEXED_DRAW_COUNT_TRIANGLE_FAN;
uint32_t shader_params_size =
triangle_fan ?
sizeof(struct dzn_indirect_draw_triangle_fan_rewrite_params) :
@@ -153,12 +159,24 @@ dzn_meta_indirect_draw_init(struct dzn_device *device,
.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
};
if (indirect_count) {
root_params[root_param_count++] = (D3D12_ROOT_PARAMETER1) {
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV,
.Descriptor = {
.ShaderRegister = 3,
.RegisterSpace = 0,
.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
},
.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
};
}
if (triangle_fan) {
root_params[root_param_count++] = (D3D12_ROOT_PARAMETER1) {
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV,
.Descriptor = {
.ShaderRegister = 3,
.ShaderRegister = 4,
.RegisterSpace = 0,
.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
},
+39 -4
View File
@@ -86,17 +86,29 @@ dzn_nir_indirect_draw_shader(enum dzn_indirect_draw_type type)
{
const char *type_str[] = {
"draw",
"draw_count",
"indexed_draw",
"indexed_draw_count",
"draw_triangle_fan",
"draw_count_triangle_fan",
"indexed_draw_triangle_fan",
"indexed_draw_count_triangle_fan",
};
assert(type < ARRAY_SIZE(type_str));
bool indexed = type == DZN_INDIRECT_INDEXED_DRAW ||
type == DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN;
type == DZN_INDIRECT_INDEXED_DRAW_COUNT ||
type == DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN ||
type == DZN_INDIRECT_INDEXED_DRAW_COUNT_TRIANGLE_FAN;
bool triangle_fan = type == DZN_INDIRECT_DRAW_TRIANGLE_FAN ||
type == DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN;
type == DZN_INDIRECT_DRAW_COUNT_TRIANGLE_FAN ||
type == DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN ||
type == DZN_INDIRECT_INDEXED_DRAW_COUNT_TRIANGLE_FAN;
bool indirect_count = type == DZN_INDIRECT_DRAW_COUNT ||
type == DZN_INDIRECT_INDEXED_DRAW_COUNT ||
type == DZN_INDIRECT_DRAW_COUNT_TRIANGLE_FAN ||
type == DZN_INDIRECT_INDEXED_DRAW_COUNT_TRIANGLE_FAN;
nir_builder b =
nir_builder_init_simple_shader(MESA_SHADER_COMPUTE,
dxil_get_nir_compiler_options(),
@@ -136,8 +148,29 @@ dzn_nir_indirect_draw_shader(enum dzn_indirect_draw_type type)
nir_ssa_def *index =
nir_channel(&b, nir_load_global_invocation_id(&b, 32), 0);
if (indirect_count) {
nir_ssa_def *count_buf_desc =
dzn_nir_create_bo_desc(&b, nir_var_mem_ssbo, 0, 3, "count_buf", ACCESS_NON_WRITEABLE);
nir_ssa_def *draw_count =
nir_load_ssbo(&b, 1, 32, count_buf_desc, nir_imm_int(&b, 0), .align_mul = 4);
nir_push_if(&b, nir_ieq(&b, index, nir_imm_int(&b, 0)));
nir_store_ssbo(&b, draw_count, exec_buf_desc, nir_imm_int(&b, 0),
.write_mask = 0x1, .access = ACCESS_NON_READABLE,
.align_mul = 16);
nir_pop_if(&b, NULL);
nir_push_if(&b, nir_ult(&b, index, draw_count));
}
nir_ssa_def *draw_offset = nir_imul(&b, draw_stride, index);
nir_ssa_def *exec_offset = nir_imul(&b, exec_stride, index);
/* The first entry contains the indirect count */
nir_ssa_def *exec_offset =
indirect_count ?
nir_imul(&b, exec_stride, nir_iadd_imm(&b, index, 1)) :
nir_imul(&b, exec_stride, index);
nir_ssa_def *draw_info1 =
nir_load_ssbo(&b, 4, 32, draw_buf_desc, draw_offset, .align_mul = 4);
@@ -168,7 +201,7 @@ dzn_nir_indirect_draw_shader(enum dzn_indirect_draw_type type)
exec_vals[7] = base_instance;
nir_ssa_def *triangle_fan_exec_buf_desc =
dzn_nir_create_bo_desc(&b, nir_var_mem_ssbo, 0, 3,
dzn_nir_create_bo_desc(&b, nir_var_mem_ssbo, 0, 4,
"triangle_fan_exec_buf",
ACCESS_NON_READABLE);
nir_ssa_def *triangle_fan_index_buf_stride = nir_channel(&b, params, 1);
@@ -232,6 +265,8 @@ dzn_nir_indirect_draw_shader(enum dzn_indirect_draw_type type)
exec_buf_desc, nir_iadd_imm(&b, exec_offset, 16),
.write_mask = 0xf, .access = ACCESS_NON_READABLE, .align_mul = 16);
if (indirect_count)
nir_pop_if(&b, NULL);
return b.shader;
}
+4
View File
@@ -94,9 +94,13 @@ struct dzn_indirect_triangle_fan_rewrite_index_exec_params {
enum dzn_indirect_draw_type {
DZN_INDIRECT_DRAW,
DZN_INDIRECT_DRAW_COUNT,
DZN_INDIRECT_INDEXED_DRAW,
DZN_INDIRECT_INDEXED_DRAW_COUNT,
DZN_INDIRECT_DRAW_TRIANGLE_FAN,
DZN_INDIRECT_DRAW_COUNT_TRIANGLE_FAN,
DZN_INDIRECT_INDEXED_DRAW_TRIANGLE_FAN,
DZN_INDIRECT_INDEXED_DRAW_COUNT_TRIANGLE_FAN,
DZN_NUM_INDIRECT_DRAW_TYPES,
};