Skip to content

Commit

Permalink
gpuav: Fix / 0 in draw mesh indirect validation
Browse files Browse the repository at this point in the history
  • Loading branch information
arno-lunarg committed Dec 16, 2024
1 parent cf3372f commit c71f5b9
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 7 deletions.
12 changes: 9 additions & 3 deletions layers/gpu/cmd_validation/gpuav_draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ void DrawMeshIndirect(Validator &gpuav, CommandBuffer &cb_state, const Location
const bool is_task_shader = (stages & VK_SHADER_STAGE_TASK_BIT_EXT) == VK_SHADER_STAGE_TASK_BIT_EXT;

CommandBuffer::ValidationCommandFunc validation_cmd =
[draw_buffer, draw_buffer_size = draw_buffer_state->create_info.size, draw_buffer_offset, draw_cmds_byte_stride,
[draw_buffer, draw_buffer_full_size = draw_buffer_state->create_info.size, draw_buffer_offset, draw_cmds_byte_stride,
count_buffer, count_buffer_offset, draw_count, is_task_shader, draw_i = cb_state.draw_index,
error_logger_i = uint32_t(cb_state.per_command_error_loggers.size()), loc](Validator &gpuav, CommandBuffer &cb_state) {
SharedDrawValidationResources &shared_draw_validation_resources =
Expand Down Expand Up @@ -656,8 +656,14 @@ void DrawMeshIndirect(Validator &gpuav, CommandBuffer &cb_state, const Location
DispatchCmdBindPipeline(cb_state.VkHandle(), VK_PIPELINE_BIND_POINT_COMPUTE, validation_pipeline.pipeline);

uint32_t max_held_draw_cmds = 0;
if (draw_buffer_size > draw_buffer_offset) {
max_held_draw_cmds = static_cast<uint32_t>((draw_buffer_size - draw_buffer_offset) / draw_cmds_byte_stride);
if (draw_buffer_full_size > draw_buffer_offset) {
// If drawCount is less than or equal to one, stride is ignored
if (draw_cmds_byte_stride > 0) {
max_held_draw_cmds =
static_cast<uint32_t>((draw_buffer_full_size - draw_buffer_offset) / draw_cmds_byte_stride);
} else {
max_held_draw_cmds = 1;
}
}
const uint32_t work_group_count = std::min(draw_count, max_held_draw_cmds);
VVL_TracyPlot("gpuav::valcmd::DrawMeshIndirect Dispatch size", int64_t(work_group_count));
Expand Down
72 changes: 68 additions & 4 deletions tests/unit/gpu_av_indirect_buffer_positive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,14 @@ TEST_F(PositiveGpuAVIndirectBuffer, Mesh) {
if (mesh_shader_props.maxMeshWorkGroupTotalCount > 0xfffffffe) {
GTEST_SKIP() << "MeshWorkGroupTotalCount too high for this test";
}
const uint32_t num_commands = 3;
uint32_t buffer_size = num_commands * (sizeof(VkDrawMeshTasksIndirectCommandEXT) + 4); // 4 byte pad between commands
const uint32_t mesh_commands = 3;
uint32_t buffer_size = mesh_commands * (sizeof(VkDrawMeshTasksIndirectCommandEXT) + 4); // 4 byte pad between commands

vkt::Buffer draw_buffer(*m_device, buffer_size, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, kHostVisibleMemProps);
uint32_t *draw_ptr = static_cast<uint32_t *>(draw_buffer.Memory().Map());
// Set all mesh group counts to 1
for (uint32_t i = 0; i < num_commands * 4; ++i) {
draw_ptr[i] = 42;
for (uint32_t i = 0; i < mesh_commands * 4; ++i) {
draw_ptr[i] = 1;
}
draw_buffer.Memory().Unmap();

Expand Down Expand Up @@ -176,3 +176,67 @@ TEST_F(PositiveGpuAVIndirectBuffer, Mesh) {
m_default_queue->Submit(m_command_buffer);
m_default_queue->Wait();
}

TEST_F(PositiveGpuAVIndirectBuffer, MeshSingleCommand) {
TEST_DESCRIPTION("GPU validation: Validate DrawMeshTasksIndirect* DrawBuffer contents");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_MESH_SHADER_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::maintenance4);
AddRequiredFeature(vkt::Feature::meshShader);
AddRequiredFeature(vkt::Feature::taskShader);
AddRequiredFeature(vkt::Feature::multiDrawIndirect);

RETURN_IF_SKIP(InitGpuAvFramework());
RETURN_IF_SKIP(InitState());
InitRenderTarget();
VkPhysicalDeviceMeshShaderPropertiesEXT mesh_shader_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(mesh_shader_props);

if (mesh_shader_props.maxMeshWorkGroupTotalCount > 0xfffffffe) {
GTEST_SKIP() << "MeshWorkGroupTotalCount too high for this test";
}
const uint32_t mesh_commands = 1;
uint32_t buffer_size = mesh_commands * (sizeof(VkDrawMeshTasksIndirectCommandEXT) + 4); // 4 byte pad between commands

vkt::Buffer draw_buffer(*m_device, buffer_size, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, kHostVisibleMemProps);
uint32_t *draw_ptr = static_cast<uint32_t *>(draw_buffer.Memory().Map());
// Set all mesh group counts to 1
for (uint32_t i = 0; i < mesh_commands * 4; ++i) {
draw_ptr[i] = 1;
}
draw_buffer.Memory().Unmap();

vkt::Buffer count_buffer(*m_device, sizeof(uint32_t), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, kHostVisibleMemProps);
uint32_t *count_ptr = static_cast<uint32_t *>(count_buffer.Memory().Map());
*count_ptr = 3;
count_buffer.Memory().Unmap();
char const *mesh_shader_source = R"glsl(
#version 450
#extension GL_EXT_mesh_shader : require
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(max_vertices = 3, max_primitives = 1) out;
layout(triangles) out;
struct Task {
uint baseID;
};
taskPayloadSharedEXT Task IN;
void main() {}
)glsl";
VkShaderObj mesh_shader(this, mesh_shader_source, VK_SHADER_STAGE_MESH_BIT_EXT, SPV_ENV_VULKAN_1_3);
CreatePipelineHelper mesh_pipe(*this);
mesh_pipe.shader_stages_[0] = mesh_shader.GetStageCreateInfo();
mesh_pipe.CreateGraphicsPipeline();

// Set x in third draw
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, mesh_pipe.Handle());

vk::CmdDrawMeshTasksIndirectEXT(m_command_buffer.handle(), draw_buffer.handle(), 0, 1, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.end();

m_default_queue->Submit(m_command_buffer);
m_default_queue->Wait();
}

0 comments on commit c71f5b9

Please sign in to comment.