├── 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 |
--------------------------------------------------------------------------------