2016-05-24 23:44:15 +02:00
/*
* Vulkan Example - Example for VK_EXT_debug_marker extension . To be used in conjuction with a debugging app like RenderDoc ( https : //renderdoc.org)
*
* Copyright ( C ) 2016 by Sascha Willems - www . saschawillems . de
*
* This code is licensed under the MIT license ( MIT ) ( http : //opensource.org/licenses/MIT)
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <assert.h>
# include <vector>
# define GLM_FORCE_RADIANS
# define GLM_FORCE_DEPTH_ZERO_TO_ONE
# include <glm/glm.hpp>
# include <glm/gtc/matrix_transform.hpp>
# include <vulkan/vulkan.h>
# include "vulkanexamplebase.h"
2017-02-12 10:44:51 +01:00
# include "VulkanBuffer.hpp"
2017-02-11 14:18:24 +01:00
# include "VulkanModel.hpp"
2016-05-24 23:44:15 +02:00
# define VERTEX_BUFFER_BIND_ID 0
# define ENABLE_VALIDATION false
2016-05-26 13:58:38 +02:00
// Offscreen properties
# define OFFSCREEN_DIM 256
# define OFFSCREEN_FORMAT VK_FORMAT_R8G8B8A8_UNORM
# define OFFSCREEN_FILTER VK_FILTER_LINEAR;
2016-05-24 23:44:15 +02:00
// Setup and functions for the VK_EXT_debug_marker_extension
// Extension spec can be found at https://github.com/KhronosGroup/Vulkan-Docs/blob/1.0-VK_EXT_debug_marker/doc/specs/vulkan/appendices/VK_EXT_debug_marker.txt
2016-05-25 22:54:25 +02:00
// Note that the extension will only be present if run from an offline debugging application
2016-05-27 19:42:32 +02:00
namespace DebugMarker
2016-05-24 23:44:15 +02:00
{
bool active = false ;
2017-02-07 19:58:38 +01:00
bool extensionPresent = false ;
2016-05-24 23:44:15 +02:00
2017-02-07 19:58:38 +01:00
PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTag = VK_NULL_HANDLE ;
PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectName = VK_NULL_HANDLE ;
PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBegin = VK_NULL_HANDLE ;
PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEnd = VK_NULL_HANDLE ;
PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsert = VK_NULL_HANDLE ;
2016-05-24 23:44:15 +02:00
2016-05-27 19:42:32 +02:00
// Get function pointers for the debug report extensions from the device
2017-02-07 19:58:38 +01:00
void setup ( VkDevice device , VkPhysicalDevice physicalDevice )
2016-05-24 23:44:15 +02:00
{
2017-02-07 19:58:38 +01:00
// Check if the debug marker extension is present (which is the case if run from a graphics debugger)
uint32_t extensionCount ;
vkEnumerateDeviceExtensionProperties ( physicalDevice , nullptr , & extensionCount , nullptr ) ;
std : : vector < VkExtensionProperties > extensions ( extensionCount ) ;
vkEnumerateDeviceExtensionProperties ( physicalDevice , nullptr , & extensionCount , extensions . data ( ) ) ;
for ( auto extension : extensions ) {
if ( strcmp ( extension . extensionName , VK_EXT_DEBUG_MARKER_EXTENSION_NAME ) = = 0 ) {
extensionPresent = true ;
break ;
}
}
if ( extensionPresent ) {
// The debug marker extension is not part of the core, so function pointers need to be loaded manually
vkDebugMarkerSetObjectTag = ( PFN_vkDebugMarkerSetObjectTagEXT ) vkGetDeviceProcAddr ( device , " vkDebugMarkerSetObjectTagEXT " ) ;
vkDebugMarkerSetObjectName = ( PFN_vkDebugMarkerSetObjectNameEXT ) vkGetDeviceProcAddr ( device , " vkDebugMarkerSetObjectNameEXT " ) ;
vkCmdDebugMarkerBegin = ( PFN_vkCmdDebugMarkerBeginEXT ) vkGetDeviceProcAddr ( device , " vkCmdDebugMarkerBeginEXT " ) ;
vkCmdDebugMarkerEnd = ( PFN_vkCmdDebugMarkerEndEXT ) vkGetDeviceProcAddr ( device , " vkCmdDebugMarkerEndEXT " ) ;
vkCmdDebugMarkerInsert = ( PFN_vkCmdDebugMarkerInsertEXT ) vkGetDeviceProcAddr ( device , " vkCmdDebugMarkerInsertEXT " ) ;
// Set flag if at least one function pointer is present
active = ( vkDebugMarkerSetObjectName ! = VK_NULL_HANDLE ) ;
}
else {
std : : cout < < " Warning: " < < VK_EXT_DEBUG_MARKER_EXTENSION_NAME < < " not present, debug markers are disabled. " ;
std : : cout < < " Try running from inside a Vulkan graphics debugger (e.g. RenderDoc) " < < std : : endl ;
}
2016-05-24 23:44:15 +02:00
}
// Sets the debug name of an object
// All Objects in Vulkan are represented by their 64-bit handles which are passed into this function
// along with the object type
void setObjectName ( VkDevice device , uint64_t object , VkDebugReportObjectTypeEXT objectType , const char * name )
{
2016-05-27 22:02:34 +02:00
// Check for valid function pointer (may not be present if not running in a debugging application)
2017-02-07 19:58:38 +01:00
if ( active )
2016-05-24 23:44:15 +02:00
{
VkDebugMarkerObjectNameInfoEXT nameInfo = { } ;
nameInfo . sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT ;
nameInfo . objectType = objectType ;
nameInfo . object = object ;
nameInfo . pObjectName = name ;
2017-02-07 19:58:38 +01:00
vkDebugMarkerSetObjectName ( device , & nameInfo ) ;
2016-05-24 23:44:15 +02:00
}
}
2016-05-27 22:02:34 +02:00
// Set the tag for an object
void setObjectTag ( VkDevice device , uint64_t object , VkDebugReportObjectTypeEXT objectType , uint64_t name , size_t tagSize , const void * tag )
{
// Check for valid function pointer (may not be present if not running in a debugging application)
2017-02-07 19:58:38 +01:00
if ( active )
2016-05-27 22:02:34 +02:00
{
VkDebugMarkerObjectTagInfoEXT tagInfo = { } ;
tagInfo . sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT ;
tagInfo . objectType = objectType ;
tagInfo . object = object ;
tagInfo . tagName = name ;
tagInfo . tagSize = tagSize ;
tagInfo . pTag = tag ;
2017-02-07 19:58:38 +01:00
vkDebugMarkerSetObjectTag ( device , & tagInfo ) ;
2016-05-27 22:02:34 +02:00
}
}
2016-05-24 23:44:15 +02:00
// Start a new debug marker region
2016-05-27 19:42:32 +02:00
void beginRegion ( VkCommandBuffer cmdbuffer , const char * pMarkerName , glm : : vec4 color )
2016-05-24 23:44:15 +02:00
{
2016-05-27 22:02:34 +02:00
// Check for valid function pointer (may not be present if not running in a debugging application)
2017-02-07 19:58:38 +01:00
if ( active )
2016-05-24 23:44:15 +02:00
{
VkDebugMarkerMarkerInfoEXT markerInfo = { } ;
markerInfo . sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT ;
memcpy ( markerInfo . color , & color [ 0 ] , sizeof ( float ) * 4 ) ;
markerInfo . pMarkerName = pMarkerName ;
2017-02-07 19:58:38 +01:00
vkCmdDebugMarkerBegin ( cmdbuffer , & markerInfo ) ;
2016-05-24 23:44:15 +02:00
}
}
// Insert a new debug marker into the command buffer
2016-05-27 19:42:32 +02:00
void insert ( VkCommandBuffer cmdbuffer , std : : string markerName , glm : : vec4 color )
2016-05-24 23:44:15 +02:00
{
2016-05-27 22:02:34 +02:00
// Check for valid function pointer (may not be present if not running in a debugging application)
2017-02-07 19:58:38 +01:00
if ( active )
2016-05-24 23:44:15 +02:00
{
VkDebugMarkerMarkerInfoEXT markerInfo = { } ;
markerInfo . sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT ;
memcpy ( markerInfo . color , & color [ 0 ] , sizeof ( float ) * 4 ) ;
2016-05-25 22:54:25 +02:00
markerInfo . pMarkerName = markerName . c_str ( ) ;
2017-02-07 19:58:38 +01:00
vkCmdDebugMarkerInsert ( cmdbuffer , & markerInfo ) ;
2016-05-24 23:44:15 +02:00
}
}
// End the current debug marker region
2016-05-27 19:42:32 +02:00
void endRegion ( VkCommandBuffer cmdBuffer )
2016-05-24 23:44:15 +02:00
{
// Check for valid function (may not be present if not runnin in a debugging application)
2017-02-07 19:58:38 +01:00
if ( vkCmdDebugMarkerEnd )
2016-05-24 23:44:15 +02:00
{
2017-02-07 19:58:38 +01:00
vkCmdDebugMarkerEnd ( cmdBuffer ) ;
2016-05-24 23:44:15 +02:00
}
}
} ;
2017-02-11 14:18:24 +01:00
// Vertex layout for the models
vks : : VertexLayout vertexLayout = vks : : VertexLayout ( {
vks : : VERTEX_COMPONENT_POSITION ,
vks : : VERTEX_COMPONENT_NORMAL ,
vks : : VERTEX_COMPONENT_UV ,
vks : : VERTEX_COMPONENT_COLOR ,
} ) ;
2016-05-25 22:54:25 +02:00
2016-05-26 11:31:52 +02:00
struct Scene {
2017-02-11 14:18:24 +01:00
vks : : Model model ;
std : : vector < std : : string > modelPartNames ;
2016-05-26 11:31:52 +02:00
void draw ( VkCommandBuffer cmdBuffer )
{
VkDeviceSize offsets [ 1 ] = { 0 } ;
2017-02-11 14:18:24 +01:00
vkCmdBindVertexBuffers ( cmdBuffer , VERTEX_BUFFER_BIND_ID , 1 , & model . vertices . buffer , offsets ) ;
vkCmdBindIndexBuffer ( cmdBuffer , model . indices . buffer , 0 , VK_INDEX_TYPE_UINT32 ) ;
for ( auto i = 0 ; i < model . parts . size ( ) ; i + + )
2016-05-26 11:31:52 +02:00
{
// Add debug marker for mesh name
2017-02-11 14:18:24 +01:00
DebugMarker : : insert ( cmdBuffer , " Draw \" " + modelPartNames [ i ] + " \" " , glm : : vec4 ( 0.0f ) ) ;
vkCmdDrawIndexed ( cmdBuffer , model . parts [ i ] . indexCount , 1 , model . parts [ i ] . indexBase , 0 , 0 ) ;
2016-05-26 11:31:52 +02:00
}
}
2017-02-11 14:18:24 +01:00
2017-02-12 10:16:07 +01:00
void loadFromFile ( std : : string filename , vks : : VulkanDevice * vulkanDevice , VkQueue queue )
2017-02-11 14:18:24 +01:00
{
model . loadFromFile ( filename , vertexLayout , 1.0f , vulkanDevice , queue ) ;
}
2016-05-26 11:31:52 +02:00
} ;
2016-05-24 23:44:15 +02:00
class VulkanExample : public VulkanExampleBase
{
public :
2016-05-26 20:13:28 +02:00
bool wireframe = true ;
2016-05-26 13:58:38 +02:00
bool glow = true ;
2016-05-24 23:44:15 +02:00
2016-05-26 11:31:52 +02:00
Scene scene , sceneGlow ;
2016-05-24 23:44:15 +02:00
2017-02-12 10:44:51 +01:00
vks : : Buffer uniformBuffer ;
2016-05-24 23:44:15 +02:00
2016-12-24 12:48:01 +01:00
struct UBOVS {
2016-05-24 23:44:15 +02:00
glm : : mat4 projection ;
glm : : mat4 model ;
glm : : vec4 lightPos = glm : : vec4 ( 0.0f , 5.0f , 15.0f , 1.0f ) ;
} uboVS ;
struct {
2016-05-26 20:13:28 +02:00
VkPipeline toonshading ;
2016-05-26 13:58:38 +02:00
VkPipeline color ;
2016-05-24 23:44:15 +02:00
VkPipeline wireframe ;
2016-05-26 13:58:38 +02:00
VkPipeline postprocess ;
2016-05-24 23:44:15 +02:00
} pipelines ;
VkPipelineLayout pipelineLayout ;
VkDescriptorSetLayout descriptorSetLayout ;
2016-05-26 13:58:38 +02:00
struct {
VkDescriptorSet scene ;
VkDescriptorSet fullscreen ;
} descriptorSets ;
// Framebuffer for offscreen rendering
struct FrameBufferAttachment {
VkImage image ;
VkDeviceMemory mem ;
VkImageView view ;
} ;
2016-08-13 18:38:13 +02:00
struct OffscreenPass {
2016-05-26 13:58:38 +02:00
int32_t width , height ;
VkFramebuffer frameBuffer ;
FrameBufferAttachment color , depth ;
2016-08-13 18:38:13 +02:00
VkRenderPass renderPass ;
VkSampler sampler ;
VkDescriptorImageInfo descriptor ;
VkCommandBuffer commandBuffer = VK_NULL_HANDLE ;
// Semaphore used to synchronize between offscreen and final scene render pass
VkSemaphore semaphore = VK_NULL_HANDLE ;
} offscreenPass ;
2016-05-26 13:58:38 +02:00
2016-05-27 22:02:34 +02:00
// Random tag data
2016-12-24 12:48:01 +01:00
struct DemoTag {
2016-05-27 22:02:34 +02:00
const char name [ 17 ] = " debug marker tag " ;
} demoTag ;
2016-05-24 23:44:15 +02:00
VulkanExample ( ) : VulkanExampleBase ( ENABLE_VALIDATION )
{
zoom = - 8.5f ;
zoomSpeed = 2.5f ;
rotationSpeed = 0.5f ;
rotation = { - 4.35f , 16.25f , 0.0f } ;
cameraPos = { 0.1f , 1.1f , 0.0f } ;
enableTextOverlay = true ;
title = " Vulkan Example - VK_EXT_debug_marker " ;
2016-12-24 12:48:01 +01:00
// Enable required device features
enabledFeatures . fillModeNonSolid = VK_TRUE ;
enabledFeatures . wideLines = VK_TRUE ;
2016-05-24 23:44:15 +02:00
}
~ VulkanExample ( )
{
// Clean up used Vulkan resources
// Note : Inherited destructor cleans up resources stored in base class
2016-05-26 20:13:28 +02:00
vkDestroyPipeline ( device , pipelines . toonshading , nullptr ) ;
2016-05-26 13:58:38 +02:00
vkDestroyPipeline ( device , pipelines . color , nullptr ) ;
vkDestroyPipeline ( device , pipelines . wireframe , nullptr ) ;
2016-05-26 20:13:28 +02:00
vkDestroyPipeline ( device , pipelines . postprocess , nullptr ) ;
2016-05-24 23:44:15 +02:00
vkDestroyPipelineLayout ( device , pipelineLayout , nullptr ) ;
vkDestroyDescriptorSetLayout ( device , descriptorSetLayout , nullptr ) ;
// Destroy and free mesh resources
2017-02-11 14:18:24 +01:00
scene . model . destroy ( ) ;
sceneGlow . model . destroy ( ) ;
2016-05-24 23:44:15 +02:00
2016-12-24 12:48:01 +01:00
uniformBuffer . destroy ( ) ;
2016-05-26 20:13:28 +02:00
// Offscreen
// Color attachment
2016-08-13 18:38:13 +02:00
vkDestroyImageView ( device , offscreenPass . color . view , nullptr ) ;
vkDestroyImage ( device , offscreenPass . color . image , nullptr ) ;
vkFreeMemory ( device , offscreenPass . color . mem , nullptr ) ;
2016-05-26 20:13:28 +02:00
// Depth attachment
2016-08-13 18:38:13 +02:00
vkDestroyImageView ( device , offscreenPass . depth . view , nullptr ) ;
vkDestroyImage ( device , offscreenPass . depth . image , nullptr ) ;
vkFreeMemory ( device , offscreenPass . depth . mem , nullptr ) ;
vkDestroyRenderPass ( device , offscreenPass . renderPass , nullptr ) ;
vkDestroySampler ( device , offscreenPass . sampler , nullptr ) ;
vkDestroyFramebuffer ( device , offscreenPass . frameBuffer , nullptr ) ;
vkFreeCommandBuffers ( device , cmdPool , 1 , & offscreenPass . commandBuffer ) ;
vkDestroySemaphore ( device , offscreenPass . semaphore , nullptr ) ;
2016-05-24 23:44:15 +02:00
}
2016-05-26 13:58:38 +02:00
// Prepare a texture target and framebuffer for offscreen rendering
void prepareOffscreen ( )
{
2016-08-13 18:38:13 +02:00
offscreenPass . width = OFFSCREEN_DIM ;
offscreenPass . height = OFFSCREEN_DIM ;
2016-05-26 13:58:38 +02:00
// Find a suitable depth format
VkFormat fbDepthFormat ;
2017-02-12 13:10:05 +01:00
VkBool32 validDepthFormat = vks : : tools : : getSupportedDepthFormat ( physicalDevice , & fbDepthFormat ) ;
2016-05-26 13:58:38 +02:00
assert ( validDepthFormat ) ;
// Color attachment
2017-02-12 11:12:42 +01:00
VkImageCreateInfo image = vks : : initializers : : imageCreateInfo ( ) ;
2016-05-26 13:58:38 +02:00
image . imageType = VK_IMAGE_TYPE_2D ;
image . format = OFFSCREEN_FORMAT ;
2016-08-13 18:38:13 +02:00
image . extent . width = offscreenPass . width ;
image . extent . height = offscreenPass . height ;
2016-05-26 13:58:38 +02:00
image . extent . depth = 1 ;
image . mipLevels = 1 ;
image . arrayLayers = 1 ;
image . samples = VK_SAMPLE_COUNT_1_BIT ;
image . tiling = VK_IMAGE_TILING_OPTIMAL ;
2016-08-13 18:38:13 +02:00
// We will sample directly from the color attachment
image . usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT ;
2017-02-12 11:12:42 +01:00
VkMemoryAllocateInfo memAlloc = vks : : initializers : : memoryAllocateInfo ( ) ;
2016-08-13 18:38:13 +02:00
VkMemoryRequirements memReqs ;
VK_CHECK_RESULT ( vkCreateImage ( device , & image , nullptr , & offscreenPass . color . image ) ) ;
vkGetImageMemoryRequirements ( device , offscreenPass . color . image , & memReqs ) ;
memAlloc . allocationSize = memReqs . size ;
memAlloc . memoryTypeIndex = vulkanDevice - > getMemoryType ( memReqs . memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ) ;
VK_CHECK_RESULT ( vkAllocateMemory ( device , & memAlloc , nullptr , & offscreenPass . color . mem ) ) ;
VK_CHECK_RESULT ( vkBindImageMemory ( device , offscreenPass . color . image , offscreenPass . color . mem , 0 ) ) ;
2016-05-26 13:58:38 +02:00
2017-02-12 11:12:42 +01:00
VkImageViewCreateInfo colorImageView = vks : : initializers : : imageViewCreateInfo ( ) ;
2016-05-26 13:58:38 +02:00
colorImageView . viewType = VK_IMAGE_VIEW_TYPE_2D ;
colorImageView . format = OFFSCREEN_FORMAT ;
colorImageView . subresourceRange = { } ;
colorImageView . subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
colorImageView . subresourceRange . baseMipLevel = 0 ;
colorImageView . subresourceRange . levelCount = 1 ;
colorImageView . subresourceRange . baseArrayLayer = 0 ;
colorImageView . subresourceRange . layerCount = 1 ;
2016-08-13 18:38:13 +02:00
colorImageView . image = offscreenPass . color . image ;
VK_CHECK_RESULT ( vkCreateImageView ( device , & colorImageView , nullptr , & offscreenPass . color . view ) ) ;
// Create sampler to sample from the attachment in the fragment shader
2017-02-12 11:12:42 +01:00
VkSamplerCreateInfo samplerInfo = vks : : initializers : : samplerCreateInfo ( ) ;
2016-08-13 18:38:13 +02:00
samplerInfo . magFilter = OFFSCREEN_FILTER ;
samplerInfo . minFilter = OFFSCREEN_FILTER ;
samplerInfo . mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR ;
samplerInfo . addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerInfo . addressModeV = samplerInfo . addressModeU ;
samplerInfo . addressModeW = samplerInfo . addressModeU ;
samplerInfo . mipLodBias = 0.0f ;
samplerInfo . maxAnisotropy = 0 ;
samplerInfo . minLod = 0.0f ;
samplerInfo . maxLod = 1.0f ;
samplerInfo . borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE ;
VK_CHECK_RESULT ( vkCreateSampler ( device , & samplerInfo , nullptr , & offscreenPass . sampler ) ) ;
2016-05-26 13:58:38 +02:00
// Depth stencil attachment
image . format = fbDepthFormat ;
image . usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ;
2016-08-13 18:38:13 +02:00
VK_CHECK_RESULT ( vkCreateImage ( device , & image , nullptr , & offscreenPass . depth . image ) ) ;
vkGetImageMemoryRequirements ( device , offscreenPass . depth . image , & memReqs ) ;
memAlloc . allocationSize = memReqs . size ;
memAlloc . memoryTypeIndex = vulkanDevice - > getMemoryType ( memReqs . memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ) ;
VK_CHECK_RESULT ( vkAllocateMemory ( device , & memAlloc , nullptr , & offscreenPass . depth . mem ) ) ;
VK_CHECK_RESULT ( vkBindImageMemory ( device , offscreenPass . depth . image , offscreenPass . depth . mem , 0 ) ) ;
2017-02-12 11:12:42 +01:00
VkImageViewCreateInfo depthStencilView = vks : : initializers : : imageViewCreateInfo ( ) ;
2016-05-26 13:58:38 +02:00
depthStencilView . viewType = VK_IMAGE_VIEW_TYPE_2D ;
depthStencilView . format = fbDepthFormat ;
depthStencilView . flags = 0 ;
depthStencilView . subresourceRange = { } ;
depthStencilView . subresourceRange . aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT ;
depthStencilView . subresourceRange . baseMipLevel = 0 ;
depthStencilView . subresourceRange . levelCount = 1 ;
depthStencilView . subresourceRange . baseArrayLayer = 0 ;
depthStencilView . subresourceRange . layerCount = 1 ;
2016-08-13 18:38:13 +02:00
depthStencilView . image = offscreenPass . depth . image ;
VK_CHECK_RESULT ( vkCreateImageView ( device , & depthStencilView , nullptr , & offscreenPass . depth . view ) ) ;
2016-05-26 13:58:38 +02:00
2016-08-13 18:38:13 +02:00
// Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering
2016-05-26 13:58:38 +02:00
2016-08-13 18:38:13 +02:00
std : : array < VkAttachmentDescription , 2 > attchmentDescriptions = { } ;
// Color attachment
attchmentDescriptions [ 0 ] . format = OFFSCREEN_FORMAT ;
attchmentDescriptions [ 0 ] . samples = VK_SAMPLE_COUNT_1_BIT ;
attchmentDescriptions [ 0 ] . loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
attchmentDescriptions [ 0 ] . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
attchmentDescriptions [ 0 ] . stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE ;
attchmentDescriptions [ 0 ] . stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE ;
attchmentDescriptions [ 0 ] . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
attchmentDescriptions [ 0 ] . finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ;
// Depth attachment
attchmentDescriptions [ 1 ] . format = fbDepthFormat ;
attchmentDescriptions [ 1 ] . samples = VK_SAMPLE_COUNT_1_BIT ;
attchmentDescriptions [ 1 ] . loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
attchmentDescriptions [ 1 ] . storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE ;
attchmentDescriptions [ 1 ] . stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE ;
attchmentDescriptions [ 1 ] . stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE ;
attchmentDescriptions [ 1 ] . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
attchmentDescriptions [ 1 ] . finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ;
VkAttachmentReference colorReference = { 0 , VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } ;
VkAttachmentReference depthReference = { 1 , VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL } ;
VkSubpassDescription subpassDescription = { } ;
subpassDescription . pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS ;
subpassDescription . colorAttachmentCount = 1 ;
subpassDescription . pColorAttachments = & colorReference ;
subpassDescription . pDepthStencilAttachment = & depthReference ;
// Use subpass dependencies for layout transitions
std : : array < VkSubpassDependency , 2 > dependencies ;
dependencies [ 0 ] . srcSubpass = VK_SUBPASS_EXTERNAL ;
dependencies [ 0 ] . dstSubpass = 0 ;
dependencies [ 0 ] . srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT ;
dependencies [ 0 ] . dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
dependencies [ 0 ] . srcAccessMask = VK_ACCESS_MEMORY_READ_BIT ;
dependencies [ 0 ] . dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
dependencies [ 0 ] . dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT ;
dependencies [ 1 ] . srcSubpass = 0 ;
dependencies [ 1 ] . dstSubpass = VK_SUBPASS_EXTERNAL ;
dependencies [ 1 ] . srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
dependencies [ 1 ] . dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT ;
dependencies [ 1 ] . srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
dependencies [ 1 ] . dstAccessMask = VK_ACCESS_MEMORY_READ_BIT ;
dependencies [ 1 ] . dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT ;
// Create the actual renderpass
VkRenderPassCreateInfo renderPassInfo = { } ;
renderPassInfo . sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO ;
renderPassInfo . attachmentCount = static_cast < uint32_t > ( attchmentDescriptions . size ( ) ) ;
renderPassInfo . pAttachments = attchmentDescriptions . data ( ) ;
renderPassInfo . subpassCount = 1 ;
renderPassInfo . pSubpasses = & subpassDescription ;
renderPassInfo . dependencyCount = static_cast < uint32_t > ( dependencies . size ( ) ) ;
renderPassInfo . pDependencies = dependencies . data ( ) ;
VK_CHECK_RESULT ( vkCreateRenderPass ( device , & renderPassInfo , nullptr , & offscreenPass . renderPass ) ) ;
2016-05-26 13:58:38 +02:00
VkImageView attachments [ 2 ] ;
2016-08-13 18:38:13 +02:00
attachments [ 0 ] = offscreenPass . color . view ;
attachments [ 1 ] = offscreenPass . depth . view ;
2016-05-26 13:58:38 +02:00
2017-02-12 11:12:42 +01:00
VkFramebufferCreateInfo fbufCreateInfo = vks : : initializers : : framebufferCreateInfo ( ) ;
2016-08-13 18:38:13 +02:00
fbufCreateInfo . renderPass = offscreenPass . renderPass ;
2016-05-26 13:58:38 +02:00
fbufCreateInfo . attachmentCount = 2 ;
fbufCreateInfo . pAttachments = attachments ;
2016-08-13 18:38:13 +02:00
fbufCreateInfo . width = offscreenPass . width ;
fbufCreateInfo . height = offscreenPass . height ;
2016-05-26 13:58:38 +02:00
fbufCreateInfo . layers = 1 ;
2016-08-13 18:38:13 +02:00
VK_CHECK_RESULT ( vkCreateFramebuffer ( device , & fbufCreateInfo , nullptr , & offscreenPass . frameBuffer ) ) ;
2016-05-26 13:58:38 +02:00
2016-08-13 18:38:13 +02:00
// Fill a descriptor for later use in a descriptor set
offscreenPass . descriptor . imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ;
offscreenPass . descriptor . imageView = offscreenPass . color . view ;
offscreenPass . descriptor . sampler = offscreenPass . sampler ;
2016-05-26 20:22:48 +02:00
2016-08-13 18:38:13 +02:00
// Name some objects for debugging
DebugMarker : : setObjectName ( device , ( uint64_t ) offscreenPass . color . image , VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT , " Off-screen color framebuffer " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) offscreenPass . depth . image , VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT , " Off-screen depth framebuffer " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) offscreenPass . sampler , VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT , " Off-screen framebuffer default sampler " ) ;
2016-05-26 13:58:38 +02:00
}
// Command buffer for rendering color only scene for glow
void buildOffscreenCommandBuffer ( )
{
2016-08-13 18:38:13 +02:00
if ( offscreenPass . commandBuffer = = VK_NULL_HANDLE )
{
offscreenPass . commandBuffer = VulkanExampleBase : : createCommandBuffer ( VK_COMMAND_BUFFER_LEVEL_PRIMARY , false ) ;
}
if ( offscreenPass . semaphore = = VK_NULL_HANDLE )
{
// Create a semaphore used to synchronize offscreen rendering and usage
2017-02-12 11:12:42 +01:00
VkSemaphoreCreateInfo semaphoreCreateInfo = vks : : initializers : : semaphoreCreateInfo ( ) ;
2016-08-13 18:38:13 +02:00
VK_CHECK_RESULT ( vkCreateSemaphore ( device , & semaphoreCreateInfo , nullptr , & offscreenPass . semaphore ) ) ;
}
2017-02-12 11:12:42 +01:00
VkCommandBufferBeginInfo cmdBufInfo = vks : : initializers : : commandBufferBeginInfo ( ) ;
2016-05-26 13:58:38 +02:00
VkClearValue clearValues [ 2 ] ;
clearValues [ 0 ] . color = { { 0.0f , 0.0f , 0.0f , 0.0f } } ;
clearValues [ 1 ] . depthStencil = { 1.0f , 0 } ;
2017-02-12 11:12:42 +01:00
VkRenderPassBeginInfo renderPassBeginInfo = vks : : initializers : : renderPassBeginInfo ( ) ;
2016-08-13 18:38:13 +02:00
renderPassBeginInfo . renderPass = offscreenPass . renderPass ;
renderPassBeginInfo . framebuffer = offscreenPass . frameBuffer ;
renderPassBeginInfo . renderArea . extent . width = offscreenPass . width ;
renderPassBeginInfo . renderArea . extent . height = offscreenPass . height ;
2016-05-26 13:58:38 +02:00
renderPassBeginInfo . clearValueCount = 2 ;
renderPassBeginInfo . pClearValues = clearValues ;
2016-08-13 18:38:13 +02:00
VK_CHECK_RESULT ( vkBeginCommandBuffer ( offscreenPass . commandBuffer , & cmdBufInfo ) ) ;
2016-05-26 13:58:38 +02:00
2016-05-26 20:22:48 +02:00
// Start a new debug marker region
2016-08-13 18:38:13 +02:00
DebugMarker : : beginRegion ( offscreenPass . commandBuffer , " Off-screen scene rendering " , glm : : vec4 ( 1.0f , 0.78f , 0.05f , 1.0f ) ) ;
2016-05-26 20:22:48 +02:00
2017-02-12 11:12:42 +01:00
VkViewport viewport = vks : : initializers : : viewport ( ( float ) offscreenPass . width , ( float ) offscreenPass . height , 0.0f , 1.0f ) ;
2016-08-13 18:38:13 +02:00
vkCmdSetViewport ( offscreenPass . commandBuffer , 0 , 1 , & viewport ) ;
2016-05-26 13:58:38 +02:00
2017-02-12 11:12:42 +01:00
VkRect2D scissor = vks : : initializers : : rect2D ( offscreenPass . width , offscreenPass . height , 0 , 0 ) ;
2016-08-13 18:38:13 +02:00
vkCmdSetScissor ( offscreenPass . commandBuffer , 0 , 1 , & scissor ) ;
2016-05-26 13:58:38 +02:00
2016-08-13 18:38:13 +02:00
vkCmdBeginRenderPass ( offscreenPass . commandBuffer , & renderPassBeginInfo , VK_SUBPASS_CONTENTS_INLINE ) ;
2016-05-26 13:58:38 +02:00
2016-08-13 18:38:13 +02:00
vkCmdBindDescriptorSets ( offscreenPass . commandBuffer , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelineLayout , 0 , 1 , & descriptorSets . scene , 0 , NULL ) ;
vkCmdBindPipeline ( offscreenPass . commandBuffer , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelines . color ) ;
2016-05-26 13:58:38 +02:00
// Draw glow scene
2016-08-13 18:38:13 +02:00
sceneGlow . draw ( offscreenPass . commandBuffer ) ;
vkCmdEndRenderPass ( offscreenPass . commandBuffer ) ;
DebugMarker : : endRegion ( offscreenPass . commandBuffer ) ;
VK_CHECK_RESULT ( vkEndCommandBuffer ( offscreenPass . commandBuffer ) ) ;
2016-05-26 13:58:38 +02:00
}
2016-05-26 11:31:52 +02:00
void loadScene ( )
{
2017-02-11 14:18:24 +01:00
scene . loadFromFile ( getAssetPath ( ) + " models/treasure_smooth.dae " , vulkanDevice , queue ) ;
sceneGlow . loadFromFile ( getAssetPath ( ) + " models/treasure_glow.dae " , vulkanDevice , queue ) ;
2016-05-25 22:54:25 +02:00
// Name the meshes
2017-02-11 14:18:24 +01:00
// ASSIMP does not load mesh names from the COLLADA file used in this example so we need to set them manually
2016-05-25 22:54:25 +02:00
// These names are used in command buffer creation for setting debug markers
2017-02-11 14:18:24 +01:00
std : : vector < std : : string > names = { " hill " , " crystals " , " rocks " , " cave " , " tree " , " mushroom stems " , " blue mushroom caps " , " red mushroom caps " , " grass blades " , " chest box " , " chest fittings " } ;
for ( size_t i = 0 ; i < names . size ( ) ; i + + ) {
scene . modelPartNames . push_back ( names [ i ] ) ;
sceneGlow . modelPartNames . push_back ( names [ i ] ) ;
2016-05-26 11:31:52 +02:00
}
2016-05-25 22:54:25 +02:00
// Name the buffers for debugging
2016-05-26 11:31:52 +02:00
// Scene
2017-02-11 14:18:24 +01:00
DebugMarker : : setObjectName ( device , ( uint64_t ) scene . model . vertices . buffer , VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT , " Scene vertex buffer " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) scene . model . indices . buffer , VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT , " Scene index buffer " ) ;
2016-05-26 11:31:52 +02:00
// Glow
2017-02-11 14:18:24 +01:00
DebugMarker : : setObjectName ( device , ( uint64_t ) sceneGlow . model . vertices . buffer , VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT , " Glow vertex buffer " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) sceneGlow . model . indices . buffer , VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT , " Glow index buffer " ) ;
2016-05-24 23:44:15 +02:00
}
2016-05-25 22:54:25 +02:00
void reBuildCommandBuffers ( )
{
if ( ! checkCommandBuffers ( ) )
{
destroyCommandBuffers ( ) ;
createCommandBuffers ( ) ;
}
buildCommandBuffers ( ) ;
}
void buildCommandBuffers ( )
{
2017-02-12 11:12:42 +01:00
VkCommandBufferBeginInfo cmdBufInfo = vks : : initializers : : commandBufferBeginInfo ( ) ;
2016-05-25 22:54:25 +02:00
VkClearValue clearValues [ 2 ] ;
clearValues [ 0 ] . color = defaultClearColor ;
clearValues [ 1 ] . depthStencil = { 1.0f , 0 } ;
2017-02-12 11:12:42 +01:00
VkRenderPassBeginInfo renderPassBeginInfo = vks : : initializers : : renderPassBeginInfo ( ) ;
2016-05-25 22:54:25 +02:00
renderPassBeginInfo . renderPass = renderPass ;
renderPassBeginInfo . renderArea . offset . x = 0 ;
renderPassBeginInfo . renderArea . offset . y = 0 ;
renderPassBeginInfo . renderArea . extent . width = width ;
renderPassBeginInfo . renderArea . extent . height = height ;
renderPassBeginInfo . clearValueCount = 2 ;
renderPassBeginInfo . pClearValues = clearValues ;
for ( int32_t i = 0 ; i < drawCmdBuffers . size ( ) ; + + i )
{
// Set target frame buffer
renderPassBeginInfo . framebuffer = frameBuffers [ i ] ;
VK_CHECK_RESULT ( vkBeginCommandBuffer ( drawCmdBuffers [ i ] , & cmdBufInfo ) ) ;
// Start a new debug marker region
2016-05-28 11:28:55 +02:00
DebugMarker : : beginRegion ( drawCmdBuffers [ i ] , " Render scene " , glm : : vec4 ( 0.5f , 0.76f , 0.34f , 1.0f ) ) ;
2016-05-25 22:54:25 +02:00
vkCmdBeginRenderPass ( drawCmdBuffers [ i ] , & renderPassBeginInfo , VK_SUBPASS_CONTENTS_INLINE ) ;
2017-02-12 11:12:42 +01:00
VkViewport viewport = vks : : initializers : : viewport ( ( float ) width , ( float ) height , 0.0f , 1.0f ) ;
2016-05-25 22:54:25 +02:00
vkCmdSetViewport ( drawCmdBuffers [ i ] , 0 , 1 , & viewport ) ;
2017-02-12 11:12:42 +01:00
VkRect2D scissor = vks : : initializers : : rect2D ( wireframe ? width / 2 : width , height , 0 , 0 ) ;
2016-05-25 22:54:25 +02:00
vkCmdSetScissor ( drawCmdBuffers [ i ] , 0 , 1 , & scissor ) ;
2016-05-26 13:58:38 +02:00
vkCmdBindDescriptorSets ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelineLayout , 0 , 1 , & descriptorSets . scene , 0 , NULL ) ;
2016-05-25 22:54:25 +02:00
// Solid rendering
// Start a new debug marker region
2016-05-28 11:28:55 +02:00
DebugMarker : : beginRegion ( drawCmdBuffers [ i ] , " Toon shading draw " , glm : : vec4 ( 0.78f , 0.74f , 0.9f , 1.0f ) ) ;
2016-05-25 22:54:25 +02:00
2016-05-26 20:13:28 +02:00
vkCmdBindPipeline ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelines . toonshading ) ;
2016-05-26 11:31:52 +02:00
scene . draw ( drawCmdBuffers [ i ] ) ;
2016-05-25 22:54:25 +02:00
2016-05-27 19:42:32 +02:00
DebugMarker : : endRegion ( drawCmdBuffers [ i ] ) ;
2016-05-25 22:54:25 +02:00
// Wireframe rendering
if ( wireframe )
{
// Insert debug marker
2016-05-28 11:28:55 +02:00
DebugMarker : : beginRegion ( drawCmdBuffers [ i ] , " Wireframe draw " , glm : : vec4 ( 0.53f , 0.78f , 0.91f , 1.0f ) ) ;
2016-05-25 22:54:25 +02:00
scissor . offset . x = width / 2 ;
vkCmdSetScissor ( drawCmdBuffers [ i ] , 0 , 1 , & scissor ) ;
vkCmdBindPipeline ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelines . wireframe ) ;
2016-05-26 11:31:52 +02:00
scene . draw ( drawCmdBuffers [ i ] ) ;
2016-05-25 22:54:25 +02:00
2016-05-27 19:42:32 +02:00
DebugMarker : : endRegion ( drawCmdBuffers [ i ] ) ;
2016-05-26 20:13:28 +02:00
scissor . offset . x = 0 ;
scissor . extent . width = width ;
vkCmdSetScissor ( drawCmdBuffers [ i ] , 0 , 1 , & scissor ) ;
2016-05-25 22:54:25 +02:00
}
2016-05-26 13:58:38 +02:00
// Post processing
if ( glow )
{
2016-05-28 11:28:55 +02:00
DebugMarker : : beginRegion ( drawCmdBuffers [ i ] , " Apply post processing " , glm : : vec4 ( 0.93f , 0.89f , 0.69f , 1.0f ) ) ;
2016-05-26 13:58:38 +02:00
vkCmdBindPipeline ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelines . postprocess ) ;
// Full screen quad is generated by the vertex shaders, so we reuse four vertices (for four invocations) from current vertex buffer
vkCmdDraw ( drawCmdBuffers [ i ] , 4 , 1 , 0 , 0 ) ;
2016-05-27 19:42:32 +02:00
DebugMarker : : endRegion ( drawCmdBuffers [ i ] ) ;
2016-05-26 13:58:38 +02:00
}
2016-05-25 22:54:25 +02:00
vkCmdEndRenderPass ( drawCmdBuffers [ i ] ) ;
// End current debug marker region
2016-05-27 19:42:32 +02:00
DebugMarker : : endRegion ( drawCmdBuffers [ i ] ) ;
2016-05-25 22:54:25 +02:00
VK_CHECK_RESULT ( vkEndCommandBuffer ( drawCmdBuffers [ i ] ) ) ;
}
}
2016-05-24 23:44:15 +02:00
void setupDescriptorPool ( )
{
// Example uses one ubo and one combined image sampler
std : : vector < VkDescriptorPoolSize > poolSizes =
{
2017-02-12 11:12:42 +01:00
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , 1 ) ,
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 1 ) ,
2016-05-24 23:44:15 +02:00
} ;
VkDescriptorPoolCreateInfo descriptorPoolInfo =
2017-02-12 11:12:42 +01:00
vks : : initializers : : descriptorPoolCreateInfo (
2016-05-24 23:44:15 +02:00
poolSizes . size ( ) ,
poolSizes . data ( ) ,
1 ) ;
VK_CHECK_RESULT ( vkCreateDescriptorPool ( device , & descriptorPoolInfo , nullptr , & descriptorPool ) ) ;
}
void setupDescriptorSetLayout ( )
{
std : : vector < VkDescriptorSetLayoutBinding > setLayoutBindings =
{
// Binding 0 : Vertex shader uniform buffer
2017-02-12 11:12:42 +01:00
vks : : initializers : : descriptorSetLayoutBinding (
2016-05-24 23:44:15 +02:00
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ,
VK_SHADER_STAGE_VERTEX_BIT ,
0 ) ,
// Binding 1 : Fragment shader combined sampler
2017-02-12 11:12:42 +01:00
vks : : initializers : : descriptorSetLayoutBinding (
2016-05-24 23:44:15 +02:00
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ,
VK_SHADER_STAGE_FRAGMENT_BIT ,
1 ) ,
} ;
VkDescriptorSetLayoutCreateInfo descriptorLayout =
2017-02-12 11:12:42 +01:00
vks : : initializers : : descriptorSetLayoutCreateInfo (
2016-05-24 23:44:15 +02:00
setLayoutBindings . data ( ) ,
setLayoutBindings . size ( ) ) ;
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device , & descriptorLayout , nullptr , & descriptorSetLayout ) ) ;
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineLayoutCreateInfo (
2016-05-24 23:44:15 +02:00
& descriptorSetLayout ,
1 ) ;
VK_CHECK_RESULT ( vkCreatePipelineLayout ( device , & pPipelineLayoutCreateInfo , nullptr , & pipelineLayout ) ) ;
2016-05-27 22:02:34 +02:00
// Name for debugging
DebugMarker : : setObjectName ( device , ( uint64_t ) pipelineLayout , VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT , " Shared pipeline layout " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) descriptorSetLayout , VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT , " Shared descriptor set layout " ) ;
2016-05-24 23:44:15 +02:00
}
void setupDescriptorSet ( )
{
VkDescriptorSetAllocateInfo allocInfo =
2017-02-12 11:12:42 +01:00
vks : : initializers : : descriptorSetAllocateInfo (
2016-05-24 23:44:15 +02:00
descriptorPool ,
& descriptorSetLayout ,
1 ) ;
2016-05-26 13:58:38 +02:00
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & descriptorSets . scene ) ) ;
2016-05-24 23:44:15 +02:00
std : : vector < VkWriteDescriptorSet > writeDescriptorSets =
{
// Binding 0 : Vertex shader uniform buffer
2017-02-12 11:12:42 +01:00
vks : : initializers : : writeDescriptorSet (
2016-05-26 13:58:38 +02:00
descriptorSets . scene ,
2016-05-24 23:44:15 +02:00
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ,
0 ,
2016-12-24 12:48:01 +01:00
& uniformBuffer . descriptor ) ,
2016-05-24 23:44:15 +02:00
// Binding 1 : Color map
2017-02-12 11:12:42 +01:00
vks : : initializers : : writeDescriptorSet (
2016-05-26 13:58:38 +02:00
descriptorSets . scene ,
2016-05-24 23:44:15 +02:00
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ,
1 ,
2016-08-13 18:38:13 +02:00
& offscreenPass . descriptor )
2016-05-24 23:44:15 +02:00
} ;
vkUpdateDescriptorSets ( device , writeDescriptorSets . size ( ) , writeDescriptorSets . data ( ) , 0 , NULL ) ;
}
void preparePipelines ( )
{
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineInputAssemblyStateCreateInfo (
2016-05-24 23:44:15 +02:00
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ,
0 ,
VK_FALSE ) ;
VkPipelineRasterizationStateCreateInfo rasterizationState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineRasterizationStateCreateInfo (
2016-05-24 23:44:15 +02:00
VK_POLYGON_MODE_FILL ,
VK_CULL_MODE_BACK_BIT ,
VK_FRONT_FACE_CLOCKWISE ,
0 ) ;
VkPipelineColorBlendAttachmentState blendAttachmentState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineColorBlendAttachmentState (
2016-05-24 23:44:15 +02:00
0xf ,
VK_FALSE ) ;
VkPipelineColorBlendStateCreateInfo colorBlendState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineColorBlendStateCreateInfo (
2016-05-24 23:44:15 +02:00
1 ,
& blendAttachmentState ) ;
VkPipelineDepthStencilStateCreateInfo depthStencilState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineDepthStencilStateCreateInfo (
2016-05-24 23:44:15 +02:00
VK_TRUE ,
VK_TRUE ,
VK_COMPARE_OP_LESS_OR_EQUAL ) ;
VkPipelineViewportStateCreateInfo viewportState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineViewportStateCreateInfo ( 1 , 1 , 0 ) ;
2016-05-24 23:44:15 +02:00
VkPipelineMultisampleStateCreateInfo multisampleState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineMultisampleStateCreateInfo (
2016-05-24 23:44:15 +02:00
VK_SAMPLE_COUNT_1_BIT ,
0 ) ;
std : : vector < VkDynamicState > dynamicStateEnables = {
VK_DYNAMIC_STATE_VIEWPORT ,
VK_DYNAMIC_STATE_SCISSOR
} ;
VkPipelineDynamicStateCreateInfo dynamicState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineDynamicStateCreateInfo (
2016-05-24 23:44:15 +02:00
dynamicStateEnables . data ( ) ,
dynamicStateEnables . size ( ) ,
0 ) ;
std : : array < VkPipelineShaderStageCreateInfo , 2 > shaderStages ;
VkGraphicsPipelineCreateInfo pipelineCreateInfo =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineCreateInfo (
2016-05-24 23:44:15 +02:00
pipelineLayout ,
renderPass ,
0 ) ;
pipelineCreateInfo . pInputAssemblyState = & inputAssemblyState ;
pipelineCreateInfo . pRasterizationState = & rasterizationState ;
pipelineCreateInfo . pColorBlendState = & colorBlendState ;
pipelineCreateInfo . pMultisampleState = & multisampleState ;
pipelineCreateInfo . pViewportState = & viewportState ;
pipelineCreateInfo . pDepthStencilState = & depthStencilState ;
pipelineCreateInfo . pDynamicState = & dynamicState ;
pipelineCreateInfo . stageCount = shaderStages . size ( ) ;
pipelineCreateInfo . pStages = shaderStages . data ( ) ;
2017-02-11 14:18:24 +01:00
// Shared vertex inputs
// Binding description
VkVertexInputBindingDescription vertexInputBinding =
2017-02-12 11:12:42 +01:00
vks : : initializers : : vertexInputBindingDescription ( VERTEX_BUFFER_BIND_ID , vertexLayout . stride ( ) , VK_VERTEX_INPUT_RATE_VERTEX ) ;
2017-02-11 14:18:24 +01:00
// Attribute descriptions
// Describes memory layout and shader positions
std : : vector < VkVertexInputAttributeDescription > vertexInputAttributes = {
2017-02-12 11:12:42 +01:00
vks : : initializers : : vertexInputAttributeDescription ( VERTEX_BUFFER_BIND_ID , 0 , VK_FORMAT_R32G32B32_SFLOAT , 0 ) , // Location 0: Position
vks : : initializers : : vertexInputAttributeDescription ( VERTEX_BUFFER_BIND_ID , 1 , VK_FORMAT_R32G32B32_SFLOAT , sizeof ( float ) * 3 ) , // Location 1: Normal
vks : : initializers : : vertexInputAttributeDescription ( VERTEX_BUFFER_BIND_ID , 2 , VK_FORMAT_R32G32_SFLOAT , sizeof ( float ) * 6 ) , // Location 2: Texture coordinates
vks : : initializers : : vertexInputAttributeDescription ( VERTEX_BUFFER_BIND_ID , 3 , VK_FORMAT_R32G32B32_SFLOAT , sizeof ( float ) * 8 ) , // Location 3: Color
2017-02-11 14:18:24 +01:00
} ;
2017-02-12 11:12:42 +01:00
VkPipelineVertexInputStateCreateInfo vertexInputState = vks : : initializers : : pipelineVertexInputStateCreateInfo ( ) ;
2017-02-11 14:18:24 +01:00
vertexInputState . vertexBindingDescriptionCount = 1 ;
vertexInputState . pVertexBindingDescriptions = & vertexInputBinding ;
vertexInputState . vertexAttributeDescriptionCount = static_cast < uint32_t > ( vertexInputAttributes . size ( ) ) ;
vertexInputState . pVertexAttributeDescriptions = vertexInputAttributes . data ( ) ;
pipelineCreateInfo . pVertexInputState = & vertexInputState ;
// Toon shading pipeline
shaderStages [ 0 ] = loadShader ( getAssetPath ( ) + " shaders/debugmarker/toon.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = loadShader ( getAssetPath ( ) + " shaders/debugmarker/toon.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
2016-05-26 20:13:28 +02:00
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCreateInfo , nullptr , & pipelines . toonshading ) ) ;
2016-05-26 13:58:38 +02:00
// Color only pipeline
shaderStages [ 0 ] = loadShader ( getAssetPath ( ) + " shaders/debugmarker/colorpass.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = loadShader ( getAssetPath ( ) + " shaders/debugmarker/colorpass.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
2016-08-13 18:38:13 +02:00
pipelineCreateInfo . renderPass = offscreenPass . renderPass ;
2016-05-26 13:58:38 +02:00
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCreateInfo , nullptr , & pipelines . color ) ) ;
2016-05-24 23:44:15 +02:00
// Wire frame rendering pipeline
rasterizationState . polygonMode = VK_POLYGON_MODE_LINE ;
rasterizationState . lineWidth = 1.0f ;
2016-08-13 18:38:13 +02:00
pipelineCreateInfo . renderPass = renderPass ;
2016-05-24 23:44:15 +02:00
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCreateInfo , nullptr , & pipelines . wireframe ) ) ;
2016-05-25 22:54:25 +02:00
2016-05-26 13:58:38 +02:00
// Post processing effect
shaderStages [ 0 ] = loadShader ( getAssetPath ( ) + " shaders/debugmarker/postprocess.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = loadShader ( getAssetPath ( ) + " shaders/debugmarker/postprocess.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
depthStencilState . depthTestEnable = VK_FALSE ;
depthStencilState . depthWriteEnable = VK_FALSE ;
rasterizationState . polygonMode = VK_POLYGON_MODE_FILL ;
rasterizationState . cullMode = VK_CULL_MODE_NONE ;
blendAttachmentState . colorWriteMask = 0xF ;
blendAttachmentState . blendEnable = VK_TRUE ;
blendAttachmentState . colorBlendOp = VK_BLEND_OP_ADD ;
blendAttachmentState . srcColorBlendFactor = VK_BLEND_FACTOR_ONE ;
blendAttachmentState . dstColorBlendFactor = VK_BLEND_FACTOR_ONE ;
blendAttachmentState . alphaBlendOp = VK_BLEND_OP_ADD ;
blendAttachmentState . srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA ;
blendAttachmentState . dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCreateInfo , nullptr , & pipelines . postprocess ) ) ;
2016-05-27 22:02:34 +02:00
// Name shader moduels for debugging
2016-05-28 11:28:55 +02:00
// Shader module count starts at 2 when text overlay in base class is enabled
uint32_t moduleIndex = enableTextOverlay ? 2 : 0 ;
DebugMarker : : setObjectName ( device , ( uint64_t ) shaderModules [ moduleIndex + 0 ] , VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT , " Toon shading vertex shader " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) shaderModules [ moduleIndex + 1 ] , VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT , " Toon shading fragment shader " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) shaderModules [ moduleIndex + 2 ] , VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT , " Color-only vertex shader " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) shaderModules [ moduleIndex + 3 ] , VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT , " Color-only fragment shader " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) shaderModules [ moduleIndex + 4 ] , VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT , " Postprocess vertex shader " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) shaderModules [ moduleIndex + 5 ] , VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT , " Postprocess fragment shader " ) ;
2016-05-27 22:02:34 +02:00
2016-05-25 22:54:25 +02:00
// Name pipelines for debugging
2016-05-27 19:42:32 +02:00
DebugMarker : : setObjectName ( device , ( uint64_t ) pipelines . toonshading , VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT , " Toon shading pipeline " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) pipelines . color , VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT , " Color only pipeline " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) pipelines . wireframe , VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT , " Wireframe rendering pipeline " ) ;
DebugMarker : : setObjectName ( device , ( uint64_t ) pipelines . postprocess , VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT , " Post processing pipeline " ) ;
2016-05-24 23:44:15 +02:00
}
// Prepare and initialize uniform buffer containing shader uniforms
void prepareUniformBuffers ( )
{
// Vertex shader uniform buffer block
2016-12-24 12:48:01 +01:00
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
2016-05-24 23:44:15 +02:00
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,
2016-12-24 12:48:01 +01:00
& uniformBuffer ,
sizeof ( uboVS ) ) ) ;
// Map persistent
VK_CHECK_RESULT ( uniformBuffer . map ( ) ) ;
2016-05-24 23:44:15 +02:00
2016-05-25 22:54:25 +02:00
// Name uniform buffer for debugging
2016-12-24 12:48:01 +01:00
DebugMarker : : setObjectName ( device , ( uint64_t ) uniformBuffer . buffer , VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT , " Scene uniform buffer block " ) ;
2016-05-27 22:02:34 +02:00
// Add some random tag
2016-12-24 12:48:01 +01:00
DebugMarker : : setObjectTag ( device , ( uint64_t ) uniformBuffer . buffer , VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT , 0 , sizeof ( demoTag ) , & demoTag ) ;
2016-05-25 22:54:25 +02:00
2016-05-24 23:44:15 +02:00
updateUniformBuffers ( ) ;
}
void updateUniformBuffers ( )
{
uboVS . projection = glm : : perspective ( glm : : radians ( 60.0f ) , ( float ) width / ( float ) height , 0.1f , 256.0f ) ;
glm : : mat4 viewMatrix = glm : : translate ( glm : : mat4 ( ) , glm : : vec3 ( 0.0f , 0.0f , zoom ) ) ;
uboVS . model = viewMatrix * glm : : translate ( glm : : mat4 ( ) , cameraPos ) ;
uboVS . model = glm : : rotate ( uboVS . model , glm : : radians ( rotation . x ) , glm : : vec3 ( 1.0f , 0.0f , 0.0f ) ) ;
uboVS . model = glm : : rotate ( uboVS . model , glm : : radians ( rotation . y ) , glm : : vec3 ( 0.0f , 1.0f , 0.0f ) ) ;
uboVS . model = glm : : rotate ( uboVS . model , glm : : radians ( rotation . z ) , glm : : vec3 ( 0.0f , 0.0f , 1.0f ) ) ;
2016-12-24 12:48:01 +01:00
memcpy ( uniformBuffer . mapped , & uboVS , sizeof ( uboVS ) ) ;
2016-05-24 23:44:15 +02:00
}
void draw ( )
{
VulkanExampleBase : : prepareFrame ( ) ;
2016-08-13 18:47:11 +02:00
// Offscreen rendering
2016-05-26 13:58:38 +02:00
if ( glow )
{
2016-08-13 18:47:11 +02:00
// Wait for swap chain presentation to finish
submitInfo . pWaitSemaphores = & semaphores . presentComplete ;
// Signal ready with offscreen semaphore
submitInfo . pSignalSemaphores = & offscreenPass . semaphore ;
// Submit work
submitInfo . commandBufferCount = 1 ;
submitInfo . pCommandBuffers = & offscreenPass . commandBuffer ;
VK_CHECK_RESULT ( vkQueueSubmit ( queue , 1 , & submitInfo , VK_NULL_HANDLE ) ) ;
2016-05-26 13:58:38 +02:00
}
2016-08-13 18:47:11 +02:00
// Scene rendering
// Wait for offscreen semaphore
submitInfo . pWaitSemaphores = & offscreenPass . semaphore ;
// Signal ready with render complete semaphpre
submitInfo . pSignalSemaphores = & semaphores . renderComplete ;
// Submit work
submitInfo . pCommandBuffers = & drawCmdBuffers [ currentBuffer ] ;
2016-05-24 23:44:15 +02:00
VK_CHECK_RESULT ( vkQueueSubmit ( queue , 1 , & submitInfo , VK_NULL_HANDLE ) ) ;
VulkanExampleBase : : submitFrame ( ) ;
}
void prepare ( )
{
VulkanExampleBase : : prepare ( ) ;
2017-02-07 19:58:38 +01:00
DebugMarker : : setup ( device , physicalDevice ) ;
2016-05-26 11:31:52 +02:00
loadScene ( ) ;
2016-05-26 13:58:38 +02:00
prepareOffscreen ( ) ;
2016-05-24 23:44:15 +02:00
prepareUniformBuffers ( ) ;
setupDescriptorSetLayout ( ) ;
preparePipelines ( ) ;
setupDescriptorPool ( ) ;
setupDescriptorSet ( ) ;
buildCommandBuffers ( ) ;
2016-05-26 13:58:38 +02:00
buildOffscreenCommandBuffer ( ) ;
2016-05-24 23:44:15 +02:00
updateTextOverlay ( ) ;
prepared = true ;
}
virtual void render ( )
{
if ( ! prepared )
return ;
draw ( ) ;
}
virtual void viewChanged ( )
{
updateUniformBuffers ( ) ;
}
virtual void keyPressed ( uint32_t keyCode )
{
switch ( keyCode )
{
case 0x57 :
2016-05-26 13:58:38 +02:00
case GAMEPAD_BUTTON_X :
2016-05-24 23:44:15 +02:00
wireframe = ! wireframe ;
reBuildCommandBuffers ( ) ;
break ;
2016-05-26 13:58:38 +02:00
case 0x47 :
case GAMEPAD_BUTTON_A :
glow = ! glow ;
reBuildCommandBuffers ( ) ;
break ;
2016-05-24 23:44:15 +02:00
}
}
virtual void getOverlayText ( VulkanTextOverlay * textOverlay )
{
2016-05-27 19:42:32 +02:00
if ( DebugMarker : : active )
2016-05-24 23:44:15 +02:00
{
textOverlay - > addText ( " VK_EXT_debug_marker active " , 5.0f , 85.0f , VulkanTextOverlay : : alignLeft ) ;
}
else
{
textOverlay - > addText ( " VK_EXT_debug_marker not present " , 5.0f , 85.0f , VulkanTextOverlay : : alignLeft ) ;
}
}
} ;
2016-12-13 19:25:56 +01:00
VULKAN_EXAMPLE_MAIN ( )