diff options
author | Chris Forbes <chrisforbes@google.com> | 2016-09-28 15:19:39 +1300 |
---|---|---|
committer | Chris Forbes <chrisforbes@google.com> | 2016-09-30 09:38:13 +1300 |
commit | c307df2953e6b023531a6ef7fd11e3ee2f2c58b0 (patch) | |
tree | 1e0e66736a367b8eaedfa0a649f9df3c7c1a6e40 | |
parent | a1a137ec383fef3881f86d4c202b1de56a91edf0 (diff) |
layers: Complain about subpass mismatch between CB and pipeline
Fixes #933.
Signed-off-by: Chris Forbes <chrisforbes@google.com>
-rw-r--r-- | layers/core_validation.cpp | 8 | ||||
-rw-r--r-- | tests/layer_validation_tests.cpp | 115 |
2 files changed, 123 insertions, 0 deletions
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index a513989f..b8eaa2c6 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3180,6 +3180,14 @@ static bool validatePipelineDrawtimeState(layer_data const *my_data, reinterpret_cast<uint64_t &>(pCB->activeRenderPass->renderPass), reinterpret_cast<uint64_t &>(pPipeline), reinterpret_cast<const uint64_t &>(pPipeline->graphicsPipelineCI.renderPass), err_string.c_str()); } + + if (pPipeline->graphicsPipelineCI.subpass != pCB->activeSubpass) { + skip_call |= + log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, + reinterpret_cast<uint64_t const &>(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", + "Pipeline was built for subpass %u but used in subpass %u", pPipeline->graphicsPipelineCI.subpass, + pCB->activeSubpass); + } } // TODO : Add more checks here diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp index 3a16fe85..e7a8e45f 100644 --- a/tests/layer_validation_tests.cpp +++ b/tests/layer_validation_tests.cpp @@ -4100,6 +4100,121 @@ TEST_F(VkLayerTest, RenderPassSubpassZeroTransitionsApplied) { vkDestroyImageView(m_device->device(), view, nullptr); } +TEST_F(VkLayerTest, RenderPassPipelineSubpassMismatch) { + TEST_DESCRIPTION("Use a pipeline for the wrong subpass in a render pass instance"); + ASSERT_NO_FATAL_FAILURE(InitState()); + + // A renderpass with two subpasses, both writing the same attachment. + VkAttachmentDescription attach[] = { + { 0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, + VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, + VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + }, + }; + VkAttachmentReference ref = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; + VkSubpassDescription subpasses[] = { + { 0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, + 1, &ref, nullptr, nullptr, 0, nullptr }, + { 0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, + 1, &ref, nullptr, nullptr, 0, nullptr }, + }; + VkSubpassDependency dep = { + 0, 1, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_DEPENDENCY_BY_REGION_BIT + }; + VkRenderPassCreateInfo rpci = { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, + 0, 1, attach, 2, subpasses, 1, &dep + }; + VkRenderPass rp; + VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp); + ASSERT_VK_SUCCESS(err); + + VkImageObj image(m_device); + image.init_no_layout(32, 32, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + VK_IMAGE_TILING_OPTIMAL, 0); + VkImageView imageView = image.targetView(VK_FORMAT_R8G8B8A8_UNORM); + + VkFramebufferCreateInfo fbci = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, + 0, rp, 1, &imageView, 32, 32, 1 + }; + VkFramebuffer fb; + err = vkCreateFramebuffer(m_device->device(), &fbci, nullptr, &fb); + ASSERT_VK_SUCCESS(err); + + char const *vsSource = + "#version 450\n" + "void main() { gl_Position = vec4(1); }\n"; + char const *fsSource = + "#version 450\n" + "layout(location=0) out vec4 color;\n" + "void main() { color = vec4(1); }\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.AddColorAttachment(); + pipe.AddShader(&vs); + pipe.AddShader(&fs); + VkViewport view_port = {}; + m_viewports.push_back(view_port); + pipe.SetViewport(m_viewports); + VkRect2D rect = {}; + m_scissors.push_back(rect); + pipe.SetScissor(m_scissors); + + VkPipelineLayoutCreateInfo plci = { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, + 0, 0, nullptr, 0, nullptr + }; + VkPipelineLayout pl; + err = vkCreatePipelineLayout(m_device->device(), &plci, nullptr, &pl); + ASSERT_VK_SUCCESS(err); + pipe.CreateVKPipeline(pl, rp); + + BeginCommandBuffer(); + + VkRenderPassBeginInfo rpbi = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, + rp, fb, { { 0, 0, }, { 32, 32 } }, 0, nullptr + }; + + // subtest 1: bind in the wrong subpass + vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); + vkCmdNextSubpass(m_commandBuffer->handle(), VK_SUBPASS_CONTENTS_INLINE); + m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, + "built for subpass 0 but used in subpass 1"); + vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); + vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); + m_errorMonitor->VerifyFound(); + + vkCmdEndRenderPass(m_commandBuffer->handle()); + + // subtest 2: bind in correct subpass, then transition to next subpass + vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE); + vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle()); + vkCmdNextSubpass(m_commandBuffer->handle(), VK_SUBPASS_CONTENTS_INLINE); + m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, + "built for subpass 0 but used in subpass 1"); + vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); + m_errorMonitor->VerifyFound(); + + vkCmdEndRenderPass(m_commandBuffer->handle()); + + EndCommandBuffer(); + + vkDestroyPipelineLayout(m_device->device(), pl, nullptr); + vkDestroyFramebuffer(m_device->device(), fb, nullptr); + vkDestroyRenderPass(m_device->device(), rp, nullptr); +} + TEST_F(VkLayerTest, DepthStencilLayoutTransitionForDepthOnlyImageview) { TEST_DESCRIPTION("Validate that when an imageView of a depth/stencil image " "is used as a depth/stencil framebuffer attachment, the " |