2019-04-09 13:19:18 +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 : InputAttachment
// Use an input attachment to draw a yellow triangle
# 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 = " InputAttachment " ;
static char const * EngineName = " Vulkan.hpp " ;
static std : : string vertexShaderText = R " (
# version 450
vec2 vertices [ 3 ] ;
void main ( )
{
vertices [ 0 ] = vec2 ( - 1.0f , - 1.0f ) ;
vertices [ 1 ] = vec2 ( 1.0f , - 1.0f ) ;
vertices [ 2 ] = vec2 ( 0.0f , 1.0f ) ;
gl_Position = vec4 ( vertices [ gl_VertexIndex % 3 ] , 0.0f , 1.0f ) ;
}
) " ;
// Use subpassLoad to read from input attachment
static const char * fragmentShaderText = R " (
# version 450
layout ( input_attachment_index = 0 , set = 0 , binding = 0 ) uniform subpassInput inputAttachment ;
layout ( location = 0 ) out vec4 outColor ;
void main ( )
{
outColor = subpassLoad ( inputAttachment ) ;
}
) " ;
int main ( int /*argc*/ , char * * /*argv*/ )
{
try
{
2019-07-09 07:25:48 +00:00
vk : : UniqueInstance instance = vk : : su : : createInstance ( AppName , EngineName , { } , vk : : su : : getInstanceExtensions ( ) ) ;
2019-04-09 13:19:18 +00:00
# if !defined(NDEBUG)
2019-09-25 09:56:46 +00:00
vk : : UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk : : su : : createDebugUtilsMessenger ( instance ) ;
2019-04-09 13:19:18 +00:00
# endif
2019-06-25 07:47:27 +00:00
vk : : PhysicalDevice physicalDevice = instance - > enumeratePhysicalDevices ( ) . front ( ) ;
2019-04-09 13:19:18 +00:00
2019-06-25 07:47:27 +00:00
vk : : FormatProperties formatProperties = physicalDevice . getFormatProperties ( vk : : Format : : eR8G8B8A8Unorm ) ;
2019-04-09 13:19:18 +00:00
if ( ! ( formatProperties . optimalTilingFeatures & vk : : FormatFeatureFlagBits : : eColorAttachment ) )
{
std : : cout < < " vk::Format::eR8G8B8A8Unorm format unsupported for input attachment \n " ;
exit ( - 1 ) ;
}
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-09 13:19:18 +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-09 13:19:18 +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-09 13:19:18 +00:00
/* VULKAN_KEY_START */
// Create a framebuffer with 2 attachments, one the color attachment the shaders render into, and the other an input 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
// 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
vk : : UniqueImage inputImage = device - > createImageUnique ( vk : : ImageCreateInfo ( vk : : ImageCreateFlags ( ) , vk : : ImageType : : e2D , swapChainData . colorFormat , vk : : Extent3D ( surfaceData . extent , 1 ) , 1 , 1 ,
vk : : SampleCountFlagBits : : e1 , vk : : ImageTiling : : eOptimal , vk : : ImageUsageFlagBits : : eInputAttachment | vk : : ImageUsageFlagBits : : eTransferDst ) ) ;
vk : : MemoryRequirements memoryRequirements = device - > getImageMemoryRequirements ( inputImage . get ( ) ) ;
2019-06-25 07:47:27 +00:00
uint32_t memoryTypeIndex = vk : : su : : findMemoryType ( physicalDevice . getMemoryProperties ( ) , memoryRequirements . memoryTypeBits , vk : : MemoryPropertyFlags ( ) ) ;
2019-04-09 13:19:18 +00:00
vk : : UniqueDeviceMemory inputMemory = device - > allocateMemoryUnique ( vk : : MemoryAllocateInfo ( memoryRequirements . size , memoryTypeIndex ) ) ;
device - > bindImageMemory ( inputImage . get ( ) , inputMemory . get ( ) , 0 ) ;
// Set the image layout to TRANSFER_DST_OPTIMAL to be ready for clear
2019-06-25 07:47:27 +00:00
commandBuffer - > begin ( vk : : CommandBufferBeginInfo ( ) ) ;
vk : : su : : setImageLayout ( commandBuffer , inputImage . get ( ) , swapChainData . colorFormat , vk : : ImageLayout : : eUndefined , vk : : ImageLayout : : eTransferDstOptimal ) ;
2019-04-09 13:19:18 +00:00
2019-06-25 07:47:27 +00:00
commandBuffer - > clearColorImage ( inputImage . get ( ) , vk : : ImageLayout : : eTransferDstOptimal , vk : : ClearColorValue ( std : : array < float , 4 > ( { { 1.0f , 1.0f , 0.0f , 0.0f } } ) ) ,
2019-04-09 13:19:18 +00:00
vk : : ImageSubresourceRange ( vk : : ImageAspectFlagBits : : eColor , 0 , VK_REMAINING_MIP_LEVELS , 0 , VK_REMAINING_ARRAY_LAYERS ) ) ;
// Set the image layout to SHADER_READONLY_OPTIMAL for use by the shaders
2019-06-25 07:47:27 +00:00
vk : : su : : setImageLayout ( commandBuffer , inputImage . get ( ) , swapChainData . colorFormat , vk : : ImageLayout : : eTransferDstOptimal , vk : : ImageLayout : : eShaderReadOnlyOptimal ) ;
2019-04-09 13:19:18 +00:00
vk : : ComponentMapping componentMapping ( vk : : ComponentSwizzle : : eR , vk : : ComponentSwizzle : : eG , vk : : ComponentSwizzle : : eB , vk : : ComponentSwizzle : : eA ) ;
vk : : ImageViewCreateInfo imageViewCreateInfo ( vk : : ImageViewCreateFlags ( ) , inputImage . get ( ) , vk : : ImageViewType : : e2D , swapChainData . colorFormat , componentMapping , vk : : ImageSubresourceRange ( vk : : ImageAspectFlagBits : : eColor , 0 , 1 , 0 , 1 ) ) ;
vk : : UniqueImageView inputAttachmentView = device - > createImageViewUnique ( imageViewCreateInfo ) ;
vk : : DescriptorSetLayoutBinding layoutBinding ( 0 , vk : : DescriptorType : : eInputAttachment , 1 , vk : : ShaderStageFlagBits : : eFragment ) ;
vk : : UniqueDescriptorSetLayout descriptorSetLayout = device - > createDescriptorSetLayoutUnique ( vk : : DescriptorSetLayoutCreateInfo ( vk : : DescriptorSetLayoutCreateFlags ( ) , 1 , & layoutBinding ) ) ;
vk : : UniquePipelineLayout pipelineLayout = device - > createPipelineLayoutUnique ( vk : : PipelineLayoutCreateInfo ( vk : : PipelineLayoutCreateFlags ( ) , 1 , & descriptorSetLayout . get ( ) ) ) ;
vk : : AttachmentDescription attachments [ 2 ] =
{
// First attachment is the color attachment - clear at the beginning of the renderpass and transition layout to PRESENT_SRC_KHR at the end of renderpass
vk : : AttachmentDescription ( vk : : AttachmentDescriptionFlags ( ) , swapChainData . colorFormat , vk : : SampleCountFlagBits : : e1 , vk : : AttachmentLoadOp : : eClear , vk : : AttachmentStoreOp : : eStore ,
vk : : AttachmentLoadOp : : eDontCare , vk : : AttachmentStoreOp : : eDontCare , vk : : ImageLayout : : eUndefined , vk : : ImageLayout : : ePresentSrcKHR ) ,
// Second attachment is input attachment. Once cleared it should have width*height yellow pixels.
// Doing a subpassLoad in the fragment shader should give the shader the color at the fragments x,y location from the input attachment
vk : : AttachmentDescription ( vk : : AttachmentDescriptionFlags ( ) , swapChainData . colorFormat , vk : : SampleCountFlagBits : : e1 , vk : : AttachmentLoadOp : : eLoad , vk : : AttachmentStoreOp : : eDontCare ,
vk : : AttachmentLoadOp : : eDontCare , vk : : AttachmentStoreOp : : eDontCare , vk : : ImageLayout : : eShaderReadOnlyOptimal , vk : : ImageLayout : : eShaderReadOnlyOptimal )
} ;
vk : : AttachmentReference colorReference ( 0 , vk : : ImageLayout : : eColorAttachmentOptimal ) ;
vk : : AttachmentReference inputReference ( 1 , vk : : ImageLayout : : eShaderReadOnlyOptimal ) ;
vk : : SubpassDescription subPass ( vk : : SubpassDescriptionFlags ( ) , vk : : PipelineBindPoint : : eGraphics , 1 , & inputReference , 1 , & colorReference ) ;
vk : : UniqueRenderPass renderPass = device - > createRenderPassUnique ( vk : : RenderPassCreateInfo ( vk : : RenderPassCreateFlags ( ) , 2 , attachments , 1 , & subPass ) ) ;
glslang : : InitializeProcess ( ) ;
vk : : UniqueShaderModule vertexShaderModule = vk : : su : : createShaderModule ( device , vk : : ShaderStageFlagBits : : eVertex , vertexShaderText ) ;
vk : : UniqueShaderModule fragmentShaderModule = vk : : su : : createShaderModule ( device , vk : : ShaderStageFlagBits : : eFragment , fragmentShaderText ) ;
glslang : : FinalizeProcess ( ) ;
std : : vector < vk : : UniqueFramebuffer > framebuffers = vk : : su : : createFramebuffers ( device , renderPass , swapChainData . imageViews , inputAttachmentView , surfaceData . extent ) ;
vk : : DescriptorPoolSize poolSize ( vk : : DescriptorType : : eInputAttachment , 1 ) ;
vk : : UniqueDescriptorPool descriptorPool = device - > createDescriptorPoolUnique ( vk : : DescriptorPoolCreateInfo ( vk : : DescriptorPoolCreateFlagBits : : eFreeDescriptorSet , 1 , 1 , & poolSize ) ) ;
2019-06-25 07:47:27 +00:00
vk : : UniqueDescriptorSet descriptorSet = std : : move ( device - > allocateDescriptorSetsUnique ( vk : : DescriptorSetAllocateInfo ( * descriptorPool , 1 , & * descriptorSetLayout ) ) . front ( ) ) ;
2019-04-09 13:19:18 +00:00
vk : : DescriptorImageInfo inputImageInfo ( nullptr , inputAttachmentView . get ( ) , vk : : ImageLayout : : eShaderReadOnlyOptimal ) ;
2019-06-25 07:47:27 +00:00
vk : : WriteDescriptorSet writeDescriptorSet ( descriptorSet . get ( ) , 0 , 0 , 1 , vk : : DescriptorType : : eInputAttachment , & inputImageInfo ) ;
2019-04-09 13:19:18 +00:00
device - > updateDescriptorSets ( vk : : ArrayProxy < const vk : : WriteDescriptorSet > ( 1 , & writeDescriptorSet ) , nullptr ) ;
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 ) , 0 , { } ,
vk : : FrontFace : : eClockwise , false , pipelineLayout , renderPass ) ;
2019-04-09 13:19:18 +00:00
vk : : UniqueSemaphore imageAcquiredSemaphore = device - > createSemaphoreUnique ( vk : : SemaphoreCreateInfo ( ) ) ;
2019-04-30 15:03:26 +00:00
vk : : ResultValue < uint32_t > result = device - > acquireNextImage2KHR ( vk : : AcquireNextImageInfoKHR ( swapChainData . swapChain . get ( ) , UINT64_MAX , imageAcquiredSemaphore . get ( ) , { } , 1 ) ) ;
2019-04-09 13:19:18 +00:00
assert ( result . result = = vk : : Result : : eSuccess ) ;
uint32_t currentBuffer = result . value ;
vk : : ClearValue clearValue ;
clearValue . color = vk : : ClearColorValue ( std : : array < float , 4 > ( { 0.2f , 0.2f , 0.2f , 0.2f } ) ) ;
2019-06-25 07:47:27 +00:00
commandBuffer - > beginRenderPass ( vk : : RenderPassBeginInfo ( renderPass . get ( ) , framebuffers [ currentBuffer ] . get ( ) , vk : : Rect2D ( vk : : Offset2D ( 0 , 0 ) , surfaceData . extent ) , 1 , & clearValue ) , vk : : SubpassContents : : eInline ) ;
commandBuffer - > bindPipeline ( vk : : PipelineBindPoint : : eGraphics , graphicsPipeline . get ( ) ) ;
commandBuffer - > bindDescriptorSets ( vk : : PipelineBindPoint : : eGraphics , pipelineLayout . get ( ) , 0 , descriptorSet . get ( ) , nullptr ) ;
2019-04-09 13:19:18 +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-09 13:19:18 +00:00
2019-06-25 07:47:27 +00:00
commandBuffer - > draw ( 3 , 1 , 0 , 0 ) ;
commandBuffer - > endRenderPass ( ) ;
commandBuffer - > end ( ) ;
2019-04-09 13:19:18 +00:00
/* VULKAN_KEY_END */
2019-06-25 07:47:27 +00:00
vk : : su : : submitAndWait ( device , graphicsQueue , commandBuffer ) ;
2019-04-09 13:19:18 +00:00
presentQueue . presentKHR ( vk : : PresentInfoKHR ( 0 , nullptr , 1 , & swapChainData . swapChain . get ( ) , & currentBuffer ) ) ;
Sleep ( 1000 ) ;
# 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 ;
}