mirror of
https://github.com/opus-tango/IntroductionToVulkan.git
synced 2026-03-20 03:55:26 +00:00
Added code for tutorial 05 - Staging Resources
This commit is contained in:
BIN
Document/Images/05 - Staging Resources.png
Normal file
BIN
Document/Images/05 - Staging Resources.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 164 KiB |
@@ -128,3 +128,9 @@ add_executable( "04" "Vertex_Attributes"
|
||||
Tutorial04/Tutorial04.h
|
||||
Tutorial04/main.cpp
|
||||
Tutorial04/Tutorial04.cpp )
|
||||
|
||||
add_executable( "05" "Staging_Resources"
|
||||
${ALL_BASIC_AND_ADVANCED_SHARED_FILES}
|
||||
Tutorial05/Tutorial05.h
|
||||
Tutorial05/main.cpp
|
||||
Tutorial05/Tutorial05.cpp )
|
||||
@@ -157,4 +157,7 @@ VK_DEVICE_LEVEL_FUNCTION( vkFreeMemory )
|
||||
VK_DEVICE_LEVEL_FUNCTION( vkDestroyBuffer )
|
||||
VK_DEVICE_LEVEL_FUNCTION( vkDestroyFence )
|
||||
|
||||
// Tutorial 05
|
||||
VK_DEVICE_LEVEL_FUNCTION( vkCmdCopyBuffer )
|
||||
|
||||
#undef VK_DEVICE_LEVEL_FUNCTION
|
||||
BIN
Project/Tutorial05/Data05/frag.spv
Normal file
BIN
Project/Tutorial05/Data05/frag.spv
Normal file
Binary file not shown.
36
Project/Tutorial05/Data05/frag.spv.txt
Normal file
36
Project/Tutorial05/Data05/frag.spv.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
shader.frag
|
||||
Warning, version 430 is not yet complete; most version-specific features are present, but some are missing.
|
||||
|
||||
|
||||
Linked fragment stage:
|
||||
|
||||
|
||||
// Module Version 10000
|
||||
// Generated by (magic number): 80001
|
||||
// Id's are bound by 13
|
||||
|
||||
Capability Shader
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
MemoryModel Logical GLSL450
|
||||
EntryPoint Fragment 4 "main" 9 11
|
||||
ExecutionMode 4 OriginLowerLeft
|
||||
Source GLSL 430
|
||||
Name 4 "main"
|
||||
Name 9 "o_Color"
|
||||
Name 11 "v_Color"
|
||||
Decorate 9(o_Color) Location 0
|
||||
Decorate 11(v_Color) Location 0
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
6: TypeFloat 32
|
||||
7: TypeVector 6(float) 4
|
||||
8: TypePointer Output 7(fvec4)
|
||||
9(o_Color): 8(ptr) Variable Output
|
||||
10: TypePointer Input 7(fvec4)
|
||||
11(v_Color): 10(ptr) Variable Input
|
||||
4(main): 2 Function None 3
|
||||
5: Label
|
||||
12: 7(fvec4) Load 11(v_Color)
|
||||
Store 9(o_Color) 12
|
||||
Return
|
||||
FunctionEnd
|
||||
19
Project/Tutorial05/Data05/shader.frag
Normal file
19
Project/Tutorial05/Data05/shader.frag
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2016 Intel Corporation All Rights Reserved
|
||||
//
|
||||
// Intel makes no representations about the suitability of this software for any purpose.
|
||||
// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
|
||||
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES,
|
||||
// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY
|
||||
// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// Intel does not assume any responsibility for any errors which may appear in this software
|
||||
// nor any responsibility to update it.
|
||||
|
||||
#version 430
|
||||
|
||||
layout(location = 0) in vec4 v_Color;
|
||||
|
||||
layout(location = 0) out vec4 o_Color;
|
||||
|
||||
void main() {
|
||||
o_Color = v_Color;
|
||||
}
|
||||
21
Project/Tutorial05/Data05/shader.vert
Normal file
21
Project/Tutorial05/Data05/shader.vert
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2016 Intel Corporation All Rights Reserved
|
||||
//
|
||||
// Intel makes no representations about the suitability of this software for any purpose.
|
||||
// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
|
||||
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES,
|
||||
// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY
|
||||
// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// Intel does not assume any responsibility for any errors which may appear in this software
|
||||
// nor any responsibility to update it.
|
||||
|
||||
#version 430
|
||||
|
||||
layout(location = 0) in vec4 i_Position;
|
||||
layout(location = 1) in vec4 i_Color;
|
||||
|
||||
layout(location = 0) out vec4 v_Color;
|
||||
|
||||
void main() {
|
||||
gl_Position = i_Position;
|
||||
v_Color = i_Color;
|
||||
}
|
||||
BIN
Project/Tutorial05/Data05/vert.spv
Normal file
BIN
Project/Tutorial05/Data05/vert.spv
Normal file
Binary file not shown.
59
Project/Tutorial05/Data05/vert.spv.txt
Normal file
59
Project/Tutorial05/Data05/vert.spv.txt
Normal file
@@ -0,0 +1,59 @@
|
||||
shader.vert
|
||||
Warning, version 430 is not yet complete; most version-specific features are present, but some are missing.
|
||||
|
||||
|
||||
Linked vertex stage:
|
||||
|
||||
|
||||
// Module Version 10000
|
||||
// Generated by (magic number): 80001
|
||||
// Id's are bound by 24
|
||||
|
||||
Capability Shader
|
||||
Capability ClipDistance
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
MemoryModel Logical GLSL450
|
||||
EntryPoint Vertex 4 "main" 13 17 21 22
|
||||
Source GLSL 430
|
||||
Name 4 "main"
|
||||
Name 11 "gl_PerVertex"
|
||||
MemberName 11(gl_PerVertex) 0 "gl_Position"
|
||||
MemberName 11(gl_PerVertex) 1 "gl_PointSize"
|
||||
MemberName 11(gl_PerVertex) 2 "gl_ClipDistance"
|
||||
Name 13 ""
|
||||
Name 17 "i_Position"
|
||||
Name 21 "v_Color"
|
||||
Name 22 "i_Color"
|
||||
MemberDecorate 11(gl_PerVertex) 0 BuiltIn Position
|
||||
MemberDecorate 11(gl_PerVertex) 1 BuiltIn PointSize
|
||||
MemberDecorate 11(gl_PerVertex) 2 BuiltIn ClipDistance
|
||||
Decorate 11(gl_PerVertex) Block
|
||||
Decorate 17(i_Position) Location 0
|
||||
Decorate 21(v_Color) Location 0
|
||||
Decorate 22(i_Color) Location 1
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
6: TypeFloat 32
|
||||
7: TypeVector 6(float) 4
|
||||
8: TypeInt 32 0
|
||||
9: 8(int) Constant 1
|
||||
10: TypeArray 6(float) 9
|
||||
11(gl_PerVertex): TypeStruct 7(fvec4) 6(float) 10
|
||||
12: TypePointer Output 11(gl_PerVertex)
|
||||
13: 12(ptr) Variable Output
|
||||
14: TypeInt 32 1
|
||||
15: 14(int) Constant 0
|
||||
16: TypePointer Input 7(fvec4)
|
||||
17(i_Position): 16(ptr) Variable Input
|
||||
19: TypePointer Output 7(fvec4)
|
||||
21(v_Color): 19(ptr) Variable Output
|
||||
22(i_Color): 16(ptr) Variable Input
|
||||
4(main): 2 Function None 3
|
||||
5: Label
|
||||
18: 7(fvec4) Load 17(i_Position)
|
||||
20: 19(ptr) AccessChain 13 15
|
||||
Store 20 18
|
||||
23: 7(fvec4) Load 22(i_Color)
|
||||
Store 21(v_Color) 23
|
||||
Return
|
||||
FunctionEnd
|
||||
834
Project/Tutorial05/Tutorial05.cpp
Normal file
834
Project/Tutorial05/Tutorial05.cpp
Normal file
@@ -0,0 +1,834 @@
|
||||
// Copyright 2016 Intel Corporation All Rights Reserved
|
||||
//
|
||||
// Intel makes no representations about the suitability of this software for any purpose.
|
||||
// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
|
||||
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES,
|
||||
// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY
|
||||
// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// Intel does not assume any responsibility for any errors which may appear in this software
|
||||
// nor any responsibility to update it.
|
||||
|
||||
#include "Tutorial05.h"
|
||||
#include "VulkanFunctions.h"
|
||||
|
||||
namespace ApiWithoutSecrets {
|
||||
|
||||
Tutorial05::Tutorial05() :
|
||||
Vulkan() {
|
||||
}
|
||||
|
||||
bool Tutorial05::CreateRenderPass() {
|
||||
VkAttachmentDescription attachment_descriptions[] = {
|
||||
{
|
||||
0, // VkAttachmentDescriptionFlags flags
|
||||
GetSwapChain().Format, // VkFormat format
|
||||
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
|
||||
VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
|
||||
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
|
||||
}
|
||||
};
|
||||
|
||||
VkAttachmentReference color_attachment_references[] = {
|
||||
{
|
||||
0, // uint32_t attachment
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout
|
||||
}
|
||||
};
|
||||
|
||||
VkSubpassDescription subpass_descriptions[] = {
|
||||
{
|
||||
0, // VkSubpassDescriptionFlags flags
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
|
||||
0, // uint32_t inputAttachmentCount
|
||||
nullptr, // const VkAttachmentReference *pInputAttachments
|
||||
1, // uint32_t colorAttachmentCount
|
||||
color_attachment_references, // const VkAttachmentReference *pColorAttachments
|
||||
nullptr, // const VkAttachmentReference *pResolveAttachments
|
||||
nullptr, // const VkAttachmentReference *pDepthStencilAttachment
|
||||
0, // uint32_t preserveAttachmentCount
|
||||
nullptr // const uint32_t* pPreserveAttachments
|
||||
}
|
||||
};
|
||||
|
||||
VkRenderPassCreateInfo render_pass_create_info = {
|
||||
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkRenderPassCreateFlags flags
|
||||
1, // uint32_t attachmentCount
|
||||
attachment_descriptions, // const VkAttachmentDescription *pAttachments
|
||||
1, // uint32_t subpassCount
|
||||
subpass_descriptions, // const VkSubpassDescription *pSubpasses
|
||||
0, // uint32_t dependencyCount
|
||||
nullptr // const VkSubpassDependency *pDependencies
|
||||
};
|
||||
|
||||
if( vkCreateRenderPass( GetDevice(), &render_pass_create_info, nullptr, &Vulkan.RenderPass ) != VK_SUCCESS ) {
|
||||
std::cout << "Could not create render pass!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Tools::AutoDeleter<VkShaderModule, PFN_vkDestroyShaderModule> Tutorial05::CreateShaderModule( const char* filename ) {
|
||||
const std::vector<char> code = Tools::GetBinaryFileContents( filename );
|
||||
if( code.size() == 0 ) {
|
||||
return Tools::AutoDeleter<VkShaderModule, PFN_vkDestroyShaderModule>();
|
||||
}
|
||||
|
||||
VkShaderModuleCreateInfo shader_module_create_info = {
|
||||
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkShaderModuleCreateFlags flags
|
||||
code.size(), // size_t codeSize
|
||||
reinterpret_cast<const uint32_t*>(&code[0]) // const uint32_t *pCode
|
||||
};
|
||||
|
||||
VkShaderModule shader_module;
|
||||
if( vkCreateShaderModule( GetDevice(), &shader_module_create_info, nullptr, &shader_module ) != VK_SUCCESS ) {
|
||||
std::cout << "Could not create shader module from a \"" << filename << "\" file!" << std::endl;
|
||||
return Tools::AutoDeleter<VkShaderModule, PFN_vkDestroyShaderModule>();
|
||||
}
|
||||
|
||||
return Tools::AutoDeleter<VkShaderModule, PFN_vkDestroyShaderModule>( shader_module, vkDestroyShaderModule, GetDevice() );
|
||||
}
|
||||
|
||||
Tools::AutoDeleter<VkPipelineLayout, PFN_vkDestroyPipelineLayout> Tutorial05::CreatePipelineLayout() {
|
||||
VkPipelineLayoutCreateInfo layout_create_info = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkPipelineLayoutCreateFlags flags
|
||||
0, // uint32_t setLayoutCount
|
||||
nullptr, // const VkDescriptorSetLayout *pSetLayouts
|
||||
0, // uint32_t pushConstantRangeCount
|
||||
nullptr // const VkPushConstantRange *pPushConstantRanges
|
||||
};
|
||||
|
||||
VkPipelineLayout pipeline_layout;
|
||||
if( vkCreatePipelineLayout( GetDevice(), &layout_create_info, nullptr, &pipeline_layout ) != VK_SUCCESS ) {
|
||||
std::cout << "Could not create pipeline layout!" << std::endl;
|
||||
return Tools::AutoDeleter<VkPipelineLayout, PFN_vkDestroyPipelineLayout>();
|
||||
}
|
||||
|
||||
return Tools::AutoDeleter<VkPipelineLayout, PFN_vkDestroyPipelineLayout>( pipeline_layout, vkDestroyPipelineLayout, GetDevice() );
|
||||
}
|
||||
|
||||
bool Tutorial05::CreatePipeline() {
|
||||
Tools::AutoDeleter<VkShaderModule, PFN_vkDestroyShaderModule> vertex_shader_module = CreateShaderModule( "Data05/vert.spv" );
|
||||
Tools::AutoDeleter<VkShaderModule, PFN_vkDestroyShaderModule> fragment_shader_module = CreateShaderModule( "Data05/frag.spv" );
|
||||
|
||||
if( !vertex_shader_module || !fragment_shader_module ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<VkPipelineShaderStageCreateInfo> shader_stage_create_infos = {
|
||||
// Vertex shader
|
||||
{
|
||||
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkPipelineShaderStageCreateFlags flags
|
||||
VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage
|
||||
vertex_shader_module.Get(), // VkShaderModule module
|
||||
"main", // const char *pName
|
||||
nullptr // const VkSpecializationInfo *pSpecializationInfo
|
||||
},
|
||||
// Fragment shader
|
||||
{
|
||||
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkPipelineShaderStageCreateFlags flags
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage
|
||||
fragment_shader_module.Get(), // VkShaderModule module
|
||||
"main", // const char *pName
|
||||
nullptr // const VkSpecializationInfo *pSpecializationInfo
|
||||
}
|
||||
};
|
||||
|
||||
VkVertexInputBindingDescription vertex_binding_description = {
|
||||
0, // uint32_t binding
|
||||
sizeof(VertexData), // uint32_t stride
|
||||
VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate
|
||||
};
|
||||
|
||||
VkVertexInputAttributeDescription vertex_attribute_descriptions[] = {
|
||||
{
|
||||
0, // uint32_t location
|
||||
vertex_binding_description.binding, // uint32_t binding
|
||||
VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format
|
||||
0 // uint32_t offset
|
||||
},
|
||||
{
|
||||
1, // uint32_t location
|
||||
vertex_binding_description.binding, // uint32_t binding
|
||||
VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format
|
||||
4 * sizeof(float) // uint32_t offset
|
||||
}
|
||||
};
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkPipelineVertexInputStateCreateFlags flags;
|
||||
1, // uint32_t vertexBindingDescriptionCount
|
||||
&vertex_binding_description, // const VkVertexInputBindingDescription *pVertexBindingDescriptions
|
||||
2, // uint32_t vertexAttributeDescriptionCount
|
||||
vertex_attribute_descriptions // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions
|
||||
};
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkPipelineInputAssemblyStateCreateFlags flags
|
||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology
|
||||
VK_FALSE // VkBool32 primitiveRestartEnable
|
||||
};
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewport_state_create_info = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkPipelineViewportStateCreateFlags flags
|
||||
1, // uint32_t viewportCount
|
||||
nullptr, // const VkViewport *pViewports
|
||||
1, // uint32_t scissorCount
|
||||
nullptr // const VkRect2D *pScissors
|
||||
};
|
||||
|
||||
VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkPipelineRasterizationStateCreateFlags flags
|
||||
VK_FALSE, // VkBool32 depthClampEnable
|
||||
VK_FALSE, // VkBool32 rasterizerDiscardEnable
|
||||
VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
|
||||
VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode
|
||||
VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
|
||||
VK_FALSE, // VkBool32 depthBiasEnable
|
||||
0.0f, // float depthBiasConstantFactor
|
||||
0.0f, // float depthBiasClamp
|
||||
0.0f, // float depthBiasSlopeFactor
|
||||
1.0f // float lineWidth
|
||||
};
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo multisample_state_create_info = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkPipelineMultisampleStateCreateFlags flags
|
||||
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples
|
||||
VK_FALSE, // VkBool32 sampleShadingEnable
|
||||
1.0f, // float minSampleShading
|
||||
nullptr, // const VkSampleMask *pSampleMask
|
||||
VK_FALSE, // VkBool32 alphaToCoverageEnable
|
||||
VK_FALSE // VkBool32 alphaToOneEnable
|
||||
};
|
||||
|
||||
VkPipelineColorBlendAttachmentState color_blend_attachment_state = {
|
||||
VK_FALSE, // VkBool32 blendEnable
|
||||
VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor
|
||||
VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
|
||||
VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
|
||||
VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor
|
||||
VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
|
||||
VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
|
||||
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
|
||||
};
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkPipelineColorBlendStateCreateFlags flags
|
||||
VK_FALSE, // VkBool32 logicOpEnable
|
||||
VK_LOGIC_OP_COPY, // VkLogicOp logicOp
|
||||
1, // uint32_t attachmentCount
|
||||
&color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
|
||||
};
|
||||
|
||||
VkDynamicState dynamic_states[] = {
|
||||
VK_DYNAMIC_STATE_VIEWPORT,
|
||||
VK_DYNAMIC_STATE_SCISSOR,
|
||||
};
|
||||
|
||||
VkPipelineDynamicStateCreateInfo dynamic_state_create_info = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkPipelineDynamicStateCreateFlags flags
|
||||
2, // uint32_t dynamicStateCount
|
||||
dynamic_states // const VkDynamicState *pDynamicStates
|
||||
};
|
||||
|
||||
Tools::AutoDeleter<VkPipelineLayout, PFN_vkDestroyPipelineLayout> pipeline_layout = CreatePipelineLayout();
|
||||
if( !pipeline_layout ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipeline_create_info = {
|
||||
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkPipelineCreateFlags flags
|
||||
static_cast<uint32_t>(shader_stage_create_infos.size()), // uint32_t stageCount
|
||||
&shader_stage_create_infos[0], // const VkPipelineShaderStageCreateInfo *pStages
|
||||
&vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState;
|
||||
&input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState
|
||||
nullptr, // const VkPipelineTessellationStateCreateInfo *pTessellationState
|
||||
&viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState
|
||||
&rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState
|
||||
&multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState
|
||||
nullptr, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState
|
||||
&color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState
|
||||
&dynamic_state_create_info, // const VkPipelineDynamicStateCreateInfo *pDynamicState
|
||||
pipeline_layout.Get(), // VkPipelineLayout layout
|
||||
Vulkan.RenderPass, // VkRenderPass renderPass
|
||||
0, // uint32_t subpass
|
||||
VK_NULL_HANDLE, // VkPipeline basePipelineHandle
|
||||
-1 // int32_t basePipelineIndex
|
||||
};
|
||||
|
||||
if( vkCreateGraphicsPipelines( GetDevice(), VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &Vulkan.GraphicsPipeline ) != VK_SUCCESS ) {
|
||||
std::cout << "Could not create graphics pipeline!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::CreateRenderingResources() {
|
||||
if( !CreateCommandBuffers() ) {
|
||||
return false;
|
||||
}
|
||||
if( !CreateSemaphores() ) {
|
||||
return false;
|
||||
}
|
||||
if( !CreateFences() ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::CreateCommandBuffers() {
|
||||
if( !CreateCommandPool( GetGraphicsQueue().FamilyIndex, &Vulkan.CommandPool ) ) {
|
||||
std::cout << "Could not create command pool!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) {
|
||||
if( !AllocateCommandBuffers( Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer ) ) {
|
||||
std::cout << "Could not allocate command buffer!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) {
|
||||
VkCommandPoolCreateInfo cmd_pool_create_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | // VkCommandPoolCreateFlags flags
|
||||
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
|
||||
queue_family_index // uint32_t queueFamilyIndex
|
||||
};
|
||||
|
||||
if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers ) {
|
||||
VkCommandBufferAllocateInfo command_buffer_allocate_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
pool, // VkCommandPool commandPool
|
||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level
|
||||
count // uint32_t bufferCount
|
||||
};
|
||||
|
||||
if( vkAllocateCommandBuffers( GetDevice(), &command_buffer_allocate_info, command_buffers ) != VK_SUCCESS ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::CreateSemaphores() {
|
||||
VkSemaphoreCreateInfo semaphore_create_info = {
|
||||
VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void* pNext
|
||||
0 // VkSemaphoreCreateFlags flags
|
||||
};
|
||||
|
||||
for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) {
|
||||
if( (vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].ImageAvailableSemaphore ) != VK_SUCCESS) ||
|
||||
(vkCreateSemaphore( GetDevice(), &semaphore_create_info, nullptr, &Vulkan.RenderingResources[i].FinishedRenderingSemaphore ) != VK_SUCCESS) ) {
|
||||
std::cout << "Could not create semaphores!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::CreateFences() {
|
||||
VkFenceCreateInfo fence_create_info = {
|
||||
VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
VK_FENCE_CREATE_SIGNALED_BIT // VkFenceCreateFlags flags
|
||||
};
|
||||
|
||||
for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) {
|
||||
if( vkCreateFence( GetDevice(), &fence_create_info, nullptr, &Vulkan.RenderingResources[i].Fence ) != VK_SUCCESS ) {
|
||||
std::cout << "Could not create a fence!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::CreateVertexBuffer() {
|
||||
const std::vector<float>& vertex_data = GetVertexData();
|
||||
|
||||
Vulkan.VertexBuffer.Size = static_cast<uint32_t>(vertex_data.size() * sizeof(vertex_data[0]));
|
||||
if( !CreateBuffer( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Vulkan.VertexBuffer ) ) {
|
||||
std::cout << "Could not create vertex buffer!" << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::CreateStagingBuffer() {
|
||||
Vulkan.StagingBuffer.Size = 4000;
|
||||
if( !CreateBuffer( VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, Vulkan.StagingBuffer ) ) {
|
||||
std::cout << "Could not staging buffer!" << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::CreateBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer ) {
|
||||
VkBufferCreateInfo buffer_create_info = {
|
||||
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkBufferCreateFlags flags
|
||||
buffer.Size, // VkDeviceSize size
|
||||
usage, // VkBufferUsageFlags usage
|
||||
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
|
||||
0, // uint32_t queueFamilyIndexCount
|
||||
nullptr // const uint32_t *pQueueFamilyIndices
|
||||
};
|
||||
|
||||
if( vkCreateBuffer( GetDevice(), &buffer_create_info, nullptr, &buffer.Handle ) != VK_SUCCESS ) {
|
||||
std::cout << "Could not create buffer!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !AllocateBufferMemory( buffer.Handle, memoryProperty, &buffer.Memory ) ) {
|
||||
std::cout << "Could not allocate memory for a buffer!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( vkBindBufferMemory( GetDevice(), buffer.Handle, buffer.Memory, 0 ) != VK_SUCCESS ) {
|
||||
std::cout << "Could not bind memory to a buffer!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::AllocateBufferMemory( VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory ) {
|
||||
VkMemoryRequirements buffer_memory_requirements;
|
||||
vkGetBufferMemoryRequirements( GetDevice(), Vulkan.VertexBuffer.Handle, &buffer_memory_requirements );
|
||||
|
||||
VkPhysicalDeviceMemoryProperties memory_properties;
|
||||
vkGetPhysicalDeviceMemoryProperties( GetPhysicalDevice(), &memory_properties );
|
||||
|
||||
for( uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i ) {
|
||||
if( (buffer_memory_requirements.memoryTypeBits & (1 << i)) &&
|
||||
(memory_properties.memoryTypes[i].propertyFlags & property) ) {
|
||||
|
||||
VkMemoryAllocateInfo memory_allocate_info = {
|
||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
buffer_memory_requirements.size, // VkDeviceSize allocationSize
|
||||
i // uint32_t memoryTypeIndex
|
||||
};
|
||||
|
||||
if( vkAllocateMemory( GetDevice(), &memory_allocate_info, nullptr, memory ) == VK_SUCCESS ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<float>& Tutorial05::GetVertexData() const {
|
||||
static const std::vector<float> vertex_data = {
|
||||
-0.7f, -0.7f, 0.0f, 1.0f,
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
//
|
||||
-0.7f, 0.7f, 0.0f, 1.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
//
|
||||
0.7f, -0.7f, 0.0f, 1.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
//
|
||||
0.7f, 0.7f, 0.0f, 1.0f,
|
||||
0.3f, 0.3f, 0.3f, 0.0f
|
||||
};
|
||||
|
||||
return vertex_data;
|
||||
}
|
||||
|
||||
bool Tutorial05::CopyVertexData() {
|
||||
// Prepare data in staging buffer
|
||||
const std::vector<float>& vertex_data = GetVertexData();
|
||||
|
||||
void *staging_buffer_memory_pointer;
|
||||
if( vkMapMemory( GetDevice(), Vulkan.StagingBuffer.Memory, 0, Vulkan.VertexBuffer.Size, 0, &staging_buffer_memory_pointer) != VK_SUCCESS ) {
|
||||
std::cout << "Could not map memory and upload data to a staging buffer!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy( staging_buffer_memory_pointer, &vertex_data[0], Vulkan.VertexBuffer.Size );
|
||||
|
||||
VkMappedMemoryRange flush_range = {
|
||||
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
Vulkan.StagingBuffer.Memory, // VkDeviceMemory memory
|
||||
0, // VkDeviceSize offset
|
||||
Vulkan.VertexBuffer.Size // VkDeviceSize size
|
||||
};
|
||||
vkFlushMappedMemoryRanges( GetDevice(), 1, &flush_range );
|
||||
|
||||
vkUnmapMemory( GetDevice(), Vulkan.StagingBuffer.Memory );
|
||||
|
||||
// Prepare command buffer to copy data from staging buffer to a vertex buffer
|
||||
VkCommandBufferBeginInfo command_buffer_begin_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags
|
||||
nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo
|
||||
};
|
||||
|
||||
VkCommandBuffer command_buffer = Vulkan.RenderingResources[0].CommandBuffer;
|
||||
|
||||
vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info);
|
||||
|
||||
VkBufferCopy buffer_copy_info = {
|
||||
0, // VkDeviceSize srcOffset
|
||||
0, // VkDeviceSize dstOffset
|
||||
Vulkan.VertexBuffer.Size // VkDeviceSize size
|
||||
};
|
||||
vkCmdCopyBuffer(command_buffer, Vulkan.StagingBuffer.Handle, Vulkan.VertexBuffer.Handle, 1, &buffer_copy_info);
|
||||
|
||||
VkBufferMemoryBarrier buffer_memory_barrier = {
|
||||
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
|
||||
nullptr, // const void *pNext
|
||||
VK_ACCESS_MEMORY_WRITE_BIT, // VkAccessFlags srcAccessMask
|
||||
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkAccessFlags dstAccessMask
|
||||
VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
|
||||
VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
|
||||
Vulkan.VertexBuffer.Handle, // VkBuffer buffer
|
||||
0, // VkDeviceSize offset
|
||||
VK_WHOLE_SIZE // VkDeviceSize size
|
||||
};
|
||||
vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 1, &buffer_memory_barrier, 0, nullptr );
|
||||
|
||||
vkEndCommandBuffer( command_buffer );
|
||||
|
||||
// Submit command buffer and copy data from staging buffer to a vertex buffer
|
||||
VkSubmitInfo submit_info = {
|
||||
VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // uint32_t waitSemaphoreCount
|
||||
nullptr, // const VkSemaphore *pWaitSemaphores
|
||||
nullptr, // const VkPipelineStageFlags *pWaitDstStageMask;
|
||||
1, // uint32_t commandBufferCount
|
||||
&command_buffer, // const VkCommandBuffer *pCommandBuffers
|
||||
0, // uint32_t signalSemaphoreCount
|
||||
nullptr // const VkSemaphore *pSignalSemaphores
|
||||
};
|
||||
|
||||
if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, VK_NULL_HANDLE ) != VK_SUCCESS ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vkDeviceWaitIdle( GetDevice() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer ) {
|
||||
if( !CreateFramebuffer( framebuffer, image_parameters.ImageView ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VkCommandBufferBeginInfo command_buffer_begin_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags
|
||||
nullptr // const VkCommandBufferInheritanceInfo *pInheritanceInfo
|
||||
};
|
||||
|
||||
vkBeginCommandBuffer( command_buffer, &command_buffer_begin_info );
|
||||
|
||||
VkImageSubresourceRange image_subresource_range = {
|
||||
VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
|
||||
0, // uint32_t baseMipLevel
|
||||
1, // uint32_t levelCount
|
||||
0, // uint32_t baseArrayLayer
|
||||
1 // uint32_t layerCount
|
||||
};
|
||||
|
||||
uint32_t present_queue_family_index = (GetPresentQueue().Handle != GetGraphicsQueue().Handle) ? GetPresentQueue().FamilyIndex : VK_QUEUE_FAMILY_IGNORED;
|
||||
uint32_t graphics_queue_family_index = (GetPresentQueue().Handle != GetGraphicsQueue().Handle) ? GetGraphicsQueue().FamilyIndex : VK_QUEUE_FAMILY_IGNORED;
|
||||
VkImageMemoryBarrier barrier_from_present_to_draw = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags srcAccessMask
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
|
||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout oldLayout
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout
|
||||
present_queue_family_index, // uint32_t srcQueueFamilyIndex
|
||||
graphics_queue_family_index, // uint32_t dstQueueFamilyIndex
|
||||
image_parameters.Handle, // VkImage image
|
||||
image_subresource_range // VkImageSubresourceRange subresourceRange
|
||||
};
|
||||
vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_present_to_draw );
|
||||
|
||||
VkClearValue clear_value = {
|
||||
{ 1.0f, 0.8f, 0.4f, 0.0f }, // VkClearColorValue color
|
||||
};
|
||||
|
||||
VkRenderPassBeginInfo render_pass_begin_info = {
|
||||
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
Vulkan.RenderPass, // VkRenderPass renderPass
|
||||
framebuffer, // VkFramebuffer framebuffer
|
||||
{ // VkRect2D renderArea
|
||||
{ // VkOffset2D offset
|
||||
0, // int32_t x
|
||||
0 // int32_t y
|
||||
},
|
||||
GetSwapChain().Extent, // VkExtent2D extent;
|
||||
},
|
||||
1, // uint32_t clearValueCount
|
||||
&clear_value // const VkClearValue *pClearValues
|
||||
};
|
||||
|
||||
vkCmdBeginRenderPass( command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE );
|
||||
|
||||
vkCmdBindPipeline( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Vulkan.GraphicsPipeline );
|
||||
|
||||
VkViewport viewport = {
|
||||
0.0f, // float x
|
||||
0.0f, // float y
|
||||
static_cast<float>(GetSwapChain().Extent.width), // float width
|
||||
static_cast<float>(GetSwapChain().Extent.height), // float height
|
||||
0.0f, // float minDepth
|
||||
1.0f // float maxDepth
|
||||
};
|
||||
|
||||
VkRect2D scissor = {
|
||||
{ // VkOffset2D offset
|
||||
0, // int32_t x
|
||||
0 // int32_t y
|
||||
},
|
||||
{ // VkExtent2D extent
|
||||
GetSwapChain().Extent.width, // uint32_t width
|
||||
GetSwapChain().Extent.height // uint32_t height
|
||||
}
|
||||
};
|
||||
|
||||
vkCmdSetViewport( command_buffer, 0, 1, &viewport );
|
||||
vkCmdSetScissor( command_buffer, 0, 1, &scissor );
|
||||
|
||||
VkDeviceSize offset = 0;
|
||||
vkCmdBindVertexBuffers( command_buffer, 0, 1, &Vulkan.VertexBuffer.Handle, &offset );
|
||||
|
||||
vkCmdDraw( command_buffer, 4, 1, 0, 0 );
|
||||
|
||||
vkCmdEndRenderPass( command_buffer );
|
||||
|
||||
VkImageMemoryBarrier barrier_from_draw_to_present = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask
|
||||
VK_ACCESS_MEMORY_READ_BIT, // VkAccessFlags dstAccessMask
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout
|
||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VkImageLayout newLayout
|
||||
graphics_queue_family_index, // uint32_t srcQueueFamilyIndex
|
||||
present_queue_family_index, // uint32_t dstQueueFamilyIndex
|
||||
image_parameters.Handle, // VkImage image
|
||||
image_subresource_range // VkImageSubresourceRange subresourceRange
|
||||
};
|
||||
vkCmdPipelineBarrier( command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier_from_draw_to_present );
|
||||
|
||||
if( vkEndCommandBuffer( command_buffer ) != VK_SUCCESS ) {
|
||||
std::cout << "Could not record command buffer!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view ) {
|
||||
if( framebuffer != VK_NULL_HANDLE ) {
|
||||
vkDestroyFramebuffer( GetDevice(), framebuffer, nullptr );
|
||||
}
|
||||
|
||||
VkFramebufferCreateInfo framebuffer_create_info = {
|
||||
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
0, // VkFramebufferCreateFlags flags
|
||||
Vulkan.RenderPass, // VkRenderPass renderPass
|
||||
1, // uint32_t attachmentCount
|
||||
&image_view, // const VkImageView *pAttachments
|
||||
GetSwapChain().Extent.width, // uint32_t width
|
||||
GetSwapChain().Extent.height, // uint32_t height
|
||||
1 // uint32_t layers
|
||||
};
|
||||
|
||||
if( vkCreateFramebuffer( GetDevice(), &framebuffer_create_info, nullptr, &framebuffer ) != VK_SUCCESS ) {
|
||||
std::cout << "Could not create a framebuffer!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::ChildOnWindowSizeChanged() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tutorial05::Draw() {
|
||||
static size_t resource_index = 0;
|
||||
RenderingResourcesData ¤t_rendering_resource = Vulkan.RenderingResources[resource_index];
|
||||
VkSwapchainKHR swap_chain = GetSwapChain().Handle;
|
||||
uint32_t image_index;
|
||||
|
||||
resource_index = (resource_index + 1) % VulkanTutorial05Parameters::ResourcesCount;
|
||||
|
||||
if( vkWaitForFences( GetDevice(), 1, ¤t_rendering_resource.Fence, VK_FALSE, 1000000000 ) != VK_SUCCESS ) {
|
||||
std::cout << "Waiting for fence takes too long!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
vkResetFences( GetDevice(), 1, ¤t_rendering_resource.Fence );
|
||||
|
||||
VkResult result = vkAcquireNextImageKHR( GetDevice(), swap_chain, UINT64_MAX, current_rendering_resource.ImageAvailableSemaphore, VK_NULL_HANDLE, &image_index );
|
||||
switch( result ) {
|
||||
case VK_SUCCESS:
|
||||
case VK_SUBOPTIMAL_KHR:
|
||||
break;
|
||||
case VK_ERROR_OUT_OF_DATE_KHR:
|
||||
return OnWindowSizeChanged();
|
||||
default:
|
||||
std::cout << "Problem occurred during swap chain image acquisition!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !PrepareFrame( current_rendering_resource.CommandBuffer, GetSwapChain( ).Images[image_index], current_rendering_resource.Framebuffer ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
VkSubmitInfo submit_info = {
|
||||
VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
1, // uint32_t waitSemaphoreCount
|
||||
¤t_rendering_resource.ImageAvailableSemaphore, // const VkSemaphore *pWaitSemaphores
|
||||
&wait_dst_stage_mask, // const VkPipelineStageFlags *pWaitDstStageMask;
|
||||
1, // uint32_t commandBufferCount
|
||||
¤t_rendering_resource.CommandBuffer, // const VkCommandBuffer *pCommandBuffers
|
||||
1, // uint32_t signalSemaphoreCount
|
||||
¤t_rendering_resource.FinishedRenderingSemaphore // const VkSemaphore *pSignalSemaphores
|
||||
};
|
||||
|
||||
if( vkQueueSubmit( GetGraphicsQueue().Handle, 1, &submit_info, current_rendering_resource.Fence ) != VK_SUCCESS ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VkPresentInfoKHR present_info = {
|
||||
VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // VkStructureType sType
|
||||
nullptr, // const void *pNext
|
||||
1, // uint32_t waitSemaphoreCount
|
||||
¤t_rendering_resource.FinishedRenderingSemaphore, // const VkSemaphore *pWaitSemaphores
|
||||
1, // uint32_t swapchainCount
|
||||
&swap_chain, // const VkSwapchainKHR *pSwapchains
|
||||
&image_index, // const uint32_t *pImageIndices
|
||||
nullptr // VkResult *pResults
|
||||
};
|
||||
result = vkQueuePresentKHR( GetPresentQueue().Handle, &present_info );
|
||||
|
||||
switch( result ) {
|
||||
case VK_SUCCESS:
|
||||
break;
|
||||
case VK_ERROR_OUT_OF_DATE_KHR:
|
||||
case VK_SUBOPTIMAL_KHR:
|
||||
return OnWindowSizeChanged();
|
||||
default:
|
||||
std::cout << "Problem occurred during image presentation!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tutorial05::ChildClear() {
|
||||
}
|
||||
|
||||
Tutorial05::~Tutorial05() {
|
||||
if( GetDevice() != VK_NULL_HANDLE ) {
|
||||
vkDeviceWaitIdle( GetDevice() );
|
||||
|
||||
for( size_t i = 0; i < Vulkan.RenderingResources.size(); ++i ) {
|
||||
if( Vulkan.RenderingResources[i].Framebuffer != VK_NULL_HANDLE ) {
|
||||
vkDestroyFramebuffer( GetDevice(), Vulkan.RenderingResources[i].Framebuffer, nullptr );
|
||||
}
|
||||
if( Vulkan.RenderingResources[i].CommandBuffer != VK_NULL_HANDLE ) {
|
||||
vkFreeCommandBuffers( GetDevice(), Vulkan.CommandPool, 1, &Vulkan.RenderingResources[i].CommandBuffer );
|
||||
}
|
||||
if( Vulkan.RenderingResources[i].ImageAvailableSemaphore != VK_NULL_HANDLE ) {
|
||||
vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].ImageAvailableSemaphore, nullptr );
|
||||
}
|
||||
if( Vulkan.RenderingResources[i].FinishedRenderingSemaphore != VK_NULL_HANDLE ) {
|
||||
vkDestroySemaphore( GetDevice(), Vulkan.RenderingResources[i].FinishedRenderingSemaphore, nullptr );
|
||||
}
|
||||
if( Vulkan.RenderingResources[i].Fence != VK_NULL_HANDLE ) {
|
||||
vkDestroyFence( GetDevice(), Vulkan.RenderingResources[i].Fence, nullptr );
|
||||
}
|
||||
}
|
||||
|
||||
if( Vulkan.CommandPool != VK_NULL_HANDLE ) {
|
||||
vkDestroyCommandPool( GetDevice(), Vulkan.CommandPool, nullptr );
|
||||
Vulkan.CommandPool = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
DestroyBuffer( Vulkan.VertexBuffer );
|
||||
|
||||
DestroyBuffer( Vulkan.StagingBuffer );
|
||||
|
||||
if( Vulkan.GraphicsPipeline != VK_NULL_HANDLE ) {
|
||||
vkDestroyPipeline( GetDevice(), Vulkan.GraphicsPipeline, nullptr );
|
||||
Vulkan.GraphicsPipeline = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if( Vulkan.RenderPass != VK_NULL_HANDLE ) {
|
||||
vkDestroyRenderPass( GetDevice(), Vulkan.RenderPass, nullptr );
|
||||
Vulkan.RenderPass = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tutorial05::DestroyBuffer( BufferParameters& buffer ) {
|
||||
if( buffer.Handle != VK_NULL_HANDLE ) {
|
||||
vkDestroyBuffer( GetDevice(), buffer.Handle, nullptr );
|
||||
buffer.Handle = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if( buffer.Memory != VK_NULL_HANDLE ) {
|
||||
vkFreeMemory( GetDevice(), buffer.Memory, nullptr );
|
||||
buffer.Memory = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ApiWithoutSecrets
|
||||
133
Project/Tutorial05/Tutorial05.h
Normal file
133
Project/Tutorial05/Tutorial05.h
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2016 Intel Corporation All Rights Reserved
|
||||
//
|
||||
// Intel makes no representations about the suitability of this software for any purpose.
|
||||
// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
|
||||
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES,
|
||||
// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY
|
||||
// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// Intel does not assume any responsibility for any errors which may appear in this software
|
||||
// nor any responsibility to update it.
|
||||
|
||||
#if !defined(TUTORIAL_05_HEADER)
|
||||
#define TUTORIAL_05_HEADER
|
||||
|
||||
#include "VulkanCommon.h"
|
||||
#include "Tools.h"
|
||||
|
||||
namespace ApiWithoutSecrets {
|
||||
|
||||
// ************************************************************ //
|
||||
// BufferParameters //
|
||||
// //
|
||||
// Vulkan Buffer's parameters container class //
|
||||
// ************************************************************ //
|
||||
struct BufferParameters {
|
||||
VkBuffer Handle;
|
||||
VkDeviceMemory Memory;
|
||||
uint32_t Size;
|
||||
|
||||
BufferParameters() :
|
||||
Handle( VK_NULL_HANDLE ),
|
||||
Memory( VK_NULL_HANDLE ),
|
||||
Size( 0 ) {
|
||||
}
|
||||
};
|
||||
|
||||
// ************************************************************ //
|
||||
// VertexData //
|
||||
// //
|
||||
// Struct describing data type and format of vertex attributes //
|
||||
// ************************************************************ //
|
||||
struct VertexData {
|
||||
float x, y, z, w;
|
||||
float r, g, b, a;
|
||||
};
|
||||
|
||||
// ************************************************************ //
|
||||
// RenderingResourcesData //
|
||||
// //
|
||||
// Struct containing data used during rendering process //
|
||||
// ************************************************************ //
|
||||
struct RenderingResourcesData {
|
||||
VkFramebuffer Framebuffer;
|
||||
VkCommandBuffer CommandBuffer;
|
||||
VkSemaphore ImageAvailableSemaphore;
|
||||
VkSemaphore FinishedRenderingSemaphore;
|
||||
VkFence Fence;
|
||||
|
||||
RenderingResourcesData() :
|
||||
Framebuffer( VK_NULL_HANDLE ),
|
||||
CommandBuffer( VK_NULL_HANDLE ),
|
||||
ImageAvailableSemaphore( VK_NULL_HANDLE ),
|
||||
FinishedRenderingSemaphore( VK_NULL_HANDLE ),
|
||||
Fence( VK_NULL_HANDLE ) {
|
||||
}
|
||||
};
|
||||
|
||||
// ************************************************************ //
|
||||
// VulkanTutorial04Parameters //
|
||||
// //
|
||||
// Vulkan specific parameters //
|
||||
// ************************************************************ //
|
||||
struct VulkanTutorial05Parameters {
|
||||
VkRenderPass RenderPass;
|
||||
VkPipeline GraphicsPipeline;
|
||||
BufferParameters VertexBuffer;
|
||||
BufferParameters StagingBuffer;
|
||||
VkCommandPool CommandPool;
|
||||
std::vector<RenderingResourcesData> RenderingResources;
|
||||
|
||||
static const size_t ResourcesCount = 3;
|
||||
|
||||
VulkanTutorial05Parameters() :
|
||||
RenderPass( VK_NULL_HANDLE ),
|
||||
GraphicsPipeline( VK_NULL_HANDLE ),
|
||||
VertexBuffer(),
|
||||
CommandPool( VK_NULL_HANDLE ),
|
||||
RenderingResources( ResourcesCount ) {
|
||||
}
|
||||
};
|
||||
|
||||
// ************************************************************ //
|
||||
// Tutorial04 //
|
||||
// //
|
||||
// Class for presenting Vulkan usage topics //
|
||||
// ************************************************************ //
|
||||
class Tutorial05 : public VulkanCommon {
|
||||
public:
|
||||
Tutorial05();
|
||||
~Tutorial05();
|
||||
|
||||
bool CreateRenderPass();
|
||||
bool CreatePipeline();
|
||||
bool CreateRenderingResources();
|
||||
bool CreateVertexBuffer();
|
||||
bool CreateStagingBuffer();
|
||||
bool CopyVertexData();
|
||||
|
||||
bool Draw() override;
|
||||
|
||||
private:
|
||||
VulkanTutorial05Parameters Vulkan;
|
||||
|
||||
Tools::AutoDeleter<VkShaderModule, PFN_vkDestroyShaderModule> CreateShaderModule( const char* filename );
|
||||
Tools::AutoDeleter<VkPipelineLayout, PFN_vkDestroyPipelineLayout> CreatePipelineLayout();
|
||||
bool CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool );
|
||||
bool AllocateCommandBuffers( VkCommandPool pool, uint32_t count, VkCommandBuffer *command_buffers );
|
||||
bool CreateCommandBuffers();
|
||||
bool CreateSemaphores();
|
||||
bool CreateFences();
|
||||
bool CreateBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlagBits memoryProperty, BufferParameters &buffer );
|
||||
bool AllocateBufferMemory( VkBuffer buffer, VkMemoryPropertyFlagBits property, VkDeviceMemory *memory );
|
||||
const std::vector<float>& GetVertexData() const;
|
||||
bool PrepareFrame( VkCommandBuffer command_buffer, const ImageParameters &image_parameters, VkFramebuffer &framebuffer );
|
||||
bool CreateFramebuffer( VkFramebuffer &framebuffer, VkImageView image_view );
|
||||
void DestroyBuffer( BufferParameters& buffer );
|
||||
|
||||
void ChildClear() override;
|
||||
bool ChildOnWindowSizeChanged() override;
|
||||
};
|
||||
|
||||
} // namespace ApiWithoutSecrets
|
||||
|
||||
#endif // TUTORIAL_03_HEADER
|
||||
53
Project/Tutorial05/main.cpp
Normal file
53
Project/Tutorial05/main.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright 2016 Intel Corporation All Rights Reserved
|
||||
//
|
||||
// Intel makes no representations about the suitability of this software for any purpose.
|
||||
// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
|
||||
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES,
|
||||
// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY
|
||||
// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// Intel does not assume any responsibility for any errors which may appear in this software
|
||||
// nor any responsibility to update it.
|
||||
|
||||
#include "Tutorial05.h"
|
||||
|
||||
int main( int argc, char **argv ) {
|
||||
ApiWithoutSecrets::OS::Window window;
|
||||
ApiWithoutSecrets::Tutorial05 tutorial05;
|
||||
|
||||
// Window creation
|
||||
if( !window.Create( "05 - Staging Resources" ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Vulkan preparations and initialization
|
||||
if( !tutorial05.PrepareVulkan( window.GetParameters() ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Tutorial 04
|
||||
if( !tutorial05.CreateRenderPass() ) {
|
||||
return -1;
|
||||
}
|
||||
if( !tutorial05.CreatePipeline() ) {
|
||||
return -1;
|
||||
}
|
||||
if( !tutorial05.CreateRenderingResources() ) {
|
||||
return -1;
|
||||
}
|
||||
if( !tutorial05.CreateVertexBuffer() ) {
|
||||
return -1;
|
||||
}
|
||||
if( !tutorial05.CreateStagingBuffer() ) {
|
||||
return -1;
|
||||
}
|
||||
if( !tutorial05.CopyVertexData() ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Rendering loop
|
||||
if( !window.RenderingLoop( tutorial05 ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -49,3 +49,12 @@ Here I present render pass, framebuffer and pipeline objects which are necessary
|
||||
#### Buffers, images and fences
|
||||
|
||||
This tutorial shows how to set up vertex attributes and bind buffer with vertex data. Here we also create images, memory objects and fences.
|
||||
|
||||
<hr>
|
||||
|
||||
### [05 - Staging Resources](./Project/Tutorial05/)
|
||||
<img src="./Document/Images/05 - Staging Resources.png" height="96px" align="right">
|
||||
|
||||
#### Copying data between buffers
|
||||
|
||||
In this example staging resources are presented. They are used as an intermediate resources for copying data between CPU and GPU. This way, resources involved in rendering can be bound only to a device local (very fast) memory.
|
||||
Reference in New Issue
Block a user