├── 01_ClearScreen ├── 01_ClearScreen.sln ├── 01_ClearScreen.vcxproj ├── 01_ClearScreen.vcxproj.filters ├── main.cpp └── packages.config ├── 02_SimpleTriangle ├── 02_SimpleTriangle.sln ├── 02_SimpleTriangle.vcxproj ├── 02_SimpleTriangle.vcxproj.filters ├── TriangleApp.cpp ├── TriangleApp.h ├── main.cpp ├── packages.config ├── shader.frag ├── shader.frag.spv ├── shader.vert └── shader.vert.spv ├── 03_TexturedCube ├── 03_TexturedCube.sln ├── 03_TexturedCube.vcxproj ├── 03_TexturedCube.vcxproj.filters ├── CubeApp.cpp ├── CubeApp.h ├── main.cpp ├── packages.config ├── shader.frag ├── shader.frag.spv ├── shader.vert ├── shader.vert.spv └── texture.tga ├── 04_DrawModel ├── 04_DrawModel.sln ├── 04_DrawModel.vcxproj ├── 04_DrawModel.vcxproj.filters ├── ModelApp.cpp ├── ModelApp.h ├── alicia-solid.vrm ├── main.cpp ├── packages.config ├── shader.vert ├── shader.vert.spv ├── shaderAlpha.frag ├── shaderAlpha.frag.spv ├── shaderOpaque.frag ├── shaderOpaque.frag.spv └── streamreader.h ├── Readme.md └── common ├── stb_image.h ├── vkappbase.cpp └── vkappbase.h /01_ClearScreen/01_ClearScreen.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.271 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "01_ClearScreen", "01_ClearScreen.vcxproj", "{6852E8F2-BF37-4491-9B52-EFEF7C099A14}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {6852E8F2-BF37-4491-9B52-EFEF7C099A14}.Debug|x64.ActiveCfg = Debug|x64 17 | {6852E8F2-BF37-4491-9B52-EFEF7C099A14}.Debug|x64.Build.0 = Debug|x64 18 | {6852E8F2-BF37-4491-9B52-EFEF7C099A14}.Debug|x86.ActiveCfg = Debug|Win32 19 | {6852E8F2-BF37-4491-9B52-EFEF7C099A14}.Debug|x86.Build.0 = Debug|Win32 20 | {6852E8F2-BF37-4491-9B52-EFEF7C099A14}.Release|x64.ActiveCfg = Release|x64 21 | {6852E8F2-BF37-4491-9B52-EFEF7C099A14}.Release|x64.Build.0 = Release|x64 22 | {6852E8F2-BF37-4491-9B52-EFEF7C099A14}.Release|x86.ActiveCfg = Release|Win32 23 | {6852E8F2-BF37-4491-9B52-EFEF7C099A14}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {5878C61B-5731-477B-8FDA-6B76296BE24D} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /01_ClearScreen/01_ClearScreen.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {6852E8F2-BF37-4491-9B52-EFEF7C099A14} 24 | Win32Proj 25 | My01ClearScreen 26 | 10.0.18362.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | Disabled 89 | true 90 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 91 | true 92 | $(VK_SDK_PATH)\include;$(ProjectDir) 93 | 94 | 95 | true 96 | Windows 97 | $(VK_SDK_PATH)\Lib32 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | true 105 | _DEBUG;_WINDOWS;%(PreprocessorDefinitions) 106 | true 107 | $(VK_SDK_PATH)\include;$(ProjectDir) 108 | 109 | 110 | true 111 | Windows 112 | $(VK_SDK_PATH)\Lib 113 | 114 | 115 | 116 | 117 | Level3 118 | MaxSpeed 119 | true 120 | true 121 | true 122 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 123 | true 124 | $(VK_SDK_PATH)\include;$(ProjectDir) 125 | 126 | 127 | true 128 | true 129 | true 130 | Windows 131 | $(VK_SDK_PATH)\Lib32 132 | 133 | 134 | 135 | 136 | Level3 137 | MaxSpeed 138 | true 139 | true 140 | true 141 | NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 142 | true 143 | $(VK_SDK_PATH)\include;$(ProjectDir) 144 | 145 | 146 | true 147 | true 148 | true 149 | Windows 150 | $(VK_SDK_PATH)\Lib 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | このプロジェクトは、このコンピューター上にない NuGet パッケージを参照しています。それらのパッケージをダウンロードするには、[NuGet パッケージの復元] を使用します。詳細については、http://go.microsoft.com/fwlink/?LinkID=322105 を参照してください。見つからないファイルは {0} です。 171 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /01_ClearScreen/01_ClearScreen.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ソース ファイル 23 | 24 | 25 | ソース ファイル 26 | 27 | 28 | 29 | 30 | ヘッダー ファイル 31 | 32 | 33 | -------------------------------------------------------------------------------- /01_ClearScreen/main.cpp: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../common/vkappbase.h" 11 | 12 | #pragma comment(lib, "vulkan-1.lib") 13 | 14 | const int WindowWidth = 640, WindowHeight = 480; 15 | const char* AppTitle = "ClearScreen"; 16 | 17 | int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 18 | { 19 | UNREFERENCED_PARAMETER(hPrevInstance); 20 | UNREFERENCED_PARAMETER(lpCmdLine); 21 | glfwInit(); 22 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 23 | glfwWindowHint(GLFW_RESIZABLE, 0); 24 | auto window = glfwCreateWindow(WindowWidth, WindowHeight, AppTitle, nullptr, nullptr); 25 | 26 | // Vulkan 初期化 27 | VulkanAppBase theApp; 28 | theApp.initialize(window, AppTitle); 29 | 30 | while (glfwWindowShouldClose(window) == GLFW_FALSE) 31 | { 32 | glfwPollEvents(); 33 | theApp.render(); 34 | } 35 | 36 | // Vulkan 終了 37 | theApp.terminate(); 38 | glfwTerminate(); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /01_ClearScreen/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /02_SimpleTriangle/02_SimpleTriangle.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.271 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "02_SimpleTriangle", "02_SimpleTriangle.vcxproj", "{090BCD2C-CB5A-4984-B51F-C72041384E42}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {090BCD2C-CB5A-4984-B51F-C72041384E42}.Debug|x64.ActiveCfg = Debug|x64 17 | {090BCD2C-CB5A-4984-B51F-C72041384E42}.Debug|x64.Build.0 = Debug|x64 18 | {090BCD2C-CB5A-4984-B51F-C72041384E42}.Debug|x86.ActiveCfg = Debug|Win32 19 | {090BCD2C-CB5A-4984-B51F-C72041384E42}.Debug|x86.Build.0 = Debug|Win32 20 | {090BCD2C-CB5A-4984-B51F-C72041384E42}.Release|x64.ActiveCfg = Release|x64 21 | {090BCD2C-CB5A-4984-B51F-C72041384E42}.Release|x64.Build.0 = Release|x64 22 | {090BCD2C-CB5A-4984-B51F-C72041384E42}.Release|x86.ActiveCfg = Release|Win32 23 | {090BCD2C-CB5A-4984-B51F-C72041384E42}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {AE5B8885-3A09-43C2-8A2F-2A7E6399B35F} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /02_SimpleTriangle/02_SimpleTriangle.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {090BCD2C-CB5A-4984-B51F-C72041384E42} 24 | Win32Proj 25 | My02SimpleTriangle 26 | 10.0.17763.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | Disabled 89 | true 90 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 91 | true 92 | $(VK_SDK_PATH)\include;$(ProjectDir) 93 | 94 | 95 | true 96 | Windows 97 | $(VK_SDK_PATH)\Lib32 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | true 105 | _DEBUG;_WINDOWS;%(PreprocessorDefinitions) 106 | true 107 | $(VK_SDK_PATH)\include;$(ProjectDir) 108 | 109 | 110 | true 111 | Windows 112 | $(VK_SDK_PATH)\Lib 113 | 114 | 115 | 116 | 117 | Level3 118 | MaxSpeed 119 | true 120 | true 121 | true 122 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 123 | true 124 | $(VK_SDK_PATH)\include;$(ProjectDir) 125 | 126 | 127 | true 128 | true 129 | true 130 | Windows 131 | $(VK_SDK_PATH)\Lib32 132 | 133 | 134 | 135 | 136 | Level3 137 | MaxSpeed 138 | true 139 | true 140 | true 141 | NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 142 | true 143 | $(VK_SDK_PATH)\include;$(ProjectDir) 144 | 145 | 146 | true 147 | true 148 | true 149 | Windows 150 | $(VK_SDK_PATH)\Lib 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | このプロジェクトは、このコンピューター上にない NuGet パッケージを参照しています。それらのパッケージをダウンロードするには、[NuGet パッケージの復元] を使用します。詳細については、http://go.microsoft.com/fwlink/?LinkID=322105 を参照してください。見つからないファイルは {0} です。 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /02_SimpleTriangle/02_SimpleTriangle.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | ソース ファイル 20 | 21 | 22 | ソース ファイル 23 | 24 | 25 | ソース ファイル 26 | 27 | 28 | 29 | 30 | ヘッダー ファイル 31 | 32 | 33 | ヘッダー ファイル 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /02_SimpleTriangle/TriangleApp.cpp: -------------------------------------------------------------------------------- 1 | #include "TriangleApp.h" 2 | 3 | #include 4 | #include 5 | 6 | using namespace glm; 7 | using namespace std; 8 | 9 | void TriangleApp::prepare() 10 | { 11 | const vec3 red(1.0f, 0.0f, 0.0f); 12 | const vec3 green(0.0f, 1.0f, 0.0f); 13 | const vec3 blue(0.0f, 0.0f, 1.0f); 14 | Vertex vertices[] = { 15 | { vec3(-1.0f, 0.0f, 0.0f), red }, 16 | { vec3(+1.0f, 0.0f, 0.0f), blue }, 17 | { vec3(0.0f, 1.0f, 0.0f), green }, 18 | }; 19 | uint32_t indices[] = { 0, 1, 2 }; 20 | 21 | m_vertexBuffer = createBuffer(sizeof(vertices), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 22 | m_indexBuffer = createBuffer(sizeof(indices), VK_BUFFER_USAGE_INDEX_BUFFER_BIT); 23 | 24 | // 頂点データの書き込み 25 | { 26 | void* p; 27 | vkMapMemory(m_device, m_vertexBuffer.memory, 0, VK_WHOLE_SIZE, 0, &p); 28 | memcpy(p, vertices, sizeof(vertices)); 29 | vkUnmapMemory(m_device, m_vertexBuffer.memory); 30 | } 31 | // インデックスデータの書き込み 32 | { 33 | void* p; 34 | vkMapMemory(m_device, m_indexBuffer.memory, 0, VK_WHOLE_SIZE, 0, &p); 35 | memcpy(p, indices, sizeof(indices)); 36 | vkUnmapMemory(m_device, m_indexBuffer.memory); 37 | } 38 | m_indexCount = _countof(indices); 39 | 40 | // 頂点の入力設定 41 | VkVertexInputBindingDescription inputBinding{ 42 | 0, // binding 43 | sizeof(Vertex), // stride 44 | VK_VERTEX_INPUT_RATE_VERTEX // inputRate 45 | }; 46 | array inputAttribs{ 47 | { 48 | { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)}, 49 | { 1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color)}, 50 | } 51 | }; 52 | VkPipelineVertexInputStateCreateInfo vertexInputCI{}; 53 | vertexInputCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 54 | vertexInputCI.vertexBindingDescriptionCount = 1; 55 | vertexInputCI.pVertexBindingDescriptions = &inputBinding; 56 | vertexInputCI.vertexAttributeDescriptionCount = uint32_t(inputAttribs.size()); 57 | vertexInputCI.pVertexAttributeDescriptions = inputAttribs.data(); 58 | 59 | // ブレンディングの設定 60 | const auto colorWriteAll = \ 61 | VK_COLOR_COMPONENT_R_BIT | \ 62 | VK_COLOR_COMPONENT_G_BIT | \ 63 | VK_COLOR_COMPONENT_B_BIT | \ 64 | VK_COLOR_COMPONENT_A_BIT; 65 | VkPipelineColorBlendAttachmentState blendAttachment{}; 66 | blendAttachment.blendEnable = VK_TRUE; 67 | blendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; 68 | blendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; 69 | blendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; 70 | blendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 71 | blendAttachment.colorBlendOp = VK_BLEND_OP_ADD; 72 | blendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; 73 | blendAttachment.colorWriteMask = colorWriteAll; 74 | VkPipelineColorBlendStateCreateInfo cbCI{}; 75 | cbCI.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 76 | cbCI.attachmentCount = 1; 77 | cbCI.pAttachments = &blendAttachment; 78 | 79 | // ビューポートの設定 80 | VkViewport viewport; 81 | { 82 | viewport.x = 0.0f; 83 | viewport.y = float(m_swapchainExtent.height); 84 | viewport.width = float(m_swapchainExtent.width); 85 | viewport.height = -1.0f * float(m_swapchainExtent.height); 86 | viewport.minDepth = 0.0f; 87 | viewport.maxDepth = 1.0f; 88 | } 89 | VkRect2D scissor = { 90 | { 0,0},// offset 91 | m_swapchainExtent 92 | }; 93 | VkPipelineViewportStateCreateInfo viewportCI{}; 94 | viewportCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 95 | viewportCI.viewportCount = 1; 96 | viewportCI.pViewports = &viewport; 97 | viewportCI.scissorCount = 1; 98 | viewportCI.pScissors = &scissor; 99 | 100 | // プリミティブトポロジー設定 101 | VkPipelineInputAssemblyStateCreateInfo inputAssemblyCI{}; 102 | inputAssemblyCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 103 | inputAssemblyCI.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 104 | 105 | 106 | // ラスタライザーステート設定 107 | VkPipelineRasterizationStateCreateInfo rasterizerCI{}; 108 | rasterizerCI.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 109 | rasterizerCI.polygonMode = VK_POLYGON_MODE_FILL; 110 | rasterizerCI.cullMode = VK_CULL_MODE_NONE; 111 | rasterizerCI.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; 112 | rasterizerCI.lineWidth = 1.0f; 113 | 114 | // マルチサンプル設定 115 | VkPipelineMultisampleStateCreateInfo multisampleCI{}; 116 | multisampleCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 117 | multisampleCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 118 | 119 | // デプスステンシルステート設定 120 | VkPipelineDepthStencilStateCreateInfo depthStencilCI{}; 121 | depthStencilCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 122 | depthStencilCI.depthTestEnable = VK_TRUE; 123 | depthStencilCI.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; 124 | depthStencilCI.depthWriteEnable = VK_TRUE; 125 | depthStencilCI.stencilTestEnable = VK_FALSE; 126 | 127 | // シェーダーバイナリの読み込み 128 | vector shaderStages 129 | { 130 | loadShaderModule("shader.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), 131 | loadShaderModule("shader.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) 132 | }; 133 | 134 | // パイプラインレイアウト 135 | VkPipelineLayoutCreateInfo pipelineLayoutCI{}; 136 | pipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 137 | vkCreatePipelineLayout(m_device, &pipelineLayoutCI, nullptr, &m_pipelineLayout); 138 | 139 | // パイプラインの構築 140 | VkGraphicsPipelineCreateInfo ci{}; 141 | ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 142 | ci.stageCount = uint32_t(shaderStages.size()); 143 | ci.pStages = shaderStages.data(); 144 | ci.pInputAssemblyState = &inputAssemblyCI; 145 | ci.pVertexInputState = &vertexInputCI; 146 | ci.pRasterizationState = &rasterizerCI; 147 | ci.pDepthStencilState = &depthStencilCI; 148 | ci.pMultisampleState = &multisampleCI; 149 | ci.pViewportState = &viewportCI; 150 | ci.pColorBlendState = &cbCI; 151 | ci.renderPass = m_renderPass; 152 | ci.layout = m_pipelineLayout; 153 | vkCreateGraphicsPipelines(m_device, VK_NULL_HANDLE, 1, &ci, nullptr, &m_pipeline); 154 | 155 | // ShaderModule はもう不要のため破棄 156 | for (const auto& v : shaderStages) 157 | { 158 | vkDestroyShaderModule(m_device, v.module, nullptr); 159 | } 160 | } 161 | void TriangleApp::cleanup() 162 | { 163 | vkDestroyPipelineLayout(m_device, m_pipelineLayout, nullptr); 164 | vkDestroyPipeline(m_device, m_pipeline, nullptr); 165 | 166 | vkFreeMemory(m_device, m_vertexBuffer.memory, nullptr); 167 | vkFreeMemory(m_device, m_indexBuffer.memory, nullptr); 168 | vkDestroyBuffer(m_device, m_vertexBuffer.buffer, nullptr); 169 | vkDestroyBuffer(m_device, m_indexBuffer.buffer, nullptr); 170 | } 171 | 172 | void TriangleApp::makeCommand(VkCommandBuffer command) 173 | { 174 | // 作成したパイプラインをセット 175 | vkCmdBindPipeline(command, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline); 176 | 177 | // 各バッファオブジェクトのセット 178 | VkDeviceSize offset = 0; 179 | vkCmdBindVertexBuffers(command, 0, 1, &m_vertexBuffer.buffer, &offset); 180 | vkCmdBindIndexBuffer(command, m_indexBuffer.buffer, offset, VK_INDEX_TYPE_UINT32); 181 | 182 | // 3角形描画 183 | vkCmdDrawIndexed(command, m_indexCount, 1, 0, 0, 0); 184 | } 185 | 186 | 187 | TriangleApp::BufferObject TriangleApp::createBuffer(uint32_t size, VkBufferUsageFlags usage) 188 | { 189 | BufferObject obj; 190 | VkBufferCreateInfo ci{}; 191 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 192 | ci.usage = usage; 193 | ci.size = size; 194 | auto result = vkCreateBuffer(m_device, &ci, nullptr, &obj.buffer); 195 | checkResult(result); 196 | 197 | // メモリ量の算出 198 | VkMemoryRequirements reqs; 199 | vkGetBufferMemoryRequirements(m_device, obj.buffer, &reqs); 200 | VkMemoryAllocateInfo info{}; 201 | info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 202 | info.allocationSize = reqs.size; 203 | // メモリタイプの判定 204 | auto flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; 205 | info.memoryTypeIndex = getMemoryTypeIndex(reqs.memoryTypeBits, flags); 206 | // メモリの確保 207 | vkAllocateMemory(m_device, &info, nullptr, &obj.memory); 208 | 209 | // メモリのバインド 210 | vkBindBufferMemory(m_device, obj.buffer, obj.memory, 0); 211 | return obj; 212 | } 213 | 214 | VkPipelineShaderStageCreateInfo TriangleApp::loadShaderModule(const char* fileName, VkShaderStageFlagBits stage) 215 | { 216 | ifstream infile(fileName, std::ios::binary); 217 | if (!infile) 218 | { 219 | OutputDebugStringA("file not found.\n"); 220 | DebugBreak(); 221 | } 222 | vector filedata; 223 | filedata.resize(uint32_t(infile.seekg(0, ifstream::end).tellg())); 224 | infile.seekg(0, ifstream::beg).read(filedata.data(), filedata.size()); 225 | 226 | VkShaderModule shaderModule; 227 | VkShaderModuleCreateInfo ci{}; 228 | ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 229 | ci.pCode = reinterpret_cast(filedata.data()); 230 | ci.codeSize = filedata.size(); 231 | vkCreateShaderModule(m_device, &ci, nullptr, &shaderModule); 232 | 233 | VkPipelineShaderStageCreateInfo shaderStageCI{}; 234 | shaderStageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 235 | shaderStageCI.stage = stage; 236 | shaderStageCI.module = shaderModule; 237 | shaderStageCI.pName = "main"; 238 | return shaderStageCI; 239 | } -------------------------------------------------------------------------------- /02_SimpleTriangle/TriangleApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../common/vkappbase.h" 4 | #include "glm/glm.hpp" 5 | 6 | class TriangleApp : public VulkanAppBase 7 | { 8 | public: 9 | TriangleApp() : VulkanAppBase() { } 10 | 11 | virtual void prepare() override; 12 | virtual void cleanup() override; 13 | 14 | virtual void makeCommand(VkCommandBuffer command) override; 15 | 16 | struct Vertex 17 | { 18 | glm::vec3 pos; 19 | glm::vec3 color; 20 | }; 21 | private: 22 | struct BufferObject 23 | { 24 | VkBuffer buffer; 25 | VkDeviceMemory memory; 26 | }; 27 | BufferObject createBuffer(uint32_t size, VkBufferUsageFlags usage); 28 | VkPipelineShaderStageCreateInfo loadShaderModule(const char* fileName, VkShaderStageFlagBits stage); 29 | 30 | 31 | BufferObject m_vertexBuffer; 32 | BufferObject m_indexBuffer; 33 | 34 | VkPipelineLayout m_pipelineLayout; 35 | VkPipeline m_pipeline; 36 | uint32_t m_indexCount; 37 | }; -------------------------------------------------------------------------------- /02_SimpleTriangle/main.cpp: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "TriangleApp.h" 11 | 12 | #pragma comment(lib, "vulkan-1.lib") 13 | 14 | const int WindowWidth = 640, WindowHeight = 480; 15 | const char* AppTitle = "SimpleTriangle"; 16 | 17 | int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 18 | { 19 | UNREFERENCED_PARAMETER(hPrevInstance); 20 | UNREFERENCED_PARAMETER(lpCmdLine); 21 | glfwInit(); 22 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 23 | glfwWindowHint(GLFW_RESIZABLE, 0); 24 | auto window = glfwCreateWindow(WindowWidth, WindowHeight, AppTitle, nullptr, nullptr); 25 | 26 | // Vulkan 初期化 27 | TriangleApp theApp; 28 | theApp.initialize(window, AppTitle); 29 | 30 | while (glfwWindowShouldClose(window) == GLFW_FALSE) 31 | { 32 | glfwPollEvents(); 33 | theApp.render(); 34 | } 35 | 36 | // Vulkan 終了 37 | theApp.terminate(); 38 | glfwTerminate(); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /02_SimpleTriangle/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /02_SimpleTriangle/shader.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location=0) in vec4 inColor; 4 | layout(location=0) out vec4 outColor; 5 | 6 | 7 | void main() 8 | { 9 | outColor = inColor; 10 | } 11 | -------------------------------------------------------------------------------- /02_SimpleTriangle/shader.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techlabxe/vulkan_book_1/c70a1cf609a1f11488d7f770017af4e0cacc9a86/02_SimpleTriangle/shader.frag.spv -------------------------------------------------------------------------------- /02_SimpleTriangle/shader.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location=0) in vec3 inPos; 4 | layout(location=1) in vec3 inColor; 5 | 6 | layout(location=0) out vec4 outColor; 7 | 8 | out gl_PerVertex 9 | { 10 | vec4 gl_Position; 11 | }; 12 | 13 | void main() 14 | { 15 | gl_Position = vec4(inPos, 1.0); 16 | outColor = vec4(inColor, 1.0); 17 | } 18 | -------------------------------------------------------------------------------- /02_SimpleTriangle/shader.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techlabxe/vulkan_book_1/c70a1cf609a1f11488d7f770017af4e0cacc9a86/02_SimpleTriangle/shader.vert.spv -------------------------------------------------------------------------------- /03_TexturedCube/03_TexturedCube.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.271 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "03_TexturedCube", "03_TexturedCube.vcxproj", "{EC138B9D-7CD1-4BA2-81DF-03E5197F5EC2}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {EC138B9D-7CD1-4BA2-81DF-03E5197F5EC2}.Debug|x64.ActiveCfg = Debug|x64 17 | {EC138B9D-7CD1-4BA2-81DF-03E5197F5EC2}.Debug|x64.Build.0 = Debug|x64 18 | {EC138B9D-7CD1-4BA2-81DF-03E5197F5EC2}.Debug|x86.ActiveCfg = Debug|Win32 19 | {EC138B9D-7CD1-4BA2-81DF-03E5197F5EC2}.Debug|x86.Build.0 = Debug|Win32 20 | {EC138B9D-7CD1-4BA2-81DF-03E5197F5EC2}.Release|x64.ActiveCfg = Release|x64 21 | {EC138B9D-7CD1-4BA2-81DF-03E5197F5EC2}.Release|x64.Build.0 = Release|x64 22 | {EC138B9D-7CD1-4BA2-81DF-03E5197F5EC2}.Release|x86.ActiveCfg = Release|Win32 23 | {EC138B9D-7CD1-4BA2-81DF-03E5197F5EC2}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {3CB650CB-2AAA-4B62-9B63-BB57CBC7C585} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /03_TexturedCube/03_TexturedCube.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {EC138B9D-7CD1-4BA2-81DF-03E5197F5EC2} 24 | Win32Proj 25 | My03TexturedCube 26 | 10.0.17763.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | Disabled 89 | true 90 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 91 | true 92 | $(VK_SDK_PATH)\include;$(ProjectDir) 93 | 94 | 95 | true 96 | Windows 97 | $(VK_SDK_PATH)\Lib32 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | true 105 | _DEBUG;_WINDOWS;%(PreprocessorDefinitions) 106 | true 107 | $(VK_SDK_PATH)\include;$(ProjectDir) 108 | 109 | 110 | true 111 | Windows 112 | $(VK_SDK_PATH)\Lib 113 | 114 | 115 | 116 | 117 | Level3 118 | MaxSpeed 119 | true 120 | true 121 | true 122 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 123 | true 124 | $(VK_SDK_PATH)\include;$(ProjectDir) 125 | 126 | 127 | true 128 | true 129 | true 130 | Windows 131 | $(VK_SDK_PATH)\Lib32 132 | 133 | 134 | 135 | 136 | Level3 137 | MaxSpeed 138 | true 139 | true 140 | true 141 | NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 142 | true 143 | $(VK_SDK_PATH)\include;$(ProjectDir) 144 | 145 | 146 | true 147 | true 148 | true 149 | Windows 150 | $(VK_SDK_PATH)\Lib 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | このプロジェクトは、このコンピューター上にない NuGet パッケージを参照しています。それらのパッケージをダウンロードするには、[NuGet パッケージの復元] を使用します。詳細については、http://go.microsoft.com/fwlink/?LinkID=322105 を参照してください。見つからないファイルは {0} です。 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /03_TexturedCube/03_TexturedCube.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | ヘッダー ファイル 20 | 21 | 22 | ヘッダー ファイル 23 | 24 | 25 | 26 | 27 | ソース ファイル 28 | 29 | 30 | ソース ファイル 31 | 32 | 33 | ソース ファイル 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /03_TexturedCube/CubeApp.cpp: -------------------------------------------------------------------------------- 1 | #include "CubeApp.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define STB_IMAGE_IMPLEMENTATION 8 | #include "../common/stb_image.h" 9 | 10 | using namespace glm; 11 | using namespace std; 12 | 13 | void CubeApp::prepare() 14 | { 15 | makeCubeGeometry(); 16 | prepareUniformBuffers(); 17 | prepareDescriptorSetLayout(); 18 | prepareDescriptorPool(); 19 | 20 | m_texture = createTexture("texture.tga"); 21 | 22 | m_sampler = createSampler(); 23 | prepareDescriptorSet(); 24 | 25 | // 頂点の入力設定 26 | VkVertexInputBindingDescription inputBinding{ 27 | 0, // binding 28 | sizeof(CubeVertex), // stride 29 | VK_VERTEX_INPUT_RATE_VERTEX // inputRate 30 | }; 31 | array inputAttribs{ 32 | { 33 | { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(CubeVertex, pos)}, 34 | { 1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(CubeVertex, color)}, 35 | { 2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(CubeVertex, uv)}, 36 | } 37 | }; 38 | VkPipelineVertexInputStateCreateInfo vertexInputCI{}; 39 | vertexInputCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 40 | vertexInputCI.vertexBindingDescriptionCount = 1; 41 | vertexInputCI.pVertexBindingDescriptions = &inputBinding; 42 | vertexInputCI.vertexAttributeDescriptionCount = uint32_t(inputAttribs.size()); 43 | vertexInputCI.pVertexAttributeDescriptions = inputAttribs.data(); 44 | 45 | // ブレンディングの設定 46 | const auto colorWriteAll = \ 47 | VK_COLOR_COMPONENT_R_BIT | \ 48 | VK_COLOR_COMPONENT_G_BIT | \ 49 | VK_COLOR_COMPONENT_B_BIT | \ 50 | VK_COLOR_COMPONENT_A_BIT; 51 | VkPipelineColorBlendAttachmentState blendAttachment{}; 52 | blendAttachment.blendEnable = VK_TRUE; 53 | blendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; 54 | blendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; 55 | blendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; 56 | blendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 57 | blendAttachment.colorBlendOp = VK_BLEND_OP_ADD; 58 | blendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; 59 | blendAttachment.colorWriteMask = colorWriteAll; 60 | VkPipelineColorBlendStateCreateInfo cbCI{}; 61 | cbCI.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 62 | cbCI.attachmentCount = 1; 63 | cbCI.pAttachments = &blendAttachment; 64 | 65 | // ビューポートの設定 66 | VkViewport viewport; 67 | { 68 | viewport.x = 0.0f; 69 | viewport.y = float(m_swapchainExtent.height); 70 | viewport.width = float(m_swapchainExtent.width); 71 | viewport.height = -1.0f * float(m_swapchainExtent.height); 72 | viewport.minDepth = 0.0f; 73 | viewport.maxDepth = 1.0f; 74 | } 75 | VkRect2D scissor = { 76 | { 0,0},// offset 77 | m_swapchainExtent 78 | }; 79 | VkPipelineViewportStateCreateInfo viewportCI{}; 80 | viewportCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 81 | viewportCI.viewportCount = 1; 82 | viewportCI.pViewports = &viewport; 83 | viewportCI.scissorCount = 1; 84 | viewportCI.pScissors = &scissor; 85 | 86 | // プリミティブトポロジー設定 87 | VkPipelineInputAssemblyStateCreateInfo inputAssemblyCI{}; 88 | inputAssemblyCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 89 | inputAssemblyCI.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 90 | 91 | 92 | // ラスタライザーステート設定 93 | VkPipelineRasterizationStateCreateInfo rasterizerCI{}; 94 | rasterizerCI.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 95 | rasterizerCI.polygonMode = VK_POLYGON_MODE_FILL; 96 | rasterizerCI.cullMode = VK_CULL_MODE_NONE; 97 | rasterizerCI.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; 98 | rasterizerCI.lineWidth = 1.0f; 99 | 100 | // マルチサンプル設定 101 | VkPipelineMultisampleStateCreateInfo multisampleCI{}; 102 | multisampleCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 103 | multisampleCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 104 | 105 | // デプスステンシルステート設定 106 | VkPipelineDepthStencilStateCreateInfo depthStencilCI{}; 107 | depthStencilCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 108 | depthStencilCI.depthTestEnable = VK_TRUE; 109 | depthStencilCI.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; 110 | depthStencilCI.depthWriteEnable = VK_TRUE; 111 | depthStencilCI.stencilTestEnable = VK_FALSE; 112 | 113 | // シェーダーバイナリの読み込み 114 | vector shaderStages 115 | { 116 | loadShaderModule("shader.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), 117 | loadShaderModule("shader.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) 118 | }; 119 | 120 | // パイプラインレイアウト 121 | VkPipelineLayoutCreateInfo pipelineLayoutCI{}; 122 | pipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 123 | pipelineLayoutCI.setLayoutCount = 1; 124 | pipelineLayoutCI.pSetLayouts = &m_descriptorSetLayout; 125 | vkCreatePipelineLayout(m_device, &pipelineLayoutCI, nullptr, &m_pipelineLayout); 126 | 127 | // パイプラインの構築 128 | VkGraphicsPipelineCreateInfo ci{}; 129 | ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 130 | ci.stageCount = uint32_t(shaderStages.size()); 131 | ci.pStages = shaderStages.data(); 132 | ci.pInputAssemblyState = &inputAssemblyCI; 133 | ci.pVertexInputState = &vertexInputCI; 134 | ci.pRasterizationState = &rasterizerCI; 135 | ci.pDepthStencilState = &depthStencilCI; 136 | ci.pMultisampleState = &multisampleCI; 137 | ci.pViewportState = &viewportCI; 138 | ci.pColorBlendState = &cbCI; 139 | ci.renderPass = m_renderPass; 140 | ci.layout = m_pipelineLayout; 141 | vkCreateGraphicsPipelines(m_device, VK_NULL_HANDLE, 1, &ci, nullptr, &m_pipeline); 142 | 143 | // ShaderModule はもう不要のため破棄 144 | for (const auto& v : shaderStages) 145 | { 146 | vkDestroyShaderModule(m_device, v.module, nullptr); 147 | } 148 | } 149 | void CubeApp::cleanup() 150 | { 151 | for (auto& v : m_uniformBuffers) 152 | { 153 | vkDestroyBuffer(m_device, v.buffer, nullptr); 154 | vkFreeMemory(m_device, v.memory, nullptr); 155 | } 156 | vkDestroySampler(m_device, m_sampler, nullptr); 157 | vkDestroyImage(m_device, m_texture.image, nullptr); 158 | vkDestroyImageView(m_device, m_texture.view, nullptr); 159 | vkFreeMemory(m_device, m_texture.memory, nullptr); 160 | 161 | vkDestroyPipelineLayout(m_device, m_pipelineLayout, nullptr); 162 | vkDestroyPipeline(m_device, m_pipeline, nullptr); 163 | 164 | vkFreeMemory(m_device, m_vertexBuffer.memory, nullptr); 165 | vkFreeMemory(m_device, m_indexBuffer.memory, nullptr); 166 | vkDestroyBuffer(m_device, m_vertexBuffer.buffer, nullptr); 167 | vkDestroyBuffer(m_device, m_indexBuffer.buffer, nullptr); 168 | 169 | vkDestroyDescriptorPool(m_device, m_descriptorPool, nullptr); 170 | vkDestroyDescriptorSetLayout(m_device, m_descriptorSetLayout, nullptr); 171 | } 172 | 173 | void CubeApp::makeCommand(VkCommandBuffer command) 174 | { 175 | // ユニフォームバッファの中身を更新する. 176 | ShaderParameters shaderParam{}; 177 | shaderParam.mtxWorld = glm::rotate(glm::identity(), glm::radians(45.0f), glm::vec3(0, 1, 0)); 178 | shaderParam.mtxView = lookAtRH(vec3(0.0f, 3.0f, 5.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); 179 | shaderParam.mtxProj = perspective(glm::radians(60.0f), 640.0f / 480, 0.01f, 100.0f); 180 | { 181 | auto memory = m_uniformBuffers[m_imageIndex].memory; 182 | void* p; 183 | vkMapMemory(m_device, memory, 0, VK_WHOLE_SIZE, 0, &p); 184 | memcpy(p, &shaderParam, sizeof(shaderParam)); 185 | vkUnmapMemory(m_device, memory); 186 | } 187 | 188 | // 作成したパイプラインをセット 189 | vkCmdBindPipeline(command, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline); 190 | 191 | // 各バッファオブジェクトのセット 192 | VkDeviceSize offset = 0; 193 | vkCmdBindVertexBuffers(command, 0, 1, &m_vertexBuffer.buffer, &offset); 194 | vkCmdBindIndexBuffer(command, m_indexBuffer.buffer, offset, VK_INDEX_TYPE_UINT32); 195 | 196 | // ディスクリプタセットをセット 197 | VkDescriptorSet descriptorSets[] = { 198 | m_descriptorSet[m_imageIndex] 199 | }; 200 | vkCmdBindDescriptorSets(command, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, descriptorSets, 0, nullptr); 201 | 202 | // 3角形描画 203 | vkCmdDrawIndexed(command, m_indexCount, 1, 0, 0, 0); 204 | } 205 | 206 | 207 | void CubeApp::makeCubeGeometry() 208 | { 209 | const float k = 1.0f; 210 | const vec3 red(1.0f, 0.0f, 0.0f); 211 | const vec3 green(0.0f, 1.0f, 0.0f); 212 | const vec3 blue(0.0f, 0.0f, 1.0f); 213 | const vec3 white(1.0f); 214 | const vec3 black(0.0f); 215 | const vec3 yellow(1.0f, 1.0f, 0.0f); 216 | const vec3 magenta(1.0f, 0.0f, 1.0f); 217 | const vec3 cyan(0.0f, 1.0f, 1.0f); 218 | 219 | const vec2 lb(0.0f, 0.0f); 220 | const vec2 lt(0.0f, 1.0f); 221 | const vec2 rb(1.0f, 0.0f); 222 | const vec2 rt(1.0f, 1.0f); 223 | CubeVertex vertices[] = { 224 | // front 225 | // 正面. 226 | { vec3(-k, k, k), yellow, lb }, 227 | { vec3(-k,-k, k), red, lt }, 228 | { vec3(k, k, k), white, rb }, 229 | { vec3(k,-k, k), magenta, rt }, 230 | // 右. 231 | { vec3(k, k, k), white, lb }, 232 | { vec3(k,-k, k), magenta, lt }, 233 | { vec3(k, k,-k), cyan, rb }, 234 | { vec3(k,-k,-k), blue, rt }, 235 | // 左 236 | { vec3(-k, k,-k), green, lb }, 237 | { vec3(-k,-k,-k), black, lt }, 238 | { vec3(-k, k, k), yellow, rb }, 239 | { vec3(-k,-k, k), red, rt }, 240 | // 裏. 241 | { vec3(k, k,-k), cyan, lb }, 242 | { vec3(k,-k,-k), blue, lt }, 243 | { vec3(-k, k,-k), green, rb }, 244 | { vec3(-k,-k,-k), black, rt }, 245 | // 上. 246 | { vec3(-k, k,-k), green, lb }, 247 | { vec3(-k, k, k), yellow, lt }, 248 | { vec3(k, k,-k), cyan, rb }, 249 | { vec3(k, k, k), white, rt }, 250 | // 底. 251 | { vec3(-k,-k, k), red, lb }, 252 | { vec3(-k,-k,-k), black, lt }, 253 | { vec3(k,-k, k), magenta, rb }, 254 | { vec3(k,-k,-k), blue, rt }, 255 | }; 256 | uint32_t indices[] = { 257 | 0, 2, 1, 1, 2, 3, // front 258 | 4, 6, 5, 5, 6, 7, // right 259 | 8,10, 9, 9,10,11, // left 260 | 261 | 12, 14, 13, 13, 14, 15, // back 262 | 16, 18, 17, 17, 18, 19, // top 263 | 20, 22, 21, 21, 22, 23, // bottom 264 | }; 265 | 266 | 267 | m_vertexBuffer = createBuffer(sizeof(vertices), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 268 | m_indexBuffer = createBuffer(sizeof(indices), VK_BUFFER_USAGE_INDEX_BUFFER_BIT); 269 | 270 | // 頂点データの書き込み 271 | { 272 | void* p; 273 | vkMapMemory(m_device, m_vertexBuffer.memory, 0, VK_WHOLE_SIZE, 0, &p); 274 | memcpy(p, vertices, sizeof(vertices)); 275 | vkUnmapMemory(m_device, m_vertexBuffer.memory); 276 | } 277 | // インデックスデータの書き込み 278 | { 279 | void* p; 280 | vkMapMemory(m_device, m_indexBuffer.memory, 0, VK_WHOLE_SIZE, 0, &p); 281 | memcpy(p, indices, sizeof(indices)); 282 | vkUnmapMemory(m_device, m_indexBuffer.memory); 283 | } 284 | m_indexCount = _countof(indices); 285 | } 286 | 287 | void CubeApp::prepareUniformBuffers() 288 | { 289 | m_uniformBuffers.resize(m_swapchainViews.size()); 290 | for (auto& v : m_uniformBuffers) 291 | { 292 | VkMemoryPropertyFlags uboFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; 293 | v = createBuffer(sizeof(ShaderParameters), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, uboFlags ); 294 | } 295 | } 296 | void CubeApp::prepareDescriptorSetLayout() 297 | { 298 | vector bindings; 299 | VkDescriptorSetLayoutBinding bindingUBO{}, bindingTex{}; 300 | bindingUBO.binding = 0; 301 | bindingUBO.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 302 | bindingUBO.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; 303 | bindingUBO.descriptorCount = 1; 304 | bindings.push_back(bindingUBO); 305 | 306 | bindingTex.binding = 1; 307 | bindingTex.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 308 | bindingTex.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; 309 | bindingTex.descriptorCount = 1; 310 | bindings.push_back(bindingTex); 311 | 312 | VkDescriptorSetLayoutCreateInfo ci{}; 313 | ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 314 | ci.bindingCount = uint32_t(bindings.size()); 315 | ci.pBindings = bindings.data(); 316 | vkCreateDescriptorSetLayout(m_device, &ci, nullptr, &m_descriptorSetLayout); 317 | } 318 | 319 | void CubeApp::prepareDescriptorPool() 320 | { 321 | array descPoolSize; 322 | descPoolSize[0].descriptorCount = uint32_t(m_uniformBuffers.size()); 323 | descPoolSize[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 324 | descPoolSize[1].descriptorCount = uint32_t(m_uniformBuffers.size()); 325 | descPoolSize[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 326 | 327 | VkDescriptorPoolCreateInfo ci{}; 328 | ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 329 | ci.maxSets = uint32_t(m_uniformBuffers.size()); 330 | ci.poolSizeCount = uint32_t(descPoolSize.size()); 331 | ci.pPoolSizes = descPoolSize.data(); 332 | vkCreateDescriptorPool(m_device, &ci, nullptr, &m_descriptorPool); 333 | } 334 | 335 | void CubeApp::prepareDescriptorSet() 336 | { 337 | vector layouts; 338 | for (int i = 0; i writeSets = { 380 | ubo, tex 381 | }; 382 | vkUpdateDescriptorSets(m_device, uint32_t(writeSets.size()), writeSets.data(), 0, nullptr); 383 | } 384 | } 385 | 386 | CubeApp::BufferObject CubeApp::createBuffer(uint32_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlags flags) 387 | { 388 | BufferObject obj; 389 | VkBufferCreateInfo ci{}; 390 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 391 | ci.usage = usage; 392 | ci.size = size; 393 | auto result = vkCreateBuffer(m_device, &ci, nullptr, &obj.buffer); 394 | checkResult(result); 395 | 396 | // メモリ量の算出 397 | VkMemoryRequirements reqs; 398 | vkGetBufferMemoryRequirements(m_device, obj.buffer, &reqs); 399 | VkMemoryAllocateInfo info{}; 400 | info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 401 | info.allocationSize = reqs.size; 402 | // メモリタイプの判定 403 | info.memoryTypeIndex = getMemoryTypeIndex(reqs.memoryTypeBits, flags); 404 | // メモリの確保 405 | vkAllocateMemory(m_device, &info, nullptr, &obj.memory); 406 | 407 | // メモリのバインド 408 | vkBindBufferMemory(m_device, obj.buffer, obj.memory, 0); 409 | return obj; 410 | } 411 | 412 | VkPipelineShaderStageCreateInfo CubeApp::loadShaderModule(const char* fileName, VkShaderStageFlagBits stage) 413 | { 414 | ifstream infile(fileName, std::ios::binary); 415 | if (!infile) 416 | { 417 | OutputDebugStringA("file not found.\n"); 418 | DebugBreak(); 419 | } 420 | vector filedata; 421 | filedata.resize(uint32_t(infile.seekg(0, ifstream::end).tellg())); 422 | infile.seekg(0, ifstream::beg).read(filedata.data(), filedata.size()); 423 | 424 | VkShaderModule shaderModule; 425 | VkShaderModuleCreateInfo ci{}; 426 | ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 427 | ci.pCode = reinterpret_cast(filedata.data()); 428 | ci.codeSize = filedata.size(); 429 | vkCreateShaderModule(m_device, &ci, nullptr, &shaderModule); 430 | 431 | VkPipelineShaderStageCreateInfo shaderStageCI{}; 432 | shaderStageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 433 | shaderStageCI.stage = stage; 434 | shaderStageCI.module = shaderModule; 435 | shaderStageCI.pName = "main"; 436 | return shaderStageCI; 437 | } 438 | 439 | VkSampler CubeApp::createSampler() 440 | { 441 | VkSampler sampler; 442 | VkSamplerCreateInfo ci{}; 443 | ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 444 | ci.minFilter = VK_FILTER_LINEAR; 445 | ci.magFilter = VK_FILTER_LINEAR; 446 | ci.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; 447 | ci.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; 448 | ci.maxAnisotropy = 1.0f; 449 | ci.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; 450 | vkCreateSampler(m_device, &ci, nullptr, &sampler); 451 | return sampler; 452 | } 453 | 454 | CubeApp::TextureObject CubeApp::createTexture(const char* fileName) 455 | { 456 | BufferObject stagingBuffer; 457 | TextureObject texture{}; 458 | int width, height, channels; 459 | auto* pImage = stbi_load(fileName, &width, &height, &channels, 0); 460 | auto format = VK_FORMAT_R8G8B8A8_UNORM; 461 | 462 | { 463 | // テクスチャのVkImage を生成 464 | VkImageCreateInfo ci{}; 465 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 466 | ci.extent = { uint32_t(width), uint32_t(height), 1 }; 467 | ci.format = format; 468 | ci.imageType = VK_IMAGE_TYPE_2D; 469 | ci.arrayLayers = 1; 470 | ci.mipLevels = 1; 471 | ci.samples = VK_SAMPLE_COUNT_1_BIT; 472 | ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; 473 | vkCreateImage(m_device, &ci, nullptr, &texture.image); 474 | 475 | // メモリ量の算出 476 | VkMemoryRequirements reqs; 477 | vkGetImageMemoryRequirements(m_device, texture.image, &reqs); 478 | VkMemoryAllocateInfo info{}; 479 | info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 480 | info.allocationSize = reqs.size; 481 | // メモリタイプの判定 482 | info.memoryTypeIndex = getMemoryTypeIndex(reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 483 | // メモリの確保 484 | vkAllocateMemory(m_device, &info, nullptr, &texture.memory); 485 | // メモリのバインド 486 | vkBindImageMemory(m_device, texture.image, texture.memory, 0); 487 | } 488 | 489 | { 490 | uint32_t imageSize = width * height * sizeof(uint32_t); 491 | // ステージングバッファを用意. 492 | stagingBuffer = createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); 493 | void* p; 494 | vkMapMemory(m_device, stagingBuffer.memory, 0, VK_WHOLE_SIZE, 0, &p); 495 | memcpy(p, pImage, imageSize); 496 | vkUnmapMemory(m_device, stagingBuffer.memory); 497 | } 498 | 499 | VkBufferImageCopy copyRegion{}; 500 | copyRegion.imageExtent = { uint32_t(width), uint32_t(height), 1 }; 501 | copyRegion.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 502 | VkCommandBuffer command; 503 | { 504 | VkCommandBufferAllocateInfo ai{}; 505 | ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 506 | ai.commandBufferCount = 1; 507 | ai.commandPool = m_commandPool; 508 | ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 509 | vkAllocateCommandBuffers(m_device, &ai, &command); 510 | } 511 | 512 | VkCommandBufferBeginInfo commandBI{}; 513 | commandBI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 514 | vkBeginCommandBuffer(command, &commandBI); 515 | setImageMemoryBarrier(command, texture.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); 516 | vkCmdCopyBufferToImage(command, stagingBuffer.buffer, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); 517 | 518 | setImageMemoryBarrier(command, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 519 | vkEndCommandBuffer(command); 520 | 521 | VkSubmitInfo submitInfo{}; 522 | submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 523 | submitInfo.commandBufferCount = 1; 524 | submitInfo.pCommandBuffers = &command; 525 | vkQueueSubmit(m_deviceQueue, 1, &submitInfo, VK_NULL_HANDLE); 526 | { 527 | // テクスチャ参照用のビューを生成 528 | VkImageViewCreateInfo ci{}; 529 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 530 | ci.viewType = VK_IMAGE_VIEW_TYPE_2D; 531 | ci.image = texture.image; 532 | ci.format = format; 533 | ci.components = { 534 | VK_COMPONENT_SWIZZLE_R, 535 | VK_COMPONENT_SWIZZLE_G, 536 | VK_COMPONENT_SWIZZLE_B, 537 | VK_COMPONENT_SWIZZLE_A, 538 | }; 539 | ci.subresourceRange = { 540 | VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,1 541 | }; 542 | vkCreateImageView(m_device, &ci, nullptr, &texture.view); 543 | } 544 | 545 | vkDeviceWaitIdle(m_device); 546 | vkFreeCommandBuffers(m_device, m_commandPool, 1, &command); 547 | 548 | // ステージングバッファ解放. 549 | vkFreeMemory(m_device, stagingBuffer.memory, nullptr); 550 | vkDestroyBuffer(m_device, stagingBuffer.buffer, nullptr); 551 | 552 | stbi_image_free(pImage); 553 | return texture; 554 | } 555 | 556 | void CubeApp::setImageMemoryBarrier( 557 | VkCommandBuffer command, 558 | VkImage image, 559 | VkImageLayout oldLayout, VkImageLayout newLayout) 560 | { 561 | VkImageMemoryBarrier imb{}; 562 | imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 563 | imb.oldLayout = oldLayout; 564 | imb.newLayout = newLayout; 565 | imb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 566 | imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 567 | imb.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; 568 | imb.image = image; 569 | 570 | VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 571 | VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 572 | 573 | switch (oldLayout) 574 | { 575 | case VK_IMAGE_LAYOUT_UNDEFINED: 576 | imb.srcAccessMask = 0; 577 | break; 578 | case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: 579 | imb.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 580 | srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; 581 | break; 582 | } 583 | 584 | switch (newLayout) 585 | { 586 | case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: 587 | imb.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 588 | dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; 589 | break; 590 | case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: 591 | imb.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 592 | dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; 593 | break; 594 | case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: 595 | imb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 596 | dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; 597 | break; 598 | } 599 | 600 | //srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; // パイプライン中でリソースへの書込み最終のステージ. 601 | //dstStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; // パイプライン中で次にリソースに書き込むステージ. 602 | 603 | vkCmdPipelineBarrier( 604 | command, 605 | srcStage, 606 | dstStage, 607 | 0, 608 | 0, // memoryBarrierCount 609 | nullptr, 610 | 0, // bufferMemoryBarrierCount 611 | nullptr, 612 | 1, // imageMemoryBarrierCount 613 | &imb); 614 | } 615 | -------------------------------------------------------------------------------- /03_TexturedCube/CubeApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../common/vkappbase.h" 4 | #include "glm/glm.hpp" 5 | 6 | class CubeApp : public VulkanAppBase 7 | { 8 | public: 9 | CubeApp() : VulkanAppBase() { } 10 | 11 | virtual void prepare() override; 12 | virtual void cleanup() override; 13 | 14 | virtual void makeCommand(VkCommandBuffer command) override; 15 | 16 | struct CubeVertex 17 | { 18 | glm::vec3 pos; 19 | glm::vec3 color; 20 | glm::vec2 uv; 21 | }; 22 | private: 23 | struct BufferObject 24 | { 25 | VkBuffer buffer; 26 | VkDeviceMemory memory; 27 | }; 28 | struct TextureObject 29 | { 30 | VkImage image; 31 | VkDeviceMemory memory; 32 | VkImageView view; 33 | }; 34 | struct ShaderParameters 35 | { 36 | glm::mat4 mtxWorld; 37 | glm::mat4 mtxView; 38 | glm::mat4 mtxProj; 39 | }; 40 | void makeCubeGeometry(); 41 | void prepareUniformBuffers(); 42 | void prepareDescriptorSetLayout(); 43 | void prepareDescriptorPool(); 44 | void prepareDescriptorSet(); 45 | 46 | BufferObject createBuffer(uint32_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); 47 | VkPipelineShaderStageCreateInfo loadShaderModule(const char* fileName, VkShaderStageFlagBits stage); 48 | VkSampler createSampler(); 49 | TextureObject createTexture(const char* fileName); 50 | void setImageMemoryBarrier( VkCommandBuffer command, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout); 51 | 52 | BufferObject m_vertexBuffer; 53 | BufferObject m_indexBuffer; 54 | std::vector m_uniformBuffers; 55 | TextureObject m_texture; 56 | 57 | VkDescriptorSetLayout m_descriptorSetLayout; 58 | VkDescriptorPool m_descriptorPool; 59 | std::vector m_descriptorSet; 60 | 61 | VkSampler m_sampler; 62 | 63 | VkPipelineLayout m_pipelineLayout; 64 | VkPipeline m_pipeline; 65 | uint32_t m_indexCount; 66 | }; -------------------------------------------------------------------------------- /03_TexturedCube/main.cpp: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "CubeApp.h" 11 | 12 | #pragma comment(lib, "vulkan-1.lib") 13 | 14 | const int WindowWidth = 640, WindowHeight = 480; 15 | const char* AppTitle = "TexturedCube"; 16 | 17 | int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 18 | { 19 | UNREFERENCED_PARAMETER(hPrevInstance); 20 | UNREFERENCED_PARAMETER(lpCmdLine); 21 | glfwInit(); 22 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 23 | glfwWindowHint(GLFW_RESIZABLE, 0); 24 | auto window = glfwCreateWindow(WindowWidth, WindowHeight, AppTitle, nullptr, nullptr); 25 | 26 | // Vulkan 初期化 27 | CubeApp theApp; 28 | theApp.initialize(window, AppTitle); 29 | 30 | while (glfwWindowShouldClose(window) == GLFW_FALSE) 31 | { 32 | glfwPollEvents(); 33 | theApp.render(); 34 | } 35 | 36 | // Vulkan 終了 37 | theApp.terminate(); 38 | glfwTerminate(); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /03_TexturedCube/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /03_TexturedCube/shader.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location=0) in vec4 inColor; 4 | layout(location=1) in vec2 inUV; 5 | layout(location=0) out vec4 outColor; 6 | 7 | layout(binding=1) uniform sampler2D diffuseMap; 8 | 9 | void main() 10 | { 11 | outColor = inColor * texture(diffuseMap, inUV); 12 | } 13 | -------------------------------------------------------------------------------- /03_TexturedCube/shader.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techlabxe/vulkan_book_1/c70a1cf609a1f11488d7f770017af4e0cacc9a86/03_TexturedCube/shader.frag.spv -------------------------------------------------------------------------------- /03_TexturedCube/shader.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location=0) in vec3 inPos; 4 | layout(location=1) in vec3 inColor; 5 | layout(location=2) in vec2 inUV; 6 | layout(location=0) out vec4 outColor; 7 | layout(location=1) out vec2 outUV; 8 | 9 | layout(binding=0) uniform Matrices 10 | { 11 | mat4 world; 12 | mat4 view; 13 | mat4 proj; 14 | }; 15 | 16 | out gl_PerVertex 17 | { 18 | vec4 gl_Position; 19 | }; 20 | 21 | void main() 22 | { 23 | mat4 pvw = proj * view * world; 24 | gl_Position = pvw * vec4(inPos, 1.0); 25 | outColor = vec4(inColor, 1.0); 26 | outUV = inUV; 27 | } 28 | -------------------------------------------------------------------------------- /03_TexturedCube/shader.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techlabxe/vulkan_book_1/c70a1cf609a1f11488d7f770017af4e0cacc9a86/03_TexturedCube/shader.vert.spv -------------------------------------------------------------------------------- /03_TexturedCube/texture.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techlabxe/vulkan_book_1/c70a1cf609a1f11488d7f770017af4e0cacc9a86/03_TexturedCube/texture.tga -------------------------------------------------------------------------------- /04_DrawModel/04_DrawModel.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.271 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "04_DrawModel", "04_DrawModel.vcxproj", "{F9FA7C84-5272-4214-A676-45004BF7824A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F9FA7C84-5272-4214-A676-45004BF7824A}.Debug|x64.ActiveCfg = Debug|x64 17 | {F9FA7C84-5272-4214-A676-45004BF7824A}.Debug|x64.Build.0 = Debug|x64 18 | {F9FA7C84-5272-4214-A676-45004BF7824A}.Debug|x86.ActiveCfg = Debug|Win32 19 | {F9FA7C84-5272-4214-A676-45004BF7824A}.Debug|x86.Build.0 = Debug|Win32 20 | {F9FA7C84-5272-4214-A676-45004BF7824A}.Release|x64.ActiveCfg = Release|x64 21 | {F9FA7C84-5272-4214-A676-45004BF7824A}.Release|x64.Build.0 = Release|x64 22 | {F9FA7C84-5272-4214-A676-45004BF7824A}.Release|x86.ActiveCfg = Release|Win32 23 | {F9FA7C84-5272-4214-A676-45004BF7824A}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {FAFD9619-1FCC-44B0-B2C6-65F19BF717BD} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /04_DrawModel/04_DrawModel.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {F9FA7C84-5272-4214-A676-45004BF7824A} 24 | Win32Proj 25 | My04DrawModel 26 | 10.0.17763.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | Disabled 89 | true 90 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 91 | true 92 | $(VK_SDK_PATH)\include;$(ProjectDir) 93 | 94 | 95 | true 96 | Windows 97 | $(VK_SDK_PATH)\Lib32 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | true 105 | _DEBUG;_WINDOWS;%(PreprocessorDefinitions) 106 | true 107 | $(VK_SDK_PATH)\include;$(ProjectDir) 108 | 109 | 110 | true 111 | Windows 112 | $(VK_SDK_PATH)\Lib 113 | 114 | 115 | 116 | 117 | Level3 118 | MaxSpeed 119 | true 120 | true 121 | true 122 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 123 | true 124 | $(VK_SDK_PATH)\include;$(ProjectDir) 125 | 126 | 127 | true 128 | true 129 | true 130 | Windows 131 | $(VK_SDK_PATH)\Lib32 132 | 133 | 134 | 135 | 136 | Level3 137 | MaxSpeed 138 | true 139 | true 140 | true 141 | NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 142 | true 143 | $(VK_SDK_PATH)\include;$(ProjectDir) 144 | 145 | 146 | true 147 | true 148 | true 149 | Windows 150 | $(VK_SDK_PATH)\Lib 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | このプロジェクトは、このコンピューター上にない NuGet パッケージを参照しています。それらのパッケージをダウンロードするには、[NuGet パッケージの復元] を使用します。詳細については、http://go.microsoft.com/fwlink/?LinkID=322105 を参照してください。見つからないファイルは {0} です。 177 | 178 | 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /04_DrawModel/04_DrawModel.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | ソース ファイル 20 | 21 | 22 | ソース ファイル 23 | 24 | 25 | ソース ファイル 26 | 27 | 28 | 29 | 30 | ヘッダー ファイル 31 | 32 | 33 | ヘッダー ファイル 34 | 35 | 36 | ヘッダー ファイル 37 | 38 | 39 | ヘッダー ファイル 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /04_DrawModel/ModelApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ModelApp.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define STB_IMAGE_IMPLEMENTATION 8 | #include "../common/stb_image.h" 9 | 10 | #include "streamreader.h" 11 | 12 | using namespace glm; 13 | using namespace std; 14 | 15 | void ModelApp::prepare() 16 | { 17 | // モデルデータの読み込み 18 | auto modelFilePath = experimental::filesystem::path("alicia-solid.vrm"); 19 | if (modelFilePath.is_relative()) 20 | { 21 | auto current = experimental::filesystem::current_path(); 22 | current /= modelFilePath; 23 | current.swap(modelFilePath); 24 | } 25 | 26 | auto reader = make_unique(modelFilePath.parent_path()); 27 | auto glbStream = reader->GetInputStream(modelFilePath.filename().u8string()); 28 | auto glbResourceReader = make_shared(std::move(reader), std::move(glbStream)); 29 | auto document = Microsoft::glTF::Deserialize(glbResourceReader->GetJson()); 30 | 31 | makeModelGeometry(document, glbResourceReader); 32 | makeModelMaterial(document, glbResourceReader); 33 | 34 | prepareUniformBuffers(); 35 | prepareDescriptorSetLayout(); 36 | prepareDescriptorPool(); 37 | 38 | m_sampler = createSampler(); 39 | prepareDescriptorSet(); 40 | 41 | // 頂点の入力設定 42 | VkVertexInputBindingDescription inputBinding{ 43 | 0, // binding 44 | sizeof(Vertex), // stride 45 | VK_VERTEX_INPUT_RATE_VERTEX // inputRate 46 | }; 47 | array inputAttribs{ 48 | { 49 | { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)}, 50 | { 1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color)}, 51 | { 2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, uv)}, 52 | } 53 | }; 54 | VkPipelineVertexInputStateCreateInfo vertexInputCI{}; 55 | vertexInputCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 56 | vertexInputCI.vertexBindingDescriptionCount = 1; 57 | vertexInputCI.pVertexBindingDescriptions = &inputBinding; 58 | vertexInputCI.vertexAttributeDescriptionCount = uint32_t(inputAttribs.size()); 59 | vertexInputCI.pVertexAttributeDescriptions = inputAttribs.data(); 60 | 61 | 62 | // ビューポートの設定 63 | VkViewport viewport; 64 | { 65 | viewport.x = 0.0f; 66 | viewport.y = float(m_swapchainExtent.height); 67 | viewport.width = float(m_swapchainExtent.width); 68 | viewport.height = -1.0f * float(m_swapchainExtent.height); 69 | viewport.minDepth = 0.0f; 70 | viewport.maxDepth = 1.0f; 71 | } 72 | VkRect2D scissor = { 73 | { 0,0},// offset 74 | m_swapchainExtent 75 | }; 76 | VkPipelineViewportStateCreateInfo viewportCI{}; 77 | viewportCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 78 | viewportCI.viewportCount = 1; 79 | viewportCI.pViewports = &viewport; 80 | viewportCI.scissorCount = 1; 81 | viewportCI.pScissors = &scissor; 82 | 83 | // プリミティブトポロジー設定 84 | VkPipelineInputAssemblyStateCreateInfo inputAssemblyCI{}; 85 | inputAssemblyCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 86 | inputAssemblyCI.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 87 | 88 | 89 | // ラスタライザーステート設定 90 | VkPipelineRasterizationStateCreateInfo rasterizerCI{}; 91 | rasterizerCI.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 92 | rasterizerCI.polygonMode = VK_POLYGON_MODE_FILL; 93 | rasterizerCI.cullMode = VK_CULL_MODE_NONE; 94 | rasterizerCI.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; 95 | rasterizerCI.lineWidth = 1.0f; 96 | 97 | // マルチサンプル設定 98 | VkPipelineMultisampleStateCreateInfo multisampleCI{}; 99 | multisampleCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 100 | multisampleCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 101 | 102 | // パイプラインレイアウト 103 | VkPipelineLayoutCreateInfo pipelineLayoutCI{}; 104 | pipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 105 | pipelineLayoutCI.setLayoutCount = 1; 106 | pipelineLayoutCI.pSetLayouts = &m_descriptorSetLayout; 107 | vkCreatePipelineLayout(m_device, &pipelineLayoutCI, nullptr, &m_pipelineLayout); 108 | 109 | // 不透明用: パイプラインの構築 110 | { 111 | // ブレンディングの設定 112 | const auto colorWriteAll = \ 113 | VK_COLOR_COMPONENT_R_BIT | \ 114 | VK_COLOR_COMPONENT_G_BIT | \ 115 | VK_COLOR_COMPONENT_B_BIT | \ 116 | VK_COLOR_COMPONENT_A_BIT; 117 | VkPipelineColorBlendAttachmentState blendAttachment{}; 118 | blendAttachment.blendEnable = VK_TRUE; 119 | blendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; 120 | blendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; 121 | blendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; 122 | blendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 123 | blendAttachment.colorBlendOp = VK_BLEND_OP_ADD; 124 | blendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; 125 | blendAttachment.colorWriteMask = colorWriteAll; 126 | VkPipelineColorBlendStateCreateInfo cbCI{}; 127 | cbCI.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 128 | cbCI.attachmentCount = 1; 129 | cbCI.pAttachments = &blendAttachment; 130 | 131 | // デプスステンシルステート設定 132 | VkPipelineDepthStencilStateCreateInfo depthStencilCI{}; 133 | depthStencilCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 134 | depthStencilCI.depthTestEnable = VK_TRUE; 135 | depthStencilCI.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; 136 | depthStencilCI.depthWriteEnable = VK_TRUE; 137 | depthStencilCI.stencilTestEnable = VK_FALSE; 138 | 139 | // シェーダーバイナリの読み込み 140 | vector shaderStages 141 | { 142 | loadShaderModule("shader.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), 143 | loadShaderModule("shaderOpaque.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) 144 | }; 145 | // パイプラインの構築 146 | VkGraphicsPipelineCreateInfo ci{}; 147 | ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 148 | ci.stageCount = uint32_t(shaderStages.size()); 149 | ci.pStages = shaderStages.data(); 150 | ci.pInputAssemblyState = &inputAssemblyCI; 151 | ci.pVertexInputState = &vertexInputCI; 152 | ci.pRasterizationState = &rasterizerCI; 153 | ci.pDepthStencilState = &depthStencilCI; 154 | ci.pMultisampleState = &multisampleCI; 155 | ci.pViewportState = &viewportCI; 156 | ci.pColorBlendState = &cbCI; 157 | ci.renderPass = m_renderPass; 158 | ci.layout = m_pipelineLayout; 159 | vkCreateGraphicsPipelines(m_device, VK_NULL_HANDLE, 1, &ci, nullptr, &m_pipelineOpaque); 160 | 161 | // ShaderModule はもう不要のため破棄 162 | for (const auto& v : shaderStages) 163 | { 164 | vkDestroyShaderModule(m_device, v.module, nullptr); 165 | } 166 | } 167 | 168 | // 半透明用: パイプラインの構築 169 | { 170 | // ブレンディングの設定 171 | const auto colorWriteAll = \ 172 | VK_COLOR_COMPONENT_R_BIT | \ 173 | VK_COLOR_COMPONENT_G_BIT | \ 174 | VK_COLOR_COMPONENT_B_BIT | \ 175 | VK_COLOR_COMPONENT_A_BIT; 176 | VkPipelineColorBlendAttachmentState blendAttachment{}; 177 | blendAttachment.blendEnable = VK_TRUE; 178 | blendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; 179 | blendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 180 | blendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; 181 | blendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 182 | blendAttachment.colorBlendOp = VK_BLEND_OP_ADD; 183 | blendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; 184 | blendAttachment.colorWriteMask = colorWriteAll; 185 | VkPipelineColorBlendStateCreateInfo cbCI{}; 186 | cbCI.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 187 | cbCI.attachmentCount = 1; 188 | cbCI.pAttachments = &blendAttachment; 189 | 190 | // デプスステンシルステート設定 191 | VkPipelineDepthStencilStateCreateInfo depthStencilCI{}; 192 | depthStencilCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 193 | depthStencilCI.depthTestEnable = VK_TRUE; 194 | depthStencilCI.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; 195 | depthStencilCI.depthWriteEnable = VK_FALSE; 196 | depthStencilCI.stencilTestEnable = VK_FALSE; 197 | 198 | // シェーダーバイナリの読み込み 199 | vector shaderStages 200 | { 201 | loadShaderModule("shader.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), 202 | loadShaderModule("shaderAlpha.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) 203 | }; 204 | // パイプラインの構築 205 | VkGraphicsPipelineCreateInfo ci{}; 206 | ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 207 | ci.stageCount = uint32_t(shaderStages.size()); 208 | ci.pStages = shaderStages.data(); 209 | ci.pInputAssemblyState = &inputAssemblyCI; 210 | ci.pVertexInputState = &vertexInputCI; 211 | ci.pRasterizationState = &rasterizerCI; 212 | ci.pDepthStencilState = &depthStencilCI; 213 | ci.pMultisampleState = &multisampleCI; 214 | ci.pViewportState = &viewportCI; 215 | ci.pColorBlendState = &cbCI; 216 | ci.renderPass = m_renderPass; 217 | ci.layout = m_pipelineLayout; 218 | vkCreateGraphicsPipelines(m_device, VK_NULL_HANDLE, 1, &ci, nullptr, &m_pipelineAlpha); 219 | 220 | // ShaderModule はもう不要のため破棄 221 | for (const auto& v : shaderStages) 222 | { 223 | vkDestroyShaderModule(m_device, v.module, nullptr); 224 | } 225 | } 226 | } 227 | void ModelApp::cleanup() 228 | { 229 | for (auto& v : m_uniformBuffers) 230 | { 231 | vkDestroyBuffer(m_device, v.buffer, nullptr); 232 | vkFreeMemory(m_device, v.memory, nullptr); 233 | } 234 | vkDestroySampler(m_device, m_sampler, nullptr); 235 | 236 | vkDestroyPipelineLayout(m_device, m_pipelineLayout, nullptr); 237 | vkDestroyPipeline(m_device, m_pipelineOpaque, nullptr); 238 | vkDestroyPipeline(m_device, m_pipelineAlpha, nullptr); 239 | 240 | for (auto& mesh : m_model.meshes) 241 | { 242 | vkFreeMemory(m_device, mesh.vertexBuffer.memory, nullptr); 243 | vkFreeMemory(m_device, mesh.indexBuffer.memory, nullptr); 244 | vkDestroyBuffer(m_device, mesh.vertexBuffer.buffer, nullptr); 245 | vkDestroyBuffer(m_device, mesh.indexBuffer.buffer, nullptr); 246 | uint32_t count = uint32_t(mesh.descriptorSet.size()); 247 | mesh.descriptorSet.clear(); 248 | } 249 | for (auto& material : m_model.materials) 250 | { 251 | vkFreeMemory(m_device, material.texture.memory, nullptr); 252 | vkDestroyImage(m_device, material.texture.image, nullptr); 253 | vkDestroyImageView(m_device, material.texture.view, nullptr); 254 | } 255 | vkDestroyDescriptorPool(m_device, m_descriptorPool, nullptr); 256 | vkDestroyDescriptorSetLayout(m_device, m_descriptorSetLayout, nullptr); 257 | } 258 | 259 | void ModelApp::makeCommand(VkCommandBuffer command) 260 | { 261 | using namespace Microsoft::glTF; 262 | 263 | // ユニフォームバッファの中身を更新する. 264 | ShaderParameters shaderParam{}; 265 | shaderParam.mtxWorld = glm::identity(); 266 | shaderParam.mtxView = lookAtRH(vec3(0.0f, 1.5f, -1.0f), vec3(0.0f, 1.25f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); 267 | shaderParam.mtxProj = perspective(glm::radians(45.0f), 640.0f / 480, 0.01f, 100.0f); 268 | { 269 | auto memory = m_uniformBuffers[m_imageIndex].memory; 270 | void* p; 271 | vkMapMemory(m_device, memory, 0, VK_WHOLE_SIZE, 0, &p); 272 | memcpy(p, &shaderParam, sizeof(shaderParam)); 273 | vkUnmapMemory(m_device, memory); 274 | } 275 | 276 | for (auto mode : { ALPHA_OPAQUE, ALPHA_MASK, ALPHA_BLEND }) 277 | { 278 | for (const auto& mesh : m_model.meshes) 279 | { 280 | // 対応するポリゴンメッシュのみを描画する. 281 | if (m_model.materials[mesh.materialIndex].alphaMode != mode) 282 | { 283 | continue; 284 | } 285 | 286 | // モードに応じて使用するパイプラインを変える. 287 | switch (mode) 288 | { 289 | case ALPHA_OPAQUE: 290 | vkCmdBindPipeline(command, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineOpaque); 291 | break; 292 | case ALPHA_MASK: 293 | vkCmdBindPipeline(command, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineOpaque); 294 | break; 295 | case ALPHA_BLEND: 296 | vkCmdBindPipeline(command, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineAlpha); 297 | break; 298 | } 299 | 300 | // 各バッファオブジェクトのセット 301 | VkDeviceSize offset = 0; 302 | vkCmdBindVertexBuffers(command, 0, 1, &mesh.vertexBuffer.buffer, &offset); 303 | vkCmdBindIndexBuffer(command, mesh.indexBuffer.buffer, offset, VK_INDEX_TYPE_UINT32); 304 | 305 | // ディスクリプタセットをセット 306 | VkDescriptorSet descriptorSets[] = { 307 | mesh.descriptorSet[m_imageIndex] 308 | }; 309 | vkCmdBindDescriptorSets(command, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, descriptorSets, 0, nullptr); 310 | 311 | // このメッシュを描画 312 | vkCmdDrawIndexed(command, mesh.indexCount, 1, 0, 0, 0); 313 | } 314 | } 315 | } 316 | 317 | void ModelApp::makeModelGeometry(const Microsoft::glTF::Document& doc, std::shared_ptr reader ) 318 | { 319 | using namespace Microsoft::glTF; 320 | for (const auto& mesh : doc.meshes.Elements()) 321 | { 322 | for (const auto& meshPrimitive : mesh.primitives) 323 | { 324 | std::vector vertices; 325 | std::vector indices; 326 | 327 | // 頂点位置情報アクセッサの取得 328 | auto& idPos = meshPrimitive.GetAttributeAccessorId(ACCESSOR_POSITION); 329 | auto& accPos = doc.accessors.Get(idPos); 330 | // 法線情報アクセッサの取得 331 | auto& idNrm = meshPrimitive.GetAttributeAccessorId(ACCESSOR_NORMAL); 332 | auto& accNrm = doc.accessors.Get(idNrm); 333 | // テクスチャ座標情報アクセッサの取得 334 | auto& idUV = meshPrimitive.GetAttributeAccessorId(ACCESSOR_TEXCOORD_0); 335 | auto& accUV = doc.accessors.Get(idUV); 336 | // 頂点インデックス用アクセッサの取得 337 | auto& idIndex = meshPrimitive.indicesAccessorId; 338 | auto& accIndex = doc.accessors.Get(idIndex); 339 | 340 | // アクセッサからデータ列を取得 341 | auto vertPos = reader->ReadBinaryData(doc, accPos); 342 | auto vertNrm = reader->ReadBinaryData(doc, accNrm); 343 | auto vertUV = reader->ReadBinaryData(doc, accUV); 344 | 345 | auto vertexCount = accPos.count; 346 | for (uint32_t i = 0; i < vertexCount; ++i) 347 | { 348 | // 頂点データの構築 349 | int vid0 = 3*i, vid1 = 3*i+1, vid2 = 3*i+2; 350 | int tid0 = 2*i, tid1 = 2*i+1; 351 | vertices.emplace_back( 352 | Vertex{ 353 | vec3(vertPos[vid0], vertPos[vid1],vertPos[vid2]), 354 | vec3(vertNrm[vid0], vertNrm[vid1],vertNrm[vid2]), 355 | vec2(vertUV[tid0],vertUV[tid1]) 356 | } 357 | ); 358 | } 359 | // インデックスデータ 360 | indices = reader->ReadBinaryData(doc, accIndex); 361 | 362 | auto vbSize = UINT(sizeof(Vertex)*vertices.size()); 363 | auto ibSize = UINT(sizeof(uint32_t)*indices.size()); 364 | ModelMesh modelMesh; 365 | modelMesh.vertexBuffer = createBuffer(vbSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, vertices.data()); 366 | modelMesh.indexBuffer = createBuffer(ibSize,VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, indices.data()); 367 | modelMesh.vertexCount = UINT(vertices.size()); 368 | modelMesh.indexCount = UINT(indices.size()); 369 | modelMesh.materialIndex = int(doc.materials.GetIndex(meshPrimitive.materialId)); 370 | m_model.meshes.push_back(modelMesh); 371 | } 372 | } 373 | } 374 | void ModelApp::makeModelMaterial(const Microsoft::glTF::Document& doc, std::shared_ptr reader) 375 | { 376 | for (auto& m : doc.materials.Elements()) 377 | { 378 | auto textureId = m.metallicRoughness.baseColorTexture.textureId; 379 | if (textureId.empty()) 380 | { 381 | textureId = m.normalTexture.textureId; 382 | } 383 | auto& texture = doc.textures.Get(textureId); 384 | auto& image = doc.images.Get(texture.imageId); 385 | auto imageBufferView = doc.bufferViews.Get(image.bufferViewId); 386 | auto imageData = reader->ReadBinaryData(doc, imageBufferView); 387 | 388 | // imageData が画像データ. 389 | Material material{}; 390 | material.alphaMode = m.alphaMode; 391 | material.texture = createTextureFromMemory(imageData); 392 | m_model.materials.push_back(material); 393 | } 394 | } 395 | 396 | void ModelApp::prepareUniformBuffers() 397 | { 398 | m_uniformBuffers.resize(m_swapchainViews.size()); 399 | for (auto& v : m_uniformBuffers) 400 | { 401 | VkMemoryPropertyFlags uboFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; 402 | v = createBuffer(sizeof(ShaderParameters), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, uboFlags, nullptr ); 403 | } 404 | } 405 | void ModelApp::prepareDescriptorSetLayout() 406 | { 407 | vector bindings; 408 | VkDescriptorSetLayoutBinding bindingUBO{}, bindingTex{}; 409 | bindingUBO.binding = 0; 410 | bindingUBO.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 411 | bindingUBO.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; 412 | bindingUBO.descriptorCount = 1; 413 | bindings.push_back(bindingUBO); 414 | 415 | bindingTex.binding = 1; 416 | bindingTex.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 417 | bindingTex.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; 418 | bindingTex.descriptorCount = 1; 419 | bindings.push_back(bindingTex); 420 | 421 | VkDescriptorSetLayoutCreateInfo ci{}; 422 | ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 423 | ci.bindingCount = uint32_t(bindings.size()); 424 | ci.pBindings = bindings.data(); 425 | vkCreateDescriptorSetLayout(m_device, &ci, nullptr, &m_descriptorSetLayout); 426 | } 427 | 428 | void ModelApp::prepareDescriptorPool() 429 | { 430 | const uint32_t count = 100; 431 | array descPoolSize; 432 | descPoolSize[0].descriptorCount = count; 433 | descPoolSize[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 434 | descPoolSize[1].descriptorCount = count; 435 | descPoolSize[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 436 | 437 | uint32_t maxDescriptorCount = uint32_t(m_swapchainImages.size() * m_model.meshes.size()); 438 | VkDescriptorPoolCreateInfo ci{}; 439 | ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 440 | ci.maxSets = maxDescriptorCount; 441 | ci.poolSizeCount = uint32_t(descPoolSize.size()); 442 | ci.pPoolSizes = descPoolSize.data(); 443 | vkCreateDescriptorPool(m_device, &ci, nullptr, &m_descriptorPool); 444 | } 445 | 446 | void ModelApp::prepareDescriptorSet() 447 | { 448 | vector layouts; 449 | for (int i = 0; i writeSets = { 496 | ubo, tex 497 | }; 498 | vkUpdateDescriptorSets(m_device, uint32_t(writeSets.size()), writeSets.data(), 0, nullptr); 499 | } 500 | } 501 | } 502 | 503 | ModelApp::BufferObject ModelApp::createBuffer(uint32_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlags flags, const void* initialData) 504 | { 505 | BufferObject obj; 506 | VkBufferCreateInfo ci{}; 507 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 508 | ci.usage = usage; 509 | ci.size = size; 510 | auto result = vkCreateBuffer(m_device, &ci, nullptr, &obj.buffer); 511 | checkResult(result); 512 | 513 | // メモリ量の算出 514 | VkMemoryRequirements reqs; 515 | vkGetBufferMemoryRequirements(m_device, obj.buffer, &reqs); 516 | VkMemoryAllocateInfo info{}; 517 | info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 518 | info.allocationSize = reqs.size; 519 | // メモリタイプの判定 520 | info.memoryTypeIndex = getMemoryTypeIndex(reqs.memoryTypeBits, flags); 521 | // メモリの確保 522 | vkAllocateMemory(m_device, &info, nullptr, &obj.memory); 523 | 524 | // メモリのバインド 525 | vkBindBufferMemory(m_device, obj.buffer, obj.memory, 0); 526 | 527 | if ((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0 && 528 | initialData != nullptr) 529 | { 530 | void* p; 531 | vkMapMemory(m_device, obj.memory, 0, VK_WHOLE_SIZE, 0, &p); 532 | memcpy(p, initialData, size); 533 | vkUnmapMemory(m_device, obj.memory); 534 | } 535 | return obj; 536 | } 537 | 538 | VkPipelineShaderStageCreateInfo ModelApp::loadShaderModule(const char* fileName, VkShaderStageFlagBits stage) 539 | { 540 | ifstream infile(fileName, std::ios::binary); 541 | if (!infile) 542 | { 543 | OutputDebugStringA("file not found.\n"); 544 | DebugBreak(); 545 | } 546 | vector filedata; 547 | filedata.resize(uint32_t(infile.seekg(0, ifstream::end).tellg())); 548 | infile.seekg(0, ifstream::beg).read(filedata.data(), filedata.size()); 549 | 550 | VkShaderModule shaderModule; 551 | VkShaderModuleCreateInfo ci{}; 552 | ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 553 | ci.pCode = reinterpret_cast(filedata.data()); 554 | ci.codeSize = filedata.size(); 555 | vkCreateShaderModule(m_device, &ci, nullptr, &shaderModule); 556 | 557 | VkPipelineShaderStageCreateInfo shaderStageCI{}; 558 | shaderStageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 559 | shaderStageCI.stage = stage; 560 | shaderStageCI.module = shaderModule; 561 | shaderStageCI.pName = "main"; 562 | return shaderStageCI; 563 | } 564 | 565 | VkSampler ModelApp::createSampler() 566 | { 567 | VkSampler sampler; 568 | VkSamplerCreateInfo ci{}; 569 | ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 570 | ci.minFilter = VK_FILTER_LINEAR; 571 | ci.magFilter = VK_FILTER_LINEAR; 572 | ci.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; 573 | ci.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; 574 | ci.maxAnisotropy = 1.0f; 575 | ci.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; 576 | vkCreateSampler(m_device, &ci, nullptr, &sampler); 577 | return sampler; 578 | } 579 | 580 | ModelApp::TextureObject ModelApp::createTextureFromMemory(const std::vector& imageData) 581 | { 582 | BufferObject stagingBuffer; 583 | TextureObject texture{}; 584 | int width, height, channels; 585 | auto* pImage = stbi_load_from_memory( 586 | reinterpret_cast(imageData.data()), 587 | int(imageData.size()), 588 | &width, &height, &channels, 0); 589 | 590 | auto format = VK_FORMAT_R8G8B8A8_UNORM; 591 | 592 | { 593 | // テクスチャのVkImage を生成 594 | VkImageCreateInfo ci{}; 595 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 596 | ci.extent = { uint32_t(width), uint32_t(height), 1 }; 597 | ci.format = format; 598 | ci.imageType = VK_IMAGE_TYPE_2D; 599 | ci.arrayLayers = 1; 600 | ci.mipLevels = 1; 601 | ci.samples = VK_SAMPLE_COUNT_1_BIT; 602 | ci.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; 603 | vkCreateImage(m_device, &ci, nullptr, &texture.image); 604 | 605 | // メモリ量の算出 606 | VkMemoryRequirements reqs; 607 | vkGetImageMemoryRequirements(m_device, texture.image, &reqs); 608 | VkMemoryAllocateInfo info{}; 609 | info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 610 | info.allocationSize = reqs.size; 611 | // メモリタイプの判定 612 | info.memoryTypeIndex = getMemoryTypeIndex(reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 613 | // メモリの確保 614 | vkAllocateMemory(m_device, &info, nullptr, &texture.memory); 615 | // メモリのバインド 616 | vkBindImageMemory(m_device, texture.image, texture.memory, 0); 617 | } 618 | 619 | { 620 | uint32_t imageSize = width * height * sizeof(uint32_t); 621 | // ステージングバッファを用意. 622 | stagingBuffer = createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, pImage); 623 | } 624 | 625 | VkBufferImageCopy copyRegion{}; 626 | copyRegion.imageExtent = { uint32_t(width), uint32_t(height), 1 }; 627 | copyRegion.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; 628 | VkCommandBuffer command; 629 | { 630 | VkCommandBufferAllocateInfo ai{}; 631 | ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 632 | ai.commandBufferCount = 1; 633 | ai.commandPool = m_commandPool; 634 | ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 635 | vkAllocateCommandBuffers(m_device, &ai, &command); 636 | } 637 | 638 | VkCommandBufferBeginInfo commandBI{}; 639 | commandBI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 640 | vkBeginCommandBuffer(command, &commandBI); 641 | setImageMemoryBarrier(command, texture.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); 642 | vkCmdCopyBufferToImage(command, stagingBuffer.buffer, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); 643 | 644 | setImageMemoryBarrier(command, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 645 | vkEndCommandBuffer(command); 646 | 647 | VkSubmitInfo submitInfo{}; 648 | submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 649 | submitInfo.commandBufferCount = 1; 650 | submitInfo.pCommandBuffers = &command; 651 | vkQueueSubmit(m_deviceQueue, 1, &submitInfo, VK_NULL_HANDLE); 652 | { 653 | // テクスチャ参照用のビューを生成 654 | VkImageViewCreateInfo ci{}; 655 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 656 | ci.viewType = VK_IMAGE_VIEW_TYPE_2D; 657 | ci.image = texture.image; 658 | ci.format = format; 659 | ci.components = { 660 | VK_COMPONENT_SWIZZLE_R, 661 | VK_COMPONENT_SWIZZLE_G, 662 | VK_COMPONENT_SWIZZLE_B, 663 | VK_COMPONENT_SWIZZLE_A, 664 | }; 665 | ci.subresourceRange = { 666 | VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,1 667 | }; 668 | vkCreateImageView(m_device, &ci, nullptr, &texture.view); 669 | } 670 | 671 | vkDeviceWaitIdle(m_device); 672 | vkFreeCommandBuffers(m_device, m_commandPool, 1, &command); 673 | 674 | // ステージングバッファ解放. 675 | vkFreeMemory(m_device, stagingBuffer.memory, nullptr); 676 | vkDestroyBuffer(m_device, stagingBuffer.buffer, nullptr); 677 | 678 | return texture; 679 | } 680 | 681 | void ModelApp::setImageMemoryBarrier( 682 | VkCommandBuffer command, 683 | VkImage image, 684 | VkImageLayout oldLayout, VkImageLayout newLayout) 685 | { 686 | VkImageMemoryBarrier imb{}; 687 | imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 688 | imb.oldLayout = oldLayout; 689 | imb.newLayout = newLayout; 690 | imb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 691 | imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 692 | imb.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; 693 | imb.image = image; 694 | 695 | VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 696 | VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 697 | 698 | switch (oldLayout) 699 | { 700 | case VK_IMAGE_LAYOUT_UNDEFINED: 701 | imb.srcAccessMask = 0; 702 | break; 703 | case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: 704 | imb.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 705 | srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; 706 | break; 707 | } 708 | 709 | switch (newLayout) 710 | { 711 | case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: 712 | imb.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 713 | dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; 714 | break; 715 | case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: 716 | imb.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 717 | dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; 718 | break; 719 | case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: 720 | imb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 721 | dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; 722 | break; 723 | } 724 | 725 | //srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; // パイプライン中でリソースへの書込み最終のステージ. 726 | //dstStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; // パイプライン中で次にリソースに書き込むステージ. 727 | 728 | vkCmdPipelineBarrier( 729 | command, 730 | srcStage, 731 | dstStage, 732 | 0, 733 | 0, // memoryBarrierCount 734 | nullptr, 735 | 0, // bufferMemoryBarrierCount 736 | nullptr, 737 | 1, // imageMemoryBarrierCount 738 | &imb); 739 | } 740 | -------------------------------------------------------------------------------- /04_DrawModel/ModelApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../common/vkappbase.h" 4 | #include "glm/glm.hpp" 5 | #include "GLTFSDK/GLTF.h" 6 | 7 | namespace Microsoft 8 | { 9 | namespace glTF 10 | { 11 | class Document; 12 | class GLTFResourceReader; 13 | } 14 | } 15 | 16 | class ModelApp : public VulkanAppBase 17 | { 18 | public: 19 | ModelApp() : VulkanAppBase() { } 20 | 21 | virtual void prepare() override; 22 | virtual void cleanup() override; 23 | 24 | virtual void makeCommand(VkCommandBuffer command) override; 25 | 26 | struct Vertex 27 | { 28 | glm::vec3 pos; 29 | glm::vec3 color; 30 | glm::vec2 uv; 31 | }; 32 | private: 33 | struct BufferObject 34 | { 35 | VkBuffer buffer; 36 | VkDeviceMemory memory; 37 | }; 38 | struct TextureObject 39 | { 40 | VkImage image; 41 | VkDeviceMemory memory; 42 | VkImageView view; 43 | }; 44 | struct ShaderParameters 45 | { 46 | glm::mat4 mtxWorld; 47 | glm::mat4 mtxView; 48 | glm::mat4 mtxProj; 49 | }; 50 | 51 | struct ModelMesh 52 | { 53 | BufferObject vertexBuffer; 54 | BufferObject indexBuffer; 55 | uint32_t vertexCount; 56 | uint32_t indexCount; 57 | 58 | int materialIndex; 59 | 60 | std::vector descriptorSet; 61 | }; 62 | struct Material 63 | { 64 | TextureObject texture; 65 | Microsoft::glTF::AlphaMode alphaMode; 66 | }; 67 | struct Model 68 | { 69 | std::vector meshes; 70 | std::vector materials; 71 | }; 72 | 73 | void makeModelGeometry(const Microsoft::glTF::Document&, std::shared_ptr reader); 74 | void makeModelMaterial(const Microsoft::glTF::Document&, std::shared_ptr reader); 75 | 76 | void prepareUniformBuffers(); 77 | void prepareDescriptorSetLayout(); 78 | void prepareDescriptorPool(); 79 | void prepareDescriptorSet(); 80 | 81 | BufferObject createBuffer(uint32_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlags flags, const void* initialData); 82 | VkPipelineShaderStageCreateInfo loadShaderModule(const char* fileName, VkShaderStageFlagBits stage); 83 | VkSampler createSampler(); 84 | TextureObject createTextureFromMemory(const std::vector& imageData); 85 | void setImageMemoryBarrier( VkCommandBuffer command, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout); 86 | 87 | Model m_model; 88 | 89 | std::vector m_uniformBuffers; 90 | 91 | VkDescriptorSetLayout m_descriptorSetLayout; 92 | VkDescriptorPool m_descriptorPool; 93 | 94 | VkSampler m_sampler; 95 | 96 | VkPipelineLayout m_pipelineLayout; 97 | VkPipeline m_pipelineOpaque; 98 | VkPipeline m_pipelineAlpha; 99 | }; -------------------------------------------------------------------------------- /04_DrawModel/alicia-solid.vrm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techlabxe/vulkan_book_1/c70a1cf609a1f11488d7f770017af4e0cacc9a86/04_DrawModel/alicia-solid.vrm -------------------------------------------------------------------------------- /04_DrawModel/main.cpp: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "ModelApp.h" 11 | 12 | #pragma comment(lib, "vulkan-1.lib") 13 | 14 | const int WindowWidth = 640, WindowHeight = 480; 15 | const char* AppTitle = "DrawModel"; 16 | 17 | int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 18 | { 19 | UNREFERENCED_PARAMETER(hPrevInstance); 20 | UNREFERENCED_PARAMETER(lpCmdLine); 21 | glfwInit(); 22 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 23 | glfwWindowHint(GLFW_RESIZABLE, 0); 24 | auto window = glfwCreateWindow(WindowWidth, WindowHeight, AppTitle, nullptr, nullptr); 25 | 26 | // Vulkan 初期化 27 | ModelApp theApp; 28 | theApp.initialize(window, AppTitle); 29 | 30 | while (glfwWindowShouldClose(window) == GLFW_FALSE) 31 | { 32 | glfwPollEvents(); 33 | theApp.render(); 34 | } 35 | 36 | // Vulkan 終了 37 | theApp.terminate(); 38 | glfwTerminate(); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /04_DrawModel/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /04_DrawModel/shader.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location=0) in vec3 inPos; 4 | layout(location=1) in vec3 inNormal; 5 | layout(location=2) in vec2 inUV; 6 | layout(location=0) out vec2 outUV; 7 | 8 | layout(binding=0) uniform Matrices 9 | { 10 | mat4 world; 11 | mat4 view; 12 | mat4 proj; 13 | }; 14 | 15 | out gl_PerVertex 16 | { 17 | vec4 gl_Position; 18 | }; 19 | 20 | void main() 21 | { 22 | mat4 pvw = proj * view * world; 23 | gl_Position = pvw * vec4(inPos, 1.0); 24 | outUV = inUV; 25 | } 26 | -------------------------------------------------------------------------------- /04_DrawModel/shader.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techlabxe/vulkan_book_1/c70a1cf609a1f11488d7f770017af4e0cacc9a86/04_DrawModel/shader.vert.spv -------------------------------------------------------------------------------- /04_DrawModel/shaderAlpha.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location=0) in vec2 inUV; 4 | layout(location=0) out vec4 outColor; 5 | 6 | layout(binding=1) uniform sampler2D diffuseMap; 7 | 8 | void main() 9 | { 10 | vec4 color = texture(diffuseMap, inUV); 11 | outColor = color; 12 | } 13 | -------------------------------------------------------------------------------- /04_DrawModel/shaderAlpha.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techlabxe/vulkan_book_1/c70a1cf609a1f11488d7f770017af4e0cacc9a86/04_DrawModel/shaderAlpha.frag.spv -------------------------------------------------------------------------------- /04_DrawModel/shaderOpaque.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location=0) in vec2 inUV; 4 | layout(location=0) out vec4 outColor; 5 | 6 | layout(binding=1) uniform sampler2D diffuseMap; 7 | 8 | void main() 9 | { 10 | vec4 color = texture(diffuseMap, inUV); 11 | if( color.a < 0.5 ) 12 | { 13 | discard; 14 | } 15 | outColor = color; 16 | } 17 | -------------------------------------------------------------------------------- /04_DrawModel/shaderOpaque.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/techlabxe/vulkan_book_1/c70a1cf609a1f11488d7f770017af4e0cacc9a86/04_DrawModel/shaderOpaque.frag.spv -------------------------------------------------------------------------------- /04_DrawModel/streamreader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #if _MSC_VER > 1922 && !defined(_SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING) 9 | #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING 10 | #endif 11 | 12 | #include 13 | 14 | class StreamReader : public Microsoft::glTF::IStreamReader 15 | { 16 | public: 17 | StreamReader(std::experimental::filesystem::path pathBase) : m_pathBase(std::move(pathBase)){ } 18 | 19 | std::shared_ptr GetInputStream(const std::string& filename) const override 20 | { 21 | auto streamPath = m_pathBase / std::experimental::filesystem::u8path(filename); 22 | auto stream = std::make_shared(streamPath, std::ios_base::binary); 23 | if (!stream || !(*stream)) 24 | { 25 | throw std::runtime_error("Unable to create valid input stream."); 26 | } 27 | return stream; 28 | } 29 | 30 | private: 31 | std::experimental::filesystem::path m_pathBase; 32 | }; 33 | 34 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # 説明 2 | 3 | このリポジトリは、技術書典6で頒布した 4 | 「Vulkan Programming Vol.1」という本のサンプルプログラムを格納したものです。 5 | 6 | # 不具合など 7 | 8 | バグや不明点などあれば、本リポジトリの Issue のほうからお問い合わせください。 9 | 可能な範囲でサポートの方を行いたいと思います。 10 | 11 | # モデルデータについて 12 | 13 | ニコニ立体: https://3d.nicovideo.jp/alicia/ で公開されている 14 | 「アリシア・ソリッド」のモデルを使用しています。 15 | 16 | 公開されているデータ種別のうち VRM モデルを使用しています。 17 | サンプルプログラムで使用するために、VRM モデルを一度 UniVRM を用いて再エクスポートしています。 18 | glTF のバリデーション(検証)に失敗する場合にはこの手が使えるようです。 19 | 20 | 同様の手順で、バンダイナムコスタジオが公開しているミライ小町モデルも使用可能です。 21 | バンダイナムコスタジオ ミライ小町: https://www.bandainamcostudios.com/works/miraikomachi/dlcguideline.html 22 | 23 | 他にも VRoid Studio で生成したキャラクターデータ(VRM)も本サンプルで読み込めます。 24 | 25 | 26 | # ライセンスについて 27 | 28 | 本リポジトリで使用しているオープンソースライブラリ以外の部分については、MIT ライセンスとします。 29 | 同梱しているモデルデータの更なる再配布は禁止とさせていただきます。 30 | 各オープンソースライブラリについては配布元のライセンスに従ってください。 31 | 32 | # その他 33 | 34 | Vulkan SDK が新しくなることで発生する課題については徐々に修正しています。 35 | -------------------------------------------------------------------------------- /common/vkappbase.cpp: -------------------------------------------------------------------------------- 1 | #include "vkappbase.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define GetInstanceProcAddr(FuncName) \ 7 | m_##FuncName = reinterpret_cast(vkGetInstanceProcAddr(m_instance, #FuncName)) 8 | 9 | using namespace std; 10 | 11 | static VkBool32 VKAPI_CALL DebugReportCallback( 12 | VkDebugReportFlagsEXT flags, 13 | VkDebugReportObjectTypeEXT objactTypes, 14 | uint64_t object, 15 | size_t location, 16 | int32_t messageCode, 17 | const char* pLayerPrefix, 18 | const char* pMessage, 19 | void* pUserData) 20 | { 21 | VkBool32 ret = VK_FALSE; 22 | if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT || 23 | flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) 24 | { 25 | ret = VK_TRUE; 26 | } 27 | std::stringstream ss; 28 | if (pLayerPrefix) 29 | { 30 | ss << "[" << pLayerPrefix << "] "; 31 | } 32 | ss << pMessage << std::endl; 33 | 34 | OutputDebugStringA(ss.str().c_str()); 35 | 36 | return ret; 37 | } 38 | 39 | void VulkanAppBase::checkResult(VkResult result) 40 | { 41 | if (result != VK_SUCCESS) 42 | { 43 | DebugBreak(); 44 | } 45 | } 46 | 47 | VulkanAppBase::VulkanAppBase() 48 | : m_presentMode(VK_PRESENT_MODE_FIFO_KHR) 49 | ,m_imageIndex(0) 50 | { 51 | } 52 | 53 | void VulkanAppBase::initialize(GLFWwindow* window, const char* appName) 54 | { 55 | // Vulkan インスタンスの生成 56 | initializeInstance(appName); 57 | // 物理デバイスの選択 58 | selectPhysicalDevice(); 59 | m_graphicsQueueIndex = searchGraphicsQueueIndex(); 60 | 61 | #ifdef _DEBUG 62 | // デバッグレポート関数のセット. 63 | enableDebugReport(); 64 | #endif 65 | 66 | // 論理デバイスの生成 67 | createDevice(); 68 | // コマンドプールの準備 69 | prepareCommandPool(); 70 | 71 | // サーフェース生成 72 | glfwCreateWindowSurface(m_instance, window, nullptr, &m_surface); 73 | // サーフェースのフォーマット情報選択 74 | selectSurfaceFormat(VK_FORMAT_B8G8R8A8_UNORM); 75 | // サーフェースの能力値情報取得 76 | vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physDev, m_surface, &m_surfaceCaps); 77 | VkBool32 isSupport; 78 | vkGetPhysicalDeviceSurfaceSupportKHR(m_physDev, m_graphicsQueueIndex, m_surface, &isSupport); 79 | 80 | // スワップチェイン生成 81 | createSwapchain(window); 82 | // デプスバッファ生成 83 | createDepthBuffer(); 84 | // スワップチェインイメージとデプスバッファへのImageViewを生成 85 | createViews(); 86 | 87 | // レンダーパスの生成 88 | createRenderPass(); 89 | 90 | // フレームバッファの生成 91 | createFramebuffer(); 92 | 93 | // コマンドバッファの準備. 94 | prepareCommandBuffers(); 95 | 96 | // 描画フレーム同期用 97 | prepareSemaphores(); 98 | 99 | prepare(); 100 | } 101 | 102 | void VulkanAppBase::terminate() 103 | { 104 | vkDeviceWaitIdle(m_device); 105 | 106 | cleanup(); 107 | 108 | vkFreeCommandBuffers(m_device, m_commandPool, uint32_t(m_commands.size()), m_commands.data()); 109 | m_commands.clear(); 110 | 111 | vkDestroyRenderPass(m_device, m_renderPass, nullptr); 112 | for (auto& v : m_framebuffers) 113 | { 114 | vkDestroyFramebuffer(m_device, v, nullptr); 115 | } 116 | m_framebuffers.clear(); 117 | 118 | vkFreeMemory(m_device, m_depthBufferMemory, nullptr); 119 | vkDestroyImage(m_device, m_depthBuffer, nullptr); 120 | vkDestroyImageView(m_device, m_depthBufferView, nullptr); 121 | 122 | for (auto& v : m_swapchainViews) 123 | { 124 | vkDestroyImageView(m_device, v, nullptr); 125 | } 126 | m_swapchainImages.clear(); 127 | vkDestroySwapchainKHR(m_device, m_swapchain, nullptr); 128 | 129 | for (auto& v : m_fences) 130 | { 131 | vkDestroyFence(m_device, v, nullptr); 132 | } 133 | m_fences.clear(); 134 | vkDestroySemaphore(m_device, m_presentCompletedSem, nullptr); 135 | vkDestroySemaphore(m_device, m_renderCompletedSem, nullptr); 136 | 137 | vkDestroyCommandPool(m_device, m_commandPool, nullptr); 138 | 139 | vkDestroySurfaceKHR(m_instance, m_surface, nullptr); 140 | vkDestroyDevice(m_device, nullptr); 141 | #ifdef _DEBUG 142 | disableDebugReport(); 143 | #endif 144 | vkDestroyInstance(m_instance,nullptr); 145 | } 146 | 147 | 148 | void VulkanAppBase::initializeInstance(const char* appName) 149 | { 150 | vector extensions; 151 | VkApplicationInfo appInfo{}; 152 | appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 153 | appInfo.pApplicationName = appName; 154 | appInfo.pEngineName = appName; 155 | appInfo.apiVersion = VK_API_VERSION_1_1; 156 | appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); 157 | 158 | // 拡張情報の取得. 159 | vector props; 160 | { 161 | uint32_t count = 0; 162 | vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); 163 | props.resize(count); 164 | vkEnumerateInstanceExtensionProperties(nullptr, &count, props.data()); 165 | 166 | for (const auto& v : props) 167 | { 168 | extensions.push_back(v.extensionName); 169 | } 170 | } 171 | 172 | VkInstanceCreateInfo ci{}; 173 | ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 174 | ci.enabledExtensionCount = uint32_t(extensions.size()); 175 | ci.ppEnabledExtensionNames = extensions.data(); 176 | ci.pApplicationInfo = &appInfo; 177 | #ifdef _DEBUG 178 | // デバッグビルド時には検証レイヤーを有効化 179 | const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; 180 | if (VK_HEADER_VERSION_COMPLETE < VK_MAKE_VERSION(1, 1, 106)) { 181 | // "VK_LAYER_LUNARG_standard_validation" は廃止になっているが昔の Vulkan SDK では動くので対処しておく. 182 | layers[0] = "VK_LAYER_LUNARG_standard_validation"; 183 | } 184 | ci.enabledLayerCount = 1; 185 | ci.ppEnabledLayerNames = layers; 186 | #endif 187 | 188 | // インスタンス生成 189 | auto result = vkCreateInstance(&ci, nullptr, &m_instance); 190 | checkResult(result); 191 | } 192 | 193 | void VulkanAppBase::selectPhysicalDevice() 194 | { 195 | uint32_t devCount = 0; 196 | vkEnumeratePhysicalDevices(m_instance, &devCount, nullptr); 197 | vector physDevs(devCount); 198 | vkEnumeratePhysicalDevices(m_instance, &devCount, physDevs.data()); 199 | 200 | // 最初のデバイスを使用する 201 | m_physDev = physDevs[0]; 202 | // メモリプロパティを取得しておく 203 | vkGetPhysicalDeviceMemoryProperties(m_physDev, &m_physMemProps); 204 | } 205 | 206 | uint32_t VulkanAppBase::searchGraphicsQueueIndex() 207 | { 208 | uint32_t propCount; 209 | vkGetPhysicalDeviceQueueFamilyProperties(m_physDev, &propCount, nullptr); 210 | vector props(propCount); 211 | vkGetPhysicalDeviceQueueFamilyProperties(m_physDev, &propCount, props.data()); 212 | 213 | uint32_t graphicsQueue = ~0u; 214 | for (uint32_t i = 0; i < propCount; ++i) 215 | { 216 | if (props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) 217 | { 218 | graphicsQueue = i; break; 219 | } 220 | } 221 | return graphicsQueue; 222 | } 223 | void VulkanAppBase::createDevice() 224 | { 225 | const float defaultQueuePriority(1.0f); 226 | VkDeviceQueueCreateInfo devQueueCI{}; 227 | devQueueCI.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 228 | devQueueCI.queueFamilyIndex = m_graphicsQueueIndex; 229 | devQueueCI.queueCount = 1; 230 | devQueueCI.pQueuePriorities = &defaultQueuePriority; 231 | 232 | 233 | vector devExtProps; 234 | { 235 | // 拡張情報の取得. 236 | uint32_t count = 0; 237 | vkEnumerateDeviceExtensionProperties(m_physDev, nullptr, &count, nullptr); 238 | devExtProps.resize(count); 239 | vkEnumerateDeviceExtensionProperties(m_physDev, nullptr, &count, devExtProps.data()); 240 | } 241 | 242 | vector extensions; 243 | for (const auto& v : devExtProps) 244 | { 245 | extensions.push_back(v.extensionName); 246 | } 247 | VkDeviceCreateInfo ci{}; 248 | ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 249 | ci.pQueueCreateInfos = &devQueueCI; 250 | ci.queueCreateInfoCount = 1; 251 | ci.ppEnabledExtensionNames = extensions.data(); 252 | ci.enabledExtensionCount = uint32_t(extensions.size()); 253 | 254 | auto result = vkCreateDevice(m_physDev, &ci, nullptr, &m_device); 255 | checkResult(result); 256 | 257 | // デバイスキューの取得 258 | vkGetDeviceQueue(m_device, m_graphicsQueueIndex, 0, &m_deviceQueue); 259 | } 260 | 261 | void VulkanAppBase::prepareCommandPool() 262 | { 263 | VkCommandPoolCreateInfo ci{}; 264 | ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 265 | ci.queueFamilyIndex = m_graphicsQueueIndex; 266 | ci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; 267 | auto result = vkCreateCommandPool(m_device, &ci, nullptr, &m_commandPool); 268 | checkResult(result); 269 | } 270 | 271 | void VulkanAppBase::selectSurfaceFormat(VkFormat format) 272 | { 273 | uint32_t surfaceFormatCount = 0; 274 | vkGetPhysicalDeviceSurfaceFormatsKHR(m_physDev, m_surface, &surfaceFormatCount, nullptr); 275 | std::vector formats(surfaceFormatCount); 276 | vkGetPhysicalDeviceSurfaceFormatsKHR(m_physDev, m_surface, &surfaceFormatCount, formats.data()); 277 | 278 | // 検索して一致するフォーマットを見つける. 279 | for (const auto& f : formats) 280 | { 281 | if (f.format == format) 282 | { 283 | m_surfaceFormat = f; 284 | } 285 | } 286 | } 287 | 288 | void VulkanAppBase::createSwapchain(GLFWwindow* window) 289 | { 290 | auto imageCount = (std::max)(2u, m_surfaceCaps.minImageCount); 291 | auto extent = m_surfaceCaps.currentExtent; 292 | if (extent.width == ~0u) 293 | { 294 | // 値が無効なのでウィンドウサイズを使用する. 295 | int width, height; 296 | glfwGetWindowSize(window, &width, &height); 297 | extent.width = uint32_t(width); 298 | extent.height = uint32_t(height); 299 | } 300 | uint32_t queueFamilyIndices[] = { m_graphicsQueueIndex }; 301 | VkSwapchainCreateInfoKHR ci{}; 302 | ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 303 | ci.surface = m_surface; 304 | ci.minImageCount = imageCount; 305 | ci.imageFormat = m_surfaceFormat.format; 306 | ci.imageColorSpace = m_surfaceFormat.colorSpace; 307 | ci.imageExtent = extent; 308 | ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 309 | ci.preTransform = m_surfaceCaps.currentTransform; 310 | ci.imageArrayLayers = 1; 311 | ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; 312 | ci.queueFamilyIndexCount = 0; 313 | ci.presentMode = m_presentMode; 314 | ci.oldSwapchain = VK_NULL_HANDLE; 315 | ci.clipped = VK_TRUE; 316 | ci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; 317 | 318 | auto result = vkCreateSwapchainKHR(m_device, &ci, nullptr, &m_swapchain); 319 | checkResult(result); 320 | m_swapchainExtent = extent; 321 | } 322 | void VulkanAppBase::createDepthBuffer() 323 | { 324 | VkImageCreateInfo ci{}; 325 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 326 | ci.imageType = VK_IMAGE_TYPE_2D; 327 | ci.format = VK_FORMAT_D32_SFLOAT; 328 | ci.extent.width = m_swapchainExtent.width; 329 | ci.extent.height = m_swapchainExtent.height; 330 | ci.extent.depth = 1; 331 | ci.mipLevels = 1; 332 | ci.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; 333 | ci.samples = VK_SAMPLE_COUNT_1_BIT; 334 | ci.arrayLayers = 1; 335 | auto result = vkCreateImage(m_device, &ci, nullptr, &m_depthBuffer); 336 | checkResult(result); 337 | 338 | VkMemoryRequirements reqs; 339 | vkGetImageMemoryRequirements(m_device, m_depthBuffer, &reqs); 340 | VkMemoryAllocateInfo ai{}; 341 | ai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 342 | ai.allocationSize = reqs.size; 343 | ai.memoryTypeIndex = getMemoryTypeIndex(reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 344 | vkAllocateMemory(m_device, &ai, nullptr, &m_depthBufferMemory); 345 | vkBindImageMemory(m_device, m_depthBuffer, m_depthBufferMemory, 0); 346 | } 347 | 348 | void VulkanAppBase::createViews() 349 | { 350 | uint32_t imageCount; 351 | vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, nullptr); 352 | m_swapchainImages.resize(imageCount); 353 | vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, m_swapchainImages.data()); 354 | m_swapchainViews.resize(imageCount); 355 | for (uint32_t i = 0; i < imageCount; ++i) 356 | { 357 | VkImageViewCreateInfo ci{}; 358 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 359 | ci.viewType = VK_IMAGE_VIEW_TYPE_2D; 360 | ci.format = m_surfaceFormat.format; 361 | ci.components = { 362 | VK_COMPONENT_SWIZZLE_R, 363 | VK_COMPONENT_SWIZZLE_G, 364 | VK_COMPONENT_SWIZZLE_B, 365 | VK_COMPONENT_SWIZZLE_A, 366 | }; 367 | ci.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; 368 | ci.image = m_swapchainImages[i]; 369 | auto result = vkCreateImageView(m_device, &ci, nullptr, &m_swapchainViews[i]); 370 | checkResult(result); 371 | } 372 | 373 | // for depthbuffer 374 | { 375 | VkImageViewCreateInfo ci{}; 376 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 377 | ci.viewType = VK_IMAGE_VIEW_TYPE_2D; 378 | ci.format = VK_FORMAT_D32_SFLOAT; 379 | ci.components = { 380 | VK_COMPONENT_SWIZZLE_R, 381 | VK_COMPONENT_SWIZZLE_G, 382 | VK_COMPONENT_SWIZZLE_B, 383 | VK_COMPONENT_SWIZZLE_A, 384 | }; 385 | ci.subresourceRange = { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1 }; 386 | ci.image = m_depthBuffer; 387 | auto result = vkCreateImageView(m_device, &ci, nullptr, &m_depthBufferView); 388 | checkResult(result); 389 | } 390 | } 391 | 392 | void VulkanAppBase::createRenderPass() 393 | { 394 | VkRenderPassCreateInfo ci{}; 395 | ci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 396 | 397 | array attachments; 398 | auto& colorTarget = attachments[0]; 399 | auto& depthTarget = attachments[1]; 400 | 401 | colorTarget = VkAttachmentDescription{}; 402 | colorTarget.format = m_surfaceFormat.format; 403 | colorTarget.samples = VK_SAMPLE_COUNT_1_BIT; 404 | colorTarget.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 405 | colorTarget.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 406 | colorTarget.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 407 | colorTarget.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 408 | colorTarget.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 409 | colorTarget.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 410 | 411 | depthTarget = VkAttachmentDescription{}; 412 | depthTarget.format = VK_FORMAT_D32_SFLOAT; 413 | depthTarget.samples = VK_SAMPLE_COUNT_1_BIT; 414 | depthTarget.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 415 | depthTarget.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 416 | depthTarget.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 417 | depthTarget.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 418 | depthTarget.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 419 | depthTarget.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 420 | 421 | VkAttachmentReference colorReference{}, depthReference{}; 422 | colorReference.attachment = 0; 423 | colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 424 | 425 | depthReference.attachment = 1; 426 | depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 427 | 428 | VkSubpassDescription subpassDesc{}; 429 | subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 430 | subpassDesc.colorAttachmentCount = 1; 431 | subpassDesc.pColorAttachments = &colorReference; 432 | subpassDesc.pDepthStencilAttachment = &depthReference; 433 | 434 | ci.attachmentCount = uint32_t(attachments.size()); 435 | ci.pAttachments = attachments.data(); 436 | ci.subpassCount = 1; 437 | ci.pSubpasses = &subpassDesc; 438 | 439 | auto result = vkCreateRenderPass(m_device, &ci, nullptr, &m_renderPass); 440 | checkResult(result); 441 | } 442 | 443 | void VulkanAppBase::createFramebuffer() 444 | { 445 | VkFramebufferCreateInfo ci{}; 446 | ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 447 | ci.renderPass = m_renderPass; 448 | ci.width = m_swapchainExtent.width; 449 | ci.height = m_swapchainExtent.height; 450 | ci.layers = 1; 451 | m_framebuffers.clear(); 452 | for (auto& v : m_swapchainViews) 453 | { 454 | array attachments; 455 | ci.attachmentCount = uint32_t(attachments.size()); 456 | ci.pAttachments = attachments.data(); 457 | attachments[0] = v; 458 | attachments[1] = m_depthBufferView; 459 | 460 | VkFramebuffer framebuffer; 461 | auto result = vkCreateFramebuffer(m_device, &ci, nullptr, &framebuffer); 462 | checkResult(result); 463 | m_framebuffers.push_back(framebuffer); 464 | } 465 | } 466 | void VulkanAppBase::prepareCommandBuffers() 467 | { 468 | VkCommandBufferAllocateInfo ai{}; 469 | ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 470 | ai.commandPool = m_commandPool; 471 | ai.commandBufferCount = uint32_t(m_swapchainViews.size()); 472 | ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 473 | m_commands.resize(ai.commandBufferCount); 474 | auto result = vkAllocateCommandBuffers(m_device, &ai, m_commands.data()); 475 | checkResult(result); 476 | 477 | // コマンドバッファのフェンスも同数用意する. 478 | m_fences.resize(ai.commandBufferCount); 479 | VkFenceCreateInfo ci{}; 480 | ci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 481 | ci.flags = VK_FENCE_CREATE_SIGNALED_BIT; 482 | for (auto& v : m_fences) 483 | { 484 | result = vkCreateFence(m_device, &ci, nullptr, &v); 485 | checkResult(result); 486 | } 487 | } 488 | 489 | void VulkanAppBase::prepareSemaphores() 490 | { 491 | VkSemaphoreCreateInfo ci{}; 492 | ci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 493 | vkCreateSemaphore(m_device, &ci, nullptr, &m_renderCompletedSem); 494 | vkCreateSemaphore(m_device, &ci, nullptr, &m_presentCompletedSem); 495 | } 496 | 497 | 498 | uint32_t VulkanAppBase::getMemoryTypeIndex(uint32_t requestBits, VkMemoryPropertyFlags requestProps)const 499 | { 500 | uint32_t result = ~0u; 501 | for (uint32_t i = 0; i < m_physMemProps.memoryTypeCount; ++i) 502 | { 503 | if (requestBits & 1) 504 | { 505 | const auto& types = m_physMemProps.memoryTypes[i]; 506 | if ((types.propertyFlags & requestProps) == requestProps) 507 | { 508 | result = i; 509 | break; 510 | } 511 | } 512 | requestBits >>= 1; 513 | } 514 | return result; 515 | } 516 | 517 | 518 | void VulkanAppBase::enableDebugReport() 519 | { 520 | GetInstanceProcAddr(vkCreateDebugReportCallbackEXT); 521 | GetInstanceProcAddr(vkDebugReportMessageEXT); 522 | GetInstanceProcAddr(vkDestroyDebugReportCallbackEXT); 523 | 524 | VkDebugReportFlagsEXT flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; 525 | 526 | VkDebugReportCallbackCreateInfoEXT drcCI{}; 527 | drcCI.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; 528 | drcCI.flags = flags; 529 | drcCI.pfnCallback = &DebugReportCallback; 530 | m_vkCreateDebugReportCallbackEXT(m_instance, &drcCI, nullptr, &m_debugReport); 531 | } 532 | void VulkanAppBase::disableDebugReport() 533 | { 534 | if (m_vkDestroyDebugReportCallbackEXT) 535 | { 536 | m_vkDestroyDebugReportCallbackEXT(m_instance, m_debugReport, nullptr); 537 | } 538 | } 539 | 540 | void VulkanAppBase::render() 541 | { 542 | uint32_t nextImageIndex = 0; 543 | vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX, m_presentCompletedSem, VK_NULL_HANDLE, &nextImageIndex); 544 | auto commandFence = m_fences[nextImageIndex]; 545 | vkWaitForFences(m_device, 1, &commandFence, VK_TRUE, UINT64_MAX); 546 | 547 | // クリア値 548 | array clearValue = { 549 | { {0.5f, 0.25f, 0.25f, 0.0f}, // for Color 550 | {1.0f, 0 } // for Depth 551 | } 552 | }; 553 | 554 | VkRenderPassBeginInfo renderPassBI{}; 555 | renderPassBI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 556 | renderPassBI.renderPass = m_renderPass; 557 | renderPassBI.framebuffer = m_framebuffers[nextImageIndex]; 558 | renderPassBI.renderArea.offset = VkOffset2D{ 0, 0 }; 559 | renderPassBI.renderArea.extent = m_swapchainExtent; 560 | renderPassBI.pClearValues = clearValue.data(); 561 | renderPassBI.clearValueCount = uint32_t(clearValue.size()); 562 | 563 | // コマンドバッファ・レンダーパス開始 564 | VkCommandBufferBeginInfo commandBI{}; 565 | commandBI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 566 | auto& command = m_commands[nextImageIndex]; 567 | vkBeginCommandBuffer(command, &commandBI); 568 | vkCmdBeginRenderPass(command, &renderPassBI, VK_SUBPASS_CONTENTS_INLINE); 569 | 570 | m_imageIndex = nextImageIndex; 571 | makeCommand(command); 572 | 573 | // コマンド・レンダーパス終了 574 | vkCmdEndRenderPass(command); 575 | vkEndCommandBuffer(command); 576 | 577 | // コマンドを実行(送信) 578 | VkSubmitInfo submitInfo{}; 579 | VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 580 | submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 581 | submitInfo.commandBufferCount = 1; 582 | submitInfo.pCommandBuffers = &command; 583 | submitInfo.pWaitDstStageMask = &waitStageMask; 584 | submitInfo.waitSemaphoreCount = 1; 585 | submitInfo.pWaitSemaphores = &m_presentCompletedSem; 586 | submitInfo.signalSemaphoreCount = 1; 587 | submitInfo.pSignalSemaphores = &m_renderCompletedSem; 588 | vkResetFences(m_device, 1, &commandFence); 589 | vkQueueSubmit(m_deviceQueue, 1, &submitInfo, commandFence); 590 | 591 | // Present 処理 592 | VkPresentInfoKHR presentInfo{}; 593 | presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 594 | presentInfo.swapchainCount = 1; 595 | presentInfo.pSwapchains = &m_swapchain; 596 | presentInfo.pImageIndices = &nextImageIndex; 597 | presentInfo.waitSemaphoreCount = 1; 598 | presentInfo.pWaitSemaphores = &m_renderCompletedSem; 599 | vkQueuePresentKHR(m_deviceQueue, &presentInfo); 600 | } -------------------------------------------------------------------------------- /common/vkappbase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define WIN32_LEAN_AND_MEAN 3 | #include 4 | 5 | #define VK_USE_PLATFORM_WIN32_KHR 6 | #define GLFW_INCLUDE_VULKAN 7 | #define GLFW_EXPOSE_NATIVE_WIN32 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | class VulkanAppBase 16 | { 17 | public: 18 | VulkanAppBase(); 19 | virtual ~VulkanAppBase() { } 20 | void initialize(GLFWwindow* window, const char* appName); 21 | void terminate(); 22 | 23 | virtual void render(); 24 | 25 | virtual void prepare() { } 26 | virtual void cleanup() { } 27 | virtual void makeCommand(VkCommandBuffer command) { } 28 | protected: 29 | static void checkResult(VkResult); 30 | 31 | void initializeInstance(const char* appName); 32 | void selectPhysicalDevice(); 33 | uint32_t searchGraphicsQueueIndex(); 34 | void createDevice(); 35 | void prepareCommandPool(); 36 | void selectSurfaceFormat(VkFormat format); 37 | void createSwapchain(GLFWwindow* window); 38 | void createDepthBuffer(); 39 | void createViews(); 40 | 41 | void createRenderPass(); 42 | void createFramebuffer(); 43 | 44 | void prepareCommandBuffers(); 45 | void prepareSemaphores(); 46 | 47 | uint32_t getMemoryTypeIndex(uint32_t requestBits, VkMemoryPropertyFlags requestProps)const; 48 | 49 | void enableDebugReport(); 50 | void disableDebugReport(); 51 | 52 | 53 | VkInstance m_instance; 54 | VkDevice m_device; 55 | VkPhysicalDevice m_physDev; 56 | 57 | VkSurfaceKHR m_surface; 58 | VkSurfaceFormatKHR m_surfaceFormat; 59 | VkSurfaceCapabilitiesKHR m_surfaceCaps; 60 | 61 | VkPhysicalDeviceMemoryProperties m_physMemProps; 62 | 63 | uint32_t m_graphicsQueueIndex; 64 | VkQueue m_deviceQueue; 65 | 66 | VkCommandPool m_commandPool; 67 | VkPresentModeKHR m_presentMode; 68 | VkSwapchainKHR m_swapchain; 69 | VkExtent2D m_swapchainExtent; 70 | std::vector m_swapchainImages; 71 | std::vector m_swapchainViews; 72 | 73 | VkImage m_depthBuffer; 74 | VkDeviceMemory m_depthBufferMemory; 75 | VkImageView m_depthBufferView; 76 | 77 | VkRenderPass m_renderPass; 78 | std::vector m_framebuffers; 79 | 80 | std::vector m_fences; 81 | VkSemaphore m_renderCompletedSem, m_presentCompletedSem; 82 | 83 | // デバッグレポート関連 84 | PFN_vkCreateDebugReportCallbackEXT m_vkCreateDebugReportCallbackEXT; 85 | PFN_vkDebugReportMessageEXT m_vkDebugReportMessageEXT; 86 | PFN_vkDestroyDebugReportCallbackEXT m_vkDestroyDebugReportCallbackEXT; 87 | VkDebugReportCallbackEXT m_debugReport; 88 | 89 | std::vector m_commands; 90 | 91 | uint32_t m_imageIndex; 92 | }; 93 | --------------------------------------------------------------------------------