| /* |
| * Copyright (c) 2015-2020 The Khronos Group Inc. |
| * Copyright (c) 2015-2020 Valve Corporation |
| * Copyright (c) 2015-2020 LunarG, Inc. |
| * Copyright (c) 2015-2020 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 |
| * |
| * Author: Camden Stocker <camden@lunarg.com> |
| */ |
| |
| #include "cast_utils.h" |
| #include "layer_validation_tests.h" |
| |
| void VkBestPracticesLayerTest::InitBestPracticesFramework() { |
| VkValidationFeatureEnableEXT enables[] = {VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT}; |
| VkValidationFeatureDisableEXT disables[] = {VK_VALIDATION_FEATURE_DISABLE_ALL_EXT}; |
| |
| VkValidationFeaturesEXT features = {}; |
| features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT; |
| features.enabledValidationFeatureCount = 1; |
| features.disabledValidationFeatureCount = 1; |
| features.pEnabledValidationFeatures = enables; |
| features.pDisabledValidationFeatures = disables; |
| |
| InitFramework(myDbgFunc, m_errorMonitor, &features); |
| } |
| |
| TEST_F(VkBestPracticesLayerTest, CmdClearAttachmentTest) { |
| TEST_DESCRIPTION("Test for validating usage of vkCmdClearAttachments"); |
| |
| InitBestPracticesFramework(); |
| InitState(); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| m_commandBuffer->begin(); |
| m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); |
| |
| // Main thing we care about for this test is that the VkImage obj we're |
| // clearing matches Color Attachment of FB |
| // Also pass down other dummy params to keep driver and paramchecker happy |
| VkClearAttachment color_attachment; |
| color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| color_attachment.clearValue.color.float32[0] = 1.0; |
| color_attachment.clearValue.color.float32[1] = 1.0; |
| color_attachment.clearValue.color.float32[2] = 1.0; |
| color_attachment.clearValue.color.float32[3] = 1.0; |
| color_attachment.colorAttachment = 0; |
| VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1}; |
| |
| // Call for full-sized FB Color attachment prior to issuing a Draw |
| m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, |
| "UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw"); |
| vk::CmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(VkBestPracticesLayerTest, VtxBufferBadIndex) { |
| m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, |
| "UNASSIGNED-BestPractices-DrawState-VtxIndexOutOfBounds"); |
| |
| InitBestPracticesFramework(); |
| InitState(); |
| |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {}; |
| pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; |
| pipe_ms_state_ci.pNext = NULL; |
| pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; |
| pipe_ms_state_ci.sampleShadingEnable = 0; |
| pipe_ms_state_ci.minSampleShading = 1.0; |
| pipe_ms_state_ci.pSampleMask = NULL; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.InitInfo(); |
| pipe.pipe_ms_state_ci_ = pipe_ms_state_ci; |
| pipe.InitState(); |
| pipe.CreateGraphicsPipeline(); |
| |
| m_commandBuffer->begin(); |
| m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); |
| vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_); |
| // Don't care about actual data, just need to get to draw to flag error |
| const float vbo_data[3] = {1.f, 0.f, 1.f}; |
| VkConstantBufferObj vbo(m_device, sizeof(vbo_data), (const void *)&vbo_data, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); |
| m_commandBuffer->BindVertexBuffer(&vbo, (VkDeviceSize)0, 1); // VBO idx 1, but no VBO in PSO |
| m_commandBuffer->Draw(1, 0, 0, 0); |
| |
| m_errorMonitor->VerifyFound(); |
| |
| m_commandBuffer->EndRenderPass(); |
| m_commandBuffer->end(); |
| } |
| |
| // This is a positive test. No failures are expected. |
| TEST_F(VkBestPracticesLayerTest, TestDestroyFreeNullHandles) { |
| VkResult err; |
| |
| TEST_DESCRIPTION("Call all applicable destroy and free routines with NULL handles, expecting no validation errors"); |
| |
| InitBestPracticesFramework(); |
| InitState(); |
| |
| ASSERT_NO_FATAL_FAILURE(InitViewport()); |
| ASSERT_NO_FATAL_FAILURE(InitRenderTarget()); |
| |
| m_errorMonitor->ExpectSuccess(); |
| |
| vk::DestroyBuffer(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyBufferView(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyCommandPool(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyDescriptorPool(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyDescriptorSetLayout(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyDevice(VK_NULL_HANDLE, NULL); |
| vk::DestroyEvent(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyFence(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyFramebuffer(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyImage(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyImageView(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyInstance(VK_NULL_HANDLE, NULL); |
| vk::DestroyPipeline(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyPipelineCache(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyPipelineLayout(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyQueryPool(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyRenderPass(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroySampler(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroySemaphore(m_device->device(), VK_NULL_HANDLE, NULL); |
| vk::DestroyShaderModule(m_device->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(m_device->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(m_device->device(), &command_buffer_allocate_info, &command_buffers[1]); |
| vk::FreeCommandBuffers(m_device->device(), command_pool, 3, command_buffers); |
| vk::DestroyCommandPool(m_device->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; |
| |
| VkDescriptorPool ds_pool; |
| err = vk::CreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool); |
| ASSERT_VK_SUCCESS(err); |
| |
| 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 VkDescriptorSetLayoutObj 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; |
| alloc_info.pSetLayouts = &ds_layout.handle(); |
| err = vk::AllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_sets[1]); |
| ASSERT_VK_SUCCESS(err); |
| vk::FreeDescriptorSets(m_device->device(), ds_pool, 3, descriptor_sets); |
| vk::DestroyDescriptorPool(m_device->device(), ds_pool, NULL); |
| |
| vk::FreeMemory(m_device->device(), VK_NULL_HANDLE, NULL); |
| |
| m_errorMonitor->VerifyNotFound(); |
| } |