2019-04-01 08:06:49 +00:00
// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
//
// 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
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// VulkanHpp Samples : DynamicUniform
// Draw 2 Cubes using dynamic uniform buffer
# include "../utils/geometries.hpp"
# include "../utils/math.hpp"
# include "../utils/shaders.hpp"
# include "../utils/utils.hpp"
# include "vulkan/vulkan.hpp"
# include "SPIRV/GlslangToSpv.h"
# include <iostream>
static char const * AppName = " DynamicUniform " ;
static char const * EngineName = " Vulkan.hpp " ;
int main ( int /*argc*/ , char * * /*argv*/ )
{
try
{
vk : : UniqueInstance instance = vk : : su : : createInstance ( AppName , EngineName , vk : : su : : getInstanceExtensions ( ) ) ;
# if !defined(NDEBUG)
vk : : UniqueDebugReportCallbackEXT debugReportCallback = vk : : su : : createDebugReportCallback ( instance ) ;
# endif
2019-06-25 07:47:27 +00:00
vk : : PhysicalDevice physicalDevice = instance - > enumeratePhysicalDevices ( ) . front ( ) ;
2019-04-01 08:06:49 +00:00
vk : : su : : SurfaceData surfaceData ( instance , AppName , AppName , vk : : Extent2D ( 500 , 500 ) ) ;
2019-06-25 07:47:27 +00:00
std : : pair < uint32_t , uint32_t > graphicsAndPresentQueueFamilyIndex = vk : : su : : findGraphicsAndPresentQueueFamilyIndex ( physicalDevice , * surfaceData . surface ) ;
vk : : UniqueDevice device = vk : : su : : createDevice ( physicalDevice , graphicsAndPresentQueueFamilyIndex . first , vk : : su : : getDeviceExtensions ( ) ) ;
2019-04-01 08:06:49 +00:00
vk : : UniqueCommandPool commandPool = vk : : su : : createCommandPool ( device , graphicsAndPresentQueueFamilyIndex . first ) ;
2019-06-25 07:47:27 +00:00
vk : : UniqueCommandBuffer commandBuffer = std : : move ( device - > allocateCommandBuffersUnique ( vk : : CommandBufferAllocateInfo ( commandPool . get ( ) , vk : : CommandBufferLevel : : ePrimary , 1 ) ) . front ( ) ) ;
2019-04-01 08:06:49 +00:00
vk : : Queue graphicsQueue = device - > getQueue ( graphicsAndPresentQueueFamilyIndex . first , 0 ) ;
vk : : Queue presentQueue = device - > getQueue ( graphicsAndPresentQueueFamilyIndex . second , 0 ) ;
2019-06-25 07:47:27 +00:00
vk : : su : : SwapChainData swapChainData ( physicalDevice , device , * surfaceData . surface , surfaceData . extent , vk : : ImageUsageFlagBits : : eColorAttachment | vk : : ImageUsageFlagBits : : eTransferSrc ,
vk : : UniqueSwapchainKHR ( ) , graphicsAndPresentQueueFamilyIndex . first , graphicsAndPresentQueueFamilyIndex . second ) ;
2019-04-01 08:06:49 +00:00
2019-06-25 07:47:27 +00:00
vk : : su : : DepthBufferData depthBufferData ( physicalDevice , device , vk : : Format : : eD16Unorm , surfaceData . extent ) ;
2019-04-01 08:06:49 +00:00
2019-06-25 07:47:27 +00:00
vk : : UniqueRenderPass renderPass = vk : : su : : createRenderPass ( device , vk : : su : : pickSurfaceFormat ( physicalDevice . getSurfaceFormatsKHR ( surfaceData . surface . get ( ) ) ) . format , depthBufferData . format ) ;
2019-04-01 08:06:49 +00:00
glslang : : InitializeProcess ( ) ;
vk : : UniqueShaderModule vertexShaderModule = vk : : su : : createShaderModule ( device , vk : : ShaderStageFlagBits : : eVertex , vertexShaderText_PC_C ) ;
vk : : UniqueShaderModule fragmentShaderModule = vk : : su : : createShaderModule ( device , vk : : ShaderStageFlagBits : : eFragment , fragmentShaderText_C_C ) ;
glslang : : FinalizeProcess ( ) ;
std : : vector < vk : : UniqueFramebuffer > framebuffers = vk : : su : : createFramebuffers ( device , renderPass , swapChainData . imageViews , depthBufferData . imageView , surfaceData . extent ) ;
2019-06-25 07:47:27 +00:00
vk : : su : : BufferData vertexBufferData ( physicalDevice , device , sizeof ( coloredCubeData ) , vk : : BufferUsageFlagBits : : eVertexBuffer ) ;
2019-04-01 08:06:49 +00:00
vk : : su : : copyToDevice ( device , vertexBufferData . deviceMemory , coloredCubeData , sizeof ( coloredCubeData ) / sizeof ( coloredCubeData [ 0 ] ) ) ;
/* VULKAN_KEY_START */
2019-06-25 07:47:27 +00:00
vk : : PhysicalDeviceLimits limits = physicalDevice . getProperties ( ) . limits ;
2019-04-01 08:06:49 +00:00
if ( limits . maxDescriptorSetUniformBuffersDynamic < 1 )
{
std : : cout < < " No dynamic uniform buffers supported \n " ;
exit ( - 1 ) ;
}
/* Set up uniform buffer with 2 transform matrices in it */
glm : : mat4x4 mvpcs [ 2 ] ;
glm : : mat4x4 model = glm : : mat4x4 ( 1.0f ) ;
glm : : mat4x4 view = glm : : lookAt ( glm : : vec3 ( 0.0f , 3.0f , - 10.0f ) , glm : : vec3 ( 0.0f , 0.0f , 0.0f ) , glm : : vec3 ( 0.0f , - 1.0f , 0.0f ) ) ;
glm : : mat4x4 projection = glm : : perspective ( glm : : radians ( 45.0f ) , 1.0f , 0.1f , 100.0f ) ;
glm : : mat4x4 clip = glm : : mat4x4 ( 1.0f , 0.0f , 0.0f , 0.0f , 0.0f , - 1.0f , 0.0f , 0.0f , 0.0f , 0.0f , 0.5f , 0.0f , 0.0f , 0.0f , 0.5f , 1.0f ) ; // vulkan clip space has inverted y and half z !
mvpcs [ 0 ] = clip * projection * view * model ;
2019-04-15 08:18:58 +00:00
model = glm : : translate ( model , glm : : vec3 ( - 1.5f , 1.5f , - 1.5f ) ) ;
2019-04-01 08:06:49 +00:00
mvpcs [ 1 ] = clip * projection * view * model ;
VkDeviceSize bufferSize = sizeof ( glm : : mat4x4 ) ;
if ( limits . minUniformBufferOffsetAlignment )
{
bufferSize = ( bufferSize + limits . minUniformBufferOffsetAlignment - 1 ) & ~ ( limits . minUniformBufferOffsetAlignment - 1 ) ;
}
2019-06-25 07:47:27 +00:00
vk : : su : : BufferData uniformBufferData ( physicalDevice , device , 2 * bufferSize , vk : : BufferUsageFlagBits : : eUniformBuffer ) ;
2019-04-01 08:06:49 +00:00
vk : : su : : copyToDevice ( device , uniformBufferData . deviceMemory , mvpcs , 2 , bufferSize ) ;
// create a DescriptorSetLayout with vk::DescriptorType::eUniformBufferDynamic
2019-06-25 07:47:27 +00:00
vk : : UniqueDescriptorSetLayout descriptorSetLayout = vk : : su : : createDescriptorSetLayout ( device , { { vk : : DescriptorType : : eUniformBufferDynamic , 1 , vk : : ShaderStageFlagBits : : eVertex } } ) ;
2019-04-01 08:06:49 +00:00
vk : : UniquePipelineLayout pipelineLayout = device - > createPipelineLayoutUnique ( vk : : PipelineLayoutCreateInfo ( vk : : PipelineLayoutCreateFlags ( ) , 1 , & descriptorSetLayout . get ( ) ) ) ;
// create a DescriptorPool with vk::DescriptorType::eUniformBufferDynamic
2019-05-21 13:44:52 +00:00
vk : : UniqueDescriptorPool descriptorPool = vk : : su : : createDescriptorPool ( device , { { vk : : DescriptorType : : eUniformBufferDynamic , 1 } } ) ;
2019-06-25 07:47:27 +00:00
vk : : UniqueDescriptorSet descriptorSet = std : : move ( device - > allocateDescriptorSetsUnique ( vk : : DescriptorSetAllocateInfo ( * descriptorPool , 1 , & * descriptorSetLayout ) ) . front ( ) ) ;
2019-04-01 08:06:49 +00:00
2019-07-03 07:23:56 +00:00
vk : : su : : updateDescriptorSets ( device , descriptorSet , { { vk : : DescriptorType : : eUniformBufferDynamic , uniformBufferData . buffer , vk : : UniqueBufferView ( ) } } , { } ) ;
2019-04-01 08:06:49 +00:00
vk : : UniquePipelineCache pipelineCache = device - > createPipelineCacheUnique ( vk : : PipelineCacheCreateInfo ( ) ) ;
2019-06-25 07:47:27 +00:00
vk : : UniquePipeline graphicsPipeline = vk : : su : : createGraphicsPipeline ( device , pipelineCache , std : : make_pair ( * vertexShaderModule , nullptr ) , std : : make_pair ( * fragmentShaderModule , nullptr ) ,
sizeof ( coloredCubeData [ 0 ] ) , { { vk : : Format : : eR32G32B32A32Sfloat , 0 } , { vk : : Format : : eR32G32B32A32Sfloat , 16 } } ,
vk : : FrontFace : : eClockwise , true , pipelineLayout , renderPass ) ;
2019-04-01 08:06:49 +00:00
// Get the index of the next available swapchain image:
vk : : UniqueSemaphore imageAcquiredSemaphore = device - > createSemaphoreUnique ( vk : : SemaphoreCreateInfo ( ) ) ;
vk : : ResultValue < uint32_t > currentBuffer = device - > acquireNextImageKHR ( swapChainData . swapChain . get ( ) , vk : : su : : FenceTimeout , imageAcquiredSemaphore . get ( ) , nullptr ) ;
assert ( currentBuffer . result = = vk : : Result : : eSuccess ) ;
assert ( currentBuffer . value < framebuffers . size ( ) ) ;
2019-06-25 07:47:27 +00:00
commandBuffer - > begin ( vk : : CommandBufferBeginInfo ( vk : : CommandBufferUsageFlags ( ) ) ) ;
2019-04-01 08:06:49 +00:00
vk : : ClearValue clearValues [ 2 ] ;
clearValues [ 0 ] . color = vk : : ClearColorValue ( std : : array < float , 4 > ( { 0.2f , 0.2f , 0.2f , 0.2f } ) ) ;
clearValues [ 1 ] . depthStencil = vk : : ClearDepthStencilValue ( 1.0f , 0 ) ;
vk : : RenderPassBeginInfo renderPassBeginInfo ( renderPass . get ( ) , framebuffers [ currentBuffer . value ] . get ( ) , vk : : Rect2D ( vk : : Offset2D ( 0 , 0 ) , surfaceData . extent ) , 2 , clearValues ) ;
2019-06-25 07:47:27 +00:00
commandBuffer - > beginRenderPass ( renderPassBeginInfo , vk : : SubpassContents : : eInline ) ;
commandBuffer - > bindPipeline ( vk : : PipelineBindPoint : : eGraphics , graphicsPipeline . get ( ) ) ;
2019-04-01 08:06:49 +00:00
2019-06-25 07:47:27 +00:00
commandBuffer - > setViewport ( 0 , vk : : Viewport ( 0.0f , 0.0f , static_cast < float > ( surfaceData . extent . width ) , static_cast < float > ( surfaceData . extent . height ) , 0.0f , 1.0f ) ) ;
commandBuffer - > setScissor ( 0 , vk : : Rect2D ( vk : : Offset2D ( 0 , 0 ) , surfaceData . extent ) ) ;
2019-04-01 08:06:49 +00:00
/* The first draw should use the first matrix in the buffer */
uint32_t dynamicOffset = 0 ;
2019-06-25 07:47:27 +00:00
commandBuffer - > bindDescriptorSets ( vk : : PipelineBindPoint : : eGraphics , pipelineLayout . get ( ) , 0 , descriptorSet . get ( ) , dynamicOffset ) ;
2019-04-01 08:06:49 +00:00
2019-06-25 07:47:27 +00:00
commandBuffer - > bindVertexBuffers ( 0 , * vertexBufferData . buffer , { 0 } ) ;
commandBuffer - > draw ( 12 * 3 , 1 , 0 , 0 ) ;
2019-04-01 08:06:49 +00:00
// the second draw should use the second matrix in the buffer;
dynamicOffset = ( uint32_t ) bufferSize ;
2019-06-25 07:47:27 +00:00
commandBuffer - > bindDescriptorSets ( vk : : PipelineBindPoint : : eGraphics , pipelineLayout . get ( ) , 0 , descriptorSet . get ( ) , dynamicOffset ) ;
commandBuffer - > draw ( 12 * 3 , 1 , 0 , 0 ) ;
2019-04-01 08:06:49 +00:00
2019-06-25 07:47:27 +00:00
commandBuffer - > endRenderPass ( ) ;
commandBuffer - > end ( ) ;
2019-04-01 08:06:49 +00:00
vk : : UniqueFence drawFence = device - > createFenceUnique ( vk : : FenceCreateInfo ( ) ) ;
vk : : PipelineStageFlags waitDestinationStageMask ( vk : : PipelineStageFlagBits : : eColorAttachmentOutput ) ;
2019-06-25 07:47:27 +00:00
vk : : SubmitInfo submitInfo ( 1 , & imageAcquiredSemaphore . get ( ) , & waitDestinationStageMask , 1 , & commandBuffer . get ( ) ) ;
2019-04-01 08:06:49 +00:00
graphicsQueue . submit ( submitInfo , drawFence . get ( ) ) ;
while ( vk : : Result : : eTimeout = = device - > waitForFences ( drawFence . get ( ) , VK_TRUE , vk : : su : : FenceTimeout ) )
;
presentQueue . presentKHR ( vk : : PresentInfoKHR ( 0 , nullptr , 1 , & swapChainData . swapChain . get ( ) , & currentBuffer . value ) ) ;
Sleep ( 1000 ) ;
/* VULKAN_KEY_END */
device - > waitIdle ( ) ;
# if defined(VK_USE_PLATFORM_WIN32_KHR)
DestroyWindow ( surfaceData . window ) ;
# else
# pragma error "unhandled platform"
# endif
}
catch ( vk : : SystemError err )
{
std : : cout < < " vk::SystemError: " < < err . what ( ) < < std : : endl ;
exit ( - 1 ) ;
}
catch ( std : : runtime_error err )
{
std : : cout < < " std::runtime_error: " < < err . what ( ) < < std : : endl ;
exit ( - 1 ) ;
}
catch ( . . . )
{
std : : cout < < " unknown error \n " ;
exit ( - 1 ) ;
}
return 0 ;
}