blob: bdcd225f874a58abb9a7a561eddd4fec722e1022 [file] [log] [blame]
Adam Sawickiae5c4662019-01-02 10:23:35 +01001//
Adam Sawickiaa183742021-02-16 17:28:49 +01002// Copyright (c) 2017-2021 Advanced Micro Devices, Inc. All rights reserved.
Adam Sawickiae5c4662019-01-02 10:23:35 +01003//
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#ifndef COMMON_H_
24#define COMMON_H_
25
Adam Sawickib8333fb2018-03-13 16:15:53 +010026#include "VmaUsage.h"
27
Adam Sawickif1a793c2018-03-13 15:42:22 +010028#ifdef _WIN32
29
Adam Sawickib8333fb2018-03-13 16:15:53 +010030#include <iostream>
Adam Sawickif1a793c2018-03-13 15:42:22 +010031#include <fstream>
32#include <vector>
Adam Sawickif1a793c2018-03-13 15:42:22 +010033#include <memory>
34#include <algorithm>
35#include <numeric>
36#include <array>
37#include <type_traits>
38#include <utility>
Adam Sawickib8333fb2018-03-13 16:15:53 +010039#include <chrono>
40#include <string>
Adam Sawickib8d34d52018-10-03 17:41:20 +020041#include <exception>
Adam Sawickif1a793c2018-03-13 15:42:22 +010042
Adam Sawickif1a793c2018-03-13 15:42:22 +010043#include <cassert>
44#include <cstdlib>
45#include <cstdio>
Adam Sawickib8333fb2018-03-13 16:15:53 +010046#include <cstdarg>
47
48typedef std::chrono::high_resolution_clock::time_point time_point;
49typedef std::chrono::high_resolution_clock::duration duration;
Adam Sawickif1a793c2018-03-13 15:42:22 +010050
Adam Sawickib8d34d52018-10-03 17:41:20 +020051#ifdef _DEBUG
52 #define TEST(expr) do { \
53 if(!(expr)) { \
54 assert(0 && #expr); \
55 } \
56 } while(0)
57#else
58 #define TEST(expr) do { \
59 if(!(expr)) { \
60 throw std::runtime_error("TEST FAILED: " #expr); \
61 } \
62 } while(0)
63#endif
64
65#define ERR_GUARD_VULKAN(expr) TEST((expr) >= 0)
Adam Sawickif1a793c2018-03-13 15:42:22 +010066
Adam Sawickiafd50562021-02-26 11:59:58 +010067static const uint32_t VENDOR_ID_AMD = 0x1002;
68static const uint32_t VENDOR_ID_NVIDIA = 0x10DE;
69static const uint32_t VENDOR_ID_INTEL = 0x8086;
70
Adam Sawicki50882502020-02-07 16:51:31 +010071extern VkInstance g_hVulkanInstance;
Adam Sawickib8333fb2018-03-13 16:15:53 +010072extern VkPhysicalDevice g_hPhysicalDevice;
73extern VkDevice g_hDevice;
Adam Sawicki4ac8ff82019-11-18 14:47:33 +010074extern VkInstance g_hVulkanInstance;
Adam Sawickib8333fb2018-03-13 16:15:53 +010075extern VmaAllocator g_hAllocator;
Adam Sawicki50882502020-02-07 16:51:31 +010076extern bool VK_AMD_device_coherent_memory_enabled;
77
78void SetAllocatorCreateInfo(VmaAllocatorCreateInfo& outInfo);
Adam Sawickib8333fb2018-03-13 16:15:53 +010079
80inline float ToFloatSeconds(duration d)
81{
82 return std::chrono::duration_cast<std::chrono::duration<float>>(d).count();
83}
84
85template <typename T>
86inline T ceil_div(T x, T y)
87{
Adam Sawicki82c3f332018-06-11 15:27:33 +020088 return (x+y-1) / y;
Adam Sawickib8333fb2018-03-13 16:15:53 +010089}
Adam Sawickiff0f7b82018-10-18 14:44:05 +020090template <typename T>
91inline T round_div(T x, T y)
92{
93 return (x+y/(T)2) / y;
94}
Adam Sawickib8333fb2018-03-13 16:15:53 +010095
96template <typename T>
97static inline T align_up(T val, T align)
98{
Adam Sawicki82c3f332018-06-11 15:27:33 +020099 return (val + align - 1) / align * align;
Adam Sawickib8333fb2018-03-13 16:15:53 +0100100}
101
Adam Sawicki82c3f332018-06-11 15:27:33 +0200102static const float PI = 3.14159265358979323846264338327950288419716939937510582f;
103
Adam Sawickie73e9882020-03-20 18:05:42 +0100104template<typename MainT, typename NewT>
105inline void PnextChainPushFront(MainT* mainStruct, NewT* newStruct)
106{
107 newStruct->pNext = mainStruct->pNext;
108 mainStruct->pNext = newStruct;
109}
110template<typename MainT, typename NewT>
111inline void PnextChainPushBack(MainT* mainStruct, NewT* newStruct)
112{
113 struct VkAnyStruct
114 {
115 VkStructureType sType;
116 void* pNext;
117 };
118 VkAnyStruct* lastStruct = (VkAnyStruct*)mainStruct;
119 while(lastStruct->pNext != nullptr)
120 {
121 lastStruct = (VkAnyStruct*)lastStruct->pNext;
122 }
123 newStruct->pNext = nullptr;
124 lastStruct->pNext = newStruct;
125}
126
Adam Sawicki82c3f332018-06-11 15:27:33 +0200127struct vec3
128{
129 float x, y, z;
130
131 vec3() { }
132 vec3(float x, float y, float z) : x(x), y(y), z(z) { }
133
134 float& operator[](uint32_t index) { return *(&x + index); }
135 const float& operator[](uint32_t index) const { return *(&x + index); }
136
137 vec3 operator+(const vec3& rhs) const { return vec3(x + rhs.x, y + rhs.y, z + rhs.z); }
138 vec3 operator-(const vec3& rhs) const { return vec3(x - rhs.x, y - rhs.y, z - rhs.z); }
139 vec3 operator*(float s) const { return vec3(x * s, y * s, z * s); }
140
141 vec3 Normalized() const
142 {
143 return (*this) * (1.f / sqrt(x * x + y * y + z * z));
144 }
145};
146
147inline float Dot(const vec3& lhs, const vec3& rhs)
148{
149 return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
150}
151inline vec3 Cross(const vec3& lhs, const vec3& rhs)
152{
153 return vec3(
154 lhs.y * rhs.z - lhs.z * rhs.y,
155 lhs.z * rhs.x - lhs.x * rhs.z,
156 lhs.x * rhs.y - lhs.y * rhs.x);
157}
158
159struct vec4
160{
161 float x, y, z, w;
162
163 vec4() { }
164 vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { }
165 vec4(const vec3& v, float w) : x(v.x), y(v.y), z(v.z), w(w) { }
166
167 float& operator[](uint32_t index) { return *(&x + index); }
168 const float& operator[](uint32_t index) const { return *(&x + index); }
169};
170
171struct mat4
172{
173 union
174 {
175 struct
176 {
177 float _11, _12, _13, _14;
178 float _21, _22, _23, _24;
179 float _31, _32, _33, _34;
180 float _41, _42, _43, _44;
181 };
182 float m[4][4]; // [row][column]
183 };
184
185 mat4() { }
186
187 mat4(
188 float _11, float _12, float _13, float _14,
189 float _21, float _22, float _23, float _24,
190 float _31, float _32, float _33, float _34,
191 float _41, float _42, float _43, float _44) :
192 _11(_11), _12(_12), _13(_13), _14(_14),
193 _21(_21), _22(_22), _23(_23), _24(_24),
194 _31(_31), _32(_32), _33(_33), _34(_34),
195 _41(_41), _42(_42), _43(_43), _44(_44)
196 {
197 }
198
199 mat4(
200 const vec4& row1,
201 const vec4& row2,
202 const vec4& row3,
203 const vec4& row4) :
204 _11(row1.x), _12(row1.y), _13(row1.z), _14(row1.w),
205 _21(row2.x), _22(row2.y), _23(row2.z), _24(row2.w),
206 _31(row3.x), _32(row3.y), _33(row3.z), _34(row3.w),
207 _41(row4.x), _42(row4.y), _43(row4.z), _44(row4.w)
208 {
209 }
210
211 mat4 operator*(const mat4 &rhs) const
212 {
213 return mat4(
214 _11 * rhs._11 + _12 * rhs._21 + _13 * rhs._31 + _14 * rhs._41,
215 _11 * rhs._12 + _12 * rhs._22 + _13 * rhs._32 + _14 * rhs._42,
216 _11 * rhs._13 + _12 * rhs._23 + _13 * rhs._33 + _14 * rhs._43,
217 _11 * rhs._14 + _12 * rhs._24 + _13 * rhs._34 + _14 * rhs._44,
218
219 _21 * rhs._11 + _22 * rhs._21 + _23 * rhs._31 + _24 * rhs._41,
220 _21 * rhs._12 + _22 * rhs._22 + _23 * rhs._32 + _24 * rhs._42,
221 _21 * rhs._13 + _22 * rhs._23 + _23 * rhs._33 + _24 * rhs._43,
222 _21 * rhs._14 + _22 * rhs._24 + _23 * rhs._34 + _24 * rhs._44,
223
224 _31 * rhs._11 + _32 * rhs._21 + _33 * rhs._31 + _34 * rhs._41,
225 _31 * rhs._12 + _32 * rhs._22 + _33 * rhs._32 + _34 * rhs._42,
226 _31 * rhs._13 + _32 * rhs._23 + _33 * rhs._33 + _34 * rhs._43,
227 _31 * rhs._14 + _32 * rhs._24 + _33 * rhs._34 + _34 * rhs._44,
228
229 _41 * rhs._11 + _42 * rhs._21 + _43 * rhs._31 + _44 * rhs._41,
230 _41 * rhs._12 + _42 * rhs._22 + _43 * rhs._32 + _44 * rhs._42,
231 _41 * rhs._13 + _42 * rhs._23 + _43 * rhs._33 + _44 * rhs._43,
232 _41 * rhs._14 + _42 * rhs._24 + _43 * rhs._34 + _44 * rhs._44);
233 }
234
235 static mat4 RotationY(float angle)
236 {
237 const float s = sin(angle), c = cos(angle);
238 return mat4(
239 c, 0.f, -s, 0.f,
240 0.f, 1.f, 0.f, 0.f,
241 s, 0.f, c, 0.f,
242 0.f, 0.f, 0.f, 1.f);
243 }
244
245 static mat4 Perspective(float fovY, float aspectRatio, float zNear, float zFar)
246 {
247 float yScale = 1.0f / tan(fovY * 0.5f);
248 float xScale = yScale / aspectRatio;
249 return mat4(
250 xScale, 0.0f, 0.0f, 0.0f,
251 0.0f, yScale, 0.0f, 0.0f,
252 0.0f, 0.0f, zFar / (zFar - zNear), 1.0f,
253 0.0f, 0.0f, -zNear * zFar / (zFar - zNear), 0.0f);
254 }
255
256 static mat4 LookAt(vec3 at, vec3 eye, vec3 up)
257 {
258 vec3 zAxis = (at - eye).Normalized();
259 vec3 xAxis = Cross(up, zAxis).Normalized();
260 vec3 yAxis = Cross(zAxis, xAxis);
261 return mat4(
262 xAxis.x, yAxis.x, zAxis.x, 0.0f,
263 xAxis.y, yAxis.y, zAxis.y, 0.0f,
264 xAxis.z, yAxis.z, zAxis.z, 0.0f,
265 -Dot(xAxis, eye), -Dot(yAxis, eye), -Dot(zAxis, eye), 1.0f);
266 }
267};
268
Adam Sawickib8333fb2018-03-13 16:15:53 +0100269class RandomNumberGenerator
270{
271public:
272 RandomNumberGenerator() : m_Value{GetTickCount()} {}
273 RandomNumberGenerator(uint32_t seed) : m_Value{seed} { }
274 void Seed(uint32_t seed) { m_Value = seed; }
275 uint32_t Generate() { return GenerateFast() ^ (GenerateFast() >> 7); }
276
277private:
278 uint32_t m_Value;
279 uint32_t GenerateFast() { return m_Value = (m_Value * 196314165 + 907633515); }
280};
281
Adam Sawicki0a607132018-08-24 11:18:41 +0200282// Wrapper for RandomNumberGenerator compatible with STL "UniformRandomNumberGenerator" idea.
283struct MyUniformRandomNumberGenerator
284{
285 typedef uint32_t result_type;
286 MyUniformRandomNumberGenerator(RandomNumberGenerator& gen) : m_Gen(gen) { }
287 static uint32_t min() { return 0; }
288 static uint32_t max() { return UINT32_MAX; }
289 uint32_t operator()() { return m_Gen.Generate(); }
290
291private:
292 RandomNumberGenerator& m_Gen;
293};
294
Adam Sawickib8333fb2018-03-13 16:15:53 +0100295void ReadFile(std::vector<char>& out, const char* fileName);
296
297enum class CONSOLE_COLOR
298{
299 INFO,
300 NORMAL,
301 WARNING,
302 ERROR_,
303 COUNT
304};
305
306void SetConsoleColor(CONSOLE_COLOR color);
307
308void PrintMessage(CONSOLE_COLOR color, const char* msg);
309void PrintMessage(CONSOLE_COLOR color, const wchar_t* msg);
310
311inline void Print(const char* msg) { PrintMessage(CONSOLE_COLOR::NORMAL, msg); }
312inline void Print(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::NORMAL, msg); }
313inline void PrintWarning(const char* msg) { PrintMessage(CONSOLE_COLOR::WARNING, msg); }
314inline void PrintWarning(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::WARNING, msg); }
315inline void PrintError(const char* msg) { PrintMessage(CONSOLE_COLOR::ERROR_, msg); }
316inline void PrintError(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::ERROR_, msg); }
317
318void PrintMessageV(CONSOLE_COLOR color, const char* format, va_list argList);
319void PrintMessageV(CONSOLE_COLOR color, const wchar_t* format, va_list argList);
320void PrintMessageF(CONSOLE_COLOR color, const char* format, ...);
321void PrintMessageF(CONSOLE_COLOR color, const wchar_t* format, ...);
322void PrintWarningF(const char* format, ...);
323void PrintWarningF(const wchar_t* format, ...);
324void PrintErrorF(const char* format, ...);
325void PrintErrorF(const wchar_t* format, ...);
326
327void SaveFile(const wchar_t* filePath, const void* data, size_t dataSize);
328
Adam Sawickiafd50562021-02-26 11:59:58 +0100329std::wstring SizeToStr(size_t size);
330
331const wchar_t* PhysicalDeviceTypeToStr(VkPhysicalDeviceType type);
332const wchar_t* VendorIDToStr(uint32_t vendorID);
333
334#if VMA_VULKAN_VERSION >= 1002000
335const wchar_t* DriverIDToStr(VkDriverId driverID);
336#endif
337
Adam Sawickif1a793c2018-03-13 15:42:22 +0100338#endif // #ifdef _WIN32
339
340#endif