blob: 0865bdb379df103bb53f25634528a25839b8c59b [file] [log] [blame]
Adam Sawickie6e498f2017-06-16 17:21:31 +02001//
Adam Sawickiae5c4662019-01-02 10:23:35 +01002// Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved.
Adam Sawickie6e498f2017-06-16 17:21:31 +02003//
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20// THE SOFTWARE.
21//
22
Adam Sawickif1a793c2018-03-13 15:42:22 +010023#ifdef _WIN32
Adam Sawicki59a3e7e2017-08-21 15:47:30 +020024
Adam Sawicki51fa9662018-10-03 13:44:29 +020025#include "SparseBindingTest.h"
Adam Sawickif1a793c2018-03-13 15:42:22 +010026#include "Tests.h"
27#include "VmaUsage.h"
28#include "Common.h"
Adam Sawickie6e498f2017-06-16 17:21:31 +020029
30static const char* const SHADER_PATH1 = "./";
31static const char* const SHADER_PATH2 = "../bin/";
32static const wchar_t* const WINDOW_CLASS_NAME = L"VULKAN_MEMORY_ALLOCATOR_SAMPLE";
33static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_LUNARG_standard_validation";
Adam Sawicki6c8b7a22019-03-05 13:40:29 +010034static const char* const APP_TITLE_A = "Vulkan Memory Allocator Sample 2.3.0-development";
35static const wchar_t* const APP_TITLE_W = L"Vulkan Memory Allocator Sample 2.3.0-development";
Adam Sawickie6e498f2017-06-16 17:21:31 +020036
37static const bool VSYNC = true;
38static const uint32_t COMMAND_BUFFER_COUNT = 2;
Adam Sawickia68c01c2018-03-13 16:40:45 +010039static void* const CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA = (void*)(intptr_t)43564544;
40static const bool USE_CUSTOM_CPU_ALLOCATION_CALLBACKS = false;
Adam Sawickie6e498f2017-06-16 17:21:31 +020041
Adam Sawickib8333fb2018-03-13 16:15:53 +010042VkPhysicalDevice g_hPhysicalDevice;
43VkDevice g_hDevice;
44VmaAllocator g_hAllocator;
45bool g_MemoryAliasingWarningEnabled = true;
46
Adam Sawickia68c01c2018-03-13 16:40:45 +010047static bool g_EnableValidationLayer = true;
Adam Sawicki6cc5e852018-03-13 16:37:54 +010048static bool VK_KHR_get_memory_requirements2_enabled = false;
Adam Sawicki353e3672019-11-02 14:12:05 +010049static bool VK_KHR_get_physical_device_properties2_enabled = false;
Adam Sawicki6cc5e852018-03-13 16:37:54 +010050static bool VK_KHR_dedicated_allocation_enabled = false;
Adam Sawicki4abe30c2019-07-02 14:37:21 +020051static bool VK_KHR_bind_memory2_enabled = false;
Adam Sawicki353e3672019-11-02 14:12:05 +010052static bool VK_EXT_memory_budget_enabled = false;
Adam Sawicki51fa9662018-10-03 13:44:29 +020053bool g_SparseBindingEnabled = false;
Adam Sawicki6cc5e852018-03-13 16:37:54 +010054
Adam Sawickie6e498f2017-06-16 17:21:31 +020055static HINSTANCE g_hAppInstance;
56static HWND g_hWnd;
57static LONG g_SizeX = 1280, g_SizeY = 720;
58static VkInstance g_hVulkanInstance;
59static VkSurfaceKHR g_hSurface;
Adam Sawickie6e498f2017-06-16 17:21:31 +020060static VkQueue g_hPresentQueue;
61static VkSurfaceFormatKHR g_SurfaceFormat;
62static VkExtent2D g_Extent;
63static VkSwapchainKHR g_hSwapchain;
64static std::vector<VkImage> g_SwapchainImages;
65static std::vector<VkImageView> g_SwapchainImageViews;
66static std::vector<VkFramebuffer> g_Framebuffers;
67static VkCommandPool g_hCommandPool;
68static VkCommandBuffer g_MainCommandBuffers[COMMAND_BUFFER_COUNT];
69static VkFence g_MainCommandBufferExecutedFances[COMMAND_BUFFER_COUNT];
Adam Sawicki51fa9662018-10-03 13:44:29 +020070VkFence g_ImmediateFence;
Adam Sawickie6e498f2017-06-16 17:21:31 +020071static uint32_t g_NextCommandBufferIndex;
72static VkSemaphore g_hImageAvailableSemaphore;
73static VkSemaphore g_hRenderFinishedSemaphore;
74static uint32_t g_GraphicsQueueFamilyIndex = UINT_MAX;
75static uint32_t g_PresentQueueFamilyIndex = UINT_MAX;
Adam Sawicki51fa9662018-10-03 13:44:29 +020076static uint32_t g_SparseBindingQueueFamilyIndex = UINT_MAX;
Adam Sawickie6e498f2017-06-16 17:21:31 +020077static VkDescriptorSetLayout g_hDescriptorSetLayout;
78static VkDescriptorPool g_hDescriptorPool;
79static VkDescriptorSet g_hDescriptorSet; // Automatically destroyed with m_DescriptorPool.
80static VkSampler g_hSampler;
81static VkFormat g_DepthFormat;
82static VkImage g_hDepthImage;
Adam Sawicki819860e2017-07-04 14:30:38 +020083static VmaAllocation g_hDepthImageAlloc;
Adam Sawickie6e498f2017-06-16 17:21:31 +020084static VkImageView g_hDepthImageView;
85
86static VkSurfaceCapabilitiesKHR g_SurfaceCapabilities;
87static std::vector<VkSurfaceFormatKHR> g_SurfaceFormats;
88static std::vector<VkPresentModeKHR> g_PresentModes;
89
90static PFN_vkCreateDebugReportCallbackEXT g_pvkCreateDebugReportCallbackEXT;
91static PFN_vkDebugReportMessageEXT g_pvkDebugReportMessageEXT;
92static PFN_vkDestroyDebugReportCallbackEXT g_pvkDestroyDebugReportCallbackEXT;
93static VkDebugReportCallbackEXT g_hCallback;
94
Adam Sawickie6e498f2017-06-16 17:21:31 +020095static VkQueue g_hGraphicsQueue;
Adam Sawicki51fa9662018-10-03 13:44:29 +020096VkQueue g_hSparseBindingQueue;
Adam Sawicki978fcf52018-12-05 14:38:48 +010097VkCommandBuffer g_hTemporaryCommandBuffer;
Adam Sawickie6e498f2017-06-16 17:21:31 +020098
99static VkPipelineLayout g_hPipelineLayout;
100static VkRenderPass g_hRenderPass;
101static VkPipeline g_hPipeline;
102
103static VkBuffer g_hVertexBuffer;
Adam Sawicki819860e2017-07-04 14:30:38 +0200104static VmaAllocation g_hVertexBufferAlloc;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200105static VkBuffer g_hIndexBuffer;
Adam Sawicki819860e2017-07-04 14:30:38 +0200106static VmaAllocation g_hIndexBufferAlloc;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200107static uint32_t g_VertexCount;
108static uint32_t g_IndexCount;
109
110static VkImage g_hTextureImage;
Adam Sawicki819860e2017-07-04 14:30:38 +0200111static VmaAllocation g_hTextureImageAlloc;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200112static VkImageView g_hTextureImageView;
113
Adam Sawickia68c01c2018-03-13 16:40:45 +0100114static void* CustomCpuAllocation(
115 void* pUserData, size_t size, size_t alignment,
116 VkSystemAllocationScope allocationScope)
117{
118 assert(pUserData == CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA);
119 return _aligned_malloc(size, alignment);
120}
121
122static void* CustomCpuReallocation(
123 void* pUserData, void* pOriginal, size_t size, size_t alignment,
124 VkSystemAllocationScope allocationScope)
125{
126 assert(pUserData == CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA);
127 return _aligned_realloc(pOriginal, size, alignment);
128}
129
130static void CustomCpuFree(void* pUserData, void* pMemory)
131{
132 assert(pUserData == CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA);
133 _aligned_free(pMemory);
134}
135
Adam Sawicki1f84f622019-07-02 13:40:01 +0200136static const VkAllocationCallbacks g_CpuAllocationCallbacks = {
137 CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA, // pUserData
138 &CustomCpuAllocation, // pfnAllocation
139 &CustomCpuReallocation, // pfnReallocation
140 &CustomCpuFree // pfnFree
141};
142
143const VkAllocationCallbacks* g_Allocs;
144
Adam Sawicki978fcf52018-12-05 14:38:48 +0100145void BeginSingleTimeCommands()
Adam Sawickie6e498f2017-06-16 17:21:31 +0200146{
147 VkCommandBufferBeginInfo cmdBufBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
148 cmdBufBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
149 ERR_GUARD_VULKAN( vkBeginCommandBuffer(g_hTemporaryCommandBuffer, &cmdBufBeginInfo) );
150}
151
Adam Sawicki978fcf52018-12-05 14:38:48 +0100152void EndSingleTimeCommands()
Adam Sawickie6e498f2017-06-16 17:21:31 +0200153{
154 ERR_GUARD_VULKAN( vkEndCommandBuffer(g_hTemporaryCommandBuffer) );
155
156 VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
157 submitInfo.commandBufferCount = 1;
158 submitInfo.pCommandBuffers = &g_hTemporaryCommandBuffer;
159
160 ERR_GUARD_VULKAN( vkQueueSubmit(g_hGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE) );
161 ERR_GUARD_VULKAN( vkQueueWaitIdle(g_hGraphicsQueue) );
162}
163
Adam Sawickida6c1942018-12-05 17:34:34 +0100164void LoadShader(std::vector<char>& out, const char* fileName)
Adam Sawickie6e498f2017-06-16 17:21:31 +0200165{
166 std::ifstream file(std::string(SHADER_PATH1) + fileName, std::ios::ate | std::ios::binary);
167 if(file.is_open() == false)
168 file.open(std::string(SHADER_PATH2) + fileName, std::ios::ate | std::ios::binary);
169 assert(file.is_open());
170 size_t fileSize = (size_t)file.tellg();
171 if(fileSize > 0)
172 {
173 out.resize(fileSize);
174 file.seekg(0);
175 file.read(out.data(), fileSize);
176 file.close();
177 }
178 else
179 out.clear();
180}
181
182VKAPI_ATTR VkBool32 VKAPI_CALL MyDebugReportCallback(
183 VkDebugReportFlagsEXT flags,
184 VkDebugReportObjectTypeEXT objectType,
185 uint64_t object,
186 size_t location,
187 int32_t messageCode,
188 const char* pLayerPrefix,
189 const char* pMessage,
190 void* pUserData)
191{
Adam Sawickib8333fb2018-03-13 16:15:53 +0100192 // "Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug."
193 if(!g_MemoryAliasingWarningEnabled && flags == VK_DEBUG_REPORT_WARNING_BIT_EXT &&
194 (strstr(pMessage, " is aliased with non-linear ") || strstr(pMessage, " is aliased with linear ")))
195 {
196 return VK_FALSE;
197 }
198
199 // Ignoring because when VK_KHR_dedicated_allocation extension is enabled,
200 // vkGetBufferMemoryRequirements2KHR function is used instead, while Validation
201 // Layer seems to be unaware of it.
202 if (strstr(pMessage, "but vkGetBufferMemoryRequirements() has not been called on that buffer") != nullptr)
203 {
204 return VK_FALSE;
205 }
206 if (strstr(pMessage, "but vkGetImageMemoryRequirements() has not been called on that image") != nullptr)
207 {
208 return VK_FALSE;
209 }
Adam Sawicki94e82062018-08-20 11:12:51 +0200210
211 /*
212 "Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used."
213 Ignoring because we map entire VkDeviceMemory blocks, where different types of
214 images and buffers may end up together, especially on GPUs with unified memory
215 like Intel.
216 */
217 if(strstr(pMessage, "Mapping an image with layout") != nullptr &&
218 strstr(pMessage, "can result in undefined behavior if this memory is used by the device") != nullptr)
219 {
220 return VK_FALSE;
221 }
Adam Sawickib8333fb2018-03-13 16:15:53 +0100222
223 switch(flags)
224 {
225 case VK_DEBUG_REPORT_WARNING_BIT_EXT:
226 SetConsoleColor(CONSOLE_COLOR::WARNING);
227 break;
228 case VK_DEBUG_REPORT_ERROR_BIT_EXT:
229 SetConsoleColor(CONSOLE_COLOR::ERROR_);
230 break;
231 default:
232 SetConsoleColor(CONSOLE_COLOR::INFO);
233 }
234
Adam Sawickie6e498f2017-06-16 17:21:31 +0200235 printf("%s \xBA %s\n", pLayerPrefix, pMessage);
236
Adam Sawickib8333fb2018-03-13 16:15:53 +0100237 SetConsoleColor(CONSOLE_COLOR::NORMAL);
238
239 if(flags == VK_DEBUG_REPORT_WARNING_BIT_EXT ||
240 flags == VK_DEBUG_REPORT_ERROR_BIT_EXT)
Adam Sawickie6e498f2017-06-16 17:21:31 +0200241 {
242 OutputDebugStringA(pMessage);
243 OutputDebugStringA("\n");
244 }
245
246 return VK_FALSE;
247}
248
249static VkSurfaceFormatKHR ChooseSurfaceFormat()
250{
251 assert(!g_SurfaceFormats.empty());
252
253 if((g_SurfaceFormats.size() == 1) && (g_SurfaceFormats[0].format == VK_FORMAT_UNDEFINED))
254 {
255 VkSurfaceFormatKHR result = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
256 return result;
257 }
258
259 for(const auto& format : g_SurfaceFormats)
260 {
261 if((format.format == VK_FORMAT_B8G8R8A8_UNORM) &&
262 (format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR))
263 {
264 return format;
265 }
266 }
267
268 return g_SurfaceFormats[0];
269}
270
271VkPresentModeKHR ChooseSwapPresentMode()
272{
273 VkPresentModeKHR preferredMode = VSYNC ? VK_PRESENT_MODE_MAILBOX_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR;
274
275 if(std::find(g_PresentModes.begin(), g_PresentModes.end(), preferredMode) !=
276 g_PresentModes.end())
277 {
278 return preferredMode;
279 }
280
281 return VK_PRESENT_MODE_FIFO_KHR;
282}
283
284static VkExtent2D ChooseSwapExtent()
285{
286 if(g_SurfaceCapabilities.currentExtent.width != UINT_MAX)
287 return g_SurfaceCapabilities.currentExtent;
288
289 VkExtent2D result = {
290 std::max(g_SurfaceCapabilities.minImageExtent.width,
291 std::min(g_SurfaceCapabilities.maxImageExtent.width, (uint32_t)g_SizeX)),
292 std::max(g_SurfaceCapabilities.minImageExtent.height,
293 std::min(g_SurfaceCapabilities.maxImageExtent.height, (uint32_t)g_SizeY)) };
294 return result;
295}
296
297struct Vertex
298{
299 float pos[3];
300 float color[3];
301 float texCoord[2];
302};
303
304static void CreateMesh()
305{
306 assert(g_hAllocator);
307
308 static Vertex vertices[] = {
309 // -X
310 { { -1.f, -1.f, -1.f}, {1.0f, 0.0f, 0.0f}, {0.f, 0.f} },
311 { { -1.f, -1.f, 1.f}, {1.0f, 0.0f, 0.0f}, {1.f, 0.f} },
312 { { -1.f, 1.f, -1.f}, {1.0f, 0.0f, 0.0f}, {0.f, 1.f} },
313 { { -1.f, 1.f, 1.f}, {1.0f, 0.0f, 0.0f}, {1.f, 1.f} },
314 // +X
315 { { 1.f, -1.f, 1.f}, {0.0f, 1.0f, 0.0f}, {0.f, 0.f} },
316 { { 1.f, -1.f, -1.f}, {0.0f, 1.0f, 0.0f}, {1.f, 0.f} },
317 { { 1.f, 1.f, 1.f}, {0.0f, 1.0f, 0.0f}, {0.f, 1.f} },
318 { { 1.f, 1.f, -1.f}, {0.0f, 1.0f, 0.0f}, {1.f, 1.f} },
319 // -Z
320 { { 1.f, -1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {0.f, 0.f} },
321 { {-1.f, -1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {1.f, 0.f} },
322 { { 1.f, 1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {0.f, 1.f} },
323 { {-1.f, 1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {1.f, 1.f} },
324 // +Z
325 { {-1.f, -1.f, 1.f}, {1.0f, 1.0f, 0.0f}, {0.f, 0.f} },
326 { { 1.f, -1.f, 1.f}, {1.0f, 1.0f, 0.0f}, {1.f, 0.f} },
327 { {-1.f, 1.f, 1.f}, {1.0f, 1.0f, 0.0f}, {0.f, 1.f} },
328 { { 1.f, 1.f, 1.f}, {1.0f, 1.0f, 0.0f}, {1.f, 1.f} },
329 // -Y
330 { {-1.f, -1.f, -1.f}, {0.0f, 1.0f, 1.0f}, {0.f, 0.f} },
331 { { 1.f, -1.f, -1.f}, {0.0f, 1.0f, 1.0f}, {1.f, 0.f} },
332 { {-1.f, -1.f, 1.f}, {0.0f, 1.0f, 1.0f}, {0.f, 1.f} },
333 { { 1.f, -1.f, 1.f}, {0.0f, 1.0f, 1.0f}, {1.f, 1.f} },
334 // +Y
335 { { 1.f, 1.f, -1.f}, {1.0f, 0.0f, 1.0f}, {0.f, 0.f} },
336 { {-1.f, 1.f, -1.f}, {1.0f, 0.0f, 1.0f}, {1.f, 0.f} },
337 { { 1.f, 1.f, 1.f}, {1.0f, 0.0f, 1.0f}, {0.f, 1.f} },
338 { {-1.f, 1.f, 1.f}, {1.0f, 0.0f, 1.0f}, {1.f, 1.f} },
339 };
340 static uint16_t indices[] = {
341 0, 1, 2, 3, USHRT_MAX,
342 4, 5, 6, 7, USHRT_MAX,
343 8, 9, 10, 11, USHRT_MAX,
344 12, 13, 14, 15, USHRT_MAX,
345 16, 17, 18, 19, USHRT_MAX,
346 20, 21, 22, 23, USHRT_MAX,
347 };
348
349 size_t vertexBufferSize = sizeof(Vertex) * _countof(vertices);
350 size_t indexBufferSize = sizeof(uint16_t) * _countof(indices);
351 g_IndexCount = (uint32_t)_countof(indices);
352
353 // Create vertex buffer
354
355 VkBufferCreateInfo vbInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
356 vbInfo.size = vertexBufferSize;
357 vbInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
358 vbInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200359
Adam Sawicki976f9202017-09-12 20:45:14 +0200360 VmaAllocationCreateInfo vbAllocCreateInfo = {};
361 vbAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
Adam Sawicki5268dbb2017-11-08 12:52:05 +0100362 vbAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200363
Adam Sawicki819860e2017-07-04 14:30:38 +0200364 VkBuffer stagingVertexBuffer = VK_NULL_HANDLE;
365 VmaAllocation stagingVertexBufferAlloc = VK_NULL_HANDLE;
366 VmaAllocationInfo stagingVertexBufferAllocInfo = {};
Adam Sawicki976f9202017-09-12 20:45:14 +0200367 ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &vbInfo, &vbAllocCreateInfo, &stagingVertexBuffer, &stagingVertexBufferAlloc, &stagingVertexBufferAllocInfo) );
Adam Sawicki819860e2017-07-04 14:30:38 +0200368
369 memcpy(stagingVertexBufferAllocInfo.pMappedData, vertices, vertexBufferSize);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200370
Adam Sawicki2f16fa52017-07-04 14:43:20 +0200371 // No need to flush stagingVertexBuffer memory because CPU_ONLY memory is always HOST_COHERENT.
372
Adam Sawickie6e498f2017-06-16 17:21:31 +0200373 vbInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
Adam Sawicki976f9202017-09-12 20:45:14 +0200374 vbAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
375 vbAllocCreateInfo.flags = 0;
376 ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &vbInfo, &vbAllocCreateInfo, &g_hVertexBuffer, &g_hVertexBufferAlloc, nullptr) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200377
378 // Create index buffer
379
380 VkBufferCreateInfo ibInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
381 ibInfo.size = indexBufferSize;
382 ibInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
383 ibInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
Adam Sawicki819860e2017-07-04 14:30:38 +0200384
Adam Sawicki976f9202017-09-12 20:45:14 +0200385 VmaAllocationCreateInfo ibAllocCreateInfo = {};
386 ibAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
Adam Sawicki5268dbb2017-11-08 12:52:05 +0100387 ibAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
Adam Sawicki819860e2017-07-04 14:30:38 +0200388
Adam Sawickie6e498f2017-06-16 17:21:31 +0200389 VkBuffer stagingIndexBuffer = VK_NULL_HANDLE;
Adam Sawicki819860e2017-07-04 14:30:38 +0200390 VmaAllocation stagingIndexBufferAlloc = VK_NULL_HANDLE;
391 VmaAllocationInfo stagingIndexBufferAllocInfo = {};
Adam Sawicki976f9202017-09-12 20:45:14 +0200392 ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &ibInfo, &ibAllocCreateInfo, &stagingIndexBuffer, &stagingIndexBufferAlloc, &stagingIndexBufferAllocInfo) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200393
Adam Sawicki819860e2017-07-04 14:30:38 +0200394 memcpy(stagingIndexBufferAllocInfo.pMappedData, indices, indexBufferSize);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200395
Adam Sawicki2f16fa52017-07-04 14:43:20 +0200396 // No need to flush stagingIndexBuffer memory because CPU_ONLY memory is always HOST_COHERENT.
397
Adam Sawickie6e498f2017-06-16 17:21:31 +0200398 ibInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
Adam Sawicki976f9202017-09-12 20:45:14 +0200399 ibAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
400 ibAllocCreateInfo.flags = 0;
401 ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &ibInfo, &ibAllocCreateInfo, &g_hIndexBuffer, &g_hIndexBufferAlloc, nullptr) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200402
403 // Copy buffers
404
405 BeginSingleTimeCommands();
406
407 VkBufferCopy vbCopyRegion = {};
408 vbCopyRegion.srcOffset = 0;
409 vbCopyRegion.dstOffset = 0;
410 vbCopyRegion.size = vbInfo.size;
411 vkCmdCopyBuffer(g_hTemporaryCommandBuffer, stagingVertexBuffer, g_hVertexBuffer, 1, &vbCopyRegion);
412
413 VkBufferCopy ibCopyRegion = {};
414 ibCopyRegion.srcOffset = 0;
415 ibCopyRegion.dstOffset = 0;
416 ibCopyRegion.size = ibInfo.size;
417 vkCmdCopyBuffer(g_hTemporaryCommandBuffer, stagingIndexBuffer, g_hIndexBuffer, 1, &ibCopyRegion);
418
419 EndSingleTimeCommands();
420
Adam Sawicki819860e2017-07-04 14:30:38 +0200421 vmaDestroyBuffer(g_hAllocator, stagingIndexBuffer, stagingIndexBufferAlloc);
422 vmaDestroyBuffer(g_hAllocator, stagingVertexBuffer, stagingVertexBufferAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200423}
424
Adam Sawickie6e498f2017-06-16 17:21:31 +0200425static void CreateTexture(uint32_t sizeX, uint32_t sizeY)
426{
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100427 // Create staging buffer.
Adam Sawickie6e498f2017-06-16 17:21:31 +0200428
429 const VkDeviceSize imageSize = sizeX * sizeY * 4;
430
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100431 VkBufferCreateInfo stagingBufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
432 stagingBufInfo.size = imageSize;
433 stagingBufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
434
435 VmaAllocationCreateInfo stagingBufAllocCreateInfo = {};
436 stagingBufAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
437 stagingBufAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
Adam Sawicki819860e2017-07-04 14:30:38 +0200438
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100439 VkBuffer stagingBuf = VK_NULL_HANDLE;
440 VmaAllocation stagingBufAlloc = VK_NULL_HANDLE;
441 VmaAllocationInfo stagingBufAllocInfo = {};
442 ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &stagingBufInfo, &stagingBufAllocCreateInfo, &stagingBuf, &stagingBufAlloc, &stagingBufAllocInfo) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200443
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100444 char* const pImageData = (char*)stagingBufAllocInfo.pMappedData;
445 uint8_t* pRowData = (uint8_t*)pImageData;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200446 for(uint32_t y = 0; y < sizeY; ++y)
447 {
448 uint32_t* pPixelData = (uint32_t*)pRowData;
449 for(uint32_t x = 0; x < sizeY; ++x)
450 {
451 *pPixelData =
452 ((x & 0x18) == 0x08 ? 0x000000FF : 0x00000000) |
453 ((x & 0x18) == 0x10 ? 0x0000FFFF : 0x00000000) |
454 ((y & 0x18) == 0x08 ? 0x0000FF00 : 0x00000000) |
455 ((y & 0x18) == 0x10 ? 0x00FF0000 : 0x00000000);
456 ++pPixelData;
457 }
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100458 pRowData += sizeX * 4;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200459 }
460
Adam Sawicki2f16fa52017-07-04 14:43:20 +0200461 // No need to flush stagingImage memory because CPU_ONLY memory is always HOST_COHERENT.
462
Adam Sawicki10844a82017-08-16 17:32:09 +0200463 // Create g_hTextureImage in GPU memory.
464
Adam Sawickie6e498f2017-06-16 17:21:31 +0200465 VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
466 imageInfo.imageType = VK_IMAGE_TYPE_2D;
467 imageInfo.extent.width = sizeX;
468 imageInfo.extent.height = sizeY;
469 imageInfo.extent.depth = 1;
470 imageInfo.mipLevels = 1;
471 imageInfo.arrayLayers = 1;
472 imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
473 imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
474 imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
475 imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
476 imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
477 imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
478 imageInfo.flags = 0;
Adam Sawicki10844a82017-08-16 17:32:09 +0200479
Adam Sawicki976f9202017-09-12 20:45:14 +0200480 VmaAllocationCreateInfo imageAllocCreateInfo = {};
481 imageAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
Adam Sawicki10844a82017-08-16 17:32:09 +0200482
Adam Sawicki976f9202017-09-12 20:45:14 +0200483 ERR_GUARD_VULKAN( vmaCreateImage(g_hAllocator, &imageInfo, &imageAllocCreateInfo, &g_hTextureImage, &g_hTextureImageAlloc, nullptr) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200484
Adam Sawicki10844a82017-08-16 17:32:09 +0200485 // Transition image layouts, copy image.
486
487 BeginSingleTimeCommands();
488
489 VkImageMemoryBarrier imgMemBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
Adam Sawicki10844a82017-08-16 17:32:09 +0200490 imgMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
491 imgMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Adam Sawicki10844a82017-08-16 17:32:09 +0200492 imgMemBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
493 imgMemBarrier.subresourceRange.baseMipLevel = 0;
494 imgMemBarrier.subresourceRange.levelCount = 1;
495 imgMemBarrier.subresourceRange.baseArrayLayer = 0;
496 imgMemBarrier.subresourceRange.layerCount = 1;
Adam Sawicki10844a82017-08-16 17:32:09 +0200497 imgMemBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
498 imgMemBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
499 imgMemBarrier.image = g_hTextureImage;
500 imgMemBarrier.srcAccessMask = 0;
501 imgMemBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
502
503 vkCmdPipelineBarrier(
504 g_hTemporaryCommandBuffer,
505 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
506 VK_PIPELINE_STAGE_TRANSFER_BIT,
507 0,
508 0, nullptr,
509 0, nullptr,
510 1, &imgMemBarrier);
511
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100512 VkBufferImageCopy region = {};
513 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
514 region.imageSubresource.layerCount = 1;
515 region.imageExtent.width = sizeX;
516 region.imageExtent.height = sizeY;
517 region.imageExtent.depth = 1;
518
519 vkCmdCopyBufferToImage(g_hTemporaryCommandBuffer, stagingBuf, g_hTextureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
Adam Sawicki10844a82017-08-16 17:32:09 +0200520
521 imgMemBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
522 imgMemBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
523 imgMemBarrier.image = g_hTextureImage;
524 imgMemBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
525 imgMemBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
526
527 vkCmdPipelineBarrier(
528 g_hTemporaryCommandBuffer,
529 VK_PIPELINE_STAGE_TRANSFER_BIT,
530 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
531 0,
532 0, nullptr,
533 0, nullptr,
534 1, &imgMemBarrier);
535
536 EndSingleTimeCommands();
Adam Sawickie6e498f2017-06-16 17:21:31 +0200537
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100538 vmaDestroyBuffer(g_hAllocator, stagingBuf, stagingBufAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200539
540 // Create ImageView
541
542 VkImageViewCreateInfo textureImageViewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
543 textureImageViewInfo.image = g_hTextureImage;
544 textureImageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
545 textureImageViewInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
546 textureImageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
547 textureImageViewInfo.subresourceRange.baseMipLevel = 0;
548 textureImageViewInfo.subresourceRange.levelCount = 1;
549 textureImageViewInfo.subresourceRange.baseArrayLayer = 0;
550 textureImageViewInfo.subresourceRange.layerCount = 1;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200551 ERR_GUARD_VULKAN( vkCreateImageView(g_hDevice, &textureImageViewInfo, g_Allocs, &g_hTextureImageView) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200552}
553
554struct UniformBufferObject
555{
Adam Sawicki82c3f332018-06-11 15:27:33 +0200556 mat4 ModelViewProj;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200557};
558
559static void RegisterDebugCallbacks()
560{
561 g_pvkCreateDebugReportCallbackEXT =
562 reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>
563 (vkGetInstanceProcAddr(g_hVulkanInstance, "vkCreateDebugReportCallbackEXT"));
564 g_pvkDebugReportMessageEXT =
565 reinterpret_cast<PFN_vkDebugReportMessageEXT>
566 (vkGetInstanceProcAddr(g_hVulkanInstance, "vkDebugReportMessageEXT"));
567 g_pvkDestroyDebugReportCallbackEXT =
568 reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>
569 (vkGetInstanceProcAddr(g_hVulkanInstance, "vkDestroyDebugReportCallbackEXT"));
570 assert(g_pvkCreateDebugReportCallbackEXT);
571 assert(g_pvkDebugReportMessageEXT);
572 assert(g_pvkDestroyDebugReportCallbackEXT);
573
574 VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
575 callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
576 callbackCreateInfo.pNext = nullptr;
577 callbackCreateInfo.flags = //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
578 VK_DEBUG_REPORT_ERROR_BIT_EXT |
579 VK_DEBUG_REPORT_WARNING_BIT_EXT |
580 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT /*|
581 VK_DEBUG_REPORT_DEBUG_BIT_EXT*/;
582 callbackCreateInfo.pfnCallback = &MyDebugReportCallback;
583 callbackCreateInfo.pUserData = nullptr;
584
Adam Sawicki1f84f622019-07-02 13:40:01 +0200585 ERR_GUARD_VULKAN( g_pvkCreateDebugReportCallbackEXT(g_hVulkanInstance, &callbackCreateInfo, g_Allocs, &g_hCallback) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200586}
587
588static bool IsLayerSupported(const VkLayerProperties* pProps, size_t propCount, const char* pLayerName)
589{
590 const VkLayerProperties* propsEnd = pProps + propCount;
591 return std::find_if(
592 pProps,
593 propsEnd,
594 [pLayerName](const VkLayerProperties& prop) -> bool {
595 return strcmp(pLayerName, prop.layerName) == 0;
596 }) != propsEnd;
597}
598
599static VkFormat FindSupportedFormat(
600 const std::vector<VkFormat>& candidates,
601 VkImageTiling tiling,
602 VkFormatFeatureFlags features)
603{
604 for (VkFormat format : candidates)
605 {
606 VkFormatProperties props;
607 vkGetPhysicalDeviceFormatProperties(g_hPhysicalDevice, format, &props);
608
609 if ((tiling == VK_IMAGE_TILING_LINEAR) &&
610 ((props.linearTilingFeatures & features) == features))
611 {
612 return format;
613 }
614 else if ((tiling == VK_IMAGE_TILING_OPTIMAL) &&
615 ((props.optimalTilingFeatures & features) == features))
616 {
617 return format;
618 }
619 }
620 return VK_FORMAT_UNDEFINED;
621}
622
623static VkFormat FindDepthFormat()
624{
625 std::vector<VkFormat> formats;
626 formats.push_back(VK_FORMAT_D32_SFLOAT);
627 formats.push_back(VK_FORMAT_D32_SFLOAT_S8_UINT);
628 formats.push_back(VK_FORMAT_D24_UNORM_S8_UINT);
629
630 return FindSupportedFormat(
631 formats,
632 VK_IMAGE_TILING_OPTIMAL,
633 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
634}
635
636static void CreateSwapchain()
637{
638 // Query surface formats.
639
640 ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_hPhysicalDevice, g_hSurface, &g_SurfaceCapabilities) );
641
642 uint32_t formatCount = 0;
643 ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfaceFormatsKHR(g_hPhysicalDevice, g_hSurface, &formatCount, nullptr) );
644 g_SurfaceFormats.resize(formatCount);
645 ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfaceFormatsKHR(g_hPhysicalDevice, g_hSurface, &formatCount, g_SurfaceFormats.data()) );
646
647 uint32_t presentModeCount = 0;
648 ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfacePresentModesKHR(g_hPhysicalDevice, g_hSurface, &presentModeCount, nullptr) );
649 g_PresentModes.resize(presentModeCount);
650 ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfacePresentModesKHR(g_hPhysicalDevice, g_hSurface, &presentModeCount, g_PresentModes.data()) );
651
652 // Create swap chain
653
654 g_SurfaceFormat = ChooseSurfaceFormat();
655 VkPresentModeKHR presentMode = ChooseSwapPresentMode();
656 g_Extent = ChooseSwapExtent();
657
658 uint32_t imageCount = g_SurfaceCapabilities.minImageCount + 1;
659 if((g_SurfaceCapabilities.maxImageCount > 0) &&
660 (imageCount > g_SurfaceCapabilities.maxImageCount))
661 {
662 imageCount = g_SurfaceCapabilities.maxImageCount;
663 }
664
665 VkSwapchainCreateInfoKHR swapChainInfo = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR };
666 swapChainInfo.surface = g_hSurface;
667 swapChainInfo.minImageCount = imageCount;
668 swapChainInfo.imageFormat = g_SurfaceFormat.format;
669 swapChainInfo.imageColorSpace = g_SurfaceFormat.colorSpace;
670 swapChainInfo.imageExtent = g_Extent;
671 swapChainInfo.imageArrayLayers = 1;
672 swapChainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
673 swapChainInfo.preTransform = g_SurfaceCapabilities.currentTransform;
674 swapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
675 swapChainInfo.presentMode = presentMode;
676 swapChainInfo.clipped = VK_TRUE;
677 swapChainInfo.oldSwapchain = g_hSwapchain;
678
679 uint32_t queueFamilyIndices[] = { g_GraphicsQueueFamilyIndex, g_PresentQueueFamilyIndex };
680 if(g_PresentQueueFamilyIndex != g_GraphicsQueueFamilyIndex)
681 {
682 swapChainInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
683 swapChainInfo.queueFamilyIndexCount = 2;
684 swapChainInfo.pQueueFamilyIndices = queueFamilyIndices;
685 }
686 else
687 {
688 swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
689 }
690
691 VkSwapchainKHR hNewSwapchain = VK_NULL_HANDLE;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200692 ERR_GUARD_VULKAN( vkCreateSwapchainKHR(g_hDevice, &swapChainInfo, g_Allocs, &hNewSwapchain) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200693 if(g_hSwapchain != VK_NULL_HANDLE)
Adam Sawicki1f84f622019-07-02 13:40:01 +0200694 vkDestroySwapchainKHR(g_hDevice, g_hSwapchain, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200695 g_hSwapchain = hNewSwapchain;
696
697 // Retrieve swapchain images.
698
699 uint32_t swapchainImageCount = 0;
700 ERR_GUARD_VULKAN( vkGetSwapchainImagesKHR(g_hDevice, g_hSwapchain, &swapchainImageCount, nullptr) );
701 g_SwapchainImages.resize(swapchainImageCount);
702 ERR_GUARD_VULKAN( vkGetSwapchainImagesKHR(g_hDevice, g_hSwapchain, &swapchainImageCount, g_SwapchainImages.data()) );
703
704 // Create swapchain image views.
705
706 for(size_t i = g_SwapchainImageViews.size(); i--; )
Adam Sawicki1f84f622019-07-02 13:40:01 +0200707 vkDestroyImageView(g_hDevice, g_SwapchainImageViews[i], g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200708 g_SwapchainImageViews.clear();
709
710 VkImageViewCreateInfo swapchainImageViewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
711 g_SwapchainImageViews.resize(swapchainImageCount);
712 for(uint32_t i = 0; i < swapchainImageCount; ++i)
713 {
714 swapchainImageViewInfo.image = g_SwapchainImages[i];
715 swapchainImageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
716 swapchainImageViewInfo.format = g_SurfaceFormat.format;
717 swapchainImageViewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
718 swapchainImageViewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
719 swapchainImageViewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
720 swapchainImageViewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
721 swapchainImageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
722 swapchainImageViewInfo.subresourceRange.baseMipLevel = 0;
723 swapchainImageViewInfo.subresourceRange.levelCount = 1;
724 swapchainImageViewInfo.subresourceRange.baseArrayLayer = 0;
725 swapchainImageViewInfo.subresourceRange.layerCount = 1;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200726 ERR_GUARD_VULKAN( vkCreateImageView(g_hDevice, &swapchainImageViewInfo, g_Allocs, &g_SwapchainImageViews[i]) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200727 }
728
729 // Create depth buffer
730
731 g_DepthFormat = FindDepthFormat();
732 assert(g_DepthFormat != VK_FORMAT_UNDEFINED);
733
734 VkImageCreateInfo depthImageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
735 depthImageInfo.imageType = VK_IMAGE_TYPE_2D;
736 depthImageInfo.extent.width = g_Extent.width;
737 depthImageInfo.extent.height = g_Extent.height;
738 depthImageInfo.extent.depth = 1;
739 depthImageInfo.mipLevels = 1;
740 depthImageInfo.arrayLayers = 1;
741 depthImageInfo.format = g_DepthFormat;
742 depthImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
743 depthImageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
744 depthImageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
745 depthImageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
746 depthImageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
747 depthImageInfo.flags = 0;
748
Adam Sawicki976f9202017-09-12 20:45:14 +0200749 VmaAllocationCreateInfo depthImageAllocCreateInfo = {};
750 depthImageAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200751
Adam Sawicki976f9202017-09-12 20:45:14 +0200752 ERR_GUARD_VULKAN( vmaCreateImage(g_hAllocator, &depthImageInfo, &depthImageAllocCreateInfo, &g_hDepthImage, &g_hDepthImageAlloc, nullptr) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200753
754 VkImageViewCreateInfo depthImageViewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
755 depthImageViewInfo.image = g_hDepthImage;
756 depthImageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
757 depthImageViewInfo.format = g_DepthFormat;
758 depthImageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
759 depthImageViewInfo.subresourceRange.baseMipLevel = 0;
760 depthImageViewInfo.subresourceRange.levelCount = 1;
761 depthImageViewInfo.subresourceRange.baseArrayLayer = 0;
762 depthImageViewInfo.subresourceRange.layerCount = 1;
763
Adam Sawicki1f84f622019-07-02 13:40:01 +0200764 ERR_GUARD_VULKAN( vkCreateImageView(g_hDevice, &depthImageViewInfo, g_Allocs, &g_hDepthImageView) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200765
Adam Sawickie6e498f2017-06-16 17:21:31 +0200766 // Create pipeline layout
767 {
768 if(g_hPipelineLayout != VK_NULL_HANDLE)
769 {
Adam Sawicki1f84f622019-07-02 13:40:01 +0200770 vkDestroyPipelineLayout(g_hDevice, g_hPipelineLayout, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200771 g_hPipelineLayout = VK_NULL_HANDLE;
772 }
773
774 VkPushConstantRange pushConstantRanges[1];
775 ZeroMemory(&pushConstantRanges, sizeof pushConstantRanges);
776 pushConstantRanges[0].offset = 0;
777 pushConstantRanges[0].size = sizeof(UniformBufferObject);
778 pushConstantRanges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
779
780 VkDescriptorSetLayout descriptorSetLayouts[] = { g_hDescriptorSetLayout };
781 VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
782 pipelineLayoutInfo.setLayoutCount = 1;
783 pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts;
784 pipelineLayoutInfo.pushConstantRangeCount = 1;
785 pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200786 ERR_GUARD_VULKAN( vkCreatePipelineLayout(g_hDevice, &pipelineLayoutInfo, g_Allocs, &g_hPipelineLayout) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200787 }
788
789 // Create render pass
790 {
791 if(g_hRenderPass != VK_NULL_HANDLE)
792 {
Adam Sawicki1f84f622019-07-02 13:40:01 +0200793 vkDestroyRenderPass(g_hDevice, g_hRenderPass, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200794 g_hRenderPass = VK_NULL_HANDLE;
795 }
796
797 VkAttachmentDescription attachments[2];
798 ZeroMemory(attachments, sizeof(attachments));
799
800 attachments[0].format = g_SurfaceFormat.format;
801 attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
802 attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
803 attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
804 attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
805 attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
Adam Sawicki8eb9d8e2017-11-13 16:30:14 +0100806 attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200807 attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
808
809 attachments[1].format = g_DepthFormat;
810 attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
811 attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
812 attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
813 attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
814 attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
Adam Sawicki8eb9d8e2017-11-13 16:30:14 +0100815 attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200816 attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
817
818 VkAttachmentReference colorAttachmentRef = {};
819 colorAttachmentRef.attachment = 0;
820 colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
821
822 VkAttachmentReference depthStencilAttachmentRef = {};
823 depthStencilAttachmentRef.attachment = 1;
824 depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
825
826 VkSubpassDescription subpassDesc = {};
827 subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
828 subpassDesc.colorAttachmentCount = 1;
829 subpassDesc.pColorAttachments = &colorAttachmentRef;
830 subpassDesc.pDepthStencilAttachment = &depthStencilAttachmentRef;
831
Adam Sawickie6e498f2017-06-16 17:21:31 +0200832 VkRenderPassCreateInfo renderPassInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
833 renderPassInfo.attachmentCount = (uint32_t)_countof(attachments);
834 renderPassInfo.pAttachments = attachments;
835 renderPassInfo.subpassCount = 1;
836 renderPassInfo.pSubpasses = &subpassDesc;
Adam Sawicki14137d12017-10-16 18:06:05 +0200837 renderPassInfo.dependencyCount = 0;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200838 ERR_GUARD_VULKAN( vkCreateRenderPass(g_hDevice, &renderPassInfo, g_Allocs, &g_hRenderPass) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200839 }
840
841 // Create pipeline
842 {
843 std::vector<char> vertShaderCode;
844 LoadShader(vertShaderCode, "Shader.vert.spv");
845 VkShaderModuleCreateInfo shaderModuleInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
846 shaderModuleInfo.codeSize = vertShaderCode.size();
847 shaderModuleInfo.pCode = (const uint32_t*)vertShaderCode.data();
848 VkShaderModule hVertShaderModule = VK_NULL_HANDLE;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200849 ERR_GUARD_VULKAN( vkCreateShaderModule(g_hDevice, &shaderModuleInfo, g_Allocs, &hVertShaderModule) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200850
851 std::vector<char> hFragShaderCode;
852 LoadShader(hFragShaderCode, "Shader.frag.spv");
853 shaderModuleInfo.codeSize = hFragShaderCode.size();
854 shaderModuleInfo.pCode = (const uint32_t*)hFragShaderCode.data();
855 VkShaderModule fragShaderModule = VK_NULL_HANDLE;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200856 ERR_GUARD_VULKAN( vkCreateShaderModule(g_hDevice, &shaderModuleInfo, g_Allocs, &fragShaderModule) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200857
858 VkPipelineShaderStageCreateInfo vertPipelineShaderStageInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
859 vertPipelineShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
860 vertPipelineShaderStageInfo.module = hVertShaderModule;
861 vertPipelineShaderStageInfo.pName = "main";
862
863 VkPipelineShaderStageCreateInfo fragPipelineShaderStageInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
864 fragPipelineShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
865 fragPipelineShaderStageInfo.module = fragShaderModule;
866 fragPipelineShaderStageInfo.pName = "main";
867
868 VkPipelineShaderStageCreateInfo pipelineShaderStageInfos[] = {
869 vertPipelineShaderStageInfo,
870 fragPipelineShaderStageInfo
871 };
872
873 VkVertexInputBindingDescription bindingDescription = {};
874 bindingDescription.binding = 0;
875 bindingDescription.stride = sizeof(Vertex);
876 bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
877
878 VkVertexInputAttributeDescription attributeDescriptions[3];
879 ZeroMemory(attributeDescriptions, sizeof(attributeDescriptions));
880
881 attributeDescriptions[0].binding = 0;
882 attributeDescriptions[0].location = 0;
883 attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
884 attributeDescriptions[0].offset = offsetof(Vertex, pos);
885
886 attributeDescriptions[1].binding = 0;
887 attributeDescriptions[1].location = 1;
888 attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
889 attributeDescriptions[1].offset = offsetof(Vertex, color);
890
891 attributeDescriptions[2].binding = 0;
892 attributeDescriptions[2].location = 2;
893 attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
894 attributeDescriptions[2].offset = offsetof(Vertex, texCoord);
895
896 VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
897 pipelineVertexInputStateInfo.vertexBindingDescriptionCount = 1;
898 pipelineVertexInputStateInfo.pVertexBindingDescriptions = &bindingDescription;
899 pipelineVertexInputStateInfo.vertexAttributeDescriptionCount = _countof(attributeDescriptions);
900 pipelineVertexInputStateInfo.pVertexAttributeDescriptions = attributeDescriptions;
901
902 VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
903 pipelineInputAssemblyStateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
904 pipelineInputAssemblyStateInfo.primitiveRestartEnable = VK_TRUE;
905
906 VkViewport viewport = {};
907 viewport.x = 0.f;
908 viewport.y = 0.f;
909 viewport.width = (float)g_Extent.width;
910 viewport.height = (float)g_Extent.height;
911 viewport.minDepth = 0.f;
912 viewport.maxDepth = 1.f;
913
914 VkRect2D scissor = {};
915 scissor.offset.x = 0;
916 scissor.offset.y = 0;
917 scissor.extent = g_Extent;
918
919 VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
920 pipelineViewportStateInfo.viewportCount = 1;
921 pipelineViewportStateInfo.pViewports = &viewport;
922 pipelineViewportStateInfo.scissorCount = 1;
923 pipelineViewportStateInfo.pScissors = &scissor;
924
925 VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
926 pipelineRasterizationStateInfo.depthClampEnable = VK_FALSE;
927 pipelineRasterizationStateInfo.rasterizerDiscardEnable = VK_FALSE;
928 pipelineRasterizationStateInfo.polygonMode = VK_POLYGON_MODE_FILL;
929 pipelineRasterizationStateInfo.lineWidth = 1.f;
930 pipelineRasterizationStateInfo.cullMode = VK_CULL_MODE_BACK_BIT;
931 pipelineRasterizationStateInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
932 pipelineRasterizationStateInfo.depthBiasEnable = VK_FALSE;
933 pipelineRasterizationStateInfo.depthBiasConstantFactor = 0.f;
934 pipelineRasterizationStateInfo.depthBiasClamp = 0.f;
935 pipelineRasterizationStateInfo.depthBiasSlopeFactor = 0.f;
936
937 VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
938 pipelineMultisampleStateInfo.sampleShadingEnable = VK_FALSE;
939 pipelineMultisampleStateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
940 pipelineMultisampleStateInfo.minSampleShading = 1.f;
941 pipelineMultisampleStateInfo.pSampleMask = nullptr;
942 pipelineMultisampleStateInfo.alphaToCoverageEnable = VK_FALSE;
943 pipelineMultisampleStateInfo.alphaToOneEnable = VK_FALSE;
944
945 VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {};
946 pipelineColorBlendAttachmentState.colorWriteMask =
947 VK_COLOR_COMPONENT_R_BIT |
948 VK_COLOR_COMPONENT_G_BIT |
949 VK_COLOR_COMPONENT_B_BIT |
950 VK_COLOR_COMPONENT_A_BIT;
951 pipelineColorBlendAttachmentState.blendEnable = VK_FALSE;
952 pipelineColorBlendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
953 pipelineColorBlendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
954 pipelineColorBlendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; // Optional
955 pipelineColorBlendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
956 pipelineColorBlendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
957 pipelineColorBlendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; // Optional
958
959 VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
960 pipelineColorBlendStateInfo.logicOpEnable = VK_FALSE;
961 pipelineColorBlendStateInfo.logicOp = VK_LOGIC_OP_COPY;
962 pipelineColorBlendStateInfo.attachmentCount = 1;
963 pipelineColorBlendStateInfo.pAttachments = &pipelineColorBlendAttachmentState;
964
965 VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
966 depthStencilStateInfo.depthTestEnable = VK_TRUE;
967 depthStencilStateInfo.depthWriteEnable = VK_TRUE;
968 depthStencilStateInfo.depthCompareOp = VK_COMPARE_OP_LESS;
969 depthStencilStateInfo.depthBoundsTestEnable = VK_FALSE;
970 depthStencilStateInfo.stencilTestEnable = VK_FALSE;
971
972 VkGraphicsPipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
973 pipelineInfo.stageCount = 2;
974 pipelineInfo.pStages = pipelineShaderStageInfos;
975 pipelineInfo.pVertexInputState = &pipelineVertexInputStateInfo;
976 pipelineInfo.pInputAssemblyState = &pipelineInputAssemblyStateInfo;
977 pipelineInfo.pViewportState = &pipelineViewportStateInfo;
978 pipelineInfo.pRasterizationState = &pipelineRasterizationStateInfo;
979 pipelineInfo.pMultisampleState = &pipelineMultisampleStateInfo;
980 pipelineInfo.pDepthStencilState = &depthStencilStateInfo;
981 pipelineInfo.pColorBlendState = &pipelineColorBlendStateInfo;
982 pipelineInfo.pDynamicState = nullptr;
983 pipelineInfo.layout = g_hPipelineLayout;
984 pipelineInfo.renderPass = g_hRenderPass;
985 pipelineInfo.subpass = 0;
986 pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
987 pipelineInfo.basePipelineIndex = -1;
988 ERR_GUARD_VULKAN( vkCreateGraphicsPipelines(
989 g_hDevice,
990 VK_NULL_HANDLE,
991 1,
Adam Sawicki1f84f622019-07-02 13:40:01 +0200992 &pipelineInfo,
993 g_Allocs,
Adam Sawickie6e498f2017-06-16 17:21:31 +0200994 &g_hPipeline) );
995
Adam Sawicki1f84f622019-07-02 13:40:01 +0200996 vkDestroyShaderModule(g_hDevice, fragShaderModule, g_Allocs);
997 vkDestroyShaderModule(g_hDevice, hVertShaderModule, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200998 }
999
1000 // Create frambuffers
1001
1002 for(size_t i = g_Framebuffers.size(); i--; )
Adam Sawicki1f84f622019-07-02 13:40:01 +02001003 vkDestroyFramebuffer(g_hDevice, g_Framebuffers[i], g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001004 g_Framebuffers.clear();
1005
1006 g_Framebuffers.resize(g_SwapchainImageViews.size());
1007 for(size_t i = 0; i < g_SwapchainImages.size(); ++i)
1008 {
1009 VkImageView attachments[] = { g_SwapchainImageViews[i], g_hDepthImageView };
1010
1011 VkFramebufferCreateInfo framebufferInfo = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
1012 framebufferInfo.renderPass = g_hRenderPass;
1013 framebufferInfo.attachmentCount = (uint32_t)_countof(attachments);
1014 framebufferInfo.pAttachments = attachments;
1015 framebufferInfo.width = g_Extent.width;
1016 framebufferInfo.height = g_Extent.height;
1017 framebufferInfo.layers = 1;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001018 ERR_GUARD_VULKAN( vkCreateFramebuffer(g_hDevice, &framebufferInfo, g_Allocs, &g_Framebuffers[i]) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001019 }
1020
1021 // Create semaphores
1022
1023 if(g_hImageAvailableSemaphore != VK_NULL_HANDLE)
1024 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001025 vkDestroySemaphore(g_hDevice, g_hImageAvailableSemaphore, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001026 g_hImageAvailableSemaphore = VK_NULL_HANDLE;
1027 }
1028 if(g_hRenderFinishedSemaphore != VK_NULL_HANDLE)
1029 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001030 vkDestroySemaphore(g_hDevice, g_hRenderFinishedSemaphore, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001031 g_hRenderFinishedSemaphore = VK_NULL_HANDLE;
1032 }
1033
1034 VkSemaphoreCreateInfo semaphoreInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
Adam Sawicki1f84f622019-07-02 13:40:01 +02001035 ERR_GUARD_VULKAN( vkCreateSemaphore(g_hDevice, &semaphoreInfo, g_Allocs, &g_hImageAvailableSemaphore) );
1036 ERR_GUARD_VULKAN( vkCreateSemaphore(g_hDevice, &semaphoreInfo, g_Allocs, &g_hRenderFinishedSemaphore) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001037}
1038
1039static void DestroySwapchain(bool destroyActualSwapchain)
1040{
1041 if(g_hImageAvailableSemaphore != VK_NULL_HANDLE)
1042 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001043 vkDestroySemaphore(g_hDevice, g_hImageAvailableSemaphore, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001044 g_hImageAvailableSemaphore = VK_NULL_HANDLE;
1045 }
1046 if(g_hRenderFinishedSemaphore != VK_NULL_HANDLE)
1047 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001048 vkDestroySemaphore(g_hDevice, g_hRenderFinishedSemaphore, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001049 g_hRenderFinishedSemaphore = VK_NULL_HANDLE;
1050 }
1051
1052 for(size_t i = g_Framebuffers.size(); i--; )
Adam Sawicki1f84f622019-07-02 13:40:01 +02001053 vkDestroyFramebuffer(g_hDevice, g_Framebuffers[i], g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001054 g_Framebuffers.clear();
1055
1056 if(g_hDepthImageView != VK_NULL_HANDLE)
1057 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001058 vkDestroyImageView(g_hDevice, g_hDepthImageView, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001059 g_hDepthImageView = VK_NULL_HANDLE;
1060 }
1061 if(g_hDepthImage != VK_NULL_HANDLE)
1062 {
Adam Sawicki819860e2017-07-04 14:30:38 +02001063 vmaDestroyImage(g_hAllocator, g_hDepthImage, g_hDepthImageAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001064 g_hDepthImage = VK_NULL_HANDLE;
1065 }
1066
1067 if(g_hPipeline != VK_NULL_HANDLE)
1068 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001069 vkDestroyPipeline(g_hDevice, g_hPipeline, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001070 g_hPipeline = VK_NULL_HANDLE;
1071 }
1072
1073 if(g_hRenderPass != VK_NULL_HANDLE)
1074 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001075 vkDestroyRenderPass(g_hDevice, g_hRenderPass, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001076 g_hRenderPass = VK_NULL_HANDLE;
1077 }
1078
1079 if(g_hPipelineLayout != VK_NULL_HANDLE)
1080 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001081 vkDestroyPipelineLayout(g_hDevice, g_hPipelineLayout, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001082 g_hPipelineLayout = VK_NULL_HANDLE;
1083 }
1084
1085 for(size_t i = g_SwapchainImageViews.size(); i--; )
Adam Sawicki1f84f622019-07-02 13:40:01 +02001086 vkDestroyImageView(g_hDevice, g_SwapchainImageViews[i], g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001087 g_SwapchainImageViews.clear();
1088
1089 if(destroyActualSwapchain && (g_hSwapchain != VK_NULL_HANDLE))
1090 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001091 vkDestroySwapchainKHR(g_hDevice, g_hSwapchain, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001092 g_hSwapchain = VK_NULL_HANDLE;
1093 }
1094}
1095
1096static void InitializeApplication()
1097{
Adam Sawicki1f84f622019-07-02 13:40:01 +02001098 if(USE_CUSTOM_CPU_ALLOCATION_CALLBACKS)
1099 {
1100 g_Allocs = &g_CpuAllocationCallbacks;
1101 }
1102
Adam Sawickie6e498f2017-06-16 17:21:31 +02001103 uint32_t instanceLayerPropCount = 0;
1104 ERR_GUARD_VULKAN( vkEnumerateInstanceLayerProperties(&instanceLayerPropCount, nullptr) );
1105 std::vector<VkLayerProperties> instanceLayerProps(instanceLayerPropCount);
1106 if(instanceLayerPropCount > 0)
1107 {
1108 ERR_GUARD_VULKAN( vkEnumerateInstanceLayerProperties(&instanceLayerPropCount, instanceLayerProps.data()) );
1109 }
1110
1111 if(g_EnableValidationLayer == true)
1112 {
1113 if(IsLayerSupported(instanceLayerProps.data(), instanceLayerProps.size(), VALIDATION_LAYER_NAME) == false)
1114 {
1115 printf("Layer \"%s\" not supported.", VALIDATION_LAYER_NAME);
1116 g_EnableValidationLayer = false;
1117 }
1118 }
1119
Adam Sawicki353e3672019-11-02 14:12:05 +01001120 uint32_t availableInstanceExtensionCount = 0;
1121 ERR_GUARD_VULKAN( vkEnumerateInstanceExtensionProperties(nullptr, &availableInstanceExtensionCount, nullptr) );
1122 std::vector<VkExtensionProperties> availableInstanceExtensions(availableInstanceExtensionCount);
1123 if(availableInstanceExtensionCount > 0)
1124 {
1125 ERR_GUARD_VULKAN( vkEnumerateInstanceExtensionProperties(nullptr, &availableInstanceExtensionCount, availableInstanceExtensions.data()) );
1126 }
1127
1128 std::vector<const char*> enabledInstanceExtensions;
1129 enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
1130 enabledInstanceExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001131
1132 std::vector<const char*> instanceLayers;
1133 if(g_EnableValidationLayer == true)
1134 {
1135 instanceLayers.push_back(VALIDATION_LAYER_NAME);
Adam Sawicki353e3672019-11-02 14:12:05 +01001136 enabledInstanceExtensions.push_back("VK_EXT_debug_report");
1137 }
1138
1139 for(const auto& extensionProperties : availableInstanceExtensions)
1140 {
1141 if(strcmp(extensionProperties.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0)
1142 {
1143 enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1144 VK_KHR_get_physical_device_properties2_enabled = true;
1145 }
Adam Sawickie6e498f2017-06-16 17:21:31 +02001146 }
1147
1148 VkApplicationInfo appInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
1149 appInfo.pApplicationName = APP_TITLE_A;
1150 appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
1151 appInfo.pEngineName = "Adam Sawicki Engine";
1152 appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
1153 appInfo.apiVersion = VK_API_VERSION_1_0;
1154
1155 VkInstanceCreateInfo instInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
1156 instInfo.pApplicationInfo = &appInfo;
Adam Sawicki353e3672019-11-02 14:12:05 +01001157 instInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size());
1158 instInfo.ppEnabledExtensionNames = enabledInstanceExtensions.data();
Adam Sawickie6e498f2017-06-16 17:21:31 +02001159 instInfo.enabledLayerCount = static_cast<uint32_t>(instanceLayers.size());
1160 instInfo.ppEnabledLayerNames = instanceLayers.data();
1161
Adam Sawicki1f84f622019-07-02 13:40:01 +02001162 ERR_GUARD_VULKAN( vkCreateInstance(&instInfo, g_Allocs, &g_hVulkanInstance) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001163
1164 // Create VkSurfaceKHR.
1165 VkWin32SurfaceCreateInfoKHR surfaceInfo = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR };
1166 surfaceInfo.hinstance = g_hAppInstance;
1167 surfaceInfo.hwnd = g_hWnd;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001168 VkResult result = vkCreateWin32SurfaceKHR(g_hVulkanInstance, &surfaceInfo, g_Allocs, &g_hSurface);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001169 assert(result == VK_SUCCESS);
1170
1171 if(g_EnableValidationLayer == true)
1172 RegisterDebugCallbacks();
1173
1174 // Find physical device
1175
1176 uint32_t deviceCount = 0;
1177 ERR_GUARD_VULKAN( vkEnumeratePhysicalDevices(g_hVulkanInstance, &deviceCount, nullptr) );
1178 assert(deviceCount > 0);
1179
1180 std::vector<VkPhysicalDevice> physicalDevices(deviceCount);
1181 ERR_GUARD_VULKAN( vkEnumeratePhysicalDevices(g_hVulkanInstance, &deviceCount, physicalDevices.data()) );
1182
1183 g_hPhysicalDevice = physicalDevices[0];
1184
1185 // Query for features
1186
1187 VkPhysicalDeviceProperties physicalDeviceProperties = {};
1188 vkGetPhysicalDeviceProperties(g_hPhysicalDevice, &physicalDeviceProperties);
1189
Adam Sawicki51fa9662018-10-03 13:44:29 +02001190 VkPhysicalDeviceFeatures physicalDeviceFeatures = {};
1191 vkGetPhysicalDeviceFeatures(g_hPhysicalDevice, &physicalDeviceFeatures);
1192
1193 g_SparseBindingEnabled = physicalDeviceFeatures.sparseBinding != 0;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001194
1195 // Find queue family index
1196
1197 uint32_t queueFamilyCount = 0;
1198 vkGetPhysicalDeviceQueueFamilyProperties(g_hPhysicalDevice, &queueFamilyCount, nullptr);
1199 assert(queueFamilyCount > 0);
1200 std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
1201 vkGetPhysicalDeviceQueueFamilyProperties(g_hPhysicalDevice, &queueFamilyCount, queueFamilies.data());
1202 for(uint32_t i = 0;
1203 (i < queueFamilyCount) &&
Adam Sawicki51fa9662018-10-03 13:44:29 +02001204 (g_GraphicsQueueFamilyIndex == UINT_MAX ||
1205 g_PresentQueueFamilyIndex == UINT_MAX ||
1206 (g_SparseBindingEnabled && g_SparseBindingQueueFamilyIndex == UINT_MAX));
Adam Sawickie6e498f2017-06-16 17:21:31 +02001207 ++i)
1208 {
1209 if(queueFamilies[i].queueCount > 0)
1210 {
Adam Sawickida6c1942018-12-05 17:34:34 +01001211 const uint32_t flagsForGraphicsQueue = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001212 if((g_GraphicsQueueFamilyIndex != 0) &&
Adam Sawickida6c1942018-12-05 17:34:34 +01001213 ((queueFamilies[i].queueFlags & flagsForGraphicsQueue) == flagsForGraphicsQueue))
Adam Sawickie6e498f2017-06-16 17:21:31 +02001214 {
1215 g_GraphicsQueueFamilyIndex = i;
1216 }
1217
1218 VkBool32 surfaceSupported = 0;
1219 VkResult res = vkGetPhysicalDeviceSurfaceSupportKHR(g_hPhysicalDevice, i, g_hSurface, &surfaceSupported);
1220 if((res >= 0) && (surfaceSupported == VK_TRUE))
1221 {
1222 g_PresentQueueFamilyIndex = i;
1223 }
Adam Sawicki51fa9662018-10-03 13:44:29 +02001224
1225 if(g_SparseBindingEnabled &&
1226 g_SparseBindingQueueFamilyIndex == UINT32_MAX &&
1227 (queueFamilies[i].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) != 0)
1228 {
1229 g_SparseBindingQueueFamilyIndex = i;
1230 }
Adam Sawickie6e498f2017-06-16 17:21:31 +02001231 }
1232 }
1233 assert(g_GraphicsQueueFamilyIndex != UINT_MAX);
1234
Adam Sawicki51fa9662018-10-03 13:44:29 +02001235 g_SparseBindingEnabled = g_SparseBindingEnabled && g_SparseBindingQueueFamilyIndex != UINT32_MAX;
1236
Adam Sawickie6e498f2017-06-16 17:21:31 +02001237 // Create logical device
1238
1239 const float queuePriority = 1.f;
1240
Adam Sawicki51fa9662018-10-03 13:44:29 +02001241 VkDeviceQueueCreateInfo queueCreateInfo[3] = {};
1242 uint32_t queueCount = 1;
1243 queueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
1244 queueCreateInfo[0].queueFamilyIndex = g_GraphicsQueueFamilyIndex;
1245 queueCreateInfo[0].queueCount = 1;
1246 queueCreateInfo[0].pQueuePriorities = &queuePriority;
1247
1248 if(g_PresentQueueFamilyIndex != g_GraphicsQueueFamilyIndex)
1249 {
1250
1251 queueCreateInfo[queueCount].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
1252 queueCreateInfo[queueCount].queueFamilyIndex = g_PresentQueueFamilyIndex;
1253 queueCreateInfo[queueCount].queueCount = 1;
1254 queueCreateInfo[queueCount].pQueuePriorities = &queuePriority;
1255 ++queueCount;
1256 }
1257
1258 if(g_SparseBindingEnabled &&
1259 g_SparseBindingQueueFamilyIndex != g_GraphicsQueueFamilyIndex &&
1260 g_SparseBindingQueueFamilyIndex != g_PresentQueueFamilyIndex)
1261 {
1262
1263 queueCreateInfo[queueCount].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
1264 queueCreateInfo[queueCount].queueFamilyIndex = g_SparseBindingQueueFamilyIndex;
1265 queueCreateInfo[queueCount].queueCount = 1;
1266 queueCreateInfo[queueCount].pQueuePriorities = &queuePriority;
1267 ++queueCount;
1268 }
Adam Sawickie6e498f2017-06-16 17:21:31 +02001269
1270 VkPhysicalDeviceFeatures deviceFeatures = {};
Adam Sawicki51fa9662018-10-03 13:44:29 +02001271 //deviceFeatures.fillModeNonSolid = VK_TRUE;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001272 deviceFeatures.samplerAnisotropy = VK_TRUE;
Adam Sawicki51fa9662018-10-03 13:44:29 +02001273 deviceFeatures.sparseBinding = g_SparseBindingEnabled ? VK_TRUE : VK_FALSE;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001274
Adam Sawicki6cc5e852018-03-13 16:37:54 +01001275 // Determine list of device extensions to enable.
Adam Sawickie6e498f2017-06-16 17:21:31 +02001276 std::vector<const char*> enabledDeviceExtensions;
1277 enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Adam Sawicki6cc5e852018-03-13 16:37:54 +01001278 {
1279 uint32_t propertyCount = 0;
1280 ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(g_hPhysicalDevice, nullptr, &propertyCount, nullptr) );
1281
1282 if(propertyCount)
1283 {
1284 std::vector<VkExtensionProperties> properties{propertyCount};
1285 ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(g_hPhysicalDevice, nullptr, &propertyCount, properties.data()) );
1286
1287 for(uint32_t i = 0; i < propertyCount; ++i)
1288 {
1289 if(strcmp(properties[i].extensionName, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME) == 0)
1290 {
1291 enabledDeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
1292 VK_KHR_get_memory_requirements2_enabled = true;
1293 }
1294 else if(strcmp(properties[i].extensionName, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) == 0)
1295 {
1296 enabledDeviceExtensions.push_back(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
1297 VK_KHR_dedicated_allocation_enabled = true;
1298 }
Adam Sawicki4abe30c2019-07-02 14:37:21 +02001299 else if(strcmp(properties[i].extensionName, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME) == 0)
1300 {
1301 enabledDeviceExtensions.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
1302 VK_KHR_bind_memory2_enabled = true;
1303 }
Adam Sawicki353e3672019-11-02 14:12:05 +01001304 else if(strcmp(properties[i].extensionName, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME) == 0)
1305 {
1306 enabledDeviceExtensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);
1307 VK_EXT_memory_budget_enabled = true;
1308 }
Adam Sawicki6cc5e852018-03-13 16:37:54 +01001309 }
1310 }
1311 }
Adam Sawickie6e498f2017-06-16 17:21:31 +02001312
1313 VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
1314 deviceCreateInfo.enabledLayerCount = 0;
1315 deviceCreateInfo.ppEnabledLayerNames = nullptr;
1316 deviceCreateInfo.enabledExtensionCount = (uint32_t)enabledDeviceExtensions.size();
Adam Sawicki6cc5e852018-03-13 16:37:54 +01001317 deviceCreateInfo.ppEnabledExtensionNames = !enabledDeviceExtensions.empty() ? enabledDeviceExtensions.data() : nullptr;
Adam Sawicki51fa9662018-10-03 13:44:29 +02001318 deviceCreateInfo.queueCreateInfoCount = queueCount;
1319 deviceCreateInfo.pQueueCreateInfos = queueCreateInfo;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001320 deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
1321
Adam Sawicki1f84f622019-07-02 13:40:01 +02001322 ERR_GUARD_VULKAN( vkCreateDevice(g_hPhysicalDevice, &deviceCreateInfo, g_Allocs, &g_hDevice) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001323
1324 // Create memory allocator
1325
1326 VmaAllocatorCreateInfo allocatorInfo = {};
1327 allocatorInfo.physicalDevice = g_hPhysicalDevice;
1328 allocatorInfo.device = g_hDevice;
Adam Sawicki353e3672019-11-02 14:12:05 +01001329 allocatorInfo.instance = g_hVulkanInstance;
Adam Sawickia68c01c2018-03-13 16:40:45 +01001330
Adam Sawicki6cc5e852018-03-13 16:37:54 +01001331 if(VK_KHR_dedicated_allocation_enabled)
1332 {
Adam Sawickif48896d2019-04-16 12:55:35 +02001333 /*
1334 Comment out this line to make the app working with RenderDoc.
Adam Sawicki4fb254e2019-04-23 11:29:57 +02001335
1336 Currently there is a problem with compatibility of this app with RenderDoc due
1337 to a known bug in Vulkan validation layers:
Adam Sawickif48896d2019-04-16 12:55:35 +02001338
Adam Sawicki4fb254e2019-04-23 11:29:57 +02001339 https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/579
1340
1341 It occurs because this app uses Vulkan 1.0 and VK_KHR_dedicated_allocation
1342 extension instead of equivalent functionality embedded into Vulkan 1.1.
Adam Sawickif48896d2019-04-16 12:55:35 +02001343 */
Adam Sawicki6cc5e852018-03-13 16:37:54 +01001344 allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
1345 }
Adam Sawicki4abe30c2019-07-02 14:37:21 +02001346 if(VK_KHR_bind_memory2_enabled)
1347 {
1348 allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
1349 }
Adam Sawicki353e3672019-11-02 14:12:05 +01001350 if(VK_EXT_memory_budget_enabled && VK_KHR_get_physical_device_properties2_enabled)
1351 {
1352 allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;
1353 }
Adam Sawickia68c01c2018-03-13 16:40:45 +01001354
Adam Sawickia68c01c2018-03-13 16:40:45 +01001355 if(USE_CUSTOM_CPU_ALLOCATION_CALLBACKS)
1356 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001357 allocatorInfo.pAllocationCallbacks = &g_CpuAllocationCallbacks;
Adam Sawickia68c01c2018-03-13 16:40:45 +01001358 }
1359
Adam Sawickib0c36362018-11-13 16:17:38 +01001360 // Uncomment to enable recording to CSV file.
1361 /*
1362 {
1363 VmaRecordSettings recordSettings = {};
1364 recordSettings.pFilePath = "VulkanSample.csv";
1365 allocatorInfo.pRecordSettings = &recordSettings;
1366 }
1367 */
1368
Adam Sawicki5f573f52019-10-11 15:59:58 +02001369 // Uncomment to enable HeapSizeLimit.
1370 /*
1371 std::array<VkDeviceSize, VK_MAX_MEMORY_HEAPS> heapSizeLimit;
1372 std::fill(heapSizeLimit.begin(), heapSizeLimit.end(), VK_WHOLE_SIZE);
Adam Sawicki353e3672019-11-02 14:12:05 +01001373 heapSizeLimit[0] = 512ull * 1024 * 1024;
Adam Sawicki5f573f52019-10-11 15:59:58 +02001374 allocatorInfo.pHeapSizeLimit = heapSizeLimit.data();
1375 */
1376
Adam Sawickie6e498f2017-06-16 17:21:31 +02001377 ERR_GUARD_VULKAN( vmaCreateAllocator(&allocatorInfo, &g_hAllocator) );
1378
Adam Sawicki51fa9662018-10-03 13:44:29 +02001379 // Retrieve queues (don't need to be destroyed).
Adam Sawickie6e498f2017-06-16 17:21:31 +02001380
1381 vkGetDeviceQueue(g_hDevice, g_GraphicsQueueFamilyIndex, 0, &g_hGraphicsQueue);
1382 vkGetDeviceQueue(g_hDevice, g_PresentQueueFamilyIndex, 0, &g_hPresentQueue);
1383 assert(g_hGraphicsQueue);
1384 assert(g_hPresentQueue);
1385
Adam Sawicki51fa9662018-10-03 13:44:29 +02001386 if(g_SparseBindingEnabled)
1387 {
1388 vkGetDeviceQueue(g_hDevice, g_SparseBindingQueueFamilyIndex, 0, &g_hSparseBindingQueue);
1389 assert(g_hSparseBindingQueue);
1390 }
1391
Adam Sawickie6e498f2017-06-16 17:21:31 +02001392 // Create command pool
1393
1394 VkCommandPoolCreateInfo commandPoolInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
1395 commandPoolInfo.queueFamilyIndex = g_GraphicsQueueFamilyIndex;
1396 commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001397 ERR_GUARD_VULKAN( vkCreateCommandPool(g_hDevice, &commandPoolInfo, g_Allocs, &g_hCommandPool) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001398
1399 VkCommandBufferAllocateInfo commandBufferInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
1400 commandBufferInfo.commandPool = g_hCommandPool;
1401 commandBufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1402 commandBufferInfo.commandBufferCount = COMMAND_BUFFER_COUNT;
1403 ERR_GUARD_VULKAN( vkAllocateCommandBuffers(g_hDevice, &commandBufferInfo, g_MainCommandBuffers) );
1404
1405 VkFenceCreateInfo fenceInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
1406 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
1407 for(size_t i = 0; i < COMMAND_BUFFER_COUNT; ++i)
1408 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001409 ERR_GUARD_VULKAN( vkCreateFence(g_hDevice, &fenceInfo, g_Allocs, &g_MainCommandBufferExecutedFances[i]) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001410 }
1411
Adam Sawicki1f84f622019-07-02 13:40:01 +02001412 ERR_GUARD_VULKAN( vkCreateFence(g_hDevice, &fenceInfo, g_Allocs, &g_ImmediateFence) );
Adam Sawicki51fa9662018-10-03 13:44:29 +02001413
Adam Sawickie6e498f2017-06-16 17:21:31 +02001414 commandBufferInfo.commandBufferCount = 1;
1415 ERR_GUARD_VULKAN( vkAllocateCommandBuffers(g_hDevice, &commandBufferInfo, &g_hTemporaryCommandBuffer) );
1416
1417 // Create texture sampler
1418
1419 VkSamplerCreateInfo samplerInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
1420 samplerInfo.magFilter = VK_FILTER_LINEAR;
1421 samplerInfo.minFilter = VK_FILTER_LINEAR;
1422 samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
1423 samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
1424 samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
1425 samplerInfo.anisotropyEnable = VK_TRUE;
1426 samplerInfo.maxAnisotropy = 16;
1427 samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
1428 samplerInfo.unnormalizedCoordinates = VK_FALSE;
1429 samplerInfo.compareEnable = VK_FALSE;
1430 samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
1431 samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
1432 samplerInfo.mipLodBias = 0.f;
1433 samplerInfo.minLod = 0.f;
1434 samplerInfo.maxLod = FLT_MAX;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001435 ERR_GUARD_VULKAN( vkCreateSampler(g_hDevice, &samplerInfo, g_Allocs, &g_hSampler) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001436
1437 CreateTexture(128, 128);
1438 CreateMesh();
1439
1440 VkDescriptorSetLayoutBinding samplerLayoutBinding = {};
1441 samplerLayoutBinding.binding = 1;
1442 samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1443 samplerLayoutBinding.descriptorCount = 1;
1444 samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
1445
1446 VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
1447 descriptorSetLayoutInfo.bindingCount = 1;
1448 descriptorSetLayoutInfo.pBindings = &samplerLayoutBinding;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001449 ERR_GUARD_VULKAN( vkCreateDescriptorSetLayout(g_hDevice, &descriptorSetLayoutInfo, g_Allocs, &g_hDescriptorSetLayout) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001450
1451 // Create descriptor pool
1452
1453 VkDescriptorPoolSize descriptorPoolSizes[2];
1454 ZeroMemory(descriptorPoolSizes, sizeof(descriptorPoolSizes));
1455 descriptorPoolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1456 descriptorPoolSizes[0].descriptorCount = 1;
1457 descriptorPoolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1458 descriptorPoolSizes[1].descriptorCount = 1;
1459
1460 VkDescriptorPoolCreateInfo descriptorPoolInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
1461 descriptorPoolInfo.poolSizeCount = (uint32_t)_countof(descriptorPoolSizes);
1462 descriptorPoolInfo.pPoolSizes = descriptorPoolSizes;
1463 descriptorPoolInfo.maxSets = 1;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001464 ERR_GUARD_VULKAN( vkCreateDescriptorPool(g_hDevice, &descriptorPoolInfo, g_Allocs, &g_hDescriptorPool) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001465
1466 // Create descriptor set layout
1467
1468 VkDescriptorSetLayout descriptorSetLayouts[] = { g_hDescriptorSetLayout };
1469 VkDescriptorSetAllocateInfo descriptorSetInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
1470 descriptorSetInfo.descriptorPool = g_hDescriptorPool;
1471 descriptorSetInfo.descriptorSetCount = 1;
1472 descriptorSetInfo.pSetLayouts = descriptorSetLayouts;
1473 ERR_GUARD_VULKAN( vkAllocateDescriptorSets(g_hDevice, &descriptorSetInfo, &g_hDescriptorSet) );
1474
1475 VkDescriptorImageInfo descriptorImageInfo = {};
1476 descriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1477 descriptorImageInfo.imageView = g_hTextureImageView;
1478 descriptorImageInfo.sampler = g_hSampler;
1479
1480 VkWriteDescriptorSet writeDescriptorSet = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
1481 writeDescriptorSet.dstSet = g_hDescriptorSet;
1482 writeDescriptorSet.dstBinding = 1;
1483 writeDescriptorSet.dstArrayElement = 0;
1484 writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1485 writeDescriptorSet.descriptorCount = 1;
1486 writeDescriptorSet.pImageInfo = &descriptorImageInfo;
1487
1488 vkUpdateDescriptorSets(g_hDevice, 1, &writeDescriptorSet, 0, nullptr);
1489
1490 CreateSwapchain();
1491}
1492
1493static void FinalizeApplication()
1494{
1495 vkDeviceWaitIdle(g_hDevice);
1496
1497 DestroySwapchain(true);
1498
1499 if(g_hDescriptorPool != VK_NULL_HANDLE)
1500 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001501 vkDestroyDescriptorPool(g_hDevice, g_hDescriptorPool, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001502 g_hDescriptorPool = VK_NULL_HANDLE;
1503 }
1504
1505 if(g_hDescriptorSetLayout != VK_NULL_HANDLE)
1506 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001507 vkDestroyDescriptorSetLayout(g_hDevice, g_hDescriptorSetLayout, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001508 g_hDescriptorSetLayout = VK_NULL_HANDLE;
1509 }
1510
1511 if(g_hTextureImageView != VK_NULL_HANDLE)
1512 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001513 vkDestroyImageView(g_hDevice, g_hTextureImageView, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001514 g_hTextureImageView = VK_NULL_HANDLE;
1515 }
1516 if(g_hTextureImage != VK_NULL_HANDLE)
1517 {
Adam Sawicki819860e2017-07-04 14:30:38 +02001518 vmaDestroyImage(g_hAllocator, g_hTextureImage, g_hTextureImageAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001519 g_hTextureImage = VK_NULL_HANDLE;
1520 }
1521
1522 if(g_hIndexBuffer != VK_NULL_HANDLE)
1523 {
Adam Sawicki819860e2017-07-04 14:30:38 +02001524 vmaDestroyBuffer(g_hAllocator, g_hIndexBuffer, g_hIndexBufferAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001525 g_hIndexBuffer = VK_NULL_HANDLE;
1526 }
1527 if(g_hVertexBuffer != VK_NULL_HANDLE)
1528 {
Adam Sawicki819860e2017-07-04 14:30:38 +02001529 vmaDestroyBuffer(g_hAllocator, g_hVertexBuffer, g_hVertexBufferAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001530 g_hVertexBuffer = VK_NULL_HANDLE;
1531 }
1532
1533 if(g_hSampler != VK_NULL_HANDLE)
1534 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001535 vkDestroySampler(g_hDevice, g_hSampler, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001536 g_hSampler = VK_NULL_HANDLE;
1537 }
1538
Adam Sawicki51fa9662018-10-03 13:44:29 +02001539 if(g_ImmediateFence)
1540 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001541 vkDestroyFence(g_hDevice, g_ImmediateFence, g_Allocs);
Adam Sawicki51fa9662018-10-03 13:44:29 +02001542 g_ImmediateFence = VK_NULL_HANDLE;
1543 }
1544
Adam Sawickie6e498f2017-06-16 17:21:31 +02001545 for(size_t i = COMMAND_BUFFER_COUNT; i--; )
1546 {
1547 if(g_MainCommandBufferExecutedFances[i] != VK_NULL_HANDLE)
1548 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001549 vkDestroyFence(g_hDevice, g_MainCommandBufferExecutedFances[i], g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001550 g_MainCommandBufferExecutedFances[i] = VK_NULL_HANDLE;
1551 }
1552 }
1553 if(g_MainCommandBuffers[0] != VK_NULL_HANDLE)
1554 {
1555 vkFreeCommandBuffers(g_hDevice, g_hCommandPool, COMMAND_BUFFER_COUNT, g_MainCommandBuffers);
1556 ZeroMemory(g_MainCommandBuffers, sizeof(g_MainCommandBuffers));
1557 }
1558 if(g_hTemporaryCommandBuffer != VK_NULL_HANDLE)
1559 {
1560 vkFreeCommandBuffers(g_hDevice, g_hCommandPool, 1, &g_hTemporaryCommandBuffer);
1561 g_hTemporaryCommandBuffer = VK_NULL_HANDLE;
1562 }
1563
1564 if(g_hCommandPool != VK_NULL_HANDLE)
1565 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001566 vkDestroyCommandPool(g_hDevice, g_hCommandPool, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001567 g_hCommandPool = VK_NULL_HANDLE;
1568 }
1569
1570 if(g_hAllocator != VK_NULL_HANDLE)
1571 {
1572 vmaDestroyAllocator(g_hAllocator);
1573 g_hAllocator = nullptr;
1574 }
1575
1576 if(g_hDevice != VK_NULL_HANDLE)
1577 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001578 vkDestroyDevice(g_hDevice, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001579 g_hDevice = nullptr;
1580 }
1581
1582 if(g_pvkDestroyDebugReportCallbackEXT && g_hCallback != VK_NULL_HANDLE)
1583 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001584 g_pvkDestroyDebugReportCallbackEXT(g_hVulkanInstance, g_hCallback, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001585 g_hCallback = VK_NULL_HANDLE;
1586 }
1587
1588 if(g_hSurface != VK_NULL_HANDLE)
1589 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001590 vkDestroySurfaceKHR(g_hVulkanInstance, g_hSurface, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001591 g_hSurface = VK_NULL_HANDLE;
1592 }
1593
1594 if(g_hVulkanInstance != VK_NULL_HANDLE)
1595 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001596 vkDestroyInstance(g_hVulkanInstance, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001597 g_hVulkanInstance = VK_NULL_HANDLE;
1598 }
1599}
1600
1601static void PrintAllocatorStats()
1602{
1603#if VMA_STATS_STRING_ENABLED
1604 char* statsString = nullptr;
1605 vmaBuildStatsString(g_hAllocator, &statsString, true);
1606 printf("%s\n", statsString);
1607 vmaFreeStatsString(g_hAllocator, statsString);
1608#endif
1609}
1610
1611static void RecreateSwapChain()
1612{
1613 vkDeviceWaitIdle(g_hDevice);
1614 DestroySwapchain(false);
1615 CreateSwapchain();
1616}
1617
1618static void DrawFrame()
1619{
1620 // Begin main command buffer
1621 size_t cmdBufIndex = (g_NextCommandBufferIndex++) % COMMAND_BUFFER_COUNT;
1622 VkCommandBuffer hCommandBuffer = g_MainCommandBuffers[cmdBufIndex];
1623 VkFence hCommandBufferExecutedFence = g_MainCommandBufferExecutedFances[cmdBufIndex];
1624
1625 ERR_GUARD_VULKAN( vkWaitForFences(g_hDevice, 1, &hCommandBufferExecutedFence, VK_TRUE, UINT64_MAX) );
1626 ERR_GUARD_VULKAN( vkResetFences(g_hDevice, 1, &hCommandBufferExecutedFence) );
1627
1628 VkCommandBufferBeginInfo commandBufferBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
1629 commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1630 ERR_GUARD_VULKAN( vkBeginCommandBuffer(hCommandBuffer, &commandBufferBeginInfo) );
1631
1632 // Acquire swapchain image
1633 uint32_t imageIndex = 0;
1634 VkResult res = vkAcquireNextImageKHR(g_hDevice, g_hSwapchain, UINT64_MAX, g_hImageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
1635 if(res == VK_ERROR_OUT_OF_DATE_KHR)
1636 {
1637 RecreateSwapChain();
1638 return;
1639 }
1640 else if(res < 0)
1641 {
1642 ERR_GUARD_VULKAN(res);
1643 }
1644
1645 // Record geometry pass
1646
1647 VkClearValue clearValues[2];
1648 ZeroMemory(clearValues, sizeof(clearValues));
1649 clearValues[0].color.float32[0] = 0.25f;
1650 clearValues[0].color.float32[1] = 0.25f;
1651 clearValues[0].color.float32[2] = 0.5f;
1652 clearValues[0].color.float32[3] = 1.0f;
1653 clearValues[1].depthStencil.depth = 1.0f;
1654
1655 VkRenderPassBeginInfo renderPassBeginInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
1656 renderPassBeginInfo.renderPass = g_hRenderPass;
1657 renderPassBeginInfo.framebuffer = g_Framebuffers[imageIndex];
1658 renderPassBeginInfo.renderArea.offset.x = 0;
1659 renderPassBeginInfo.renderArea.offset.y = 0;
1660 renderPassBeginInfo.renderArea.extent = g_Extent;
1661 renderPassBeginInfo.clearValueCount = (uint32_t)_countof(clearValues);
1662 renderPassBeginInfo.pClearValues = clearValues;
1663 vkCmdBeginRenderPass(hCommandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1664
1665 vkCmdBindPipeline(
1666 hCommandBuffer,
1667 VK_PIPELINE_BIND_POINT_GRAPHICS,
1668 g_hPipeline);
1669
Adam Sawicki82c3f332018-06-11 15:27:33 +02001670 mat4 view = mat4::LookAt(
1671 vec3(0.f, 0.f, 0.f),
1672 vec3(0.f, -2.f, 4.f),
1673 vec3(0.f, 1.f, 0.f));
1674 mat4 proj = mat4::Perspective(
Adam Sawickie6e498f2017-06-16 17:21:31 +02001675 1.0471975511966f, // 60 degrees
1676 (float)g_Extent.width / (float)g_Extent.height,
1677 0.1f,
Adam Sawicki82c3f332018-06-11 15:27:33 +02001678 1000.f);
1679 mat4 viewProj = view * proj;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001680
1681 vkCmdBindDescriptorSets(
1682 hCommandBuffer,
1683 VK_PIPELINE_BIND_POINT_GRAPHICS,
1684 g_hPipelineLayout,
1685 0,
1686 1,
1687 &g_hDescriptorSet,
1688 0,
1689 nullptr);
1690
Adam Sawicki82c3f332018-06-11 15:27:33 +02001691 float rotationAngle = (float)GetTickCount() * 0.001f * (float)PI * 0.2f;
1692 mat4 model = mat4::RotationY(rotationAngle);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001693
1694 UniformBufferObject ubo = {};
Adam Sawicki82c3f332018-06-11 15:27:33 +02001695 ubo.ModelViewProj = model * viewProj;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001696 vkCmdPushConstants(hCommandBuffer, g_hPipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(UniformBufferObject), &ubo);
1697
1698 VkBuffer vertexBuffers[] = { g_hVertexBuffer };
1699 VkDeviceSize offsets[] = { 0 };
1700 vkCmdBindVertexBuffers(hCommandBuffer, 0, 1, vertexBuffers, offsets);
1701
1702 vkCmdBindIndexBuffer(hCommandBuffer, g_hIndexBuffer, 0, VK_INDEX_TYPE_UINT16);
1703
1704 vkCmdDrawIndexed(hCommandBuffer, g_IndexCount, 1, 0, 0, 0);
1705
1706 vkCmdEndRenderPass(hCommandBuffer);
1707
1708 vkEndCommandBuffer(hCommandBuffer);
1709
1710 // Submit command buffer
1711
1712 VkSemaphore submitWaitSemaphores[] = { g_hImageAvailableSemaphore };
1713 VkPipelineStageFlags submitWaitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
1714 VkSemaphore submitSignalSemaphores[] = { g_hRenderFinishedSemaphore };
1715 VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
1716 submitInfo.waitSemaphoreCount = 1;
1717 submitInfo.pWaitSemaphores = submitWaitSemaphores;
1718 submitInfo.pWaitDstStageMask = submitWaitStages;
1719 submitInfo.commandBufferCount = 1;
1720 submitInfo.pCommandBuffers = &hCommandBuffer;
1721 submitInfo.signalSemaphoreCount = _countof(submitSignalSemaphores);
1722 submitInfo.pSignalSemaphores = submitSignalSemaphores;
1723 ERR_GUARD_VULKAN( vkQueueSubmit(g_hGraphicsQueue, 1, &submitInfo, hCommandBufferExecutedFence) );
1724
1725 VkSemaphore presentWaitSemaphores[] = { g_hRenderFinishedSemaphore };
1726
1727 VkSwapchainKHR swapchains[] = { g_hSwapchain };
1728 VkPresentInfoKHR presentInfo = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
1729 presentInfo.waitSemaphoreCount = _countof(presentWaitSemaphores);
1730 presentInfo.pWaitSemaphores = presentWaitSemaphores;
1731 presentInfo.swapchainCount = 1;
1732 presentInfo.pSwapchains = swapchains;
1733 presentInfo.pImageIndices = &imageIndex;
1734 presentInfo.pResults = nullptr;
1735 res = vkQueuePresentKHR(g_hPresentQueue, &presentInfo);
1736 if(res == VK_ERROR_OUT_OF_DATE_KHR)
1737 {
1738 RecreateSwapChain();
1739 }
1740 else
1741 ERR_GUARD_VULKAN(res);
1742}
1743
1744static void HandlePossibleSizeChange()
1745{
1746 RECT clientRect;
1747 GetClientRect(g_hWnd, &clientRect);
1748 LONG newSizeX = clientRect.right - clientRect.left;
1749 LONG newSizeY = clientRect.bottom - clientRect.top;
1750 if((newSizeX > 0) &&
1751 (newSizeY > 0) &&
1752 ((newSizeX != g_SizeX) || (newSizeY != g_SizeY)))
1753 {
1754 g_SizeX = newSizeX;
1755 g_SizeY = newSizeY;
1756
1757 RecreateSwapChain();
1758 }
1759}
1760
1761static LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
1762{
1763 switch(msg)
1764 {
1765 case WM_CREATE:
1766 // This is intentionally assigned here because we are now inside CreateWindow, before it returns.
1767 g_hWnd = hWnd;
1768 InitializeApplication();
1769 PrintAllocatorStats();
1770 return 0;
1771
1772 case WM_DESTROY:
1773 FinalizeApplication();
1774 PostQuitMessage(0);
1775 return 0;
1776
1777 // This prevents app from freezing when left Alt is pressed
1778 // (which normally enters modal menu loop).
1779 case WM_SYSKEYDOWN:
1780 case WM_SYSKEYUP:
1781 return 0;
1782
1783 case WM_SIZE:
1784 if((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED))
1785 HandlePossibleSizeChange();
1786 return 0;
1787
1788 case WM_EXITSIZEMOVE:
1789 HandlePossibleSizeChange();
1790 return 0;
1791
1792 case WM_KEYDOWN:
Adam Sawickib8333fb2018-03-13 16:15:53 +01001793 switch(wParam)
1794 {
1795 case VK_ESCAPE:
Adam Sawickie6e498f2017-06-16 17:21:31 +02001796 PostMessage(hWnd, WM_CLOSE, 0, 0);
Adam Sawickib8333fb2018-03-13 16:15:53 +01001797 break;
1798 case 'T':
Adam Sawickia7d77692018-10-03 16:15:27 +02001799 try
1800 {
1801 Test();
1802 }
1803 catch(const std::exception& ex)
1804 {
1805 printf("ERROR: %s\n", ex.what());
1806 }
Adam Sawickib8333fb2018-03-13 16:15:53 +01001807 break;
Adam Sawickida6c1942018-12-05 17:34:34 +01001808 case 'S':
1809 try
1810 {
1811 if(g_SparseBindingEnabled)
1812 {
1813 TestSparseBinding();
1814 }
1815 else
1816 {
1817 printf("Sparse binding not supported.\n");
1818 }
1819 }
1820 catch(const std::exception& ex)
1821 {
1822 printf("ERROR: %s\n", ex.what());
1823 }
1824 break;
Adam Sawickib8333fb2018-03-13 16:15:53 +01001825 }
Adam Sawickie6e498f2017-06-16 17:21:31 +02001826 return 0;
1827
1828 default:
1829 break;
1830 }
1831
1832 return DefWindowProc(hWnd, msg, wParam, lParam);
1833}
1834
1835int main()
1836{
1837 g_hAppInstance = (HINSTANCE)GetModuleHandle(NULL);
1838
1839 WNDCLASSEX wndClassDesc = { sizeof(WNDCLASSEX) };
1840 wndClassDesc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
1841 wndClassDesc.hbrBackground = NULL;
1842 wndClassDesc.hCursor = LoadCursor(NULL, IDC_CROSS);
1843 wndClassDesc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1844 wndClassDesc.hInstance = g_hAppInstance;
1845 wndClassDesc.lpfnWndProc = WndProc;
1846 wndClassDesc.lpszClassName = WINDOW_CLASS_NAME;
1847
1848 const ATOM hWndClass = RegisterClassEx(&wndClassDesc);
1849 assert(hWndClass);
1850
1851 const DWORD style = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;
1852 const DWORD exStyle = 0;
1853
1854 RECT rect = { 0, 0, g_SizeX, g_SizeY };
1855 AdjustWindowRectEx(&rect, style, FALSE, exStyle);
1856
Adam Sawicki86ccd632017-07-04 14:57:53 +02001857 CreateWindowEx(
Adam Sawickie6e498f2017-06-16 17:21:31 +02001858 exStyle, WINDOW_CLASS_NAME, APP_TITLE_W, style,
1859 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1860 NULL, NULL, g_hAppInstance, NULL);
1861
1862 MSG msg;
1863 for(;;)
1864 {
1865 if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
1866 {
1867 if(msg.message == WM_QUIT)
1868 break;
1869 TranslateMessage(&msg);
1870 DispatchMessage(&msg);
1871 }
1872 if(g_hDevice != VK_NULL_HANDLE)
1873 DrawFrame();
1874 }
1875
1876 return 0;
1877}
Adam Sawicki59a3e7e2017-08-21 15:47:30 +02001878
Adam Sawickif1a793c2018-03-13 15:42:22 +01001879#else // #ifdef _WIN32
Adam Sawicki59a3e7e2017-08-21 15:47:30 +02001880
Adam Sawickif1a793c2018-03-13 15:42:22 +01001881#include "VmaUsage.h"
Adam Sawicki59a3e7e2017-08-21 15:47:30 +02001882
1883int main()
1884{
1885}
1886
Adam Sawickif1a793c2018-03-13 15:42:22 +01001887#endif // #ifdef _WIN32