layers: Check for indirect buffer usage
Fixes #450.
diff --git a/layers/drawdispatch.cpp b/layers/drawdispatch.cpp
index e5b2e51..3bd5a51 100644
--- a/layers/drawdispatch.cpp
+++ b/layers/drawdispatch.cpp
@@ -139,6 +139,8 @@
"VUID-vkCmdDrawIndirect-None-00486");
BUFFER_STATE *buffer_state = GetBufferState(buffer);
skip |= ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDrawIndirect()", "VUID-vkCmdDrawIndirect-buffer-00474");
+ skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true, "VUID-vkCmdDrawIndirect-buffer-01660",
+ "vkCmdDrawIndirect()", "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
// TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the
// VkDrawIndirectCommand structures accessed by this command must be 0, which will require access to the contents of 'buffer'.
return skip;
@@ -165,6 +167,9 @@
"VUID-vkCmdDrawIndexedIndirect-None-00537", "VUID-vkCmdDrawIndexedIndirect-None-00538");
BUFFER_STATE *buffer_state = GetBufferState(buffer);
skip |= ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDrawIndexedIndirect()", "VUID-vkCmdDrawIndexedIndirect-buffer-00526");
+ skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
+ "VUID-vkCmdDrawIndexedIndirect-buffer-01665", "vkCmdDrawIndexedIndirect()",
+ "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
// TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the
// VkDrawIndexedIndirectCommand structures accessed by this command must be 0, which will require access to the contents of
// 'buffer'.
@@ -206,6 +211,9 @@
"VUID-vkCmdDispatchIndirect-renderpass", "VUID-vkCmdDispatchIndirect-None-00404", kVUIDUndefined);
BUFFER_STATE *buffer_state = GetBufferState(buffer);
skip |= ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDispatchIndirect()", "VUID-vkCmdDispatchIndirect-buffer-00401");
+ skip |=
+ ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true, "VUID-vkCmdDispatchIndirect-buffer-00405",
+ "vkCmdDispatchIndirect()", "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
return skip;
}
@@ -257,7 +265,12 @@
ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDrawIndirectCountKHR()", "VUID-vkCmdDrawIndirectCountKHR-buffer-03104");
skip |= ValidateMemoryIsBoundToBuffer(count_buffer_state, "vkCmdDrawIndirectCountKHR()",
"VUID-vkCmdDrawIndirectCountKHR-countBuffer-03106");
-
+ skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
+ "VUID-vkCmdDrawIndirectCountKHR-buffer-03105", "vkCmdDrawIndirectCountKHR()",
+ "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
+ skip |= ValidateBufferUsageFlags(count_buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
+ "VUID-vkCmdDrawIndirectCountKHR-countBuffer-03107", "vkCmdDrawIndirectCountKHR()",
+ "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
return skip;
}
@@ -311,6 +324,12 @@
"VUID-vkCmdDrawIndexedIndirectCountKHR-buffer-03136");
skip |= ValidateMemoryIsBoundToBuffer(count_buffer_state, "vkCmdDrawIndexedIndirectCountKHR()",
"VUID-vkCmdDrawIndexedIndirectCountKHR-countBuffer-03138");
+ skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
+ "VUID-vkCmdDrawIndexedIndirectCountKHR-buffer-03137", "vkCmdDrawIndexedIndirectCountKHR()",
+ "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
+ skip |= ValidateBufferUsageFlags(count_buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
+ "VUID-vkCmdDrawIndexedIndirectCountKHR-countBuffer-03139",
+ "vkCmdDrawIndexedIndirectCountKHR()", "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
return skip;
}
@@ -348,7 +367,9 @@
BUFFER_STATE *buffer_state = GetBufferState(buffer);
skip |= ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDrawMeshTasksIndirectNV()",
"VUID-vkCmdDrawMeshTasksIndirectNV-buffer-02143");
-
+ skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
+ "VUID-vkCmdDrawMeshTasksIndirectNV-buffer-02144", "vkCmdDrawMeshTasksIndirectNV()",
+ "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
return skip;
}
@@ -376,7 +397,12 @@
"VUID-vkCmdDrawMeshTasksIndirectCountNV-buffer-02176");
skip |= ValidateMemoryIsBoundToBuffer(count_buffer_state, "vkCmdDrawMeshTasksIndirectCountNV()",
"VUID-vkCmdDrawMeshTasksIndirectCountNV-countBuffer-02178");
-
+ skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
+ "VUID-vkCmdDrawMeshTasksIndirectCountNV-buffer-02177", "vkCmdDrawIndexedIndirectCountKHR()",
+ "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
+ skip |= ValidateBufferUsageFlags(count_buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
+ "VUID-vkCmdDrawMeshTasksIndirectCountNV-countBuffer-02179",
+ "vkCmdDrawIndexedIndirectCountKHR()", "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
return skip;
}
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index cfb4f92..f3071dd 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -35400,6 +35400,77 @@
m_errorMonitor->VerifyNotFound();
}
+TEST_F(VkLayerTest, DrawIndirect) {
+ TEST_DESCRIPTION("Test covered valid usage for vkCmdDrawIndirect");
+
+ ASSERT_NO_FATAL_FAILURE(Init());
+ ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
+
+ VkMemoryRequirements memory_requirements;
+ VkMemoryAllocateInfo memory_allocate_info = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
+
+ char const *vsSource =
+ "#version 450\n"
+ "\n"
+ "void main() { gl_Position = vec4(0); }\n";
+ char const *fsSource =
+ "#version 450\n"
+ "\n"
+ "layout(location=0) out vec4 color;\n"
+ "void main() {\n"
+ " color = vec4(1, 0, 0, 1);\n"
+ "}\n";
+ VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
+ VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
+
+ VkPipelineObj pipe(m_device);
+ pipe.AddShader(&vs);
+ pipe.AddShader(&fs);
+ pipe.AddDefaultColorAttachment();
+
+ VkDescriptorSetObj descriptor_set(m_device);
+ descriptor_set.AppendDummy();
+ descriptor_set.CreateVKDescriptorSet(m_commandBuffer);
+
+ VkResult err = pipe.CreateVKPipeline(descriptor_set.GetPipelineLayout(), renderPass());
+ ASSERT_VK_SUCCESS(err);
+
+ m_commandBuffer->begin();
+ m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
+
+ vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
+ m_commandBuffer->BindDescriptorSet(descriptor_set);
+
+ VkViewport viewport = {0, 0, 16, 16, 0, 1};
+ vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
+ VkRect2D scissor = {{0, 0}, {16, 16}};
+ vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
+
+ VkBufferCreateInfo buffer_create_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
+ buffer_create_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ buffer_create_info.size = sizeof(VkDrawIndirectCommand);
+ VkBuffer draw_buffer;
+ vkCreateBuffer(m_device->device(), &buffer_create_info, nullptr, &draw_buffer);
+
+ vkGetBufferMemoryRequirements(m_device->device(), draw_buffer, &memory_requirements);
+ memory_allocate_info.allocationSize = memory_requirements.size;
+ m_device->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_allocate_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+ VkDeviceMemory draw_buffer_memory;
+ vkAllocateMemory(m_device->device(), &memory_allocate_info, NULL, &draw_buffer_memory);
+ vkBindBufferMemory(m_device->device(), draw_buffer, draw_buffer_memory, 0);
+
+ // VUID-vkCmdDrawIndirect-buffer-01660
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndirect-buffer-01660");
+ vkCmdDrawIndirect(m_commandBuffer->handle(), draw_buffer, 0, 1, sizeof(VkDrawIndirectCommand));
+ m_errorMonitor->VerifyFound();
+
+ m_commandBuffer->EndRenderPass();
+ m_commandBuffer->end();
+
+ vkDestroyBuffer(m_device->device(), draw_buffer, 0);
+ vkFreeMemory(m_device->device(), draw_buffer_memory, 0);
+}
+
TEST_F(VkLayerTest, DrawIndirectCountKHR) {
TEST_DESCRIPTION("Test covered valid usage for vkCmdDrawIndirectCountKHR");