blob: bd4a422399ac13a881e43ef7cbb163ea5d029047 [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 Sawicki8317ba92019-11-18 13:14:11 +010029#include <atomic>
Adam Sawickie6e498f2017-06-16 17:21:31 +020030
31static const char* const SHADER_PATH1 = "./";
32static const char* const SHADER_PATH2 = "../bin/";
33static const wchar_t* const WINDOW_CLASS_NAME = L"VULKAN_MEMORY_ALLOCATOR_SAMPLE";
34static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_LUNARG_standard_validation";
Adam Sawicki6c8b7a22019-03-05 13:40:29 +010035static const char* const APP_TITLE_A = "Vulkan Memory Allocator Sample 2.3.0-development";
36static const wchar_t* const APP_TITLE_W = L"Vulkan Memory Allocator Sample 2.3.0-development";
Adam Sawickie6e498f2017-06-16 17:21:31 +020037
38static const bool VSYNC = true;
39static const uint32_t COMMAND_BUFFER_COUNT = 2;
Adam Sawickia68c01c2018-03-13 16:40:45 +010040static void* const CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA = (void*)(intptr_t)43564544;
Adam Sawicki8317ba92019-11-18 13:14:11 +010041static const bool USE_CUSTOM_CPU_ALLOCATION_CALLBACKS = true;
Adam Sawickie6e498f2017-06-16 17:21:31 +020042
Adam Sawickib8333fb2018-03-13 16:15:53 +010043VkPhysicalDevice g_hPhysicalDevice;
44VkDevice g_hDevice;
45VmaAllocator g_hAllocator;
Adam Sawicki4ac8ff82019-11-18 14:47:33 +010046VkInstance g_hVulkanInstance;
Adam Sawickib8333fb2018-03-13 16:15:53 +010047bool g_MemoryAliasingWarningEnabled = true;
48
Adam Sawickia68c01c2018-03-13 16:40:45 +010049static bool g_EnableValidationLayer = true;
Adam Sawicki6cc5e852018-03-13 16:37:54 +010050static bool VK_KHR_get_memory_requirements2_enabled = false;
Adam Sawicki353e3672019-11-02 14:12:05 +010051static bool VK_KHR_get_physical_device_properties2_enabled = false;
Adam Sawicki6cc5e852018-03-13 16:37:54 +010052static bool VK_KHR_dedicated_allocation_enabled = false;
Adam Sawicki4abe30c2019-07-02 14:37:21 +020053static bool VK_KHR_bind_memory2_enabled = false;
Adam Sawicki353e3672019-11-02 14:12:05 +010054static bool VK_EXT_memory_budget_enabled = false;
Adam Sawicki51fa9662018-10-03 13:44:29 +020055bool g_SparseBindingEnabled = false;
Adam Sawicki6cc5e852018-03-13 16:37:54 +010056
Adam Sawickie6e498f2017-06-16 17:21:31 +020057static HINSTANCE g_hAppInstance;
58static HWND g_hWnd;
59static LONG g_SizeX = 1280, g_SizeY = 720;
Adam Sawickie6e498f2017-06-16 17:21:31 +020060static VkSurfaceKHR g_hSurface;
Adam Sawickie6e498f2017-06-16 17:21:31 +020061static VkQueue g_hPresentQueue;
62static VkSurfaceFormatKHR g_SurfaceFormat;
63static VkExtent2D g_Extent;
64static VkSwapchainKHR g_hSwapchain;
65static std::vector<VkImage> g_SwapchainImages;
66static std::vector<VkImageView> g_SwapchainImageViews;
67static std::vector<VkFramebuffer> g_Framebuffers;
68static VkCommandPool g_hCommandPool;
69static VkCommandBuffer g_MainCommandBuffers[COMMAND_BUFFER_COUNT];
70static VkFence g_MainCommandBufferExecutedFances[COMMAND_BUFFER_COUNT];
Adam Sawicki51fa9662018-10-03 13:44:29 +020071VkFence g_ImmediateFence;
Adam Sawickie6e498f2017-06-16 17:21:31 +020072static uint32_t g_NextCommandBufferIndex;
73static VkSemaphore g_hImageAvailableSemaphore;
74static VkSemaphore g_hRenderFinishedSemaphore;
75static uint32_t g_GraphicsQueueFamilyIndex = UINT_MAX;
76static uint32_t g_PresentQueueFamilyIndex = UINT_MAX;
Adam Sawicki51fa9662018-10-03 13:44:29 +020077static uint32_t g_SparseBindingQueueFamilyIndex = UINT_MAX;
Adam Sawickie6e498f2017-06-16 17:21:31 +020078static VkDescriptorSetLayout g_hDescriptorSetLayout;
79static VkDescriptorPool g_hDescriptorPool;
80static VkDescriptorSet g_hDescriptorSet; // Automatically destroyed with m_DescriptorPool.
81static VkSampler g_hSampler;
82static VkFormat g_DepthFormat;
83static VkImage g_hDepthImage;
Adam Sawicki819860e2017-07-04 14:30:38 +020084static VmaAllocation g_hDepthImageAlloc;
Adam Sawickie6e498f2017-06-16 17:21:31 +020085static VkImageView g_hDepthImageView;
86
87static VkSurfaceCapabilitiesKHR g_SurfaceCapabilities;
88static std::vector<VkSurfaceFormatKHR> g_SurfaceFormats;
89static std::vector<VkPresentModeKHR> g_PresentModes;
90
91static PFN_vkCreateDebugReportCallbackEXT g_pvkCreateDebugReportCallbackEXT;
92static PFN_vkDebugReportMessageEXT g_pvkDebugReportMessageEXT;
93static PFN_vkDestroyDebugReportCallbackEXT g_pvkDestroyDebugReportCallbackEXT;
94static VkDebugReportCallbackEXT g_hCallback;
95
Adam Sawickie6e498f2017-06-16 17:21:31 +020096static VkQueue g_hGraphicsQueue;
Adam Sawicki51fa9662018-10-03 13:44:29 +020097VkQueue g_hSparseBindingQueue;
Adam Sawicki978fcf52018-12-05 14:38:48 +010098VkCommandBuffer g_hTemporaryCommandBuffer;
Adam Sawickie6e498f2017-06-16 17:21:31 +020099
100static VkPipelineLayout g_hPipelineLayout;
101static VkRenderPass g_hRenderPass;
102static VkPipeline g_hPipeline;
103
104static VkBuffer g_hVertexBuffer;
Adam Sawicki819860e2017-07-04 14:30:38 +0200105static VmaAllocation g_hVertexBufferAlloc;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200106static VkBuffer g_hIndexBuffer;
Adam Sawicki819860e2017-07-04 14:30:38 +0200107static VmaAllocation g_hIndexBufferAlloc;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200108static uint32_t g_VertexCount;
109static uint32_t g_IndexCount;
110
111static VkImage g_hTextureImage;
Adam Sawicki819860e2017-07-04 14:30:38 +0200112static VmaAllocation g_hTextureImageAlloc;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200113static VkImageView g_hTextureImageView;
114
Adam Sawicki8317ba92019-11-18 13:14:11 +0100115static std::atomic_uint32_t g_CpuAllocCount;
116
Adam Sawickia68c01c2018-03-13 16:40:45 +0100117static void* CustomCpuAllocation(
118 void* pUserData, size_t size, size_t alignment,
119 VkSystemAllocationScope allocationScope)
120{
121 assert(pUserData == CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA);
Adam Sawicki8317ba92019-11-18 13:14:11 +0100122 void* const result = _aligned_malloc(size, alignment);
123 if(result)
124 {
125 ++g_CpuAllocCount;
126 }
127 return result;
Adam Sawickia68c01c2018-03-13 16:40:45 +0100128}
129
130static void* CustomCpuReallocation(
131 void* pUserData, void* pOriginal, size_t size, size_t alignment,
132 VkSystemAllocationScope allocationScope)
133{
134 assert(pUserData == CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA);
Adam Sawicki8317ba92019-11-18 13:14:11 +0100135 void* const result = _aligned_realloc(pOriginal, size, alignment);
136 if(pOriginal && !result)
137 {
138 --g_CpuAllocCount;
139 }
140 else if(!pOriginal && result)
141 {
142 ++g_CpuAllocCount;
143 }
144 return result;
Adam Sawickia68c01c2018-03-13 16:40:45 +0100145}
146
147static void CustomCpuFree(void* pUserData, void* pMemory)
148{
149 assert(pUserData == CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA);
Adam Sawicki8317ba92019-11-18 13:14:11 +0100150 if(pMemory)
151 {
152 const uint32_t oldAllocCount = g_CpuAllocCount.fetch_sub(1);
153 TEST(oldAllocCount > 0);
154 _aligned_free(pMemory);
155 }
Adam Sawickia68c01c2018-03-13 16:40:45 +0100156}
157
Adam Sawicki1f84f622019-07-02 13:40:01 +0200158static const VkAllocationCallbacks g_CpuAllocationCallbacks = {
159 CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA, // pUserData
160 &CustomCpuAllocation, // pfnAllocation
161 &CustomCpuReallocation, // pfnReallocation
162 &CustomCpuFree // pfnFree
163};
164
165const VkAllocationCallbacks* g_Allocs;
166
Adam Sawicki978fcf52018-12-05 14:38:48 +0100167void BeginSingleTimeCommands()
Adam Sawickie6e498f2017-06-16 17:21:31 +0200168{
169 VkCommandBufferBeginInfo cmdBufBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
170 cmdBufBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
171 ERR_GUARD_VULKAN( vkBeginCommandBuffer(g_hTemporaryCommandBuffer, &cmdBufBeginInfo) );
172}
173
Adam Sawicki978fcf52018-12-05 14:38:48 +0100174void EndSingleTimeCommands()
Adam Sawickie6e498f2017-06-16 17:21:31 +0200175{
176 ERR_GUARD_VULKAN( vkEndCommandBuffer(g_hTemporaryCommandBuffer) );
177
178 VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
179 submitInfo.commandBufferCount = 1;
180 submitInfo.pCommandBuffers = &g_hTemporaryCommandBuffer;
181
182 ERR_GUARD_VULKAN( vkQueueSubmit(g_hGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE) );
183 ERR_GUARD_VULKAN( vkQueueWaitIdle(g_hGraphicsQueue) );
184}
185
Adam Sawickida6c1942018-12-05 17:34:34 +0100186void LoadShader(std::vector<char>& out, const char* fileName)
Adam Sawickie6e498f2017-06-16 17:21:31 +0200187{
188 std::ifstream file(std::string(SHADER_PATH1) + fileName, std::ios::ate | std::ios::binary);
189 if(file.is_open() == false)
190 file.open(std::string(SHADER_PATH2) + fileName, std::ios::ate | std::ios::binary);
191 assert(file.is_open());
192 size_t fileSize = (size_t)file.tellg();
193 if(fileSize > 0)
194 {
195 out.resize(fileSize);
196 file.seekg(0);
197 file.read(out.data(), fileSize);
198 file.close();
199 }
200 else
201 out.clear();
202}
203
204VKAPI_ATTR VkBool32 VKAPI_CALL MyDebugReportCallback(
205 VkDebugReportFlagsEXT flags,
206 VkDebugReportObjectTypeEXT objectType,
207 uint64_t object,
208 size_t location,
209 int32_t messageCode,
210 const char* pLayerPrefix,
211 const char* pMessage,
212 void* pUserData)
213{
Adam Sawickib8333fb2018-03-13 16:15:53 +0100214 // "Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug."
215 if(!g_MemoryAliasingWarningEnabled && flags == VK_DEBUG_REPORT_WARNING_BIT_EXT &&
216 (strstr(pMessage, " is aliased with non-linear ") || strstr(pMessage, " is aliased with linear ")))
217 {
218 return VK_FALSE;
219 }
220
221 // Ignoring because when VK_KHR_dedicated_allocation extension is enabled,
222 // vkGetBufferMemoryRequirements2KHR function is used instead, while Validation
223 // Layer seems to be unaware of it.
224 if (strstr(pMessage, "but vkGetBufferMemoryRequirements() has not been called on that buffer") != nullptr)
225 {
226 return VK_FALSE;
227 }
228 if (strstr(pMessage, "but vkGetImageMemoryRequirements() has not been called on that image") != nullptr)
229 {
230 return VK_FALSE;
231 }
Adam Sawicki94e82062018-08-20 11:12:51 +0200232
233 /*
234 "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."
235 Ignoring because we map entire VkDeviceMemory blocks, where different types of
236 images and buffers may end up together, especially on GPUs with unified memory
237 like Intel.
238 */
239 if(strstr(pMessage, "Mapping an image with layout") != nullptr &&
240 strstr(pMessage, "can result in undefined behavior if this memory is used by the device") != nullptr)
241 {
242 return VK_FALSE;
243 }
Adam Sawickib8333fb2018-03-13 16:15:53 +0100244
245 switch(flags)
246 {
247 case VK_DEBUG_REPORT_WARNING_BIT_EXT:
248 SetConsoleColor(CONSOLE_COLOR::WARNING);
249 break;
250 case VK_DEBUG_REPORT_ERROR_BIT_EXT:
251 SetConsoleColor(CONSOLE_COLOR::ERROR_);
252 break;
253 default:
254 SetConsoleColor(CONSOLE_COLOR::INFO);
255 }
256
Adam Sawickie6e498f2017-06-16 17:21:31 +0200257 printf("%s \xBA %s\n", pLayerPrefix, pMessage);
258
Adam Sawickib8333fb2018-03-13 16:15:53 +0100259 SetConsoleColor(CONSOLE_COLOR::NORMAL);
260
261 if(flags == VK_DEBUG_REPORT_WARNING_BIT_EXT ||
262 flags == VK_DEBUG_REPORT_ERROR_BIT_EXT)
Adam Sawickie6e498f2017-06-16 17:21:31 +0200263 {
264 OutputDebugStringA(pMessage);
265 OutputDebugStringA("\n");
266 }
267
268 return VK_FALSE;
269}
270
271static VkSurfaceFormatKHR ChooseSurfaceFormat()
272{
273 assert(!g_SurfaceFormats.empty());
274
275 if((g_SurfaceFormats.size() == 1) && (g_SurfaceFormats[0].format == VK_FORMAT_UNDEFINED))
276 {
277 VkSurfaceFormatKHR result = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
278 return result;
279 }
280
281 for(const auto& format : g_SurfaceFormats)
282 {
283 if((format.format == VK_FORMAT_B8G8R8A8_UNORM) &&
284 (format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR))
285 {
286 return format;
287 }
288 }
289
290 return g_SurfaceFormats[0];
291}
292
293VkPresentModeKHR ChooseSwapPresentMode()
294{
295 VkPresentModeKHR preferredMode = VSYNC ? VK_PRESENT_MODE_MAILBOX_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR;
296
297 if(std::find(g_PresentModes.begin(), g_PresentModes.end(), preferredMode) !=
298 g_PresentModes.end())
299 {
300 return preferredMode;
301 }
302
303 return VK_PRESENT_MODE_FIFO_KHR;
304}
305
306static VkExtent2D ChooseSwapExtent()
307{
308 if(g_SurfaceCapabilities.currentExtent.width != UINT_MAX)
309 return g_SurfaceCapabilities.currentExtent;
310
311 VkExtent2D result = {
312 std::max(g_SurfaceCapabilities.minImageExtent.width,
313 std::min(g_SurfaceCapabilities.maxImageExtent.width, (uint32_t)g_SizeX)),
314 std::max(g_SurfaceCapabilities.minImageExtent.height,
315 std::min(g_SurfaceCapabilities.maxImageExtent.height, (uint32_t)g_SizeY)) };
316 return result;
317}
318
319struct Vertex
320{
321 float pos[3];
322 float color[3];
323 float texCoord[2];
324};
325
326static void CreateMesh()
327{
328 assert(g_hAllocator);
329
330 static Vertex vertices[] = {
331 // -X
332 { { -1.f, -1.f, -1.f}, {1.0f, 0.0f, 0.0f}, {0.f, 0.f} },
333 { { -1.f, -1.f, 1.f}, {1.0f, 0.0f, 0.0f}, {1.f, 0.f} },
334 { { -1.f, 1.f, -1.f}, {1.0f, 0.0f, 0.0f}, {0.f, 1.f} },
335 { { -1.f, 1.f, 1.f}, {1.0f, 0.0f, 0.0f}, {1.f, 1.f} },
336 // +X
337 { { 1.f, -1.f, 1.f}, {0.0f, 1.0f, 0.0f}, {0.f, 0.f} },
338 { { 1.f, -1.f, -1.f}, {0.0f, 1.0f, 0.0f}, {1.f, 0.f} },
339 { { 1.f, 1.f, 1.f}, {0.0f, 1.0f, 0.0f}, {0.f, 1.f} },
340 { { 1.f, 1.f, -1.f}, {0.0f, 1.0f, 0.0f}, {1.f, 1.f} },
341 // -Z
342 { { 1.f, -1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {0.f, 0.f} },
343 { {-1.f, -1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {1.f, 0.f} },
344 { { 1.f, 1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {0.f, 1.f} },
345 { {-1.f, 1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {1.f, 1.f} },
346 // +Z
347 { {-1.f, -1.f, 1.f}, {1.0f, 1.0f, 0.0f}, {0.f, 0.f} },
348 { { 1.f, -1.f, 1.f}, {1.0f, 1.0f, 0.0f}, {1.f, 0.f} },
349 { {-1.f, 1.f, 1.f}, {1.0f, 1.0f, 0.0f}, {0.f, 1.f} },
350 { { 1.f, 1.f, 1.f}, {1.0f, 1.0f, 0.0f}, {1.f, 1.f} },
351 // -Y
352 { {-1.f, -1.f, -1.f}, {0.0f, 1.0f, 1.0f}, {0.f, 0.f} },
353 { { 1.f, -1.f, -1.f}, {0.0f, 1.0f, 1.0f}, {1.f, 0.f} },
354 { {-1.f, -1.f, 1.f}, {0.0f, 1.0f, 1.0f}, {0.f, 1.f} },
355 { { 1.f, -1.f, 1.f}, {0.0f, 1.0f, 1.0f}, {1.f, 1.f} },
356 // +Y
357 { { 1.f, 1.f, -1.f}, {1.0f, 0.0f, 1.0f}, {0.f, 0.f} },
358 { {-1.f, 1.f, -1.f}, {1.0f, 0.0f, 1.0f}, {1.f, 0.f} },
359 { { 1.f, 1.f, 1.f}, {1.0f, 0.0f, 1.0f}, {0.f, 1.f} },
360 { {-1.f, 1.f, 1.f}, {1.0f, 0.0f, 1.0f}, {1.f, 1.f} },
361 };
362 static uint16_t indices[] = {
363 0, 1, 2, 3, USHRT_MAX,
364 4, 5, 6, 7, USHRT_MAX,
365 8, 9, 10, 11, USHRT_MAX,
366 12, 13, 14, 15, USHRT_MAX,
367 16, 17, 18, 19, USHRT_MAX,
368 20, 21, 22, 23, USHRT_MAX,
369 };
370
371 size_t vertexBufferSize = sizeof(Vertex) * _countof(vertices);
372 size_t indexBufferSize = sizeof(uint16_t) * _countof(indices);
373 g_IndexCount = (uint32_t)_countof(indices);
374
375 // Create vertex buffer
376
377 VkBufferCreateInfo vbInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
378 vbInfo.size = vertexBufferSize;
379 vbInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
380 vbInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200381
Adam Sawicki976f9202017-09-12 20:45:14 +0200382 VmaAllocationCreateInfo vbAllocCreateInfo = {};
383 vbAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
Adam Sawicki5268dbb2017-11-08 12:52:05 +0100384 vbAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200385
Adam Sawicki819860e2017-07-04 14:30:38 +0200386 VkBuffer stagingVertexBuffer = VK_NULL_HANDLE;
387 VmaAllocation stagingVertexBufferAlloc = VK_NULL_HANDLE;
388 VmaAllocationInfo stagingVertexBufferAllocInfo = {};
Adam Sawicki976f9202017-09-12 20:45:14 +0200389 ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &vbInfo, &vbAllocCreateInfo, &stagingVertexBuffer, &stagingVertexBufferAlloc, &stagingVertexBufferAllocInfo) );
Adam Sawicki819860e2017-07-04 14:30:38 +0200390
391 memcpy(stagingVertexBufferAllocInfo.pMappedData, vertices, vertexBufferSize);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200392
Adam Sawicki2f16fa52017-07-04 14:43:20 +0200393 // No need to flush stagingVertexBuffer memory because CPU_ONLY memory is always HOST_COHERENT.
394
Adam Sawickie6e498f2017-06-16 17:21:31 +0200395 vbInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
Adam Sawicki976f9202017-09-12 20:45:14 +0200396 vbAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
397 vbAllocCreateInfo.flags = 0;
398 ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &vbInfo, &vbAllocCreateInfo, &g_hVertexBuffer, &g_hVertexBufferAlloc, nullptr) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200399
400 // Create index buffer
401
402 VkBufferCreateInfo ibInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
403 ibInfo.size = indexBufferSize;
404 ibInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
405 ibInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
Adam Sawicki819860e2017-07-04 14:30:38 +0200406
Adam Sawicki976f9202017-09-12 20:45:14 +0200407 VmaAllocationCreateInfo ibAllocCreateInfo = {};
408 ibAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
Adam Sawicki5268dbb2017-11-08 12:52:05 +0100409 ibAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
Adam Sawicki819860e2017-07-04 14:30:38 +0200410
Adam Sawickie6e498f2017-06-16 17:21:31 +0200411 VkBuffer stagingIndexBuffer = VK_NULL_HANDLE;
Adam Sawicki819860e2017-07-04 14:30:38 +0200412 VmaAllocation stagingIndexBufferAlloc = VK_NULL_HANDLE;
413 VmaAllocationInfo stagingIndexBufferAllocInfo = {};
Adam Sawicki976f9202017-09-12 20:45:14 +0200414 ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &ibInfo, &ibAllocCreateInfo, &stagingIndexBuffer, &stagingIndexBufferAlloc, &stagingIndexBufferAllocInfo) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200415
Adam Sawicki819860e2017-07-04 14:30:38 +0200416 memcpy(stagingIndexBufferAllocInfo.pMappedData, indices, indexBufferSize);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200417
Adam Sawicki2f16fa52017-07-04 14:43:20 +0200418 // No need to flush stagingIndexBuffer memory because CPU_ONLY memory is always HOST_COHERENT.
419
Adam Sawickie6e498f2017-06-16 17:21:31 +0200420 ibInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
Adam Sawicki976f9202017-09-12 20:45:14 +0200421 ibAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
422 ibAllocCreateInfo.flags = 0;
423 ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &ibInfo, &ibAllocCreateInfo, &g_hIndexBuffer, &g_hIndexBufferAlloc, nullptr) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200424
425 // Copy buffers
426
427 BeginSingleTimeCommands();
428
429 VkBufferCopy vbCopyRegion = {};
430 vbCopyRegion.srcOffset = 0;
431 vbCopyRegion.dstOffset = 0;
432 vbCopyRegion.size = vbInfo.size;
433 vkCmdCopyBuffer(g_hTemporaryCommandBuffer, stagingVertexBuffer, g_hVertexBuffer, 1, &vbCopyRegion);
434
435 VkBufferCopy ibCopyRegion = {};
436 ibCopyRegion.srcOffset = 0;
437 ibCopyRegion.dstOffset = 0;
438 ibCopyRegion.size = ibInfo.size;
439 vkCmdCopyBuffer(g_hTemporaryCommandBuffer, stagingIndexBuffer, g_hIndexBuffer, 1, &ibCopyRegion);
440
441 EndSingleTimeCommands();
442
Adam Sawicki819860e2017-07-04 14:30:38 +0200443 vmaDestroyBuffer(g_hAllocator, stagingIndexBuffer, stagingIndexBufferAlloc);
444 vmaDestroyBuffer(g_hAllocator, stagingVertexBuffer, stagingVertexBufferAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200445}
446
Adam Sawickie6e498f2017-06-16 17:21:31 +0200447static void CreateTexture(uint32_t sizeX, uint32_t sizeY)
448{
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100449 // Create staging buffer.
Adam Sawickie6e498f2017-06-16 17:21:31 +0200450
451 const VkDeviceSize imageSize = sizeX * sizeY * 4;
452
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100453 VkBufferCreateInfo stagingBufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
454 stagingBufInfo.size = imageSize;
455 stagingBufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
456
457 VmaAllocationCreateInfo stagingBufAllocCreateInfo = {};
458 stagingBufAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
459 stagingBufAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
Adam Sawicki819860e2017-07-04 14:30:38 +0200460
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100461 VkBuffer stagingBuf = VK_NULL_HANDLE;
462 VmaAllocation stagingBufAlloc = VK_NULL_HANDLE;
463 VmaAllocationInfo stagingBufAllocInfo = {};
464 ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &stagingBufInfo, &stagingBufAllocCreateInfo, &stagingBuf, &stagingBufAlloc, &stagingBufAllocInfo) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200465
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100466 char* const pImageData = (char*)stagingBufAllocInfo.pMappedData;
467 uint8_t* pRowData = (uint8_t*)pImageData;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200468 for(uint32_t y = 0; y < sizeY; ++y)
469 {
470 uint32_t* pPixelData = (uint32_t*)pRowData;
471 for(uint32_t x = 0; x < sizeY; ++x)
472 {
473 *pPixelData =
474 ((x & 0x18) == 0x08 ? 0x000000FF : 0x00000000) |
475 ((x & 0x18) == 0x10 ? 0x0000FFFF : 0x00000000) |
476 ((y & 0x18) == 0x08 ? 0x0000FF00 : 0x00000000) |
477 ((y & 0x18) == 0x10 ? 0x00FF0000 : 0x00000000);
478 ++pPixelData;
479 }
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100480 pRowData += sizeX * 4;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200481 }
482
Adam Sawicki2f16fa52017-07-04 14:43:20 +0200483 // No need to flush stagingImage memory because CPU_ONLY memory is always HOST_COHERENT.
484
Adam Sawicki10844a82017-08-16 17:32:09 +0200485 // Create g_hTextureImage in GPU memory.
486
Adam Sawickie6e498f2017-06-16 17:21:31 +0200487 VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
488 imageInfo.imageType = VK_IMAGE_TYPE_2D;
489 imageInfo.extent.width = sizeX;
490 imageInfo.extent.height = sizeY;
491 imageInfo.extent.depth = 1;
492 imageInfo.mipLevels = 1;
493 imageInfo.arrayLayers = 1;
494 imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
495 imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
496 imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
497 imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
498 imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
499 imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
500 imageInfo.flags = 0;
Adam Sawicki10844a82017-08-16 17:32:09 +0200501
Adam Sawicki976f9202017-09-12 20:45:14 +0200502 VmaAllocationCreateInfo imageAllocCreateInfo = {};
503 imageAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
Adam Sawicki10844a82017-08-16 17:32:09 +0200504
Adam Sawicki976f9202017-09-12 20:45:14 +0200505 ERR_GUARD_VULKAN( vmaCreateImage(g_hAllocator, &imageInfo, &imageAllocCreateInfo, &g_hTextureImage, &g_hTextureImageAlloc, nullptr) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200506
Adam Sawicki10844a82017-08-16 17:32:09 +0200507 // Transition image layouts, copy image.
508
509 BeginSingleTimeCommands();
510
511 VkImageMemoryBarrier imgMemBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
Adam Sawicki10844a82017-08-16 17:32:09 +0200512 imgMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
513 imgMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Adam Sawicki10844a82017-08-16 17:32:09 +0200514 imgMemBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
515 imgMemBarrier.subresourceRange.baseMipLevel = 0;
516 imgMemBarrier.subresourceRange.levelCount = 1;
517 imgMemBarrier.subresourceRange.baseArrayLayer = 0;
518 imgMemBarrier.subresourceRange.layerCount = 1;
Adam Sawicki10844a82017-08-16 17:32:09 +0200519 imgMemBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
520 imgMemBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
521 imgMemBarrier.image = g_hTextureImage;
522 imgMemBarrier.srcAccessMask = 0;
523 imgMemBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
524
525 vkCmdPipelineBarrier(
526 g_hTemporaryCommandBuffer,
527 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
528 VK_PIPELINE_STAGE_TRANSFER_BIT,
529 0,
530 0, nullptr,
531 0, nullptr,
532 1, &imgMemBarrier);
533
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100534 VkBufferImageCopy region = {};
535 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
536 region.imageSubresource.layerCount = 1;
537 region.imageExtent.width = sizeX;
538 region.imageExtent.height = sizeY;
539 region.imageExtent.depth = 1;
540
541 vkCmdCopyBufferToImage(g_hTemporaryCommandBuffer, stagingBuf, g_hTextureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
Adam Sawicki10844a82017-08-16 17:32:09 +0200542
543 imgMemBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
544 imgMemBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
545 imgMemBarrier.image = g_hTextureImage;
546 imgMemBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
547 imgMemBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
548
549 vkCmdPipelineBarrier(
550 g_hTemporaryCommandBuffer,
551 VK_PIPELINE_STAGE_TRANSFER_BIT,
552 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
553 0,
554 0, nullptr,
555 0, nullptr,
556 1, &imgMemBarrier);
557
558 EndSingleTimeCommands();
Adam Sawickie6e498f2017-06-16 17:21:31 +0200559
Adam Sawickif43e9cd2019-02-20 14:55:31 +0100560 vmaDestroyBuffer(g_hAllocator, stagingBuf, stagingBufAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200561
562 // Create ImageView
563
564 VkImageViewCreateInfo textureImageViewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
565 textureImageViewInfo.image = g_hTextureImage;
566 textureImageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
567 textureImageViewInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
568 textureImageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
569 textureImageViewInfo.subresourceRange.baseMipLevel = 0;
570 textureImageViewInfo.subresourceRange.levelCount = 1;
571 textureImageViewInfo.subresourceRange.baseArrayLayer = 0;
572 textureImageViewInfo.subresourceRange.layerCount = 1;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200573 ERR_GUARD_VULKAN( vkCreateImageView(g_hDevice, &textureImageViewInfo, g_Allocs, &g_hTextureImageView) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200574}
575
576struct UniformBufferObject
577{
Adam Sawicki82c3f332018-06-11 15:27:33 +0200578 mat4 ModelViewProj;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200579};
580
581static void RegisterDebugCallbacks()
582{
583 g_pvkCreateDebugReportCallbackEXT =
584 reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>
585 (vkGetInstanceProcAddr(g_hVulkanInstance, "vkCreateDebugReportCallbackEXT"));
586 g_pvkDebugReportMessageEXT =
587 reinterpret_cast<PFN_vkDebugReportMessageEXT>
588 (vkGetInstanceProcAddr(g_hVulkanInstance, "vkDebugReportMessageEXT"));
589 g_pvkDestroyDebugReportCallbackEXT =
590 reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>
591 (vkGetInstanceProcAddr(g_hVulkanInstance, "vkDestroyDebugReportCallbackEXT"));
592 assert(g_pvkCreateDebugReportCallbackEXT);
593 assert(g_pvkDebugReportMessageEXT);
594 assert(g_pvkDestroyDebugReportCallbackEXT);
595
596 VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
597 callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
598 callbackCreateInfo.pNext = nullptr;
599 callbackCreateInfo.flags = //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
600 VK_DEBUG_REPORT_ERROR_BIT_EXT |
601 VK_DEBUG_REPORT_WARNING_BIT_EXT |
602 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT /*|
603 VK_DEBUG_REPORT_DEBUG_BIT_EXT*/;
604 callbackCreateInfo.pfnCallback = &MyDebugReportCallback;
605 callbackCreateInfo.pUserData = nullptr;
606
Adam Sawicki1f84f622019-07-02 13:40:01 +0200607 ERR_GUARD_VULKAN( g_pvkCreateDebugReportCallbackEXT(g_hVulkanInstance, &callbackCreateInfo, g_Allocs, &g_hCallback) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200608}
609
610static bool IsLayerSupported(const VkLayerProperties* pProps, size_t propCount, const char* pLayerName)
611{
612 const VkLayerProperties* propsEnd = pProps + propCount;
613 return std::find_if(
614 pProps,
615 propsEnd,
616 [pLayerName](const VkLayerProperties& prop) -> bool {
617 return strcmp(pLayerName, prop.layerName) == 0;
618 }) != propsEnd;
619}
620
621static VkFormat FindSupportedFormat(
622 const std::vector<VkFormat>& candidates,
623 VkImageTiling tiling,
624 VkFormatFeatureFlags features)
625{
626 for (VkFormat format : candidates)
627 {
628 VkFormatProperties props;
629 vkGetPhysicalDeviceFormatProperties(g_hPhysicalDevice, format, &props);
630
631 if ((tiling == VK_IMAGE_TILING_LINEAR) &&
632 ((props.linearTilingFeatures & features) == features))
633 {
634 return format;
635 }
636 else if ((tiling == VK_IMAGE_TILING_OPTIMAL) &&
637 ((props.optimalTilingFeatures & features) == features))
638 {
639 return format;
640 }
641 }
642 return VK_FORMAT_UNDEFINED;
643}
644
645static VkFormat FindDepthFormat()
646{
647 std::vector<VkFormat> formats;
648 formats.push_back(VK_FORMAT_D32_SFLOAT);
649 formats.push_back(VK_FORMAT_D32_SFLOAT_S8_UINT);
650 formats.push_back(VK_FORMAT_D24_UNORM_S8_UINT);
651
652 return FindSupportedFormat(
653 formats,
654 VK_IMAGE_TILING_OPTIMAL,
655 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
656}
657
658static void CreateSwapchain()
659{
660 // Query surface formats.
661
662 ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_hPhysicalDevice, g_hSurface, &g_SurfaceCapabilities) );
663
664 uint32_t formatCount = 0;
665 ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfaceFormatsKHR(g_hPhysicalDevice, g_hSurface, &formatCount, nullptr) );
666 g_SurfaceFormats.resize(formatCount);
667 ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfaceFormatsKHR(g_hPhysicalDevice, g_hSurface, &formatCount, g_SurfaceFormats.data()) );
668
669 uint32_t presentModeCount = 0;
670 ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfacePresentModesKHR(g_hPhysicalDevice, g_hSurface, &presentModeCount, nullptr) );
671 g_PresentModes.resize(presentModeCount);
672 ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfacePresentModesKHR(g_hPhysicalDevice, g_hSurface, &presentModeCount, g_PresentModes.data()) );
673
674 // Create swap chain
675
676 g_SurfaceFormat = ChooseSurfaceFormat();
677 VkPresentModeKHR presentMode = ChooseSwapPresentMode();
678 g_Extent = ChooseSwapExtent();
679
680 uint32_t imageCount = g_SurfaceCapabilities.minImageCount + 1;
681 if((g_SurfaceCapabilities.maxImageCount > 0) &&
682 (imageCount > g_SurfaceCapabilities.maxImageCount))
683 {
684 imageCount = g_SurfaceCapabilities.maxImageCount;
685 }
686
687 VkSwapchainCreateInfoKHR swapChainInfo = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR };
688 swapChainInfo.surface = g_hSurface;
689 swapChainInfo.minImageCount = imageCount;
690 swapChainInfo.imageFormat = g_SurfaceFormat.format;
691 swapChainInfo.imageColorSpace = g_SurfaceFormat.colorSpace;
692 swapChainInfo.imageExtent = g_Extent;
693 swapChainInfo.imageArrayLayers = 1;
694 swapChainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
695 swapChainInfo.preTransform = g_SurfaceCapabilities.currentTransform;
696 swapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
697 swapChainInfo.presentMode = presentMode;
698 swapChainInfo.clipped = VK_TRUE;
699 swapChainInfo.oldSwapchain = g_hSwapchain;
700
701 uint32_t queueFamilyIndices[] = { g_GraphicsQueueFamilyIndex, g_PresentQueueFamilyIndex };
702 if(g_PresentQueueFamilyIndex != g_GraphicsQueueFamilyIndex)
703 {
704 swapChainInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
705 swapChainInfo.queueFamilyIndexCount = 2;
706 swapChainInfo.pQueueFamilyIndices = queueFamilyIndices;
707 }
708 else
709 {
710 swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
711 }
712
713 VkSwapchainKHR hNewSwapchain = VK_NULL_HANDLE;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200714 ERR_GUARD_VULKAN( vkCreateSwapchainKHR(g_hDevice, &swapChainInfo, g_Allocs, &hNewSwapchain) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200715 if(g_hSwapchain != VK_NULL_HANDLE)
Adam Sawicki1f84f622019-07-02 13:40:01 +0200716 vkDestroySwapchainKHR(g_hDevice, g_hSwapchain, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200717 g_hSwapchain = hNewSwapchain;
718
719 // Retrieve swapchain images.
720
721 uint32_t swapchainImageCount = 0;
722 ERR_GUARD_VULKAN( vkGetSwapchainImagesKHR(g_hDevice, g_hSwapchain, &swapchainImageCount, nullptr) );
723 g_SwapchainImages.resize(swapchainImageCount);
724 ERR_GUARD_VULKAN( vkGetSwapchainImagesKHR(g_hDevice, g_hSwapchain, &swapchainImageCount, g_SwapchainImages.data()) );
725
726 // Create swapchain image views.
727
728 for(size_t i = g_SwapchainImageViews.size(); i--; )
Adam Sawicki1f84f622019-07-02 13:40:01 +0200729 vkDestroyImageView(g_hDevice, g_SwapchainImageViews[i], g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200730 g_SwapchainImageViews.clear();
731
732 VkImageViewCreateInfo swapchainImageViewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
733 g_SwapchainImageViews.resize(swapchainImageCount);
734 for(uint32_t i = 0; i < swapchainImageCount; ++i)
735 {
736 swapchainImageViewInfo.image = g_SwapchainImages[i];
737 swapchainImageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
738 swapchainImageViewInfo.format = g_SurfaceFormat.format;
739 swapchainImageViewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
740 swapchainImageViewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
741 swapchainImageViewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
742 swapchainImageViewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
743 swapchainImageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
744 swapchainImageViewInfo.subresourceRange.baseMipLevel = 0;
745 swapchainImageViewInfo.subresourceRange.levelCount = 1;
746 swapchainImageViewInfo.subresourceRange.baseArrayLayer = 0;
747 swapchainImageViewInfo.subresourceRange.layerCount = 1;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200748 ERR_GUARD_VULKAN( vkCreateImageView(g_hDevice, &swapchainImageViewInfo, g_Allocs, &g_SwapchainImageViews[i]) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200749 }
750
751 // Create depth buffer
752
753 g_DepthFormat = FindDepthFormat();
754 assert(g_DepthFormat != VK_FORMAT_UNDEFINED);
755
756 VkImageCreateInfo depthImageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
757 depthImageInfo.imageType = VK_IMAGE_TYPE_2D;
758 depthImageInfo.extent.width = g_Extent.width;
759 depthImageInfo.extent.height = g_Extent.height;
760 depthImageInfo.extent.depth = 1;
761 depthImageInfo.mipLevels = 1;
762 depthImageInfo.arrayLayers = 1;
763 depthImageInfo.format = g_DepthFormat;
764 depthImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
765 depthImageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
766 depthImageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
767 depthImageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
768 depthImageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
769 depthImageInfo.flags = 0;
770
Adam Sawicki976f9202017-09-12 20:45:14 +0200771 VmaAllocationCreateInfo depthImageAllocCreateInfo = {};
772 depthImageAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200773
Adam Sawicki976f9202017-09-12 20:45:14 +0200774 ERR_GUARD_VULKAN( vmaCreateImage(g_hAllocator, &depthImageInfo, &depthImageAllocCreateInfo, &g_hDepthImage, &g_hDepthImageAlloc, nullptr) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200775
776 VkImageViewCreateInfo depthImageViewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
777 depthImageViewInfo.image = g_hDepthImage;
778 depthImageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
779 depthImageViewInfo.format = g_DepthFormat;
780 depthImageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
781 depthImageViewInfo.subresourceRange.baseMipLevel = 0;
782 depthImageViewInfo.subresourceRange.levelCount = 1;
783 depthImageViewInfo.subresourceRange.baseArrayLayer = 0;
784 depthImageViewInfo.subresourceRange.layerCount = 1;
785
Adam Sawicki1f84f622019-07-02 13:40:01 +0200786 ERR_GUARD_VULKAN( vkCreateImageView(g_hDevice, &depthImageViewInfo, g_Allocs, &g_hDepthImageView) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200787
Adam Sawickie6e498f2017-06-16 17:21:31 +0200788 // Create pipeline layout
789 {
790 if(g_hPipelineLayout != VK_NULL_HANDLE)
791 {
Adam Sawicki1f84f622019-07-02 13:40:01 +0200792 vkDestroyPipelineLayout(g_hDevice, g_hPipelineLayout, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200793 g_hPipelineLayout = VK_NULL_HANDLE;
794 }
795
796 VkPushConstantRange pushConstantRanges[1];
797 ZeroMemory(&pushConstantRanges, sizeof pushConstantRanges);
798 pushConstantRanges[0].offset = 0;
799 pushConstantRanges[0].size = sizeof(UniformBufferObject);
800 pushConstantRanges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
801
802 VkDescriptorSetLayout descriptorSetLayouts[] = { g_hDescriptorSetLayout };
803 VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
804 pipelineLayoutInfo.setLayoutCount = 1;
805 pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts;
806 pipelineLayoutInfo.pushConstantRangeCount = 1;
807 pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200808 ERR_GUARD_VULKAN( vkCreatePipelineLayout(g_hDevice, &pipelineLayoutInfo, g_Allocs, &g_hPipelineLayout) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200809 }
810
811 // Create render pass
812 {
813 if(g_hRenderPass != VK_NULL_HANDLE)
814 {
Adam Sawicki1f84f622019-07-02 13:40:01 +0200815 vkDestroyRenderPass(g_hDevice, g_hRenderPass, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +0200816 g_hRenderPass = VK_NULL_HANDLE;
817 }
818
819 VkAttachmentDescription attachments[2];
820 ZeroMemory(attachments, sizeof(attachments));
821
822 attachments[0].format = g_SurfaceFormat.format;
823 attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
824 attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
825 attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
826 attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
827 attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
Adam Sawicki8eb9d8e2017-11-13 16:30:14 +0100828 attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200829 attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
830
831 attachments[1].format = g_DepthFormat;
832 attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
833 attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
834 attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
835 attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
836 attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
Adam Sawicki8eb9d8e2017-11-13 16:30:14 +0100837 attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
Adam Sawickie6e498f2017-06-16 17:21:31 +0200838 attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
839
840 VkAttachmentReference colorAttachmentRef = {};
841 colorAttachmentRef.attachment = 0;
842 colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
843
844 VkAttachmentReference depthStencilAttachmentRef = {};
845 depthStencilAttachmentRef.attachment = 1;
846 depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
847
848 VkSubpassDescription subpassDesc = {};
849 subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
850 subpassDesc.colorAttachmentCount = 1;
851 subpassDesc.pColorAttachments = &colorAttachmentRef;
852 subpassDesc.pDepthStencilAttachment = &depthStencilAttachmentRef;
853
Adam Sawickie6e498f2017-06-16 17:21:31 +0200854 VkRenderPassCreateInfo renderPassInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
855 renderPassInfo.attachmentCount = (uint32_t)_countof(attachments);
856 renderPassInfo.pAttachments = attachments;
857 renderPassInfo.subpassCount = 1;
858 renderPassInfo.pSubpasses = &subpassDesc;
Adam Sawicki14137d12017-10-16 18:06:05 +0200859 renderPassInfo.dependencyCount = 0;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200860 ERR_GUARD_VULKAN( vkCreateRenderPass(g_hDevice, &renderPassInfo, g_Allocs, &g_hRenderPass) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200861 }
862
863 // Create pipeline
864 {
865 std::vector<char> vertShaderCode;
866 LoadShader(vertShaderCode, "Shader.vert.spv");
867 VkShaderModuleCreateInfo shaderModuleInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
868 shaderModuleInfo.codeSize = vertShaderCode.size();
869 shaderModuleInfo.pCode = (const uint32_t*)vertShaderCode.data();
870 VkShaderModule hVertShaderModule = VK_NULL_HANDLE;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200871 ERR_GUARD_VULKAN( vkCreateShaderModule(g_hDevice, &shaderModuleInfo, g_Allocs, &hVertShaderModule) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200872
873 std::vector<char> hFragShaderCode;
874 LoadShader(hFragShaderCode, "Shader.frag.spv");
875 shaderModuleInfo.codeSize = hFragShaderCode.size();
876 shaderModuleInfo.pCode = (const uint32_t*)hFragShaderCode.data();
877 VkShaderModule fragShaderModule = VK_NULL_HANDLE;
Adam Sawicki1f84f622019-07-02 13:40:01 +0200878 ERR_GUARD_VULKAN( vkCreateShaderModule(g_hDevice, &shaderModuleInfo, g_Allocs, &fragShaderModule) );
Adam Sawickie6e498f2017-06-16 17:21:31 +0200879
880 VkPipelineShaderStageCreateInfo vertPipelineShaderStageInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
881 vertPipelineShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
882 vertPipelineShaderStageInfo.module = hVertShaderModule;
883 vertPipelineShaderStageInfo.pName = "main";
884
885 VkPipelineShaderStageCreateInfo fragPipelineShaderStageInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
886 fragPipelineShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
887 fragPipelineShaderStageInfo.module = fragShaderModule;
888 fragPipelineShaderStageInfo.pName = "main";
889
890 VkPipelineShaderStageCreateInfo pipelineShaderStageInfos[] = {
891 vertPipelineShaderStageInfo,
892 fragPipelineShaderStageInfo
893 };
894
895 VkVertexInputBindingDescription bindingDescription = {};
896 bindingDescription.binding = 0;
897 bindingDescription.stride = sizeof(Vertex);
898 bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
899
900 VkVertexInputAttributeDescription attributeDescriptions[3];
901 ZeroMemory(attributeDescriptions, sizeof(attributeDescriptions));
902
903 attributeDescriptions[0].binding = 0;
904 attributeDescriptions[0].location = 0;
905 attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
906 attributeDescriptions[0].offset = offsetof(Vertex, pos);
907
908 attributeDescriptions[1].binding = 0;
909 attributeDescriptions[1].location = 1;
910 attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
911 attributeDescriptions[1].offset = offsetof(Vertex, color);
912
913 attributeDescriptions[2].binding = 0;
914 attributeDescriptions[2].location = 2;
915 attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
916 attributeDescriptions[2].offset = offsetof(Vertex, texCoord);
917
918 VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
919 pipelineVertexInputStateInfo.vertexBindingDescriptionCount = 1;
920 pipelineVertexInputStateInfo.pVertexBindingDescriptions = &bindingDescription;
921 pipelineVertexInputStateInfo.vertexAttributeDescriptionCount = _countof(attributeDescriptions);
922 pipelineVertexInputStateInfo.pVertexAttributeDescriptions = attributeDescriptions;
923
924 VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
925 pipelineInputAssemblyStateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
926 pipelineInputAssemblyStateInfo.primitiveRestartEnable = VK_TRUE;
927
928 VkViewport viewport = {};
929 viewport.x = 0.f;
930 viewport.y = 0.f;
931 viewport.width = (float)g_Extent.width;
932 viewport.height = (float)g_Extent.height;
933 viewport.minDepth = 0.f;
934 viewport.maxDepth = 1.f;
935
936 VkRect2D scissor = {};
937 scissor.offset.x = 0;
938 scissor.offset.y = 0;
939 scissor.extent = g_Extent;
940
941 VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
942 pipelineViewportStateInfo.viewportCount = 1;
943 pipelineViewportStateInfo.pViewports = &viewport;
944 pipelineViewportStateInfo.scissorCount = 1;
945 pipelineViewportStateInfo.pScissors = &scissor;
946
947 VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
948 pipelineRasterizationStateInfo.depthClampEnable = VK_FALSE;
949 pipelineRasterizationStateInfo.rasterizerDiscardEnable = VK_FALSE;
950 pipelineRasterizationStateInfo.polygonMode = VK_POLYGON_MODE_FILL;
951 pipelineRasterizationStateInfo.lineWidth = 1.f;
952 pipelineRasterizationStateInfo.cullMode = VK_CULL_MODE_BACK_BIT;
953 pipelineRasterizationStateInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
954 pipelineRasterizationStateInfo.depthBiasEnable = VK_FALSE;
955 pipelineRasterizationStateInfo.depthBiasConstantFactor = 0.f;
956 pipelineRasterizationStateInfo.depthBiasClamp = 0.f;
957 pipelineRasterizationStateInfo.depthBiasSlopeFactor = 0.f;
958
959 VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
960 pipelineMultisampleStateInfo.sampleShadingEnable = VK_FALSE;
961 pipelineMultisampleStateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
962 pipelineMultisampleStateInfo.minSampleShading = 1.f;
963 pipelineMultisampleStateInfo.pSampleMask = nullptr;
964 pipelineMultisampleStateInfo.alphaToCoverageEnable = VK_FALSE;
965 pipelineMultisampleStateInfo.alphaToOneEnable = VK_FALSE;
966
967 VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {};
968 pipelineColorBlendAttachmentState.colorWriteMask =
969 VK_COLOR_COMPONENT_R_BIT |
970 VK_COLOR_COMPONENT_G_BIT |
971 VK_COLOR_COMPONENT_B_BIT |
972 VK_COLOR_COMPONENT_A_BIT;
973 pipelineColorBlendAttachmentState.blendEnable = VK_FALSE;
974 pipelineColorBlendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
975 pipelineColorBlendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
976 pipelineColorBlendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; // Optional
977 pipelineColorBlendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
978 pipelineColorBlendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
979 pipelineColorBlendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; // Optional
980
981 VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
982 pipelineColorBlendStateInfo.logicOpEnable = VK_FALSE;
983 pipelineColorBlendStateInfo.logicOp = VK_LOGIC_OP_COPY;
984 pipelineColorBlendStateInfo.attachmentCount = 1;
985 pipelineColorBlendStateInfo.pAttachments = &pipelineColorBlendAttachmentState;
986
987 VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
988 depthStencilStateInfo.depthTestEnable = VK_TRUE;
989 depthStencilStateInfo.depthWriteEnable = VK_TRUE;
990 depthStencilStateInfo.depthCompareOp = VK_COMPARE_OP_LESS;
991 depthStencilStateInfo.depthBoundsTestEnable = VK_FALSE;
992 depthStencilStateInfo.stencilTestEnable = VK_FALSE;
993
994 VkGraphicsPipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
995 pipelineInfo.stageCount = 2;
996 pipelineInfo.pStages = pipelineShaderStageInfos;
997 pipelineInfo.pVertexInputState = &pipelineVertexInputStateInfo;
998 pipelineInfo.pInputAssemblyState = &pipelineInputAssemblyStateInfo;
999 pipelineInfo.pViewportState = &pipelineViewportStateInfo;
1000 pipelineInfo.pRasterizationState = &pipelineRasterizationStateInfo;
1001 pipelineInfo.pMultisampleState = &pipelineMultisampleStateInfo;
1002 pipelineInfo.pDepthStencilState = &depthStencilStateInfo;
1003 pipelineInfo.pColorBlendState = &pipelineColorBlendStateInfo;
1004 pipelineInfo.pDynamicState = nullptr;
1005 pipelineInfo.layout = g_hPipelineLayout;
1006 pipelineInfo.renderPass = g_hRenderPass;
1007 pipelineInfo.subpass = 0;
1008 pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
1009 pipelineInfo.basePipelineIndex = -1;
1010 ERR_GUARD_VULKAN( vkCreateGraphicsPipelines(
1011 g_hDevice,
1012 VK_NULL_HANDLE,
1013 1,
Adam Sawicki1f84f622019-07-02 13:40:01 +02001014 &pipelineInfo,
1015 g_Allocs,
Adam Sawickie6e498f2017-06-16 17:21:31 +02001016 &g_hPipeline) );
1017
Adam Sawicki1f84f622019-07-02 13:40:01 +02001018 vkDestroyShaderModule(g_hDevice, fragShaderModule, g_Allocs);
1019 vkDestroyShaderModule(g_hDevice, hVertShaderModule, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001020 }
1021
1022 // Create frambuffers
1023
1024 for(size_t i = g_Framebuffers.size(); i--; )
Adam Sawicki1f84f622019-07-02 13:40:01 +02001025 vkDestroyFramebuffer(g_hDevice, g_Framebuffers[i], g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001026 g_Framebuffers.clear();
1027
1028 g_Framebuffers.resize(g_SwapchainImageViews.size());
1029 for(size_t i = 0; i < g_SwapchainImages.size(); ++i)
1030 {
1031 VkImageView attachments[] = { g_SwapchainImageViews[i], g_hDepthImageView };
1032
1033 VkFramebufferCreateInfo framebufferInfo = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
1034 framebufferInfo.renderPass = g_hRenderPass;
1035 framebufferInfo.attachmentCount = (uint32_t)_countof(attachments);
1036 framebufferInfo.pAttachments = attachments;
1037 framebufferInfo.width = g_Extent.width;
1038 framebufferInfo.height = g_Extent.height;
1039 framebufferInfo.layers = 1;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001040 ERR_GUARD_VULKAN( vkCreateFramebuffer(g_hDevice, &framebufferInfo, g_Allocs, &g_Framebuffers[i]) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001041 }
1042
1043 // Create semaphores
1044
1045 if(g_hImageAvailableSemaphore != VK_NULL_HANDLE)
1046 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001047 vkDestroySemaphore(g_hDevice, g_hImageAvailableSemaphore, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001048 g_hImageAvailableSemaphore = VK_NULL_HANDLE;
1049 }
1050 if(g_hRenderFinishedSemaphore != VK_NULL_HANDLE)
1051 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001052 vkDestroySemaphore(g_hDevice, g_hRenderFinishedSemaphore, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001053 g_hRenderFinishedSemaphore = VK_NULL_HANDLE;
1054 }
1055
1056 VkSemaphoreCreateInfo semaphoreInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
Adam Sawicki1f84f622019-07-02 13:40:01 +02001057 ERR_GUARD_VULKAN( vkCreateSemaphore(g_hDevice, &semaphoreInfo, g_Allocs, &g_hImageAvailableSemaphore) );
1058 ERR_GUARD_VULKAN( vkCreateSemaphore(g_hDevice, &semaphoreInfo, g_Allocs, &g_hRenderFinishedSemaphore) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001059}
1060
1061static void DestroySwapchain(bool destroyActualSwapchain)
1062{
1063 if(g_hImageAvailableSemaphore != VK_NULL_HANDLE)
1064 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001065 vkDestroySemaphore(g_hDevice, g_hImageAvailableSemaphore, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001066 g_hImageAvailableSemaphore = VK_NULL_HANDLE;
1067 }
1068 if(g_hRenderFinishedSemaphore != VK_NULL_HANDLE)
1069 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001070 vkDestroySemaphore(g_hDevice, g_hRenderFinishedSemaphore, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001071 g_hRenderFinishedSemaphore = VK_NULL_HANDLE;
1072 }
1073
1074 for(size_t i = g_Framebuffers.size(); i--; )
Adam Sawicki1f84f622019-07-02 13:40:01 +02001075 vkDestroyFramebuffer(g_hDevice, g_Framebuffers[i], g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001076 g_Framebuffers.clear();
1077
1078 if(g_hDepthImageView != VK_NULL_HANDLE)
1079 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001080 vkDestroyImageView(g_hDevice, g_hDepthImageView, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001081 g_hDepthImageView = VK_NULL_HANDLE;
1082 }
1083 if(g_hDepthImage != VK_NULL_HANDLE)
1084 {
Adam Sawicki819860e2017-07-04 14:30:38 +02001085 vmaDestroyImage(g_hAllocator, g_hDepthImage, g_hDepthImageAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001086 g_hDepthImage = VK_NULL_HANDLE;
1087 }
1088
1089 if(g_hPipeline != VK_NULL_HANDLE)
1090 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001091 vkDestroyPipeline(g_hDevice, g_hPipeline, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001092 g_hPipeline = VK_NULL_HANDLE;
1093 }
1094
1095 if(g_hRenderPass != VK_NULL_HANDLE)
1096 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001097 vkDestroyRenderPass(g_hDevice, g_hRenderPass, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001098 g_hRenderPass = VK_NULL_HANDLE;
1099 }
1100
1101 if(g_hPipelineLayout != VK_NULL_HANDLE)
1102 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001103 vkDestroyPipelineLayout(g_hDevice, g_hPipelineLayout, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001104 g_hPipelineLayout = VK_NULL_HANDLE;
1105 }
1106
1107 for(size_t i = g_SwapchainImageViews.size(); i--; )
Adam Sawicki1f84f622019-07-02 13:40:01 +02001108 vkDestroyImageView(g_hDevice, g_SwapchainImageViews[i], g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001109 g_SwapchainImageViews.clear();
1110
1111 if(destroyActualSwapchain && (g_hSwapchain != VK_NULL_HANDLE))
1112 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001113 vkDestroySwapchainKHR(g_hDevice, g_hSwapchain, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001114 g_hSwapchain = VK_NULL_HANDLE;
1115 }
1116}
1117
1118static void InitializeApplication()
1119{
Adam Sawicki1f84f622019-07-02 13:40:01 +02001120 if(USE_CUSTOM_CPU_ALLOCATION_CALLBACKS)
1121 {
1122 g_Allocs = &g_CpuAllocationCallbacks;
1123 }
1124
Adam Sawickie6e498f2017-06-16 17:21:31 +02001125 uint32_t instanceLayerPropCount = 0;
1126 ERR_GUARD_VULKAN( vkEnumerateInstanceLayerProperties(&instanceLayerPropCount, nullptr) );
1127 std::vector<VkLayerProperties> instanceLayerProps(instanceLayerPropCount);
1128 if(instanceLayerPropCount > 0)
1129 {
1130 ERR_GUARD_VULKAN( vkEnumerateInstanceLayerProperties(&instanceLayerPropCount, instanceLayerProps.data()) );
1131 }
1132
1133 if(g_EnableValidationLayer == true)
1134 {
1135 if(IsLayerSupported(instanceLayerProps.data(), instanceLayerProps.size(), VALIDATION_LAYER_NAME) == false)
1136 {
1137 printf("Layer \"%s\" not supported.", VALIDATION_LAYER_NAME);
1138 g_EnableValidationLayer = false;
1139 }
1140 }
1141
Adam Sawicki353e3672019-11-02 14:12:05 +01001142 uint32_t availableInstanceExtensionCount = 0;
1143 ERR_GUARD_VULKAN( vkEnumerateInstanceExtensionProperties(nullptr, &availableInstanceExtensionCount, nullptr) );
1144 std::vector<VkExtensionProperties> availableInstanceExtensions(availableInstanceExtensionCount);
1145 if(availableInstanceExtensionCount > 0)
1146 {
1147 ERR_GUARD_VULKAN( vkEnumerateInstanceExtensionProperties(nullptr, &availableInstanceExtensionCount, availableInstanceExtensions.data()) );
1148 }
1149
1150 std::vector<const char*> enabledInstanceExtensions;
1151 enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
1152 enabledInstanceExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001153
1154 std::vector<const char*> instanceLayers;
1155 if(g_EnableValidationLayer == true)
1156 {
1157 instanceLayers.push_back(VALIDATION_LAYER_NAME);
Adam Sawicki353e3672019-11-02 14:12:05 +01001158 enabledInstanceExtensions.push_back("VK_EXT_debug_report");
1159 }
1160
1161 for(const auto& extensionProperties : availableInstanceExtensions)
1162 {
1163 if(strcmp(extensionProperties.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0)
1164 {
1165 enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1166 VK_KHR_get_physical_device_properties2_enabled = true;
1167 }
Adam Sawickie6e498f2017-06-16 17:21:31 +02001168 }
1169
1170 VkApplicationInfo appInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
1171 appInfo.pApplicationName = APP_TITLE_A;
1172 appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
1173 appInfo.pEngineName = "Adam Sawicki Engine";
1174 appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
1175 appInfo.apiVersion = VK_API_VERSION_1_0;
1176
1177 VkInstanceCreateInfo instInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
1178 instInfo.pApplicationInfo = &appInfo;
Adam Sawicki353e3672019-11-02 14:12:05 +01001179 instInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size());
1180 instInfo.ppEnabledExtensionNames = enabledInstanceExtensions.data();
Adam Sawickie6e498f2017-06-16 17:21:31 +02001181 instInfo.enabledLayerCount = static_cast<uint32_t>(instanceLayers.size());
1182 instInfo.ppEnabledLayerNames = instanceLayers.data();
1183
Adam Sawicki1f84f622019-07-02 13:40:01 +02001184 ERR_GUARD_VULKAN( vkCreateInstance(&instInfo, g_Allocs, &g_hVulkanInstance) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001185
1186 // Create VkSurfaceKHR.
1187 VkWin32SurfaceCreateInfoKHR surfaceInfo = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR };
1188 surfaceInfo.hinstance = g_hAppInstance;
1189 surfaceInfo.hwnd = g_hWnd;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001190 VkResult result = vkCreateWin32SurfaceKHR(g_hVulkanInstance, &surfaceInfo, g_Allocs, &g_hSurface);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001191 assert(result == VK_SUCCESS);
1192
1193 if(g_EnableValidationLayer == true)
1194 RegisterDebugCallbacks();
1195
1196 // Find physical device
1197
1198 uint32_t deviceCount = 0;
1199 ERR_GUARD_VULKAN( vkEnumeratePhysicalDevices(g_hVulkanInstance, &deviceCount, nullptr) );
1200 assert(deviceCount > 0);
1201
1202 std::vector<VkPhysicalDevice> physicalDevices(deviceCount);
1203 ERR_GUARD_VULKAN( vkEnumeratePhysicalDevices(g_hVulkanInstance, &deviceCount, physicalDevices.data()) );
1204
1205 g_hPhysicalDevice = physicalDevices[0];
1206
1207 // Query for features
1208
1209 VkPhysicalDeviceProperties physicalDeviceProperties = {};
1210 vkGetPhysicalDeviceProperties(g_hPhysicalDevice, &physicalDeviceProperties);
1211
Adam Sawicki51fa9662018-10-03 13:44:29 +02001212 VkPhysicalDeviceFeatures physicalDeviceFeatures = {};
1213 vkGetPhysicalDeviceFeatures(g_hPhysicalDevice, &physicalDeviceFeatures);
1214
1215 g_SparseBindingEnabled = physicalDeviceFeatures.sparseBinding != 0;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001216
1217 // Find queue family index
1218
1219 uint32_t queueFamilyCount = 0;
1220 vkGetPhysicalDeviceQueueFamilyProperties(g_hPhysicalDevice, &queueFamilyCount, nullptr);
1221 assert(queueFamilyCount > 0);
1222 std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
1223 vkGetPhysicalDeviceQueueFamilyProperties(g_hPhysicalDevice, &queueFamilyCount, queueFamilies.data());
1224 for(uint32_t i = 0;
1225 (i < queueFamilyCount) &&
Adam Sawicki51fa9662018-10-03 13:44:29 +02001226 (g_GraphicsQueueFamilyIndex == UINT_MAX ||
1227 g_PresentQueueFamilyIndex == UINT_MAX ||
1228 (g_SparseBindingEnabled && g_SparseBindingQueueFamilyIndex == UINT_MAX));
Adam Sawickie6e498f2017-06-16 17:21:31 +02001229 ++i)
1230 {
1231 if(queueFamilies[i].queueCount > 0)
1232 {
Adam Sawickida6c1942018-12-05 17:34:34 +01001233 const uint32_t flagsForGraphicsQueue = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001234 if((g_GraphicsQueueFamilyIndex != 0) &&
Adam Sawickida6c1942018-12-05 17:34:34 +01001235 ((queueFamilies[i].queueFlags & flagsForGraphicsQueue) == flagsForGraphicsQueue))
Adam Sawickie6e498f2017-06-16 17:21:31 +02001236 {
1237 g_GraphicsQueueFamilyIndex = i;
1238 }
1239
1240 VkBool32 surfaceSupported = 0;
1241 VkResult res = vkGetPhysicalDeviceSurfaceSupportKHR(g_hPhysicalDevice, i, g_hSurface, &surfaceSupported);
1242 if((res >= 0) && (surfaceSupported == VK_TRUE))
1243 {
1244 g_PresentQueueFamilyIndex = i;
1245 }
Adam Sawicki51fa9662018-10-03 13:44:29 +02001246
1247 if(g_SparseBindingEnabled &&
1248 g_SparseBindingQueueFamilyIndex == UINT32_MAX &&
1249 (queueFamilies[i].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) != 0)
1250 {
1251 g_SparseBindingQueueFamilyIndex = i;
1252 }
Adam Sawickie6e498f2017-06-16 17:21:31 +02001253 }
1254 }
1255 assert(g_GraphicsQueueFamilyIndex != UINT_MAX);
1256
Adam Sawicki51fa9662018-10-03 13:44:29 +02001257 g_SparseBindingEnabled = g_SparseBindingEnabled && g_SparseBindingQueueFamilyIndex != UINT32_MAX;
1258
Adam Sawickie6e498f2017-06-16 17:21:31 +02001259 // Create logical device
1260
1261 const float queuePriority = 1.f;
1262
Adam Sawicki51fa9662018-10-03 13:44:29 +02001263 VkDeviceQueueCreateInfo queueCreateInfo[3] = {};
1264 uint32_t queueCount = 1;
1265 queueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
1266 queueCreateInfo[0].queueFamilyIndex = g_GraphicsQueueFamilyIndex;
1267 queueCreateInfo[0].queueCount = 1;
1268 queueCreateInfo[0].pQueuePriorities = &queuePriority;
1269
1270 if(g_PresentQueueFamilyIndex != g_GraphicsQueueFamilyIndex)
1271 {
1272
1273 queueCreateInfo[queueCount].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
1274 queueCreateInfo[queueCount].queueFamilyIndex = g_PresentQueueFamilyIndex;
1275 queueCreateInfo[queueCount].queueCount = 1;
1276 queueCreateInfo[queueCount].pQueuePriorities = &queuePriority;
1277 ++queueCount;
1278 }
1279
1280 if(g_SparseBindingEnabled &&
1281 g_SparseBindingQueueFamilyIndex != g_GraphicsQueueFamilyIndex &&
1282 g_SparseBindingQueueFamilyIndex != g_PresentQueueFamilyIndex)
1283 {
1284
1285 queueCreateInfo[queueCount].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
1286 queueCreateInfo[queueCount].queueFamilyIndex = g_SparseBindingQueueFamilyIndex;
1287 queueCreateInfo[queueCount].queueCount = 1;
1288 queueCreateInfo[queueCount].pQueuePriorities = &queuePriority;
1289 ++queueCount;
1290 }
Adam Sawickie6e498f2017-06-16 17:21:31 +02001291
1292 VkPhysicalDeviceFeatures deviceFeatures = {};
Adam Sawicki51fa9662018-10-03 13:44:29 +02001293 //deviceFeatures.fillModeNonSolid = VK_TRUE;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001294 deviceFeatures.samplerAnisotropy = VK_TRUE;
Adam Sawicki51fa9662018-10-03 13:44:29 +02001295 deviceFeatures.sparseBinding = g_SparseBindingEnabled ? VK_TRUE : VK_FALSE;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001296
Adam Sawicki6cc5e852018-03-13 16:37:54 +01001297 // Determine list of device extensions to enable.
Adam Sawickie6e498f2017-06-16 17:21:31 +02001298 std::vector<const char*> enabledDeviceExtensions;
1299 enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Adam Sawicki6cc5e852018-03-13 16:37:54 +01001300 {
1301 uint32_t propertyCount = 0;
1302 ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(g_hPhysicalDevice, nullptr, &propertyCount, nullptr) );
1303
1304 if(propertyCount)
1305 {
1306 std::vector<VkExtensionProperties> properties{propertyCount};
1307 ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(g_hPhysicalDevice, nullptr, &propertyCount, properties.data()) );
1308
1309 for(uint32_t i = 0; i < propertyCount; ++i)
1310 {
1311 if(strcmp(properties[i].extensionName, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME) == 0)
1312 {
1313 enabledDeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
1314 VK_KHR_get_memory_requirements2_enabled = true;
1315 }
1316 else if(strcmp(properties[i].extensionName, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) == 0)
1317 {
1318 enabledDeviceExtensions.push_back(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
1319 VK_KHR_dedicated_allocation_enabled = true;
1320 }
Adam Sawicki4abe30c2019-07-02 14:37:21 +02001321 else if(strcmp(properties[i].extensionName, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME) == 0)
1322 {
1323 enabledDeviceExtensions.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
1324 VK_KHR_bind_memory2_enabled = true;
1325 }
Adam Sawicki353e3672019-11-02 14:12:05 +01001326 else if(strcmp(properties[i].extensionName, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME) == 0)
1327 {
1328 enabledDeviceExtensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);
1329 VK_EXT_memory_budget_enabled = true;
1330 }
Adam Sawicki6cc5e852018-03-13 16:37:54 +01001331 }
1332 }
1333 }
Adam Sawickie6e498f2017-06-16 17:21:31 +02001334
1335 VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
1336 deviceCreateInfo.enabledLayerCount = 0;
1337 deviceCreateInfo.ppEnabledLayerNames = nullptr;
1338 deviceCreateInfo.enabledExtensionCount = (uint32_t)enabledDeviceExtensions.size();
Adam Sawicki6cc5e852018-03-13 16:37:54 +01001339 deviceCreateInfo.ppEnabledExtensionNames = !enabledDeviceExtensions.empty() ? enabledDeviceExtensions.data() : nullptr;
Adam Sawicki51fa9662018-10-03 13:44:29 +02001340 deviceCreateInfo.queueCreateInfoCount = queueCount;
1341 deviceCreateInfo.pQueueCreateInfos = queueCreateInfo;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001342 deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
1343
Adam Sawicki1f84f622019-07-02 13:40:01 +02001344 ERR_GUARD_VULKAN( vkCreateDevice(g_hPhysicalDevice, &deviceCreateInfo, g_Allocs, &g_hDevice) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001345
1346 // Create memory allocator
1347
1348 VmaAllocatorCreateInfo allocatorInfo = {};
1349 allocatorInfo.physicalDevice = g_hPhysicalDevice;
1350 allocatorInfo.device = g_hDevice;
Adam Sawicki353e3672019-11-02 14:12:05 +01001351 allocatorInfo.instance = g_hVulkanInstance;
Adam Sawickia68c01c2018-03-13 16:40:45 +01001352
Adam Sawicki6cc5e852018-03-13 16:37:54 +01001353 if(VK_KHR_dedicated_allocation_enabled)
1354 {
1355 allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
1356 }
Adam Sawicki4abe30c2019-07-02 14:37:21 +02001357 if(VK_KHR_bind_memory2_enabled)
1358 {
1359 allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
1360 }
Adam Sawicki4ac8ff82019-11-18 14:47:33 +01001361#if !defined(VMA_MEMORY_BUDGET) || VMA_MEMORY_BUDGET == 1
Adam Sawicki353e3672019-11-02 14:12:05 +01001362 if(VK_EXT_memory_budget_enabled && VK_KHR_get_physical_device_properties2_enabled)
1363 {
1364 allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;
1365 }
Adam Sawicki4ac8ff82019-11-18 14:47:33 +01001366#endif
Adam Sawickia68c01c2018-03-13 16:40:45 +01001367
Adam Sawickia68c01c2018-03-13 16:40:45 +01001368 if(USE_CUSTOM_CPU_ALLOCATION_CALLBACKS)
1369 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001370 allocatorInfo.pAllocationCallbacks = &g_CpuAllocationCallbacks;
Adam Sawickia68c01c2018-03-13 16:40:45 +01001371 }
1372
Adam Sawickib0c36362018-11-13 16:17:38 +01001373 // Uncomment to enable recording to CSV file.
1374 /*
1375 {
1376 VmaRecordSettings recordSettings = {};
1377 recordSettings.pFilePath = "VulkanSample.csv";
1378 allocatorInfo.pRecordSettings = &recordSettings;
1379 }
1380 */
1381
Adam Sawicki5f573f52019-10-11 15:59:58 +02001382 // Uncomment to enable HeapSizeLimit.
1383 /*
1384 std::array<VkDeviceSize, VK_MAX_MEMORY_HEAPS> heapSizeLimit;
1385 std::fill(heapSizeLimit.begin(), heapSizeLimit.end(), VK_WHOLE_SIZE);
Adam Sawicki353e3672019-11-02 14:12:05 +01001386 heapSizeLimit[0] = 512ull * 1024 * 1024;
Adam Sawicki5f573f52019-10-11 15:59:58 +02001387 allocatorInfo.pHeapSizeLimit = heapSizeLimit.data();
1388 */
1389
Adam Sawickie6e498f2017-06-16 17:21:31 +02001390 ERR_GUARD_VULKAN( vmaCreateAllocator(&allocatorInfo, &g_hAllocator) );
1391
Adam Sawicki51fa9662018-10-03 13:44:29 +02001392 // Retrieve queues (don't need to be destroyed).
Adam Sawickie6e498f2017-06-16 17:21:31 +02001393
1394 vkGetDeviceQueue(g_hDevice, g_GraphicsQueueFamilyIndex, 0, &g_hGraphicsQueue);
1395 vkGetDeviceQueue(g_hDevice, g_PresentQueueFamilyIndex, 0, &g_hPresentQueue);
1396 assert(g_hGraphicsQueue);
1397 assert(g_hPresentQueue);
1398
Adam Sawicki51fa9662018-10-03 13:44:29 +02001399 if(g_SparseBindingEnabled)
1400 {
1401 vkGetDeviceQueue(g_hDevice, g_SparseBindingQueueFamilyIndex, 0, &g_hSparseBindingQueue);
1402 assert(g_hSparseBindingQueue);
1403 }
1404
Adam Sawickie6e498f2017-06-16 17:21:31 +02001405 // Create command pool
1406
1407 VkCommandPoolCreateInfo commandPoolInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
1408 commandPoolInfo.queueFamilyIndex = g_GraphicsQueueFamilyIndex;
1409 commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001410 ERR_GUARD_VULKAN( vkCreateCommandPool(g_hDevice, &commandPoolInfo, g_Allocs, &g_hCommandPool) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001411
1412 VkCommandBufferAllocateInfo commandBufferInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
1413 commandBufferInfo.commandPool = g_hCommandPool;
1414 commandBufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1415 commandBufferInfo.commandBufferCount = COMMAND_BUFFER_COUNT;
1416 ERR_GUARD_VULKAN( vkAllocateCommandBuffers(g_hDevice, &commandBufferInfo, g_MainCommandBuffers) );
1417
1418 VkFenceCreateInfo fenceInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
1419 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
1420 for(size_t i = 0; i < COMMAND_BUFFER_COUNT; ++i)
1421 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001422 ERR_GUARD_VULKAN( vkCreateFence(g_hDevice, &fenceInfo, g_Allocs, &g_MainCommandBufferExecutedFances[i]) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001423 }
1424
Adam Sawicki1f84f622019-07-02 13:40:01 +02001425 ERR_GUARD_VULKAN( vkCreateFence(g_hDevice, &fenceInfo, g_Allocs, &g_ImmediateFence) );
Adam Sawicki51fa9662018-10-03 13:44:29 +02001426
Adam Sawickie6e498f2017-06-16 17:21:31 +02001427 commandBufferInfo.commandBufferCount = 1;
1428 ERR_GUARD_VULKAN( vkAllocateCommandBuffers(g_hDevice, &commandBufferInfo, &g_hTemporaryCommandBuffer) );
1429
1430 // Create texture sampler
1431
1432 VkSamplerCreateInfo samplerInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
1433 samplerInfo.magFilter = VK_FILTER_LINEAR;
1434 samplerInfo.minFilter = VK_FILTER_LINEAR;
1435 samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
1436 samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
1437 samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
1438 samplerInfo.anisotropyEnable = VK_TRUE;
1439 samplerInfo.maxAnisotropy = 16;
1440 samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
1441 samplerInfo.unnormalizedCoordinates = VK_FALSE;
1442 samplerInfo.compareEnable = VK_FALSE;
1443 samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
1444 samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
1445 samplerInfo.mipLodBias = 0.f;
1446 samplerInfo.minLod = 0.f;
1447 samplerInfo.maxLod = FLT_MAX;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001448 ERR_GUARD_VULKAN( vkCreateSampler(g_hDevice, &samplerInfo, g_Allocs, &g_hSampler) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001449
1450 CreateTexture(128, 128);
1451 CreateMesh();
1452
1453 VkDescriptorSetLayoutBinding samplerLayoutBinding = {};
1454 samplerLayoutBinding.binding = 1;
1455 samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1456 samplerLayoutBinding.descriptorCount = 1;
1457 samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
1458
1459 VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
1460 descriptorSetLayoutInfo.bindingCount = 1;
1461 descriptorSetLayoutInfo.pBindings = &samplerLayoutBinding;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001462 ERR_GUARD_VULKAN( vkCreateDescriptorSetLayout(g_hDevice, &descriptorSetLayoutInfo, g_Allocs, &g_hDescriptorSetLayout) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001463
1464 // Create descriptor pool
1465
1466 VkDescriptorPoolSize descriptorPoolSizes[2];
1467 ZeroMemory(descriptorPoolSizes, sizeof(descriptorPoolSizes));
1468 descriptorPoolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1469 descriptorPoolSizes[0].descriptorCount = 1;
1470 descriptorPoolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1471 descriptorPoolSizes[1].descriptorCount = 1;
1472
1473 VkDescriptorPoolCreateInfo descriptorPoolInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
1474 descriptorPoolInfo.poolSizeCount = (uint32_t)_countof(descriptorPoolSizes);
1475 descriptorPoolInfo.pPoolSizes = descriptorPoolSizes;
1476 descriptorPoolInfo.maxSets = 1;
Adam Sawicki1f84f622019-07-02 13:40:01 +02001477 ERR_GUARD_VULKAN( vkCreateDescriptorPool(g_hDevice, &descriptorPoolInfo, g_Allocs, &g_hDescriptorPool) );
Adam Sawickie6e498f2017-06-16 17:21:31 +02001478
1479 // Create descriptor set layout
1480
1481 VkDescriptorSetLayout descriptorSetLayouts[] = { g_hDescriptorSetLayout };
1482 VkDescriptorSetAllocateInfo descriptorSetInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
1483 descriptorSetInfo.descriptorPool = g_hDescriptorPool;
1484 descriptorSetInfo.descriptorSetCount = 1;
1485 descriptorSetInfo.pSetLayouts = descriptorSetLayouts;
1486 ERR_GUARD_VULKAN( vkAllocateDescriptorSets(g_hDevice, &descriptorSetInfo, &g_hDescriptorSet) );
1487
1488 VkDescriptorImageInfo descriptorImageInfo = {};
1489 descriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1490 descriptorImageInfo.imageView = g_hTextureImageView;
1491 descriptorImageInfo.sampler = g_hSampler;
1492
1493 VkWriteDescriptorSet writeDescriptorSet = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
1494 writeDescriptorSet.dstSet = g_hDescriptorSet;
1495 writeDescriptorSet.dstBinding = 1;
1496 writeDescriptorSet.dstArrayElement = 0;
1497 writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1498 writeDescriptorSet.descriptorCount = 1;
1499 writeDescriptorSet.pImageInfo = &descriptorImageInfo;
1500
1501 vkUpdateDescriptorSets(g_hDevice, 1, &writeDescriptorSet, 0, nullptr);
1502
1503 CreateSwapchain();
1504}
1505
1506static void FinalizeApplication()
1507{
1508 vkDeviceWaitIdle(g_hDevice);
1509
1510 DestroySwapchain(true);
1511
1512 if(g_hDescriptorPool != VK_NULL_HANDLE)
1513 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001514 vkDestroyDescriptorPool(g_hDevice, g_hDescriptorPool, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001515 g_hDescriptorPool = VK_NULL_HANDLE;
1516 }
1517
1518 if(g_hDescriptorSetLayout != VK_NULL_HANDLE)
1519 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001520 vkDestroyDescriptorSetLayout(g_hDevice, g_hDescriptorSetLayout, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001521 g_hDescriptorSetLayout = VK_NULL_HANDLE;
1522 }
1523
1524 if(g_hTextureImageView != VK_NULL_HANDLE)
1525 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001526 vkDestroyImageView(g_hDevice, g_hTextureImageView, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001527 g_hTextureImageView = VK_NULL_HANDLE;
1528 }
1529 if(g_hTextureImage != VK_NULL_HANDLE)
1530 {
Adam Sawicki819860e2017-07-04 14:30:38 +02001531 vmaDestroyImage(g_hAllocator, g_hTextureImage, g_hTextureImageAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001532 g_hTextureImage = VK_NULL_HANDLE;
1533 }
1534
1535 if(g_hIndexBuffer != VK_NULL_HANDLE)
1536 {
Adam Sawicki819860e2017-07-04 14:30:38 +02001537 vmaDestroyBuffer(g_hAllocator, g_hIndexBuffer, g_hIndexBufferAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001538 g_hIndexBuffer = VK_NULL_HANDLE;
1539 }
1540 if(g_hVertexBuffer != VK_NULL_HANDLE)
1541 {
Adam Sawicki819860e2017-07-04 14:30:38 +02001542 vmaDestroyBuffer(g_hAllocator, g_hVertexBuffer, g_hVertexBufferAlloc);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001543 g_hVertexBuffer = VK_NULL_HANDLE;
1544 }
1545
1546 if(g_hSampler != VK_NULL_HANDLE)
1547 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001548 vkDestroySampler(g_hDevice, g_hSampler, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001549 g_hSampler = VK_NULL_HANDLE;
1550 }
1551
Adam Sawicki51fa9662018-10-03 13:44:29 +02001552 if(g_ImmediateFence)
1553 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001554 vkDestroyFence(g_hDevice, g_ImmediateFence, g_Allocs);
Adam Sawicki51fa9662018-10-03 13:44:29 +02001555 g_ImmediateFence = VK_NULL_HANDLE;
1556 }
1557
Adam Sawickie6e498f2017-06-16 17:21:31 +02001558 for(size_t i = COMMAND_BUFFER_COUNT; i--; )
1559 {
1560 if(g_MainCommandBufferExecutedFances[i] != VK_NULL_HANDLE)
1561 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001562 vkDestroyFence(g_hDevice, g_MainCommandBufferExecutedFances[i], g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001563 g_MainCommandBufferExecutedFances[i] = VK_NULL_HANDLE;
1564 }
1565 }
1566 if(g_MainCommandBuffers[0] != VK_NULL_HANDLE)
1567 {
1568 vkFreeCommandBuffers(g_hDevice, g_hCommandPool, COMMAND_BUFFER_COUNT, g_MainCommandBuffers);
1569 ZeroMemory(g_MainCommandBuffers, sizeof(g_MainCommandBuffers));
1570 }
1571 if(g_hTemporaryCommandBuffer != VK_NULL_HANDLE)
1572 {
1573 vkFreeCommandBuffers(g_hDevice, g_hCommandPool, 1, &g_hTemporaryCommandBuffer);
1574 g_hTemporaryCommandBuffer = VK_NULL_HANDLE;
1575 }
1576
1577 if(g_hCommandPool != VK_NULL_HANDLE)
1578 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001579 vkDestroyCommandPool(g_hDevice, g_hCommandPool, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001580 g_hCommandPool = VK_NULL_HANDLE;
1581 }
1582
1583 if(g_hAllocator != VK_NULL_HANDLE)
1584 {
1585 vmaDestroyAllocator(g_hAllocator);
1586 g_hAllocator = nullptr;
1587 }
1588
1589 if(g_hDevice != VK_NULL_HANDLE)
1590 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001591 vkDestroyDevice(g_hDevice, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001592 g_hDevice = nullptr;
1593 }
1594
1595 if(g_pvkDestroyDebugReportCallbackEXT && g_hCallback != VK_NULL_HANDLE)
1596 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001597 g_pvkDestroyDebugReportCallbackEXT(g_hVulkanInstance, g_hCallback, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001598 g_hCallback = VK_NULL_HANDLE;
1599 }
1600
1601 if(g_hSurface != VK_NULL_HANDLE)
1602 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001603 vkDestroySurfaceKHR(g_hVulkanInstance, g_hSurface, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001604 g_hSurface = VK_NULL_HANDLE;
1605 }
1606
1607 if(g_hVulkanInstance != VK_NULL_HANDLE)
1608 {
Adam Sawicki1f84f622019-07-02 13:40:01 +02001609 vkDestroyInstance(g_hVulkanInstance, g_Allocs);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001610 g_hVulkanInstance = VK_NULL_HANDLE;
1611 }
1612}
1613
1614static void PrintAllocatorStats()
1615{
1616#if VMA_STATS_STRING_ENABLED
1617 char* statsString = nullptr;
1618 vmaBuildStatsString(g_hAllocator, &statsString, true);
1619 printf("%s\n", statsString);
1620 vmaFreeStatsString(g_hAllocator, statsString);
1621#endif
1622}
1623
1624static void RecreateSwapChain()
1625{
1626 vkDeviceWaitIdle(g_hDevice);
1627 DestroySwapchain(false);
1628 CreateSwapchain();
1629}
1630
1631static void DrawFrame()
1632{
1633 // Begin main command buffer
1634 size_t cmdBufIndex = (g_NextCommandBufferIndex++) % COMMAND_BUFFER_COUNT;
1635 VkCommandBuffer hCommandBuffer = g_MainCommandBuffers[cmdBufIndex];
1636 VkFence hCommandBufferExecutedFence = g_MainCommandBufferExecutedFances[cmdBufIndex];
1637
1638 ERR_GUARD_VULKAN( vkWaitForFences(g_hDevice, 1, &hCommandBufferExecutedFence, VK_TRUE, UINT64_MAX) );
1639 ERR_GUARD_VULKAN( vkResetFences(g_hDevice, 1, &hCommandBufferExecutedFence) );
1640
1641 VkCommandBufferBeginInfo commandBufferBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
1642 commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1643 ERR_GUARD_VULKAN( vkBeginCommandBuffer(hCommandBuffer, &commandBufferBeginInfo) );
1644
1645 // Acquire swapchain image
1646 uint32_t imageIndex = 0;
1647 VkResult res = vkAcquireNextImageKHR(g_hDevice, g_hSwapchain, UINT64_MAX, g_hImageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
1648 if(res == VK_ERROR_OUT_OF_DATE_KHR)
1649 {
1650 RecreateSwapChain();
1651 return;
1652 }
1653 else if(res < 0)
1654 {
1655 ERR_GUARD_VULKAN(res);
1656 }
1657
1658 // Record geometry pass
1659
1660 VkClearValue clearValues[2];
1661 ZeroMemory(clearValues, sizeof(clearValues));
1662 clearValues[0].color.float32[0] = 0.25f;
1663 clearValues[0].color.float32[1] = 0.25f;
1664 clearValues[0].color.float32[2] = 0.5f;
1665 clearValues[0].color.float32[3] = 1.0f;
1666 clearValues[1].depthStencil.depth = 1.0f;
1667
1668 VkRenderPassBeginInfo renderPassBeginInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
1669 renderPassBeginInfo.renderPass = g_hRenderPass;
1670 renderPassBeginInfo.framebuffer = g_Framebuffers[imageIndex];
1671 renderPassBeginInfo.renderArea.offset.x = 0;
1672 renderPassBeginInfo.renderArea.offset.y = 0;
1673 renderPassBeginInfo.renderArea.extent = g_Extent;
1674 renderPassBeginInfo.clearValueCount = (uint32_t)_countof(clearValues);
1675 renderPassBeginInfo.pClearValues = clearValues;
1676 vkCmdBeginRenderPass(hCommandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1677
1678 vkCmdBindPipeline(
1679 hCommandBuffer,
1680 VK_PIPELINE_BIND_POINT_GRAPHICS,
1681 g_hPipeline);
1682
Adam Sawicki82c3f332018-06-11 15:27:33 +02001683 mat4 view = mat4::LookAt(
1684 vec3(0.f, 0.f, 0.f),
1685 vec3(0.f, -2.f, 4.f),
1686 vec3(0.f, 1.f, 0.f));
1687 mat4 proj = mat4::Perspective(
Adam Sawickie6e498f2017-06-16 17:21:31 +02001688 1.0471975511966f, // 60 degrees
1689 (float)g_Extent.width / (float)g_Extent.height,
1690 0.1f,
Adam Sawicki82c3f332018-06-11 15:27:33 +02001691 1000.f);
1692 mat4 viewProj = view * proj;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001693
1694 vkCmdBindDescriptorSets(
1695 hCommandBuffer,
1696 VK_PIPELINE_BIND_POINT_GRAPHICS,
1697 g_hPipelineLayout,
1698 0,
1699 1,
1700 &g_hDescriptorSet,
1701 0,
1702 nullptr);
1703
Adam Sawicki82c3f332018-06-11 15:27:33 +02001704 float rotationAngle = (float)GetTickCount() * 0.001f * (float)PI * 0.2f;
1705 mat4 model = mat4::RotationY(rotationAngle);
Adam Sawickie6e498f2017-06-16 17:21:31 +02001706
1707 UniformBufferObject ubo = {};
Adam Sawicki82c3f332018-06-11 15:27:33 +02001708 ubo.ModelViewProj = model * viewProj;
Adam Sawickie6e498f2017-06-16 17:21:31 +02001709 vkCmdPushConstants(hCommandBuffer, g_hPipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(UniformBufferObject), &ubo);
1710
1711 VkBuffer vertexBuffers[] = { g_hVertexBuffer };
1712 VkDeviceSize offsets[] = { 0 };
1713 vkCmdBindVertexBuffers(hCommandBuffer, 0, 1, vertexBuffers, offsets);
1714
1715 vkCmdBindIndexBuffer(hCommandBuffer, g_hIndexBuffer, 0, VK_INDEX_TYPE_UINT16);
1716
1717 vkCmdDrawIndexed(hCommandBuffer, g_IndexCount, 1, 0, 0, 0);
1718
1719 vkCmdEndRenderPass(hCommandBuffer);
1720
1721 vkEndCommandBuffer(hCommandBuffer);
1722
1723 // Submit command buffer
1724
1725 VkSemaphore submitWaitSemaphores[] = { g_hImageAvailableSemaphore };
1726 VkPipelineStageFlags submitWaitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
1727 VkSemaphore submitSignalSemaphores[] = { g_hRenderFinishedSemaphore };
1728 VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
1729 submitInfo.waitSemaphoreCount = 1;
1730 submitInfo.pWaitSemaphores = submitWaitSemaphores;
1731 submitInfo.pWaitDstStageMask = submitWaitStages;
1732 submitInfo.commandBufferCount = 1;
1733 submitInfo.pCommandBuffers = &hCommandBuffer;
1734 submitInfo.signalSemaphoreCount = _countof(submitSignalSemaphores);
1735 submitInfo.pSignalSemaphores = submitSignalSemaphores;
1736 ERR_GUARD_VULKAN( vkQueueSubmit(g_hGraphicsQueue, 1, &submitInfo, hCommandBufferExecutedFence) );
1737
1738 VkSemaphore presentWaitSemaphores[] = { g_hRenderFinishedSemaphore };
1739
1740 VkSwapchainKHR swapchains[] = { g_hSwapchain };
1741 VkPresentInfoKHR presentInfo = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
1742 presentInfo.waitSemaphoreCount = _countof(presentWaitSemaphores);
1743 presentInfo.pWaitSemaphores = presentWaitSemaphores;
1744 presentInfo.swapchainCount = 1;
1745 presentInfo.pSwapchains = swapchains;
1746 presentInfo.pImageIndices = &imageIndex;
1747 presentInfo.pResults = nullptr;
1748 res = vkQueuePresentKHR(g_hPresentQueue, &presentInfo);
1749 if(res == VK_ERROR_OUT_OF_DATE_KHR)
1750 {
1751 RecreateSwapChain();
1752 }
1753 else
1754 ERR_GUARD_VULKAN(res);
1755}
1756
1757static void HandlePossibleSizeChange()
1758{
1759 RECT clientRect;
1760 GetClientRect(g_hWnd, &clientRect);
1761 LONG newSizeX = clientRect.right - clientRect.left;
1762 LONG newSizeY = clientRect.bottom - clientRect.top;
1763 if((newSizeX > 0) &&
1764 (newSizeY > 0) &&
1765 ((newSizeX != g_SizeX) || (newSizeY != g_SizeY)))
1766 {
1767 g_SizeX = newSizeX;
1768 g_SizeY = newSizeY;
1769
1770 RecreateSwapChain();
1771 }
1772}
1773
1774static LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
1775{
1776 switch(msg)
1777 {
1778 case WM_CREATE:
1779 // This is intentionally assigned here because we are now inside CreateWindow, before it returns.
1780 g_hWnd = hWnd;
1781 InitializeApplication();
1782 PrintAllocatorStats();
1783 return 0;
1784
1785 case WM_DESTROY:
1786 FinalizeApplication();
1787 PostQuitMessage(0);
1788 return 0;
1789
1790 // This prevents app from freezing when left Alt is pressed
1791 // (which normally enters modal menu loop).
1792 case WM_SYSKEYDOWN:
1793 case WM_SYSKEYUP:
1794 return 0;
1795
1796 case WM_SIZE:
1797 if((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED))
1798 HandlePossibleSizeChange();
1799 return 0;
1800
1801 case WM_EXITSIZEMOVE:
1802 HandlePossibleSizeChange();
1803 return 0;
1804
1805 case WM_KEYDOWN:
Adam Sawickib8333fb2018-03-13 16:15:53 +01001806 switch(wParam)
1807 {
1808 case VK_ESCAPE:
Adam Sawickie6e498f2017-06-16 17:21:31 +02001809 PostMessage(hWnd, WM_CLOSE, 0, 0);
Adam Sawickib8333fb2018-03-13 16:15:53 +01001810 break;
1811 case 'T':
Adam Sawickia7d77692018-10-03 16:15:27 +02001812 try
1813 {
1814 Test();
1815 }
1816 catch(const std::exception& ex)
1817 {
1818 printf("ERROR: %s\n", ex.what());
1819 }
Adam Sawickib8333fb2018-03-13 16:15:53 +01001820 break;
Adam Sawickida6c1942018-12-05 17:34:34 +01001821 case 'S':
1822 try
1823 {
1824 if(g_SparseBindingEnabled)
1825 {
1826 TestSparseBinding();
1827 }
1828 else
1829 {
1830 printf("Sparse binding not supported.\n");
1831 }
1832 }
1833 catch(const std::exception& ex)
1834 {
1835 printf("ERROR: %s\n", ex.what());
1836 }
1837 break;
Adam Sawickib8333fb2018-03-13 16:15:53 +01001838 }
Adam Sawickie6e498f2017-06-16 17:21:31 +02001839 return 0;
1840
1841 default:
1842 break;
1843 }
1844
1845 return DefWindowProc(hWnd, msg, wParam, lParam);
1846}
1847
1848int main()
1849{
1850 g_hAppInstance = (HINSTANCE)GetModuleHandle(NULL);
1851
1852 WNDCLASSEX wndClassDesc = { sizeof(WNDCLASSEX) };
1853 wndClassDesc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
1854 wndClassDesc.hbrBackground = NULL;
1855 wndClassDesc.hCursor = LoadCursor(NULL, IDC_CROSS);
1856 wndClassDesc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1857 wndClassDesc.hInstance = g_hAppInstance;
1858 wndClassDesc.lpfnWndProc = WndProc;
1859 wndClassDesc.lpszClassName = WINDOW_CLASS_NAME;
1860
1861 const ATOM hWndClass = RegisterClassEx(&wndClassDesc);
1862 assert(hWndClass);
1863
1864 const DWORD style = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;
1865 const DWORD exStyle = 0;
1866
1867 RECT rect = { 0, 0, g_SizeX, g_SizeY };
1868 AdjustWindowRectEx(&rect, style, FALSE, exStyle);
1869
Adam Sawicki86ccd632017-07-04 14:57:53 +02001870 CreateWindowEx(
Adam Sawickie6e498f2017-06-16 17:21:31 +02001871 exStyle, WINDOW_CLASS_NAME, APP_TITLE_W, style,
1872 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1873 NULL, NULL, g_hAppInstance, NULL);
1874
1875 MSG msg;
1876 for(;;)
1877 {
1878 if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
1879 {
1880 if(msg.message == WM_QUIT)
1881 break;
1882 TranslateMessage(&msg);
1883 DispatchMessage(&msg);
1884 }
1885 if(g_hDevice != VK_NULL_HANDLE)
1886 DrawFrame();
1887 }
1888
Adam Sawicki8317ba92019-11-18 13:14:11 +01001889 TEST(g_CpuAllocCount.load() == 0);
1890
Adam Sawickie6e498f2017-06-16 17:21:31 +02001891 return 0;
1892}
Adam Sawicki59a3e7e2017-08-21 15:47:30 +02001893
Adam Sawickif1a793c2018-03-13 15:42:22 +01001894#else // #ifdef _WIN32
Adam Sawicki59a3e7e2017-08-21 15:47:30 +02001895
Adam Sawickif1a793c2018-03-13 15:42:22 +01001896#include "VmaUsage.h"
Adam Sawicki59a3e7e2017-08-21 15:47:30 +02001897
1898int main()
1899{
1900}
1901
Adam Sawickif1a793c2018-03-13 15:42:22 +01001902#endif // #ifdef _WIN32