Resolve some more validation layer issues. (#1643)

This commit is contained in:
Andreas Süßenbach 2023-08-23 13:58:54 +02:00 committed by GitHub
parent 14d048e9bf
commit fee04df943
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 40 additions and 37 deletions

View File

@ -110,6 +110,9 @@ int main( int /*argc*/, char ** /*argv*/ )
// attachment which will be cleared to yellow, and then used by the shaders to color the drawn triangle. Final // attachment which will be cleared to yellow, and then used by the shaders to color the drawn triangle. Final
// result should be a yellow triangle // result should be a yellow triangle
// in order to get a clean desctruction sequence, instantiate the DeviceMemory for the vertex buffer first
vk::raii::DeviceMemory inputMemory( nullptr );
// Create the image that will be used as the input attachment // Create the image that will be used as the input attachment
// The image for the color attachment is the presentable image already created as part of the SwapChainData // The image for the color attachment is the presentable image already created as part of the SwapChainData
vk::ImageCreateInfo imageCreateInfo( {}, vk::ImageCreateInfo imageCreateInfo( {},
@ -126,7 +129,7 @@ int main( int /*argc*/, char ** /*argv*/ )
vk::MemoryRequirements memoryRequirements = inputImage.getMemoryRequirements(); vk::MemoryRequirements memoryRequirements = inputImage.getMemoryRequirements();
uint32_t memoryTypeIndex = vk::su::findMemoryType( physicalDevice.getMemoryProperties(), memoryRequirements.memoryTypeBits, {} ); uint32_t memoryTypeIndex = vk::su::findMemoryType( physicalDevice.getMemoryProperties(), memoryRequirements.memoryTypeBits, {} );
vk::MemoryAllocateInfo memoryAllocateInfo( memoryRequirements.size, memoryTypeIndex ); vk::MemoryAllocateInfo memoryAllocateInfo( memoryRequirements.size, memoryTypeIndex );
vk::raii::DeviceMemory inputMemory( device, memoryAllocateInfo ); inputMemory = vk::raii::DeviceMemory( device, memoryAllocateInfo );
inputImage.bindMemory( *inputMemory, 0 ); inputImage.bindMemory( *inputMemory, 0 );
// Set the image layout to TRANSFER_DST_OPTIMAL to be ready for clear // Set the image layout to TRANSFER_DST_OPTIMAL to be ready for clear

View File

@ -121,6 +121,9 @@ int main( int /*argc*/, char ** /*argv*/ )
assert( result == vk::Result::eSuccess ); assert( result == vk::Result::eSuccess );
assert( imageIndex < swapChainData.images.size() ); assert( imageIndex < swapChainData.images.size() );
// in order to get a clean desctruction sequence, instantiate the DeviceMemory for the result buffer first
vk::raii::DeviceMemory queryResultMemory( nullptr );
/* Allocate a uniform buffer that will take query results. */ /* Allocate a uniform buffer that will take query results. */
vk::BufferCreateInfo bufferCreateInfo( {}, 4 * sizeof( uint64_t ), vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eTransferDst ); vk::BufferCreateInfo bufferCreateInfo( {}, 4 * sizeof( uint64_t ), vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eTransferDst );
vk::raii::Buffer queryResultBuffer( device, bufferCreateInfo ); vk::raii::Buffer queryResultBuffer( device, bufferCreateInfo );
@ -130,7 +133,7 @@ int main( int /*argc*/, char ** /*argv*/ )
memoryRequirements.memoryTypeBits, memoryRequirements.memoryTypeBits,
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent ); vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent );
vk::MemoryAllocateInfo memoryAllocateInfo( memoryRequirements.size, memoryTypeIndex ); vk::MemoryAllocateInfo memoryAllocateInfo( memoryRequirements.size, memoryTypeIndex );
vk::raii::DeviceMemory queryResultMemory( device, memoryAllocateInfo ); queryResultMemory = vk::raii::DeviceMemory( device, memoryAllocateInfo );
queryResultBuffer.bindMemory( *queryResultMemory, 0 ); queryResultBuffer.bindMemory( *queryResultMemory, 0 );

View File

@ -75,9 +75,10 @@ static_assert( sizeof( GeometryInstanceData ) == 64, "GeometryInstanceData struc
struct AccelerationStructureData struct AccelerationStructureData
{ {
vk::raii::AccelerationStructureNV acclerationStructure = nullptr; // Note: in order to have a clean destruction order, list the resultBufferData before the accelerationStructure that binds it
vk::raii::su::BufferData scratchBufferData = nullptr;
vk::raii::su::BufferData resultBufferData = nullptr; vk::raii::su::BufferData resultBufferData = nullptr;
vk::raii::AccelerationStructureNV accelerationStructure = nullptr;
vk::raii::su::BufferData scratchBufferData = nullptr;
vk::raii::su::BufferData instanceBufferData = nullptr; vk::raii::su::BufferData instanceBufferData = nullptr;
}; };
@ -95,19 +96,19 @@ AccelerationStructureData createAccelerationStructureData( vk::raii::PhysicalDev
instances.empty() ? vk::AccelerationStructureTypeNV::eBottomLevel : vk::AccelerationStructureTypeNV::eTopLevel; instances.empty() ? vk::AccelerationStructureTypeNV::eBottomLevel : vk::AccelerationStructureTypeNV::eTopLevel;
vk::AccelerationStructureInfoNV accelerationStructureInfo( accelerationStructureType, {}, vk::su::checked_cast<uint32_t>( instances.size() ), geometries ); vk::AccelerationStructureInfoNV accelerationStructureInfo( accelerationStructureType, {}, vk::su::checked_cast<uint32_t>( instances.size() ), geometries );
vk::AccelerationStructureCreateInfoNV accelerationStructureCreateInfoNV( 0, accelerationStructureInfo ); vk::AccelerationStructureCreateInfoNV accelerationStructureCreateInfoNV( 0, accelerationStructureInfo );
accelerationStructureData.acclerationStructure = vk::raii::AccelerationStructureNV( device, accelerationStructureCreateInfoNV ); accelerationStructureData.accelerationStructure = vk::raii::AccelerationStructureNV( device, accelerationStructureCreateInfoNV );
vk::AccelerationStructureMemoryRequirementsInfoNV objectRequirements( vk::AccelerationStructureMemoryRequirementsTypeNV::eObject, vk::AccelerationStructureMemoryRequirementsInfoNV objectRequirements( vk::AccelerationStructureMemoryRequirementsTypeNV::eObject,
*accelerationStructureData.acclerationStructure ); *accelerationStructureData.accelerationStructure );
vk::DeviceSize resultSizeInBytes = device.getAccelerationStructureMemoryRequirementsNV( objectRequirements ).memoryRequirements.size; vk::DeviceSize resultSizeInBytes = device.getAccelerationStructureMemoryRequirementsNV( objectRequirements ).memoryRequirements.size;
assert( 0 < resultSizeInBytes ); assert( 0 < resultSizeInBytes );
accelerationStructureData.resultBufferData = accelerationStructureData.resultBufferData =
vk::raii::su::BufferData( physicalDevice, device, resultSizeInBytes, vk::BufferUsageFlagBits::eRayTracingNV, vk::MemoryPropertyFlagBits::eDeviceLocal ); vk::raii::su::BufferData( physicalDevice, device, resultSizeInBytes, vk::BufferUsageFlagBits::eRayTracingNV, vk::MemoryPropertyFlagBits::eDeviceLocal );
vk::AccelerationStructureMemoryRequirementsInfoNV buildScratchRequirements( vk::AccelerationStructureMemoryRequirementsTypeNV::eBuildScratch, vk::AccelerationStructureMemoryRequirementsInfoNV buildScratchRequirements( vk::AccelerationStructureMemoryRequirementsTypeNV::eBuildScratch,
*accelerationStructureData.acclerationStructure ); *accelerationStructureData.accelerationStructure );
vk::AccelerationStructureMemoryRequirementsInfoNV updateScratchRequirements( vk::AccelerationStructureMemoryRequirementsTypeNV::eUpdateScratch, vk::AccelerationStructureMemoryRequirementsInfoNV updateScratchRequirements( vk::AccelerationStructureMemoryRequirementsTypeNV::eUpdateScratch,
*accelerationStructureData.acclerationStructure ); *accelerationStructureData.accelerationStructure );
vk::DeviceSize scratchSizeInBytes = std::max( device.getAccelerationStructureMemoryRequirementsNV( buildScratchRequirements ).memoryRequirements.size, vk::DeviceSize scratchSizeInBytes = std::max( device.getAccelerationStructureMemoryRequirementsNV( buildScratchRequirements ).memoryRequirements.size,
device.getAccelerationStructureMemoryRequirementsNV( updateScratchRequirements ).memoryRequirements.size ); device.getAccelerationStructureMemoryRequirementsNV( updateScratchRequirements ).memoryRequirements.size );
assert( 0 < scratchSizeInBytes ); assert( 0 < scratchSizeInBytes );
@ -141,7 +142,7 @@ AccelerationStructureData createAccelerationStructureData( vk::raii::PhysicalDev
} }
device.bindAccelerationStructureMemoryNV( device.bindAccelerationStructureMemoryNV(
vk::BindAccelerationStructureMemoryInfoNV( *accelerationStructureData.acclerationStructure, *accelerationStructureData.resultBufferData.deviceMemory ) ); vk::BindAccelerationStructureMemoryInfoNV( *accelerationStructureData.accelerationStructure, *accelerationStructureData.resultBufferData.deviceMemory ) );
vk::Buffer instanceData; vk::Buffer instanceData;
if ( *accelerationStructureData.instanceBufferData.buffer ) if ( *accelerationStructureData.instanceBufferData.buffer )
@ -153,7 +154,7 @@ AccelerationStructureData createAccelerationStructureData( vk::raii::PhysicalDev
instanceData, instanceData,
0, 0,
false, false,
*accelerationStructureData.acclerationStructure, *accelerationStructureData.accelerationStructure,
nullptr, nullptr,
*accelerationStructureData.scratchBufferData.buffer, *accelerationStructureData.scratchBufferData.buffer,
0 ); 0 );
@ -681,7 +682,6 @@ int main( int /*argc*/, char ** /*argv*/ )
{ {
instanceExtensions.push_back( glfwExtensions[i] ); instanceExtensions.push_back( glfwExtensions[i] );
} }
instanceExtensions.push_back( VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME );
#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL #if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL
vk::raii::Context context; vk::raii::Context context;
@ -734,11 +734,7 @@ int main( int /*argc*/, char ** /*argv*/ )
auto supportedFeatures = physicalDevice.getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceDescriptorIndexingFeaturesEXT>(); auto supportedFeatures = physicalDevice.getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceDescriptorIndexingFeaturesEXT>();
vk::raii::Device device = vk::raii::su::makeDevice( physicalDevice, vk::raii::Device device = vk::raii::su::makeDevice( physicalDevice,
graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.first,
{ VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, { VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_NV_RAY_TRACING_EXTENSION_NAME },
VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
VK_KHR_MAINTENANCE_3_EXTENSION_NAME,
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_NV_RAY_TRACING_EXTENSION_NAME },
&supportedFeatures.get<vk::PhysicalDeviceFeatures2>().features, &supportedFeatures.get<vk::PhysicalDeviceFeatures2>().features,
&supportedFeatures.get<vk::PhysicalDeviceDescriptorIndexingFeaturesEXT>() ); &supportedFeatures.get<vk::PhysicalDeviceDescriptorIndexingFeaturesEXT>() );
@ -929,7 +925,7 @@ int main( int /*argc*/, char ** /*argv*/ )
topLevelAS = createAccelerationStructureData( physicalDevice, topLevelAS = createAccelerationStructureData( physicalDevice,
device, device,
commandBuffer, commandBuffer,
{ std::make_pair( std::ref( bottomLevelAS.acclerationStructure ), std::ref( transform ) ) }, { std::make_pair( std::ref( bottomLevelAS.accelerationStructure ), std::ref( transform ) ) },
std::vector<vk::GeometryNV>() ); std::vector<vk::GeometryNV>() );
} ); } );
@ -943,11 +939,11 @@ int main( int /*argc*/, char ** /*argv*/ )
vk::BufferMemoryBarrier bufferMemoryBarrier( vk::BufferMemoryBarrier bufferMemoryBarrier(
{}, vk::AccessFlagBits::eShaderRead, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, *vertexBufferData.buffer, 0, VK_WHOLE_SIZE ); {}, vk::AccessFlagBits::eShaderRead, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, *vertexBufferData.buffer, 0, VK_WHOLE_SIZE );
commandBuffer.pipelineBarrier( commandBuffer.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, {}, nullptr, bufferMemoryBarrier, nullptr ); vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eRayTracingShaderKHR, {}, nullptr, bufferMemoryBarrier, nullptr );
bufferMemoryBarrier.buffer = *indexBufferData.buffer; bufferMemoryBarrier.buffer = *indexBufferData.buffer;
commandBuffer.pipelineBarrier( commandBuffer.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, {}, nullptr, bufferMemoryBarrier, nullptr ); vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eRayTracingShaderKHR, {}, nullptr, bufferMemoryBarrier, nullptr );
} ); } );
std::vector<vk::DescriptorSetLayoutBinding> bindings; std::vector<vk::DescriptorSetLayoutBinding> bindings;
@ -982,7 +978,7 @@ int main( int /*argc*/, char ** /*argv*/ )
vk::raii::DescriptorSets rayTracingDescriptorSets( device, descriptorSetAllocateInfo ); vk::raii::DescriptorSets rayTracingDescriptorSets( device, descriptorSetAllocateInfo );
// Bind ray tracing specific descriptor sets into pNext of a vk::WriteDescriptorSet // Bind ray tracing specific descriptor sets into pNext of a vk::WriteDescriptorSet
vk::WriteDescriptorSetAccelerationStructureNV writeDescriptorSetAcceleration( 1, &*topLevelAS.acclerationStructure ); vk::WriteDescriptorSetAccelerationStructureNV writeDescriptorSetAcceleration( 1, &*topLevelAS.accelerationStructure );
std::vector<vk::WriteDescriptorSet> accelerationDescriptionSets; std::vector<vk::WriteDescriptorSet> accelerationDescriptionSets;
for ( size_t i = 0; i < rayTracingDescriptorSets.size(); i++ ) for ( size_t i = 0; i < rayTracingDescriptorSets.size(); i++ )
{ {
@ -1280,7 +1276,7 @@ int main( int /*argc*/, char ** /*argv*/ )
rayTracingDescriptorSets.clear(); rayTracingDescriptorSets.clear();
rayTracingDescriptorSetLayout = vk::raii::DescriptorSetLayout( nullptr ); rayTracingDescriptorSetLayout = vk::raii::DescriptorSetLayout( nullptr );
rayTracingDescriptorPool = vk::raii::DescriptorPool( nullptr ); rayTracingDescriptorPool = vk::raii::DescriptorPool( nullptr );
topLevelAS.acclerationStructure = vk::raii::AccelerationStructureNV( nullptr ); topLevelAS.accelerationStructure = vk::raii::AccelerationStructureNV( nullptr );
topLevelAS.instanceBufferData.buffer = vk::raii::Buffer( nullptr ); topLevelAS.instanceBufferData.buffer = vk::raii::Buffer( nullptr );
topLevelAS.instanceBufferData.deviceMemory = vk::raii::DeviceMemory( nullptr ); topLevelAS.instanceBufferData.deviceMemory = vk::raii::DeviceMemory( nullptr );
topLevelAS.resultBufferData.buffer = vk::raii::Buffer( nullptr ); topLevelAS.resultBufferData.buffer = vk::raii::Buffer( nullptr );
@ -1288,7 +1284,7 @@ int main( int /*argc*/, char ** /*argv*/ )
topLevelAS.scratchBufferData.buffer = vk::raii::Buffer( nullptr ); topLevelAS.scratchBufferData.buffer = vk::raii::Buffer( nullptr );
topLevelAS.scratchBufferData.deviceMemory = vk::raii::DeviceMemory( nullptr ); topLevelAS.scratchBufferData.deviceMemory = vk::raii::DeviceMemory( nullptr );
descriptorSet = vk::raii::DescriptorSet( nullptr ); descriptorSet = vk::raii::DescriptorSet( nullptr );
bottomLevelAS.acclerationStructure = vk::raii::AccelerationStructureNV( nullptr ); bottomLevelAS.accelerationStructure = vk::raii::AccelerationStructureNV( nullptr );
bottomLevelAS.instanceBufferData.buffer = vk::raii::Buffer( nullptr ); bottomLevelAS.instanceBufferData.buffer = vk::raii::Buffer( nullptr );
bottomLevelAS.instanceBufferData.deviceMemory = vk::raii::DeviceMemory( nullptr ); bottomLevelAS.instanceBufferData.deviceMemory = vk::raii::DeviceMemory( nullptr );
bottomLevelAS.resultBufferData.buffer = vk::raii::Buffer( nullptr ); bottomLevelAS.resultBufferData.buffer = vk::raii::Buffer( nullptr );

View File

@ -192,7 +192,7 @@ int main( int /*argc*/, char ** /*argv*/ )
vk::ImageSubresourceRange imageSubresourceRange( vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 ); vk::ImageSubresourceRange imageSubresourceRange( vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 );
vk::ImageMemoryBarrier prePresentBarrier( vk::AccessFlagBits::eColorAttachmentWrite, vk::ImageMemoryBarrier prePresentBarrier( vk::AccessFlagBits::eColorAttachmentWrite,
vk::AccessFlagBits::eMemoryRead, {},
vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eColorAttachmentOptimal,
vk::ImageLayout::ePresentSrcKHR, vk::ImageLayout::ePresentSrcKHR,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,

View File

@ -263,8 +263,8 @@ int main( int /*argc*/, char ** /*argv*/ )
device.destroyPipelineLayout( pipelineLayout ); device.destroyPipelineLayout( pipelineLayout );
device.destroyDescriptorSetLayout( descriptorSetLayout ); device.destroyDescriptorSetLayout( descriptorSetLayout );
device.destroyImageView( inputAttachmentView ); device.destroyImageView( inputAttachmentView );
device.destroyImage( inputImage ); // destroy the inputImage before freeing the bound inputMemory !
device.freeMemory( inputMemory ); device.freeMemory( inputMemory );
device.destroyImage( inputImage );
swapChainData.clear( device ); swapChainData.clear( device );
device.freeCommandBuffers( commandPool, commandBuffer ); device.freeCommandBuffers( commandPool, commandBuffer );
device.destroyCommandPool( commandPool ); device.destroyCommandPool( commandPool );

View File

@ -199,8 +199,8 @@ int main( int /*argc*/, char ** /*argv*/ )
device.destroyFence( drawFence ); device.destroyFence( drawFence );
device.destroyQueryPool( queryPool ); device.destroyQueryPool( queryPool );
device.destroyBuffer( queryResultBuffer ); // destroy the queryResultBuffer before freeing the bound queryResultMemory !
device.freeMemory( queryResultMemory ); device.freeMemory( queryResultMemory );
device.destroyBuffer( queryResultBuffer );
device.destroySemaphore( imageAcquiredSemaphore ); device.destroySemaphore( imageAcquiredSemaphore );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */

View File

@ -942,11 +942,11 @@ int main( int /*argc*/, char ** /*argv*/ )
vk::BufferMemoryBarrier bufferMemoryBarrier( vk::BufferMemoryBarrier bufferMemoryBarrier(
{}, vk::AccessFlagBits::eShaderRead, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, vertexBufferData.buffer, 0, VK_WHOLE_SIZE ); {}, vk::AccessFlagBits::eShaderRead, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, vertexBufferData.buffer, 0, VK_WHOLE_SIZE );
commandBuffer.pipelineBarrier( commandBuffer.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, {}, nullptr, bufferMemoryBarrier, nullptr ); vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eRayTracingShaderKHR, {}, nullptr, bufferMemoryBarrier, nullptr );
bufferMemoryBarrier.buffer = indexBufferData.buffer; bufferMemoryBarrier.buffer = indexBufferData.buffer;
commandBuffer.pipelineBarrier( commandBuffer.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, {}, nullptr, bufferMemoryBarrier, nullptr ); vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eRayTracingShaderKHR, {}, nullptr, bufferMemoryBarrier, nullptr );
} ); } );
std::vector<vk::DescriptorSetLayoutBinding> bindings; std::vector<vk::DescriptorSetLayoutBinding> bindings;

View File

@ -188,7 +188,7 @@ int main( int /*argc*/, char ** /*argv*/ )
commandBuffer.endRenderPass(); commandBuffer.endRenderPass();
vk::ImageMemoryBarrier prePresentBarrier( vk::AccessFlagBits::eColorAttachmentWrite, vk::ImageMemoryBarrier prePresentBarrier( vk::AccessFlagBits::eColorAttachmentWrite,
vk::AccessFlagBits::eMemoryRead, {},
vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eColorAttachmentOptimal,
vk::ImageLayout::ePresentSrcKHR, vk::ImageLayout::ePresentSrcKHR,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,

View File

@ -356,14 +356,15 @@ namespace vk
void * /*pUserData*/ ) void * /*pUserData*/ )
{ {
#if !defined( NDEBUG ) #if !defined( NDEBUG )
if ( pCallbackData->messageIdNumber == 648835635 ) if ( static_cast<uint32_t>(pCallbackData->messageIdNumber) == 0x822806fa )
{ {
// UNASSIGNED-khronos-Validation-debug-build-warning-message // Validation Warning: vkCreateInstance(): to enable extension VK_EXT_debug_utils, but this extension is intended to support use by applications when
// debugging and it is strongly recommended that it be otherwise avoided.
return vk::False; return vk::False;
} }
if ( pCallbackData->messageIdNumber == 767975156 ) else if ( static_cast<uint32_t>(pCallbackData->messageIdNumber) == 0xe8d1a9fe )
{ {
// UNASSIGNED-BestPractices-vkCreateInstance-specialuse-extension // Validation Performance Warning: Using debug builds of the validation layers *will* adversely affect performance.
return vk::False; return vk::False;
} }
#endif #endif