| /* |
| * Copyright (c) 2015-2025 The Khronos Group Inc. |
| * Copyright (c) 2015-2025 Valve Corporation |
| * Copyright (c) 2015-2025 LunarG, Inc. |
| * Copyright (c) 2015-2025 Google, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| */ |
| |
| #include "../framework/layer_validation_tests.h" |
| #include "../framework/pipeline_helper.h" |
| #include "../framework/descriptor_helper.h" |
| |
| class VkPositiveBestPracticesLayerTest : public VkBestPracticesLayerTest {}; |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, TestDestroyFreeNullHandles) { |
| VkResult err; |
| |
| TEST_DESCRIPTION("Call all applicable destroy and free routines with NULL handles, expecting no validation errors"); |
| |
| RETURN_IF_SKIP(InitBestPracticesFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit); |
| |
| vk::DestroyBuffer(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyBufferView(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyCommandPool(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyDescriptorPool(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyDescriptorSetLayout(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyDevice(VK_NULL_HANDLE, NULL); |
| vk::DestroyEvent(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyFence(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyFramebuffer(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyImage(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyImageView(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyInstance(VK_NULL_HANDLE, NULL); |
| vk::DestroyPipeline(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyPipelineCache(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyPipelineLayout(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyQueryPool(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyRenderPass(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroySampler(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroySemaphore(device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyShaderModule(device(), VK_NULL_HANDLE, NULL); |
| |
| VkCommandPool command_pool; |
| VkCommandPoolCreateInfo pool_create_info{}; |
| pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; |
| pool_create_info.queueFamilyIndex = m_device->graphics_queue_node_index_; |
| pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; |
| vk::CreateCommandPool(device(), &pool_create_info, nullptr, &command_pool); |
| VkCommandBuffer command_buffers[3] = {}; |
| VkCommandBufferAllocateInfo command_buffer_allocate_info{}; |
| command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; |
| command_buffer_allocate_info.commandPool = command_pool; |
| command_buffer_allocate_info.commandBufferCount = 1; |
| command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; |
| vk::AllocateCommandBuffers(device(), &command_buffer_allocate_info, &command_buffers[1]); |
| vk::FreeCommandBuffers(device(), command_pool, 3, command_buffers); |
| vk::DestroyCommandPool(device(), command_pool, NULL); |
| |
| VkDescriptorPoolSize ds_type_count = {}; |
| ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; |
| ds_type_count.descriptorCount = 1; |
| |
| VkDescriptorPoolCreateInfo ds_pool_ci = {}; |
| ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; |
| ds_pool_ci.pNext = NULL; |
| ds_pool_ci.maxSets = 1; |
| ds_pool_ci.poolSizeCount = 1; |
| ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; |
| ds_pool_ci.pPoolSizes = &ds_type_count; |
| vkt::DescriptorPool ds_pool(*m_device, ds_pool_ci); |
| |
| VkDescriptorSetLayoutBinding dsl_binding = {}; |
| dsl_binding.binding = 2; |
| dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; |
| dsl_binding.descriptorCount = 1; |
| dsl_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; |
| dsl_binding.pImmutableSamplers = NULL; |
| |
| const vkt::DescriptorSetLayout ds_layout(*m_device, {dsl_binding}); |
| |
| VkDescriptorSet descriptor_sets[3] = {}; |
| VkDescriptorSetAllocateInfo alloc_info = {}; |
| alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; |
| alloc_info.descriptorSetCount = 1; |
| alloc_info.descriptorPool = ds_pool.handle(); |
| alloc_info.pSetLayouts = &ds_layout.handle(); |
| err = vk::AllocateDescriptorSets(device(), &alloc_info, &descriptor_sets[1]); |
| ASSERT_EQ(VK_SUCCESS, err); |
| vk::FreeDescriptorSets(device(), ds_pool.handle(), 3, descriptor_sets); |
| |
| vk::FreeMemory(device(), VK_NULL_HANDLE, NULL); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, DrawingWithUnboundUnusedSet) { |
| TEST_DESCRIPTION( |
| "Test issuing draw command with pipeline layout that has 2 descriptor sets with first descriptor set begin unused and " |
| "unbound. Its purpose is to catch regression of this bug: " |
| "https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/4597."); |
| |
| RETURN_IF_SKIP(InitBestPracticesFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.CreateGraphicsPipeline(); |
| |
| OneOffDescriptorSet empty_ds(m_device, {}); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&empty_ds.layout_, &empty_ds.layout_}); |
| |
| m_command_buffer.Begin(); |
| |
| vk::CmdBindDescriptorSets(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 1, 1, |
| &empty_ds.set_, 0, nullptr); |
| |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle()); |
| vkt::Buffer vbo(*m_device, sizeof(float) * 3, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); |
| vk::CmdBindVertexBuffers(m_command_buffer.handle(), 1, 1, &vbo.handle(), &kZeroDeviceSize); |
| |
| // The draw command will most likely produce a crash in case of a regression. |
| vk::CmdDraw(m_command_buffer.handle(), 1, 1, 0, 0); |
| |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, DynStateIgnoreAttachments) { |
| TEST_DESCRIPTION("Make sure pAttachments is ignored if dynamic state is enabled"); |
| |
| AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendAdvanced); |
| AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEnable); |
| AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEquation); |
| AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorWriteMask); |
| RETURN_IF_SKIP(InitBestPracticesFramework()); |
| if (!IsPlatformMockICD()) { |
| // Several drivers have been observed to crash on the legal null pAttachments - restrict to MockICD for now |
| GTEST_SKIP() << "This test only runs on MockICD"; |
| } |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit); |
| |
| // pAttachments should be ignored with these four states set |
| VkDynamicState dynamic_states[4] = {VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT, VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT, |
| VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT, VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT}; |
| VkPipelineDynamicStateCreateInfo dynamic_create_info = vku::InitStructHelper(); |
| dynamic_create_info.pDynamicStates = dynamic_states; |
| dynamic_create_info.dynamicStateCount = 4; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.cb_ci_.pAttachments = nullptr; |
| pipe.gp_ci_.pDynamicState = &dynamic_create_info; |
| pipe.CreateGraphicsPipeline(); |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle()); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, PipelineLibraryNoRendering) { |
| TEST_DESCRIPTION("Create a pipeline library without a render pass or rendering info"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| RETURN_IF_SKIP(InitBestPracticesFramework()); |
| RETURN_IF_SKIP(InitState()); |
| |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit); |
| |
| CreatePipelineHelper pre_raster_lib(*this); |
| const auto vs_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl); |
| vkt::GraphicsPipelineLibraryStage vs_stage(vs_spv, VK_SHADER_STAGE_VERTEX_BIT); |
| pre_raster_lib.InitPreRasterLibInfo(&vs_stage.stage_ci); |
| pre_raster_lib.gp_ci_.renderPass = VK_NULL_HANDLE; |
| pre_raster_lib.gp_ci_.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; |
| pre_raster_lib.CreateGraphicsPipeline(); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, PushConstantSet) { |
| RETURN_IF_SKIP(InitBestPracticesFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit); |
| |
| char const *const vsSource = R"glsl( |
| #version 450 |
| layout(push_constant, std430) uniform foo { uint x[4]; } constants; |
| void main(){ |
| gl_Position = vec4(constants.x[0] * constants.x[1]); |
| } |
| )glsl"; |
| |
| const char fsSource[] = R"glsl( |
| #version 460 |
| layout(push_constant, std430) uniform foo { |
| layout(offset = 16) float x; |
| } constants; |
| layout(location = 0) out vec4 uFragColor; |
| void main(){ |
| uFragColor = vec4(0,1,0,constants.x); |
| } |
| )glsl"; |
| |
| VkShaderObj const vs(this, vsSource, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj const fs(this, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| uint32_t data[5]; |
| std::vector<VkPushConstantRange> push_constant_ranges = {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, |
| {VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4}}; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {}, push_constant_ranges); |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle()); |
| vk::CmdPushConstants(m_command_buffer.handle(), pipe.pipeline_layout_.handle(), VK_SHADER_STAGE_VERTEX_BIT, 0, 16, data); |
| vk::CmdPushConstants(m_command_buffer.handle(), pipe.pipeline_layout_.handle(), VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4, data); |
| vk::CmdDraw(m_command_buffer.handle(), 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, VertexBufferNotForAllDraws) { |
| TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7636"); |
| AddRequiredExtensions(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::nullDescriptor); |
| AddRequiredFeature(vkt::Feature::robustBufferAccess); |
| RETURN_IF_SKIP(InitBestPracticesFramework()); |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| VkVertexInputBindingDescription input_binding = {0, 32, VK_VERTEX_INPUT_RATE_VERTEX}; |
| VkVertexInputAttributeDescription input_attrib; |
| memset(&input_attrib, 0, sizeof(input_attrib)); |
| input_attrib.format = VK_FORMAT_R32G32B32A32_SFLOAT; |
| input_attrib.location = 4; |
| |
| CreatePipelineHelper pipe0(*this); |
| pipe0.vi_ci_.pVertexBindingDescriptions = &input_binding; |
| pipe0.vi_ci_.vertexBindingDescriptionCount = 1; |
| pipe0.vi_ci_.pVertexAttributeDescriptions = &input_attrib; |
| pipe0.vi_ci_.vertexAttributeDescriptionCount = 1; |
| pipe0.CreateGraphicsPipeline(); |
| |
| CreatePipelineHelper pipe1(*this); |
| pipe1.CreateGraphicsPipeline(); |
| |
| vkt::Buffer vbo(*m_device, sizeof(float) * 3, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); |
| |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit | kPerformanceWarningBit); |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindVertexBuffers(m_command_buffer.handle(), 1, 1, &vbo.handle(), &kZeroDeviceSize); |
| |
| vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe0.Handle()); |
| vk::CmdDraw(m_command_buffer.handle(), 3, 1, 0, 0); |
| |
| vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe1.Handle()); |
| vk::CmdDraw(m_command_buffer.handle(), 3, 1, 0, 0); |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, SetDifferentEvents) { |
| TEST_DESCRIPTION("Signal different events"); |
| RETURN_IF_SKIP(InitBestPractices()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit); // TODO: should be part of BP config |
| |
| vkt::Event event(*m_device); |
| vkt::Event event2(*m_device); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.SetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| m_command_buffer.SetEvent(event2, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, ResetEventBeforeSet) { |
| TEST_DESCRIPTION("Set event two times with reset in between"); |
| RETURN_IF_SKIP(InitBestPractices()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit); // TODO: should be part of BP config |
| |
| vkt::Event event(*m_device); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.SetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| m_command_buffer.ResetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| m_command_buffer.SetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, ResetEventBeforeSetMultipleSubmits) { |
| TEST_DESCRIPTION("Set event two times with reset in between from multiple submits"); |
| RETURN_IF_SKIP(InitBestPractices()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit); // TODO: should be part of BP config |
| |
| vkt::Event event(*m_device); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.SetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| m_command_buffer.ResetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| m_command_buffer.End(); |
| m_default_queue->Submit(m_command_buffer); |
| |
| vkt::CommandBuffer cb2(*m_device, m_command_pool); |
| cb2.Begin(); |
| cb2.SetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| cb2.End(); |
| m_default_queue->Submit(cb2); |
| m_default_queue->Wait(); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, ResetEventBeforeSetMultipleSubmits2) { |
| TEST_DESCRIPTION("Set event two times with reset in between using single submit with two batches"); |
| RETURN_IF_SKIP(InitBestPractices()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit); // TODO: should be part of BP config |
| |
| vkt::Event event(*m_device); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.SetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| m_command_buffer.End(); |
| |
| vkt::CommandBuffer cb2(*m_device, m_command_pool); |
| cb2.Begin(); |
| cb2.ResetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| cb2.SetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| cb2.End(); |
| |
| VkSubmitInfo submits[2]; |
| submits[0] = vku::InitStructHelper(); |
| submits[0].commandBufferCount = 1; |
| submits[0].pCommandBuffers = &m_command_buffer.handle(); |
| submits[1] = vku::InitStructHelper(); |
| submits[1].commandBufferCount = 1; |
| submits[1].pCommandBuffers = &cb2.handle(); |
| |
| vk::QueueSubmit(m_default_queue->handle(), 2, submits, VK_NULL_HANDLE); |
| m_default_queue->Wait(); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, ResetEventFromSecondary) { |
| TEST_DESCRIPTION("Set event two times with reset in between executed from a secondary command buffer"); |
| RETURN_IF_SKIP(InitBestPractices()); |
| m_errorMonitor->ExpectSuccess(kErrorBit | kWarningBit); // TODO: should be part of BP config |
| |
| vkt::Event event(*m_device); |
| |
| vkt::CommandBuffer secondary_cb(*m_device, m_command_pool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); |
| secondary_cb.Begin(); |
| secondary_cb.ResetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| secondary_cb.End(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.SetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| m_command_buffer.ExecuteCommands(secondary_cb); |
| m_command_buffer.SetEvent(event, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, CreateFifoRelaxedSwapchain) { |
| TEST_DESCRIPTION("Test creating fifo relaxed swapchain"); |
| |
| AddSurfaceExtension(); |
| RETURN_IF_SKIP(InitBestPracticesFramework()); |
| RETURN_IF_SKIP(InitState()); |
| RETURN_IF_SKIP(InitSurface()); |
| InitSwapchainInfo(); |
| |
| VkBool32 supported; |
| vk::GetPhysicalDeviceSurfaceSupportKHR(Gpu(), m_device->graphics_queue_node_index_, m_surface.Handle(), &supported); |
| if (!supported) { |
| GTEST_SKIP() << "Graphics queue does not support present"; |
| } |
| |
| bool fifo_relaxed = false; |
| for (const auto &present_mode : m_surface_present_modes) { |
| if (present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR) { |
| fifo_relaxed = true; |
| break; |
| } |
| } |
| if (!fifo_relaxed) { |
| GTEST_SKIP() << "fifo relaxed present mode not supported"; |
| } |
| |
| VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| VkSurfaceTransformFlagBitsKHR preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; |
| |
| VkSwapchainCreateInfoKHR swapchain_create_info = vku::InitStructHelper(); |
| swapchain_create_info.surface = m_surface.Handle(); |
| swapchain_create_info.minImageCount = 2; |
| swapchain_create_info.imageFormat = m_surface_formats[0].format; |
| swapchain_create_info.imageColorSpace = m_surface_formats[0].colorSpace; |
| swapchain_create_info.imageExtent = {m_surface_capabilities.minImageExtent.width, m_surface_capabilities.minImageExtent.height}; |
| swapchain_create_info.imageArrayLayers = 1; |
| swapchain_create_info.imageUsage = imageUsage; |
| swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| swapchain_create_info.preTransform = preTransform; |
| swapchain_create_info.compositeAlpha = m_surface_composite_alpha; |
| swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR; |
| swapchain_create_info.clipped = VK_FALSE; |
| swapchain_create_info.oldSwapchain = 0; |
| |
| m_errorMonitor->SetAllowedFailureMsg("VUID-VkSwapchainCreateInfoKHR-presentMode-02839"); |
| m_swapchain.Init(*m_device, swapchain_create_info); |
| } |
| |
| TEST_F(VkPositiveBestPracticesLayerTest, ResetCommandPool) { |
| TEST_DESCRIPTION("Destroy event that was set in a command buffer"); |
| |
| RETURN_IF_SKIP(InitBestPracticesFramework()); |
| void *pNext = nullptr; |
| VkPhysicalDevicePortabilitySubsetFeaturesKHR portability_subset_features = vku::InitStructHelper(); |
| if (IsExtensionsEnabled(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) { |
| GetPhysicalDeviceFeatures2(portability_subset_features); |
| if (!portability_subset_features.events) { |
| GTEST_SKIP() << "VkPhysicalDevicePortabilitySubsetFeaturesKHR::events not supported"; |
| } |
| pNext = &portability_subset_features; |
| } |
| RETURN_IF_SKIP(InitState(nullptr, pNext)); |
| |
| { |
| vkt::Event event1(*m_device); |
| m_command_buffer.Begin(); |
| event1.CmdSet(m_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); |
| m_command_buffer.End(); |
| m_default_queue->Submit(m_command_buffer); |
| m_default_queue->Wait(); |
| } |
| |
| vkt::Event event2(*m_device); |
| m_command_buffer.Begin(); |
| event2.CmdSet(m_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); |
| m_command_buffer.End(); |
| m_default_queue->Submit(m_command_buffer); |
| m_default_queue->Wait(); |
| } |