1 /*
2  * Copyright 2011-2019 Branimir Karadzic. All rights reserved.
3  * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
4  */
5 
6 #include "bgfx_p.h"
7 
8 #if BGFX_CONFIG_RENDERER_VULKAN
9 #	include "renderer_vk.h"
10 
11 #if BX_PLATFORM_OSX
12 #	import <Cocoa/Cocoa.h>
13 #	import <Foundation/Foundation.h>
14 #	import <QuartzCore/QuartzCore.h>
15 #	import <Metal/Metal.h>
16 #endif // BX_PLATFORM_OSX
17 
18 namespace bgfx { namespace vk
19 {
20 	static char s_viewName[BGFX_CONFIG_MAX_VIEWS][256];
21 
22 	struct PrimInfo
23 	{
24 		VkPrimitiveTopology m_topology;
25 		uint32_t m_min;
26 		uint32_t m_div;
27 		uint32_t m_sub;
28 	};
29 
30 	static const PrimInfo s_primInfo[] =
31 	{
32 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,  3, 3, 0 },
33 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 3, 1, 2 },
34 		{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST,      2, 2, 0 },
35 		{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,     2, 1, 1 },
36 		{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST,     1, 1, 0 },
37 		{ VK_PRIMITIVE_TOPOLOGY_MAX_ENUM,       0, 0, 0 },
38 	};
39 	BX_STATIC_ASSERT(Topology::Count == BX_COUNTOF(s_primInfo)-1);
40 
41 	static const uint32_t s_checkMsaa[] =
42 	{
43 		0,
44 		2,
45 		4,
46 		8,
47 		16,
48 	};
49 
50 //	static DXGI_SAMPLE_DESC s_msaa[] =
51 //	{
52 //		{  1, 0 },
53 //		{  2, 0 },
54 //		{  4, 0 },
55 //		{  8, 0 },
56 //		{ 16, 0 },
57 //	};
58 
59 	static const VkBlendFactor s_blendFactor[][2] =
60 	{
61 		{ VkBlendFactor(0),                         VkBlendFactor(0)                         }, // ignored
62 		{ VK_BLEND_FACTOR_ZERO,                     VK_BLEND_FACTOR_ZERO                     }, // ZERO
63 		{ VK_BLEND_FACTOR_ONE,                      VK_BLEND_FACTOR_ONE                      }, // ONE
64 		{ VK_BLEND_FACTOR_SRC_COLOR,                VK_BLEND_FACTOR_SRC_ALPHA                }, // SRC_COLOR
65 		{ VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,      VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA      }, // INV_SRC_COLOR
66 		{ VK_BLEND_FACTOR_SRC_ALPHA,                VK_BLEND_FACTOR_SRC_ALPHA                }, // SRC_ALPHA
67 		{ VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,      VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA      }, // INV_SRC_ALPHA
68 		{ VK_BLEND_FACTOR_DST_ALPHA,                VK_BLEND_FACTOR_DST_ALPHA                }, // DST_ALPHA
69 		{ VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,      VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA      }, // INV_DST_ALPHA
70 		{ VK_BLEND_FACTOR_DST_COLOR,                VK_BLEND_FACTOR_DST_ALPHA                }, // DST_COLOR
71 		{ VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,      VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA      }, // INV_DST_COLOR
72 		{ VK_BLEND_FACTOR_SRC_ALPHA,                VK_BLEND_FACTOR_ONE                      }, // SRC_ALPHA_SAT
73 		{ VK_BLEND_FACTOR_CONSTANT_COLOR,           VK_BLEND_FACTOR_CONSTANT_COLOR           }, // FACTOR
74 		{ VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR }, // INV_FACTOR
75 	};
76 
77 	static const VkBlendOp s_blendEquation[] =
78 	{
79 		VK_BLEND_OP_ADD,
80 		VK_BLEND_OP_SUBTRACT,
81 		VK_BLEND_OP_REVERSE_SUBTRACT,
82 		VK_BLEND_OP_MIN,
83 		VK_BLEND_OP_MAX,
84 	};
85 
86 	static const VkCompareOp s_cmpFunc[] =
87 	{
88 		VkCompareOp(0), // ignored
89 		VK_COMPARE_OP_LESS,
90 		VK_COMPARE_OP_LESS_OR_EQUAL,
91 		VK_COMPARE_OP_EQUAL,
92 		VK_COMPARE_OP_GREATER_OR_EQUAL,
93 		VK_COMPARE_OP_GREATER,
94 		VK_COMPARE_OP_NOT_EQUAL,
95 		VK_COMPARE_OP_NEVER,
96 		VK_COMPARE_OP_ALWAYS,
97 	};
98 
99 	static const VkStencilOp s_stencilOp[] =
100 	{
101 		VK_STENCIL_OP_ZERO,
102 		VK_STENCIL_OP_KEEP,
103 		VK_STENCIL_OP_REPLACE,
104 		VK_STENCIL_OP_INCREMENT_AND_WRAP,
105 		VK_STENCIL_OP_INCREMENT_AND_CLAMP,
106 		VK_STENCIL_OP_DECREMENT_AND_WRAP,
107 		VK_STENCIL_OP_DECREMENT_AND_CLAMP,
108 		VK_STENCIL_OP_INVERT,
109 	};
110 
111 	static const VkCullModeFlagBits s_cullMode[] =
112 	{
113 		VK_CULL_MODE_NONE,
114 		VK_CULL_MODE_FRONT_BIT,
115 		VK_CULL_MODE_BACK_BIT,
116 	};
117 
118 	static const VkSamplerAddressMode s_textureAddress[] =
119 	{
120 		VK_SAMPLER_ADDRESS_MODE_REPEAT,
121 		VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
122 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
123 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
124 	};
125 
126 #define VK_IMPORT_FUNC(_optional, _func) PFN_##_func _func
127 #define VK_IMPORT_INSTANCE_FUNC VK_IMPORT_FUNC
128 #define VK_IMPORT_DEVICE_FUNC   VK_IMPORT_FUNC
129 VK_IMPORT
130 VK_IMPORT_INSTANCE
131 VK_IMPORT_DEVICE
132 #undef VK_IMPORT_DEVICE_FUNC
133 #undef VK_IMPORT_INSTANCE_FUNC
134 #undef VK_IMPORT_FUNC
135 
136 	struct TextureFormatInfo
137 	{
138 		VkFormat m_fmt;
139 		VkFormat m_fmtSrv;
140 		VkFormat m_fmtDsv;
141 		VkFormat m_fmtSrgb;
142 	};
143 
144 	static const TextureFormatInfo s_textureFormat[] =
145 	{
146 		{ VK_FORMAT_BC1_RGB_UNORM_BLOCK,       VK_FORMAT_BC1_RGB_UNORM_BLOCK,      VK_FORMAT_UNDEFINED,           VK_FORMAT_BC1_RGB_SRGB_BLOCK       }, // BC1
147 		{ VK_FORMAT_BC2_UNORM_BLOCK,           VK_FORMAT_BC2_UNORM_BLOCK,          VK_FORMAT_UNDEFINED,           VK_FORMAT_BC2_SRGB_BLOCK           }, // BC2
148 		{ VK_FORMAT_BC3_UNORM_BLOCK,           VK_FORMAT_BC3_UNORM_BLOCK,          VK_FORMAT_UNDEFINED,           VK_FORMAT_BC3_SRGB_BLOCK           }, // BC3
149 		{ VK_FORMAT_BC4_UNORM_BLOCK,           VK_FORMAT_BC4_UNORM_BLOCK,          VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // BC4
150 		{ VK_FORMAT_BC5_UNORM_BLOCK,           VK_FORMAT_BC5_UNORM_BLOCK,          VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // BC5
151 		{ VK_FORMAT_BC6H_SFLOAT_BLOCK,         VK_FORMAT_BC6H_SFLOAT_BLOCK,        VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // BC6H
152 		{ VK_FORMAT_BC7_UNORM_BLOCK,           VK_FORMAT_BC7_UNORM_BLOCK,          VK_FORMAT_UNDEFINED,           VK_FORMAT_BC7_SRGB_BLOCK           }, // BC7
153 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // ETC1
154 		{ VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,   VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK   }, // ETC2
155 		{ VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK }, // ETC2A
156 		{ VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK }, // ETC2A1
157 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // PTC12
158 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // PTC14
159 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // PTC12A
160 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // PTC14A
161 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // PTC22
162 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // PTC24
163 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // ATC
164 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // ATCE
165 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // ATCI
166 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // ASTC4x4
167 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // ASTC5x5
168 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // ASTC6x6
169 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // ASTC8x5
170 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // ASTC8x6
171 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // ASTC10x5
172 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // Unknown
173 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R1
174 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // A8
175 		{ VK_FORMAT_R8_UNORM,                  VK_FORMAT_R8_UNORM,                 VK_FORMAT_UNDEFINED,           VK_FORMAT_R8_SRGB                  }, // R8
176 		{ VK_FORMAT_R8_SINT,                   VK_FORMAT_R8_SINT,                  VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R8I
177 		{ VK_FORMAT_R8_UINT,                   VK_FORMAT_R8_UINT,                  VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R8U
178 		{ VK_FORMAT_R8_SNORM,                  VK_FORMAT_R8_SNORM,                 VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R8S
179 		{ VK_FORMAT_R16_UNORM,                 VK_FORMAT_R16_UNORM,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R16
180 		{ VK_FORMAT_R16_SINT,                  VK_FORMAT_R16_SINT,                 VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R16I
181 		{ VK_FORMAT_R16_UNORM,                 VK_FORMAT_R16_UNORM,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R16U
182 		{ VK_FORMAT_R16_SFLOAT,                VK_FORMAT_R16_SFLOAT,               VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R16F
183 		{ VK_FORMAT_R16_SNORM,                 VK_FORMAT_R16_SNORM,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R16S
184 		{ VK_FORMAT_R32_SINT,                  VK_FORMAT_R32_SINT,                 VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R32I
185 		{ VK_FORMAT_R32_UINT,                  VK_FORMAT_R32_UINT,                 VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R32U
186 		{ VK_FORMAT_R32_SFLOAT,                VK_FORMAT_R32_SFLOAT,               VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R32F
187 		{ VK_FORMAT_R8G8_UNORM,                VK_FORMAT_R8G8_UNORM,               VK_FORMAT_UNDEFINED,           VK_FORMAT_R8G8_SRGB                }, // RG8
188 		{ VK_FORMAT_R8G8_SINT,                 VK_FORMAT_R8G8_SINT,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG8I
189 		{ VK_FORMAT_R8G8_UINT,                 VK_FORMAT_R8G8_UINT,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG8U
190 		{ VK_FORMAT_R8G8_SNORM,                VK_FORMAT_R8G8_SNORM,               VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG8S
191 		{ VK_FORMAT_R16G16_UNORM,              VK_FORMAT_R16G16_UNORM,             VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG16
192 		{ VK_FORMAT_R16G16_SINT,               VK_FORMAT_R16G16_SINT,              VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG16I
193 		{ VK_FORMAT_R16G16_UINT,               VK_FORMAT_R16G16_UINT,              VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG16U
194 		{ VK_FORMAT_R16G16_SFLOAT,             VK_FORMAT_R16G16_SFLOAT,            VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG16F
195 		{ VK_FORMAT_R16G16_SNORM,              VK_FORMAT_R16G16_SNORM,             VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG16S
196 		{ VK_FORMAT_R32G32_SINT,               VK_FORMAT_R32G32_SINT,              VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG32I
197 		{ VK_FORMAT_R32G32_UINT,               VK_FORMAT_R32G32_UINT,              VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG32U
198 		{ VK_FORMAT_R32G32_SFLOAT,             VK_FORMAT_R32G32_SFLOAT,            VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG32F
199 		{ VK_FORMAT_R8G8B8_UNORM,              VK_FORMAT_R8G8B8_UNORM,             VK_FORMAT_UNDEFINED,           VK_FORMAT_R8G8B8_SRGB              }, // RGB8
200 		{ VK_FORMAT_R8G8B8_SINT,               VK_FORMAT_R8G8B8_SINT,              VK_FORMAT_UNDEFINED,           VK_FORMAT_R8G8B8_SRGB              }, // RGB8I
201 		{ VK_FORMAT_R8G8B8_UINT,               VK_FORMAT_R8G8B8_UINT,              VK_FORMAT_UNDEFINED,           VK_FORMAT_R8G8B8_SRGB              }, // RGB8U
202 		{ VK_FORMAT_R8G8B8_SNORM,              VK_FORMAT_R8G8B8_SNORM,             VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGB8S
203 		{ VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,    VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,   VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGB9E5F
204 		{ VK_FORMAT_B8G8R8A8_UNORM,            VK_FORMAT_B8G8R8A8_UNORM,           VK_FORMAT_UNDEFINED,           VK_FORMAT_B8G8R8A8_SRGB            }, // BGRA8
205 		{ VK_FORMAT_R8G8B8A8_UNORM,            VK_FORMAT_R8G8B8A8_UNORM,           VK_FORMAT_UNDEFINED,           VK_FORMAT_R8G8B8A8_SRGB            }, // RGBA8
206 		{ VK_FORMAT_R8G8B8A8_SINT,             VK_FORMAT_R8G8B8A8_SINT,            VK_FORMAT_UNDEFINED,           VK_FORMAT_R8G8B8A8_SRGB            }, // RGBA8I
207 		{ VK_FORMAT_R8G8B8A8_UINT,             VK_FORMAT_R8G8B8A8_UINT,            VK_FORMAT_UNDEFINED,           VK_FORMAT_R8G8B8A8_SRGB            }, // RGBA8U
208 		{ VK_FORMAT_R8G8B8A8_SNORM,            VK_FORMAT_R8G8B8A8_SNORM,           VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGBA8S
209 		{ VK_FORMAT_R16G16B16A16_UNORM,        VK_FORMAT_R16G16B16A16_UNORM,       VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGBA16
210 		{ VK_FORMAT_R16G16B16A16_SINT,         VK_FORMAT_R16G16B16A16_SINT,        VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGBA16I
211 		{ VK_FORMAT_R16G16B16A16_UINT,         VK_FORMAT_R16G16B16A16_UINT,        VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGBA16U
212 		{ VK_FORMAT_R16G16B16A16_SFLOAT,       VK_FORMAT_R16G16B16A16_SFLOAT,      VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGBA16F
213 		{ VK_FORMAT_R16G16B16A16_SNORM,        VK_FORMAT_R16G16B16A16_SNORM,       VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGBA16S
214 		{ VK_FORMAT_R32G32B32A32_SINT,         VK_FORMAT_R32G32B32A32_SINT,        VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGBA32I
215 		{ VK_FORMAT_R32G32B32A32_UINT,         VK_FORMAT_R32G32B32A32_UINT,        VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGBA32U
216 		{ VK_FORMAT_R32G32B32A32_SFLOAT,       VK_FORMAT_R32G32B32A32_SFLOAT,      VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGBA32F
217 		{ VK_FORMAT_B5G6R5_UNORM_PACK16,       VK_FORMAT_B5G6R5_UNORM_PACK16,      VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // R5G6B5
218 		{ VK_FORMAT_B4G4R4A4_UNORM_PACK16,     VK_FORMAT_B4G4R4A4_UNORM_PACK16,    VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGBA4
219 		{ VK_FORMAT_A1R5G5B5_UNORM_PACK16,     VK_FORMAT_A1R5G5B5_UNORM_PACK16,    VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGB5A1
220 		{ VK_FORMAT_A2R10G10B10_UNORM_PACK32,  VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RGB10A2
221 		{ VK_FORMAT_B10G11R11_UFLOAT_PACK32,   VK_FORMAT_B10G11R11_UFLOAT_PACK32,  VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // RG11B10F
222 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_UNDEFINED,                VK_FORMAT_UNDEFINED,           VK_FORMAT_UNDEFINED                }, // UnknownDepth
223 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_R16_UNORM,                VK_FORMAT_D16_UNORM,           VK_FORMAT_UNDEFINED                }, // D16
224 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_X8_D24_UNORM_PACK32,      VK_FORMAT_D24_UNORM_S8_UINT,   VK_FORMAT_UNDEFINED                }, // D24
225 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_X8_D24_UNORM_PACK32,      VK_FORMAT_D24_UNORM_S8_UINT,   VK_FORMAT_UNDEFINED                }, // D24S8
226 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_X8_D24_UNORM_PACK32,      VK_FORMAT_D24_UNORM_S8_UINT,   VK_FORMAT_UNDEFINED                }, // D32
227 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_R32_SFLOAT,               VK_FORMAT_D32_SFLOAT,          VK_FORMAT_UNDEFINED                }, // D16F
228 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_R32_SFLOAT,               VK_FORMAT_D32_SFLOAT,          VK_FORMAT_UNDEFINED                }, // D24F
229 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_R32_SFLOAT,               VK_FORMAT_D32_SFLOAT,          VK_FORMAT_UNDEFINED                }, // D32F
230 		{ VK_FORMAT_UNDEFINED,                 VK_FORMAT_X8_D24_UNORM_PACK32,      VK_FORMAT_D24_UNORM_S8_UINT,   VK_FORMAT_UNDEFINED                }, // D0S8
231 	};
232 	BX_STATIC_ASSERT(TextureFormat::Count == BX_COUNTOF(s_textureFormat) );
233 
234 	struct Extension
235 	{
236 		enum Enum
237 		{
238 			EXT_debug_utils,
239 			EXT_debug_report,
240 			EXT_memory_budget,
241 			KHR_get_physical_device_properties2,
242 
243 			Count
244 		};
245 
246 		const char* m_name;
247 		uint32_t m_minVersion;
248 		bool m_instanceExt;
249 		bool m_supported;
250 		bool m_initialize;
251 	};
252 
253 	// Extension registry
254 	//
255 	static Extension s_extension[] =
256 	{
257 		{ "VK_EXT_debug_utils",                     1, false, false, BGFX_CONFIG_DEBUG_OBJECT_NAME },
258 		{ "VK_EXT_debug_report",                    1, false, false, BGFX_CONFIG_DEBUG             },
259 		{ "VK_EXT_memory_budget",                   1, false, false, true                          },
260 		{ "VK_KHR_get_physical_device_properties2", 1, false, false, true                          },
261 	};
262 	BX_STATIC_ASSERT(Extension::Count == BX_COUNTOF(s_extension) );
263 
updateExtension(const char * _name,uint32_t _version,bool _instanceExt)264 	void updateExtension(const char* _name, uint32_t _version, bool _instanceExt)
265 	{
266 		bx::StringView ext(_name);
267 
268 		bool supported = false;
269 		for (uint32_t ii = 0; ii < Extension::Count; ++ii)
270 		{
271 			Extension& extension = s_extension[ii];
272 			if (!extension.m_supported
273 			&&   extension.m_initialize)
274 			{
275 				if (       0 == bx::strCmp(ext, extension.m_name)
276 				&&  _version >= extension.m_minVersion)
277 				{
278 					extension.m_supported   = true;
279 					extension.m_instanceExt = _instanceExt;
280 					supported = true;
281 					break;
282 				}
283 			}
284 		}
285 
286 		BX_TRACE("\tv%-3d %s%s"
287 			, _version
288 			, _name
289 			, supported ? " (supported)" : "", _name
290 			);
291 
292 		BX_UNUSED(supported);
293 	}
294 
295 	static const VkFormat s_attribType[][4][2] =
296 	{
297 		{ // Uint8
298 			{ VK_FORMAT_R8_UINT,                 VK_FORMAT_R8_UNORM                 },
299 			{ VK_FORMAT_R8G8_UINT,               VK_FORMAT_R8G8_UNORM               },
300 			{ VK_FORMAT_R8G8B8A8_UINT,           VK_FORMAT_R8G8B8A8_UNORM           },
301 			{ VK_FORMAT_R8G8B8A8_UINT,           VK_FORMAT_R8G8B8A8_UNORM           },
302 		},
303 		{ // Uint10
304 			{ VK_FORMAT_A2R10G10B10_UINT_PACK32, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
305 			{ VK_FORMAT_A2R10G10B10_UINT_PACK32, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
306 			{ VK_FORMAT_A2R10G10B10_UINT_PACK32, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
307 			{ VK_FORMAT_A2R10G10B10_UINT_PACK32, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
308 		},
309 		{ // Int16
310 			{ VK_FORMAT_R16_SINT,                VK_FORMAT_R16_SNORM                },
311 			{ VK_FORMAT_R16G16_SINT,             VK_FORMAT_R16G16_SNORM             },
312 			{ VK_FORMAT_R16G16B16_SINT,          VK_FORMAT_R16G16B16_SNORM          },
313 			{ VK_FORMAT_R16G16B16A16_SINT,       VK_FORMAT_R16G16B16A16_SNORM       },
314 		},
315 		{ // Half
316 			{ VK_FORMAT_R16_SFLOAT,              VK_FORMAT_R16_SFLOAT               },
317 			{ VK_FORMAT_R16G16_SFLOAT,           VK_FORMAT_R16G16_SFLOAT            },
318 			{ VK_FORMAT_R16G16B16_SFLOAT,        VK_FORMAT_R16G16B16_SFLOAT         },
319 			{ VK_FORMAT_R16G16B16A16_SFLOAT,     VK_FORMAT_R16G16B16A16_SFLOAT      },
320 		},
321 		{ // Float
322 			{ VK_FORMAT_R32_SFLOAT,              VK_FORMAT_R32_SFLOAT               },
323 			{ VK_FORMAT_R32G32_SFLOAT,           VK_FORMAT_R32G32_SFLOAT            },
324 			{ VK_FORMAT_R32G32B32_SFLOAT,        VK_FORMAT_R32G32B32_SFLOAT         },
325 			{ VK_FORMAT_R32G32B32A32_SFLOAT,     VK_FORMAT_R32G32B32A32_SFLOAT      },
326 		},
327 	};
328 	BX_STATIC_ASSERT(AttribType::Count == BX_COUNTOF(s_attribType) );
329 
fillVertexLayout(const ShaderVK * _vsh,VkPipelineVertexInputStateCreateInfo & _vertexInputState,const VertexLayout & _layout)330 	void fillVertexLayout(const ShaderVK* _vsh, VkPipelineVertexInputStateCreateInfo& _vertexInputState, const VertexLayout& _layout)
331 	{
332 		uint32_t numBindings = _vertexInputState.vertexBindingDescriptionCount;
333 		uint32_t numAttribs  = _vertexInputState.vertexAttributeDescriptionCount;
334 		VkVertexInputBindingDescription*   inputBinding = const_cast<VkVertexInputBindingDescription*>(_vertexInputState.pVertexBindingDescriptions + numBindings);
335 		VkVertexInputAttributeDescription* inputAttrib  = const_cast<VkVertexInputAttributeDescription*>(_vertexInputState.pVertexAttributeDescriptions + numAttribs);
336 
337 		inputBinding->binding   = numBindings;
338 		inputBinding->stride    = _layout.m_stride;
339 		inputBinding->inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
340 
341 		for (uint32_t attr = 0; attr < Attrib::Count; ++attr)
342 		{
343 			if (UINT16_MAX != _layout.m_attributes[attr])
344 			{
345 				inputAttrib->location = _vsh->m_attrRemap[attr];
346 				inputAttrib->binding  = numBindings;
347 
348 				uint8_t num;
349 				AttribType::Enum type;
350 				bool normalized;
351 				bool asInt;
352 				_layout.decode(Attrib::Enum(attr), num, type, normalized, asInt);
353 				inputAttrib->format = s_attribType[type][num-1][normalized];
354 				inputAttrib->offset = _layout.m_offset[attr];
355 
356 				++inputAttrib;
357 				++numAttribs;
358 			}
359 		}
360 
361 		_vertexInputState.vertexBindingDescriptionCount   = numBindings + 1;
362 		_vertexInputState.vertexAttributeDescriptionCount = numAttribs;
363 	}
364 
fillInstanceBinding(const ShaderVK * _vsh,VkPipelineVertexInputStateCreateInfo & _vertexInputState,uint32_t _numInstanceData)365 	void fillInstanceBinding(const ShaderVK* _vsh, VkPipelineVertexInputStateCreateInfo& _vertexInputState, uint32_t _numInstanceData)
366 	{
367 		BX_UNUSED(_vsh);
368 
369 		uint32_t numBindings = _vertexInputState.vertexBindingDescriptionCount;
370 		uint32_t numAttribs  = _vertexInputState.vertexAttributeDescriptionCount;
371 		VkVertexInputBindingDescription*   inputBinding = const_cast<VkVertexInputBindingDescription*>(_vertexInputState.pVertexBindingDescriptions + numBindings);
372 		VkVertexInputAttributeDescription* inputAttrib  = const_cast<VkVertexInputAttributeDescription*>(_vertexInputState.pVertexAttributeDescriptions + numAttribs);
373 
374 		inputBinding->binding   = numBindings;
375 		inputBinding->stride    = _numInstanceData * 16;
376 		inputBinding->inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
377 
378 		for (uint32_t inst = 0; inst < _numInstanceData; ++inst)
379 		{
380 			inputAttrib->location = numAttribs;
381 			inputAttrib->binding  = numBindings;
382 			inputAttrib->format   = VK_FORMAT_R32G32B32A32_SFLOAT;
383 			inputAttrib->offset   = inst * 16;
384 
385 			++numAttribs;
386 			++inputAttrib;
387 		}
388 
389 		_vertexInputState.vertexBindingDescriptionCount   = numBindings + 1;
390 		_vertexInputState.vertexAttributeDescriptionCount = numAttribs;
391 	}
392 
393 	static const char* s_deviceTypeName[] =
394 	{
395 		"Other",
396 		"Integrated GPU",
397 		"Discrete GPU",
398 		"Virtual GPU",
399 		"CPU",
400 
401 		"Unknown?!"
402 	};
403 
getName(VkPhysicalDeviceType _type)404 	const char* getName(VkPhysicalDeviceType _type)
405 	{
406 		return s_deviceTypeName[bx::min<int32_t>(_type, BX_COUNTOF(s_deviceTypeName) )];
407 	}
408 
409 	static const char* s_allocScopeName[] =
410 	{
411 		"vkCommand",
412 		"vkObject",
413 		"vkCache",
414 		"vkDevice",
415 		"vkInstance",
416 	};
417 	BX_STATIC_ASSERT(VK_SYSTEM_ALLOCATION_SCOPE_RANGE_SIZE == BX_COUNTOF(s_allocScopeName) );
418 
allocationFunction(void * _userData,size_t _size,size_t _alignment,VkSystemAllocationScope _allocationScope)419 	static void* VKAPI_PTR allocationFunction(void* _userData, size_t _size, size_t _alignment, VkSystemAllocationScope _allocationScope)
420 	{
421 		BX_UNUSED(_userData, _allocationScope);
422 		return bx::alignedAlloc(g_allocator, _size, _alignment, s_allocScopeName[_allocationScope]);
423 	}
424 
reallocationFunction(void * _userData,void * _original,size_t _size,size_t _alignment,VkSystemAllocationScope _allocationScope)425 	static void* VKAPI_PTR reallocationFunction(void* _userData, void* _original, size_t _size, size_t _alignment, VkSystemAllocationScope _allocationScope)
426 	{
427 		BX_UNUSED(_userData, _allocationScope);
428 		return bx::alignedRealloc(g_allocator, _original, _size, _alignment, s_allocScopeName[_allocationScope]);
429 	}
430 
freeFunction(void * _userData,void * _memory)431 	static void VKAPI_PTR freeFunction(void* _userData, void* _memory)
432 	{
433 		BX_UNUSED(_userData);
434 
435 		if (NULL == _memory)
436 		{
437 			return;
438 		}
439 
440 		bx::alignedFree(g_allocator, _memory, 8);
441 	}
442 
internalAllocationNotification(void * _userData,size_t _size,VkInternalAllocationType _allocationType,VkSystemAllocationScope _allocationScope)443 	static void VKAPI_PTR internalAllocationNotification(void* _userData, size_t _size, VkInternalAllocationType _allocationType, VkSystemAllocationScope _allocationScope)
444 	{
445 		BX_UNUSED(_userData, _size, _allocationType, _allocationScope);
446 	}
447 
internalFreeNotification(void * _userData,size_t _size,VkInternalAllocationType _allocationType,VkSystemAllocationScope _allocationScope)448 	static void VKAPI_PTR internalFreeNotification(void* _userData, size_t _size, VkInternalAllocationType _allocationType, VkSystemAllocationScope _allocationScope)
449 	{
450 		BX_UNUSED(_userData, _size, _allocationType, _allocationScope);
451 	}
452 
453 	static VkAllocationCallbacks s_allocationCb =
454 	{
455 		NULL,
456 		allocationFunction,
457 		reallocationFunction,
458 		freeFunction,
459 		internalAllocationNotification,
460 		internalFreeNotification,
461 	};
462 
stubSetDebugUtilsObjectNameEXT(VkDevice _device,const VkDebugUtilsObjectNameInfoEXT * _nameInfo)463 	VkResult VKAPI_PTR stubSetDebugUtilsObjectNameEXT(VkDevice _device, const VkDebugUtilsObjectNameInfoEXT* _nameInfo)
464 	{
465 		BX_UNUSED(_device, _nameInfo);
466 		return VK_SUCCESS;
467 	}
468 
stubCmdInsertDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer,const VkDebugUtilsLabelEXT * _labelInfo)469 	void VKAPI_PTR stubCmdInsertDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer, const VkDebugUtilsLabelEXT* _labelInfo)
470 	{
471 		BX_UNUSED(_commandBuffer, _labelInfo);
472 	}
473 
stubCmdBeginDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer,const VkDebugUtilsLabelEXT * _labelInfo)474 	void VKAPI_PTR stubCmdBeginDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer, const VkDebugUtilsLabelEXT* _labelInfo)
475 	{
476 		BX_UNUSED(_commandBuffer, _labelInfo);
477 	}
478 
stubCmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer)479 	void VKAPI_PTR stubCmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer)
480 	{
481 		BX_UNUSED(_commandBuffer);
482 	}
483 
484 	static const char* s_debugReportObjectType[] =
485 	{
486 		"Unknown",
487 		"Instance",
488 		"PhysicalDevice",
489 		"Device",
490 		"Queue",
491 		"Semaphore",
492 		"CommandBuffer",
493 		"Fence",
494 		"DeviceMemory",
495 		"Buffer",
496 		"Image",
497 		"Event",
498 		"QueryPool",
499 		"BufferView",
500 		"ImageView",
501 		"ShaderModule",
502 		"PipelineCache",
503 		"PipelineLayout",
504 		"RenderPass",
505 		"Pipeline",
506 		"DescriptorSetLayout",
507 		"Sampler",
508 		"DescriptorPool",
509 		"DescriptorSet",
510 		"Framebuffer",
511 		"CommandPool",
512 		"SurfaceKHR",
513 		"SwapchainKHR",
514 		"DebugReport",
515 	};
516 
debugReportCb(VkDebugReportFlagsEXT _flags,VkDebugReportObjectTypeEXT _objectType,uint64_t _object,size_t _location,int32_t _messageCode,const char * _layerPrefix,const char * _message,void * _userData)517 	VkBool32 VKAPI_PTR debugReportCb(
518 		VkDebugReportFlagsEXT _flags,
519 		VkDebugReportObjectTypeEXT _objectType,
520 		uint64_t _object,
521 		size_t _location,
522 		int32_t _messageCode,
523 		const char* _layerPrefix,
524 		const char* _message,
525 		void* _userData
526 	)
527 	{
528 		BX_UNUSED(_flags
529 			, _objectType
530 			, _object
531 			, _location
532 			, _messageCode
533 			, _layerPrefix
534 			, _message
535 			, _userData
536 			, s_debugReportObjectType
537 		);
538 		if (!bx::strFind(_message, "PointSizeMissing").isEmpty()
539 		||  !bx::strFind(_message, "SwapchainTooManyImages").isEmpty()
540 		||  !bx::strFind(_message, "SwapchainImageNotAcquired").isEmpty())
541 		{
542 			return VK_FALSE;
543 		}
544 		BX_TRACE("%c%c%c%c%c %19s, %s, %d: %s"
545 			, 0 != (_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT        ) ? 'I' : '-'
546 			, 0 != (_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT            ) ? 'W' : '-'
547 			, 0 != (_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) ? 'P' : '-'
548 			, 0 != (_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT              ) ? 'E' : '-'
549 			, 0 != (_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT              ) ? 'D' : '-'
550 			, s_debugReportObjectType[_objectType]
551 			, _layerPrefix
552 			, _messageCode
553 			, _message
554 			);
555 		return VK_TRUE;
556 	}
557 
enumerateLayerProperties(VkPhysicalDevice _physicalDevice,uint32_t * _propertyCount,VkLayerProperties * _properties)558 	VkResult enumerateLayerProperties(VkPhysicalDevice _physicalDevice, uint32_t* _propertyCount, VkLayerProperties* _properties)
559 	{
560 		return (VK_NULL_HANDLE == _physicalDevice)
561 			? vkEnumerateInstanceLayerProperties(_propertyCount, _properties)
562 			: vkEnumerateDeviceLayerProperties(_physicalDevice, _propertyCount, _properties)
563 			;
564 	}
565 
enumerateExtensionProperties(VkPhysicalDevice _physicalDevice,const char * _layerName,uint32_t * _propertyCount,VkExtensionProperties * _properties)566 	VkResult enumerateExtensionProperties(VkPhysicalDevice _physicalDevice, const char* _layerName, uint32_t* _propertyCount, VkExtensionProperties* _properties)
567 	{
568 		return (VK_NULL_HANDLE == _physicalDevice)
569 			? vkEnumerateInstanceExtensionProperties(_layerName, _propertyCount, _properties)
570 			: vkEnumerateDeviceExtensionProperties(_physicalDevice, _layerName, _propertyCount, _properties)
571 			;
572 	}
573 
dumpExtensions(VkPhysicalDevice _physicalDevice=VK_NULL_HANDLE)574 	void dumpExtensions(VkPhysicalDevice _physicalDevice = VK_NULL_HANDLE)
575 	{
576 		{ // Global extensions.
577 			uint32_t numExtensionProperties;
578 			VkResult result = enumerateExtensionProperties(_physicalDevice
579 				, NULL
580 				, &numExtensionProperties
581 				, NULL
582 				);
583 
584 			if (VK_SUCCESS == result
585 			&&  0 < numExtensionProperties)
586 			{
587 				VkExtensionProperties extensionProperties[64];
588 				numExtensionProperties = bx::min<uint32_t>(numExtensionProperties, BX_COUNTOF(extensionProperties) );
589 				result = enumerateExtensionProperties(_physicalDevice
590 					, NULL
591 					, &numExtensionProperties
592 					, extensionProperties
593 					);
594 
595 				BX_TRACE("Global extensions (%d):"
596 					, numExtensionProperties
597 					);
598 
599 				for (uint32_t extension = 0; extension < numExtensionProperties; ++extension)
600 				{
601 					updateExtension(
602 						  extensionProperties[extension].extensionName
603 						, extensionProperties[extension].specVersion
604 						, VK_NULL_HANDLE == _physicalDevice
605 						);
606 				}
607 			}
608 		}
609 
610 		// Layer extensions.
611 		uint32_t numLayerProperties;
612 		VkResult result = enumerateLayerProperties(_physicalDevice, &numLayerProperties, NULL);
613 
614 		if (VK_SUCCESS == result
615 		&&  0 < numLayerProperties)
616 		{
617 			VkLayerProperties layerProperties[64];
618 			numLayerProperties = bx::min<uint32_t>(numLayerProperties, BX_COUNTOF(layerProperties) );
619 			result = enumerateLayerProperties(_physicalDevice, &numLayerProperties, layerProperties);
620 
621 			char indent = VK_NULL_HANDLE == _physicalDevice ? '\0' : '\t';
622 			BX_UNUSED(indent);
623 
624 			BX_TRACE("%cLayer extensions (%d):"
625 				, indent
626 				, numLayerProperties
627 				);
628 			for (uint32_t layer = 0; layer < numLayerProperties; ++layer)
629 			{
630 				BX_TRACE("%c\t%s (s: 0x%08x, i: 0x%08x), %s"
631 					, indent
632 					, layerProperties[layer].layerName
633 					, layerProperties[layer].specVersion
634 					, layerProperties[layer].implementationVersion
635 					, layerProperties[layer].description
636 					);
637 				uint32_t numExtensionProperties;
638 				result = enumerateExtensionProperties(_physicalDevice
639 					, layerProperties[layer].layerName
640 					, &numExtensionProperties
641 					, NULL
642 					);
643 
644 				if (VK_SUCCESS == result
645 				&&  0 < numExtensionProperties)
646 				{
647 					VkExtensionProperties extensionProperties[64];
648 					numExtensionProperties = bx::min<uint32_t>(numExtensionProperties, BX_COUNTOF(extensionProperties) );
649 					result = enumerateExtensionProperties(_physicalDevice
650 						, layerProperties[layer].layerName
651 						, &numExtensionProperties
652 						, extensionProperties
653 						);
654 
655 					for (uint32_t extension = 0; extension < numExtensionProperties; ++extension)
656 					{
657 						BX_TRACE("%c\t\t%s (s: 0x%08x)"
658 							, indent
659 							, extensionProperties[extension].extensionName
660 							, extensionProperties[extension].specVersion
661 							);
662 					}
663 				}
664 			}
665 		}
666 	}
667 
getName(VkResult _result)668 	const char* getName(VkResult _result)
669 	{
670 		switch (_result)
671 		{
672 #define VKENUM(_ty) case _ty: return #_ty
673 			VKENUM(VK_SUCCESS);
674 			VKENUM(VK_NOT_READY);
675 			VKENUM(VK_TIMEOUT);
676 			VKENUM(VK_EVENT_SET);
677 			VKENUM(VK_EVENT_RESET);
678 			VKENUM(VK_INCOMPLETE);
679 			VKENUM(VK_ERROR_OUT_OF_HOST_MEMORY);
680 			VKENUM(VK_ERROR_OUT_OF_DEVICE_MEMORY);
681 			VKENUM(VK_ERROR_INITIALIZATION_FAILED);
682 			VKENUM(VK_ERROR_DEVICE_LOST);
683 			VKENUM(VK_ERROR_MEMORY_MAP_FAILED);
684 			VKENUM(VK_ERROR_LAYER_NOT_PRESENT);
685 			VKENUM(VK_ERROR_EXTENSION_NOT_PRESENT);
686 			VKENUM(VK_ERROR_FEATURE_NOT_PRESENT);
687 			VKENUM(VK_ERROR_INCOMPATIBLE_DRIVER);
688 			VKENUM(VK_ERROR_TOO_MANY_OBJECTS);
689 			VKENUM(VK_ERROR_FORMAT_NOT_SUPPORTED);
690 			VKENUM(VK_ERROR_SURFACE_LOST_KHR);
691 			VKENUM(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
692 			VKENUM(VK_SUBOPTIMAL_KHR);
693 			VKENUM(VK_ERROR_OUT_OF_DATE_KHR);
694 			VKENUM(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
695 			VKENUM(VK_ERROR_VALIDATION_FAILED_EXT);
696 #undef VKENUM
697 			default: break;
698 		}
699 
700 		BX_WARN(false, "Unknown VkResult? %x", _result);
701 		return "<VkResult?>";
702 	}
703 
704 	template<typename Ty>
705 	VkObjectType getType();
706 
getType()707 	template<> VkObjectType getType<VkBuffer      >() { return VK_OBJECT_TYPE_BUFFER;        }
getType()708 	template<> VkObjectType getType<VkShaderModule>() { return VK_OBJECT_TYPE_SHADER_MODULE; }
709 
710 	template<typename Ty>
setDebugObjectName(VkDevice _device,Ty _object,const char * _format,...)711 	static BX_NO_INLINE void setDebugObjectName(VkDevice _device, Ty _object, const char* _format, ...)
712 	{
713 		if (BX_ENABLED(BGFX_CONFIG_DEBUG_OBJECT_NAME) && s_extension[Extension::EXT_debug_utils].m_supported)
714 		{
715 			char temp[2048];
716 			va_list argList;
717 			va_start(argList, _format);
718 			int32_t size = bx::min<int32_t>(sizeof(temp)-1, bx::vsnprintf(temp, sizeof(temp), _format, argList) );
719 			va_end(argList);
720 			temp[size] = '\0';
721 
722 			VkDebugUtilsObjectNameInfoEXT ni;
723 			ni.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
724 			ni.pNext = NULL;
725 			ni.objectType   = getType<Ty>();
726 			ni.objectHandle = uint64_t(_object.vk);
727 			ni.pObjectName  = temp;
728 
729 			VK_CHECK(vkSetDebugUtilsObjectNameEXT(_device, &ni) );
730 		}
731 	}
732 
setImageMemoryBarrier(VkCommandBuffer _commandBuffer,VkImage _image,VkImageAspectFlags _aspectMask,VkImageLayout _oldLayout,VkImageLayout _newLayout,uint32_t _levelCount,uint32_t _layerCount)733 	void setImageMemoryBarrier(VkCommandBuffer _commandBuffer, VkImage _image, VkImageAspectFlags _aspectMask, VkImageLayout _oldLayout, VkImageLayout _newLayout, uint32_t _levelCount, uint32_t _layerCount)
734 	{
735 		BX_CHECK(true
736 			&& _newLayout != VK_IMAGE_LAYOUT_UNDEFINED
737 			&& _newLayout != VK_IMAGE_LAYOUT_PREINITIALIZED
738 			, "_newLayout cannot use VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREINITIALIZED."
739 			);
740 
741 		VkAccessFlags srcAccessMask = 0;
742 		VkAccessFlags dstAccessMask = 0;
743 
744 		switch (_oldLayout)
745 		{
746 		case VK_IMAGE_LAYOUT_UNDEFINED:
747 //			srcAccessMask |= VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
748 			break;
749 
750 		case VK_IMAGE_LAYOUT_GENERAL:
751 			break;
752 
753 		case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
754 			srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
755 			break;
756 
757 		case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
758 			srcAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
759 			break;
760 
761 		case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
762 			break;
763 
764 		case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
765 			srcAccessMask |= VK_ACCESS_SHADER_READ_BIT;
766 			break;
767 
768 		case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
769 			srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT;
770 			break;
771 
772 		case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
773 			break;
774 
775 		case VK_IMAGE_LAYOUT_PREINITIALIZED:
776 			srcAccessMask |= VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
777 			break;
778 
779 		case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
780 			srcAccessMask |= VK_ACCESS_MEMORY_READ_BIT;
781 			break;
782 
783 		default:
784 			break;
785 		}
786 
787 		switch (_newLayout)
788 		{
789 		case VK_IMAGE_LAYOUT_UNDEFINED:
790 			break;
791 
792 		case VK_IMAGE_LAYOUT_GENERAL:
793 			break;
794 
795 		case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
796 			dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
797 			break;
798 
799 		case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
800 			dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
801 			// aspectMask     = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
802 			break;
803 
804 		case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
805 			break;
806 
807 		case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
808 			dstAccessMask |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
809 			break;
810 
811 		case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
812 			dstAccessMask |= VK_ACCESS_SHADER_READ_BIT;
813 			break;
814 
815 		case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
816 			dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT;
817 			break;
818 
819 		case VK_IMAGE_LAYOUT_PREINITIALIZED:
820 			break;
821 
822 		case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
823 			dstAccessMask |= VK_ACCESS_MEMORY_READ_BIT;
824 			break;
825 
826 		default:
827 			break;
828 		}
829 
830 		VkImageMemoryBarrier imb;
831 		imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
832 		imb.pNext = NULL;
833 		imb.srcAccessMask = srcAccessMask;
834 		imb.dstAccessMask = dstAccessMask;
835 		imb.oldLayout = _oldLayout;
836 		imb.newLayout = _newLayout;
837 		imb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
838 		imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
839 		imb.image = _image;
840 		imb.subresourceRange.aspectMask     = _aspectMask;
841 		imb.subresourceRange.baseMipLevel   = 0;
842 		imb.subresourceRange.levelCount     = _levelCount;
843 		imb.subresourceRange.baseArrayLayer = 0;
844 		imb.subresourceRange.layerCount     = _layerCount;
845 		vkCmdPipelineBarrier(_commandBuffer
846 			, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
847 			, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
848 			, 0
849 			, 0
850 			, NULL
851 			, 0
852 			, NULL
853 			, 1
854 			, &imb
855 			);
856 	}
857 
858 	struct RendererContextVK : public RendererContextI
859 	{
RendererContextVKbgfx::vk::RendererContextVK860 		RendererContextVK()
861 			: m_allocatorCb(NULL)
862 			, m_renderDocDll(NULL)
863 			, m_vulkan1Dll(NULL)
864 			, m_maxAnisotropy(1)
865 			, m_depthClamp(false)
866 			, m_wireframe(false)
867 		{
868 		}
869 
~RendererContextVKbgfx::vk::RendererContextVK870 		~RendererContextVK()
871 		{
872 		}
873 
createSwapchainbgfx::vk::RendererContextVK874 		VkResult createSwapchain()
875 		{
876 			VkResult result = VK_SUCCESS;
877 			result = vkCreateSwapchainKHR(m_device, &m_sci, m_allocatorCb, &m_swapchain);
878 			if (VK_SUCCESS != result)
879 			{
880 				BX_TRACE("Create swapchain error: vkCreateSwapchainKHR failed %d: %s.", result, getName(result));
881 				return result;
882 			}
883 
884 			result = vkGetSwapchainImagesKHR(m_device, m_swapchain, &m_numSwapchainImages, NULL);
885 			if (VK_SUCCESS != result)
886 			{
887 				BX_TRACE("Create swapchain error: vkGetSwapchainImagesKHR failed %d: %s.", result, getName(result));
888 				return result;
889 			}
890 
891 			if (m_numSwapchainImages < m_sci.minImageCount)
892 			{
893 				BX_TRACE("Create swapchain error: vkGetSwapchainImagesKHR: numSwapchainImages %d < minImageCount %d."
894 					, m_numSwapchainImages
895 					, m_sci.minImageCount
896 				);
897 				return VK_ERROR_INITIALIZATION_FAILED;
898 			}
899 
900 			result = vkGetSwapchainImagesKHR(m_device, m_swapchain, &m_numSwapchainImages, &m_backBufferColorImage[0]);
901 			if (VK_SUCCESS != result && VK_INCOMPLETE != result)
902 			{
903 				BX_TRACE("Create swapchain error: vkGetSwapchainImagesKHR failed %d: %s.", result, getName(result));
904 				return result;
905 			}
906 
907 			VkImageCreateInfo ici;
908 			ici.sType     = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
909 			ici.pNext     = NULL;
910 			ici.flags     = 0;
911 			ici.imageType = VK_IMAGE_TYPE_2D;
912 			ici.format    = m_backBufferDepthStencilFormat;
913 			ici.extent.width  = m_sci.imageExtent.width;
914 			ici.extent.height = m_sci.imageExtent.height;
915 			ici.extent.depth  = 1;
916 			ici.mipLevels     = 1;
917 			ici.arrayLayers   = 1;
918 			ici.samples       = VK_SAMPLE_COUNT_1_BIT;
919 			ici.tiling        = VK_IMAGE_TILING_OPTIMAL;
920 			ici.usage = 0
921 				| VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
922 				| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
923 				;
924 			ici.sharingMode   = VK_SHARING_MODE_EXCLUSIVE;
925 			ici.queueFamilyIndexCount = 0; //m_sci.queueFamilyIndexCount;
926 			ici.pQueueFamilyIndices   = NULL; //m_sci.pQueueFamilyIndices;
927 			ici.initialLayout         = VK_IMAGE_LAYOUT_UNDEFINED;
928 			result = vkCreateImage(m_device, &ici, m_allocatorCb, &m_backBufferDepthStencilImage);
929 
930 			if (VK_SUCCESS != result)
931 			{
932 				BX_TRACE("Create swapchain error: vkCreateImage failed %d: %s.", result, getName(result));
933 				return result;
934 			}
935 
936 			VkMemoryRequirements mr;
937 			vkGetImageMemoryRequirements(m_device, m_backBufferDepthStencilImage, &mr);
938 
939 			VkMemoryAllocateInfo ma;
940 			ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
941 			ma.pNext = NULL;
942 			ma.allocationSize = mr.size;
943 			ma.memoryTypeIndex = selectMemoryType(mr.memoryTypeBits
944 				, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
945 			);
946 			result = vkAllocateMemory(m_device
947 				, &ma
948 				, m_allocatorCb
949 				, &m_backBufferDepthStencilMemory
950 			);
951 
952 			if (VK_SUCCESS != result)
953 			{
954 				BX_TRACE("Create swapchain error: vkAllocateMemory failed %d: %s.", result, getName(result));
955 				return result;
956 			}
957 
958 			result = vkBindImageMemory(m_device, m_backBufferDepthStencilImage, m_backBufferDepthStencilMemory, 0);
959 
960 			if (VK_SUCCESS != result)
961 			{
962 				BX_TRACE("Create swapchain error: vkBindImageMemory failed %d: %s.", result, getName(result));
963 				return result;
964 			}
965 
966 			VkImageViewCreateInfo ivci;
967 			ivci.sType    = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
968 			ivci.pNext    = NULL;
969 			ivci.flags    = 0;
970 			ivci.image    = m_backBufferDepthStencilImage;
971 			ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
972 			ivci.format   = m_backBufferDepthStencilFormat;
973 			ivci.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
974 			ivci.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
975 			ivci.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
976 			ivci.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
977 			ivci.subresourceRange.aspectMask = 0
978 				| VK_IMAGE_ASPECT_DEPTH_BIT
979 				| VK_IMAGE_ASPECT_STENCIL_BIT
980 				;
981 			ivci.subresourceRange.baseMipLevel   = 0;
982 			ivci.subresourceRange.levelCount     = 1;
983 			ivci.subresourceRange.baseArrayLayer = 0;
984 			ivci.subresourceRange.layerCount     = 1;
985 			result = vkCreateImageView(m_device, &ivci, m_allocatorCb, &m_backBufferDepthStencilImageView);
986 
987 			if (VK_SUCCESS != result)
988 			{
989 				BX_TRACE("Create swapchain error: vkCreateImageView failed %d: %s.", result, getName(result));
990 				return result;
991 			}
992 
993 			for (uint32_t ii = 0; ii < m_numSwapchainImages; ++ii)
994 			{
995 				ivci.sType    = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
996 				ivci.pNext    = NULL;
997 				ivci.flags    = 0;
998 				ivci.image    = m_backBufferColorImage[ii];
999 				ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
1000 				ivci.format   = m_sci.imageFormat;
1001 				ivci.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
1002 				ivci.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
1003 				ivci.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
1004 				ivci.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
1005 				ivci.subresourceRange.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
1006 				ivci.subresourceRange.baseMipLevel   = 0;
1007 				ivci.subresourceRange.levelCount     = 1;
1008 				ivci.subresourceRange.baseArrayLayer = 0;
1009 				ivci.subresourceRange.layerCount     = 1;
1010 
1011 				result = vkCreateImageView(m_device, &ivci, m_allocatorCb, &m_backBufferColorImageView[ii]);
1012 
1013 				if (VK_SUCCESS != result)
1014 				{
1015 					BX_TRACE("Create swapchain error: vkCreateImageView failed %d: %s.", result, getName(result));
1016 					return result;
1017 				}
1018 
1019 				m_backBufferColorImageLayout[ii] = VK_IMAGE_LAYOUT_UNDEFINED;
1020 			}
1021 
1022 			m_needToRefreshSwapchain = false;
1023 
1024 			return result;
1025 		}
1026 
releaseSwapchainbgfx::vk::RendererContextVK1027 		void releaseSwapchain()
1028 		{
1029 			VK_CHECK(vkDeviceWaitIdle(m_device) );
1030 			vkFreeMemory(m_device, m_backBufferDepthStencilMemory, m_allocatorCb);
1031 			vkDestroy(m_backBufferDepthStencilImageView);
1032 			vkDestroy(m_backBufferDepthStencilImage);
1033 			for (uint32_t ii = 0; ii < BX_COUNTOF(m_backBufferColorImageView); ++ii)
1034 			{
1035 				vkDestroy(m_backBufferColorImageView[ii]);
1036 				m_backBufferColorImageLayout[ii] = VK_IMAGE_LAYOUT_UNDEFINED;
1037 			}
1038 			vkDestroy(m_swapchain);
1039 		}
1040 
createSwapchainFramebufferbgfx::vk::RendererContextVK1041 		VkResult createSwapchainFramebuffer()
1042 		{
1043 			VkResult result = VK_SUCCESS;
1044 			for (uint32_t ii = 0; ii < m_numSwapchainImages; ++ii)
1045 			{
1046 				::VkImageView attachments[] =
1047 				{
1048 					m_backBufferColorImageView[ii],
1049 					m_backBufferDepthStencilImageView,
1050 				};
1051 
1052 				VkFramebufferCreateInfo fci;
1053 				fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
1054 				fci.pNext = NULL;
1055 				fci.flags = 0;
1056 				fci.renderPass = m_renderPass;
1057 				fci.attachmentCount = BX_COUNTOF(attachments);
1058 				fci.pAttachments = attachments;
1059 				fci.width = m_sci.imageExtent.width;
1060 				fci.height = m_sci.imageExtent.height;
1061 				fci.layers = 1;
1062 
1063 				result = vkCreateFramebuffer(m_device, &fci, m_allocatorCb, &m_backBufferColor[ii]);
1064 
1065 				if (VK_SUCCESS != result)
1066 				{
1067 					return result;
1068 				}
1069 			}
1070 			return result;
1071 		}
1072 
releaseSwapchainFramebufferbgfx::vk::RendererContextVK1073 		void releaseSwapchainFramebuffer()
1074 		{
1075 			for (uint32_t ii = 0; ii < BX_COUNTOF(m_backBufferColorImageView); ++ii)
1076 			{
1077 				vkDestroy(m_backBufferColor[ii]);
1078 			}
1079 		}
1080 
initSwapchainImageLayoutbgfx::vk::RendererContextVK1081 		void initSwapchainImageLayout()
1082 		{
1083 			VkCommandBuffer commandBuffer = beginNewCommand();
1084 
1085 			setImageMemoryBarrier(
1086 				  commandBuffer
1087 				, m_backBufferDepthStencilImage
1088 				, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT
1089 				, VK_IMAGE_LAYOUT_UNDEFINED
1090 				, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
1091 				, 1
1092 				, 1
1093 				);
1094 
1095 			m_backBufferColorIdx = 0;
1096 			submitCommandAndWait(commandBuffer);
1097 		}
1098 
initbgfx::vk::RendererContextVK1099 		bool init(const Init& _init)
1100 		{
1101 			BX_UNUSED(s_checkMsaa, s_textureAddress);
1102 
1103 			struct ErrorState
1104 			{
1105 				enum Enum
1106 				{
1107 					Default,
1108 					LoadedVulkan1,
1109 					InstanceCreated,
1110 					DeviceCreated,
1111 					SurfaceCreated,
1112 					SwapchainCreated,
1113 					RenderPassCreated,
1114 					FrameBufferCreated,
1115 					CommandBuffersCreated,
1116 					DescriptorCreated,
1117 				};
1118 			};
1119 
1120 			ErrorState::Enum errorState = ErrorState::Default;
1121 
1122 			m_fbh.idx = kInvalidHandle;
1123 			bx::memSet(m_uniforms, 0, sizeof(m_uniforms) );
1124 			bx::memSet(&m_resolution, 0, sizeof(m_resolution) );
1125 
1126 			bool imported = true;
1127 			VkResult result;
1128 			m_qfiGraphics = UINT32_MAX;
1129 			m_qfiCompute  = UINT32_MAX;
1130 
1131 			if (_init.debug
1132 			||  _init.profile)
1133 			{
1134 				m_renderDocDll = loadRenderDoc();
1135 			}
1136 
1137 			m_vulkan1Dll = bx::dlopen(
1138 #if BX_PLATFORM_WINDOWS
1139 					"vulkan-1.dll"
1140 #elif BX_PLATFORM_ANDROID
1141 					"libvulkan.so"
1142 #elif BX_PLATFORM_OSX
1143 					"libvulkan.dylib"
1144 #else
1145 					"libvulkan.so.1"
1146 #endif // BX_PLATFORM_*
1147 					);
1148 
1149 			if (NULL == m_vulkan1Dll)
1150 			{
1151 				BX_TRACE("Init error: Failed to load vulkan dynamic library.");
1152 				goto error;
1153 			}
1154 
1155 			errorState = ErrorState::LoadedVulkan1;
1156 
1157 			BX_TRACE("Shared library functions:");
1158 #define VK_IMPORT_FUNC(_optional, _func)                  \
1159 	_func = (PFN_##_func)bx::dlsym(m_vulkan1Dll, #_func); \
1160 	BX_TRACE("\t%p " #_func, _func);                      \
1161 	imported &= _optional || NULL != _func
1162 VK_IMPORT
1163 #undef VK_IMPORT_FUNC
1164 
1165 			if (!imported)
1166 			{
1167 				BX_TRACE("Init error: Failed to load shared library functions.");
1168 				goto error;
1169 			}
1170 
1171 			{
1172 				dumpExtensions();
1173 
1174 				VkApplicationInfo appInfo;
1175 				appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
1176 				appInfo.pNext = NULL;
1177 				appInfo.pApplicationName   = "bgfx";
1178 				appInfo.applicationVersion = BGFX_API_VERSION;
1179 				appInfo.pEngineName   = "bgfx";
1180 				appInfo.engineVersion = BGFX_API_VERSION;
1181 				appInfo.apiVersion    = VK_MAKE_VERSION(1, 0, 0); //VK_HEADER_VERSION);
1182 
1183 				const char* enabledLayerNames[] =
1184 				{
1185 #if BGFX_CONFIG_DEBUG
1186 //					"VK_LAYER_GOOGLE_threading",
1187 //					"VK_LAYER_GOOGLE_unique_objects",
1188 //					"VK_LAYER_LUNARG_device_limits",
1189 					"VK_LAYER_LUNARG_standard_validation",
1190 //					"VK_LAYER_LUNARG_image",
1191 //					"VK_LAYER_LUNARG_mem_tracker",
1192 //					"VK_LAYER_LUNARG_core_validation",
1193 //					"VK_LAYER_LUNARG_object_tracker",
1194 //					"VK_LAYER_LUNARG_parameter_validation",
1195 //					"VK_LAYER_LUNARG_swapchain",
1196 //					"VK_LAYER_LUNARG_vktrace",
1197 //					"VK_LAYER_RENDERDOC_Capture",
1198 #endif // BGFX_CONFIG_DEBUG
1199 					/*not used*/ ""
1200 				};
1201 
1202 				uint32_t numEnabledExtensions = 2;
1203 
1204 				const char* enabledExtension[Extension::Count + 2] =
1205 				{
1206 					VK_KHR_SURFACE_EXTENSION_NAME,
1207 					KHR_SURFACE_EXTENSION_NAME,
1208 				};
1209 
1210 				for (uint32_t ii = 0; ii < Extension::Count; ++ii)
1211 				{
1212 					const Extension& extension = s_extension[ii];
1213 
1214 					if (extension.m_supported
1215 					&&  extension.m_initialize
1216 					&&  extension.m_instanceExt)
1217 					{
1218 						enabledExtension[numEnabledExtensions++] = extension.m_name;
1219 						BX_TRACE("%d: %s", numEnabledExtensions, extension.m_name);
1220 					}
1221 				}
1222 
1223 				VkInstanceCreateInfo ici;
1224 				ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
1225 				ici.pNext = NULL;
1226 				ici.flags = 0;
1227 				ici.pApplicationInfo = &appInfo;
1228 				ici.enabledLayerCount   = BX_COUNTOF(enabledLayerNames) - 1;
1229 				ici.ppEnabledLayerNames = enabledLayerNames;
1230 				ici.enabledExtensionCount   = numEnabledExtensions;
1231 				ici.ppEnabledExtensionNames = enabledExtension;
1232 
1233 				if (BX_ENABLED(BGFX_CONFIG_DEBUG) )
1234 				{
1235 					m_allocatorCb = &s_allocationCb;
1236 					BX_UNUSED(s_allocationCb);
1237 				}
1238 
1239 				result = vkCreateInstance(&ici
1240 						, m_allocatorCb
1241 						, &m_instance
1242 						);
1243 			}
1244 
1245 			if (VK_SUCCESS != result)
1246 			{
1247 				BX_TRACE("Init error: vkCreateInstance failed %d: %s.", result, getName(result) );
1248 				goto error;
1249 			}
1250 
1251 			errorState = ErrorState::InstanceCreated;
1252 
1253 			BX_TRACE("Instance functions:");
1254 
1255 #define VK_IMPORT_INSTANCE_FUNC(_optional, _func)                           \
1256 			_func = (PFN_##_func)vkGetInstanceProcAddr(m_instance, #_func); \
1257 			BX_TRACE("\t%p " #_func, _func);                                \
1258 			imported &= _optional || NULL != _func
1259 VK_IMPORT_INSTANCE
1260 #undef VK_IMPORT_INSTANCE_FUNC
1261 
1262 			if (!imported)
1263 			{
1264 				BX_TRACE("Init error: Failed to load instance functions.");
1265 				goto error;
1266 			}
1267 
1268 			m_debugReportCallback = VK_NULL_HANDLE;
1269 
1270 			if (s_extension[Extension::EXT_debug_report].m_supported)
1271 			{
1272 				VkDebugReportCallbackCreateInfoEXT drcb;
1273 				drcb.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
1274 				drcb.pNext = NULL;
1275 				drcb.pfnCallback = debugReportCb;
1276 				drcb.pUserData   = NULL;
1277 				drcb.flags       = 0
1278 					| VK_DEBUG_REPORT_ERROR_BIT_EXT
1279 					| VK_DEBUG_REPORT_WARNING_BIT_EXT
1280 					;
1281 				result = vkCreateDebugReportCallbackEXT(m_instance
1282 					, &drcb
1283 					, m_allocatorCb
1284 					, &m_debugReportCallback
1285 					);
1286 				BX_WARN(VK_SUCCESS == result, "vkCreateDebugReportCallbackEXT failed %d: %s.", result, getName(result) );
1287 			}
1288 
1289 			{
1290 				BX_TRACE("---");
1291 
1292 				uint32_t numPhysicalDevices;
1293 				result = vkEnumeratePhysicalDevices(m_instance
1294 					, &numPhysicalDevices
1295 					, NULL
1296 					);
1297 
1298 				if (VK_SUCCESS != result)
1299 				{
1300 					BX_TRACE("Init error: vkEnumeratePhysicalDevices failed %d: %s.", result, getName(result) );
1301 					goto error;
1302 				}
1303 
1304 				VkPhysicalDevice physicalDevices[4];
1305 				numPhysicalDevices = bx::min<uint32_t>(numPhysicalDevices, BX_COUNTOF(physicalDevices) );
1306 				result = vkEnumeratePhysicalDevices(m_instance
1307 					, &numPhysicalDevices
1308 					, physicalDevices
1309 					);
1310 
1311 				if (VK_SUCCESS != result)
1312 				{
1313 					BX_TRACE("Init error: vkEnumeratePhysicalDevices failed %d: %s.", result, getName(result) );
1314 					goto error;
1315 				}
1316 
1317 				m_physicalDevice = VK_NULL_HANDLE;
1318 
1319 				for (uint32_t ii = 0; ii < numPhysicalDevices; ++ii)
1320 				{
1321 					VkPhysicalDeviceProperties pdp;
1322 					vkGetPhysicalDeviceProperties(physicalDevices[ii], &pdp);
1323 					BX_TRACE("Physical device %d:", ii);
1324 					BX_TRACE("\t          Name: %s", pdp.deviceName);
1325 					BX_TRACE("\t   API version: %x", pdp.apiVersion);
1326 					BX_TRACE("\tDriver version: %x", pdp.driverVersion);
1327 					BX_TRACE("\t      VendorId: %x", pdp.vendorID);
1328 					BX_TRACE("\t      DeviceId: %x", pdp.deviceID);
1329 					BX_TRACE("\t          Type: %d", pdp.deviceType);
1330 
1331 					g_caps.gpu[ii].vendorId = uint16_t(pdp.vendorID);
1332 					g_caps.gpu[ii].deviceId = uint16_t(pdp.deviceID);
1333 					++g_caps.numGPUs;
1334 
1335 					if ( (BGFX_PCI_ID_NONE != g_caps.vendorId ||            0 != g_caps.deviceId)
1336 					&&   (BGFX_PCI_ID_NONE == g_caps.vendorId || pdp.vendorID == g_caps.vendorId)
1337 					&&   (0 == g_caps.deviceId                || pdp.deviceID == g_caps.deviceId) )
1338 					{
1339 						m_physicalDevice = physicalDevices[ii];
1340 					}
1341 
1342 					VkPhysicalDeviceMemoryProperties pdmp;
1343 					vkGetPhysicalDeviceMemoryProperties(physicalDevices[ii], &pdmp);
1344 
1345 					BX_TRACE("\tMemory type count: %d", pdmp.memoryTypeCount);
1346 					for (uint32_t jj = 0; jj < pdmp.memoryTypeCount; ++jj)
1347 					{
1348 						BX_TRACE("\t%3d: flags 0x%08x, index %d"
1349 								, jj
1350 								, pdmp.memoryTypes[jj].propertyFlags
1351 								, pdmp.memoryTypes[jj].heapIndex
1352 								);
1353 					}
1354 
1355 					BX_TRACE("\tMemory heap count: %d", pdmp.memoryHeapCount);
1356 					for (uint32_t jj = 0; jj < pdmp.memoryHeapCount; ++jj)
1357 					{
1358 						char size[16];
1359 						bx::prettify(size, BX_COUNTOF(size), pdmp.memoryHeaps[jj].size);
1360 						BX_TRACE("\t%3d: flags 0x%08x, size %10s"
1361 								, jj
1362 								, pdmp.memoryHeaps[jj].flags
1363 								, size
1364 								);
1365 					}
1366 
1367 					dumpExtensions(physicalDevices[ii]);
1368 				}
1369 
1370 				if (VK_NULL_HANDLE == m_physicalDevice)
1371 				{
1372 					m_physicalDevice = physicalDevices[0];
1373 				}
1374 
1375 				vkGetPhysicalDeviceProperties(m_physicalDevice, &m_deviceProperties);
1376 				g_caps.vendorId = uint16_t(m_deviceProperties.vendorID);
1377 				g_caps.deviceId = uint16_t(m_deviceProperties.deviceID);
1378 
1379 				g_caps.supported |= ( 0
1380 					| BGFX_CAPS_ALPHA_TO_COVERAGE
1381 					| BGFX_CAPS_BLEND_INDEPENDENT
1382 					| BGFX_CAPS_COMPUTE
1383 					| BGFX_CAPS_DRAW_INDIRECT
1384 					| BGFX_CAPS_FRAGMENT_DEPTH
1385 					| BGFX_CAPS_INSTANCING
1386 					| BGFX_CAPS_TEXTURE_3D
1387 					| BGFX_CAPS_TEXTURE_BLIT
1388 					| BGFX_CAPS_TEXTURE_COMPARE_ALL
1389 					| BGFX_CAPS_VERTEX_ATTRIB_HALF
1390 					| BGFX_CAPS_VERTEX_ATTRIB_UINT10
1391 					| BGFX_CAPS_VERTEX_ID
1392 					);
1393 				g_caps.limits.maxTextureSize     = m_deviceProperties.limits.maxImageDimension2D;
1394 				g_caps.limits.maxFBAttachments   = bx::min(uint8_t(m_deviceProperties.limits.maxFragmentOutputAttachments), uint8_t(BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) );
1395 				g_caps.limits.maxComputeBindings = BGFX_MAX_COMPUTE_BINDINGS;
1396 				g_caps.limits.maxVertexStreams   = BGFX_CONFIG_MAX_VERTEX_STREAMS;
1397 
1398 				vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_deviceFeatures);
1399 				m_deviceFeatures.robustBufferAccess = VK_FALSE;
1400 
1401 				{
1402 					struct ImageTest
1403 					{
1404 						VkImageType type;
1405 						VkImageUsageFlags usage;
1406 						VkImageCreateFlags flags;
1407 						uint32_t formatCaps[2];
1408 					};
1409 
1410 					const ImageTest imageTest[] =
1411 					{
1412 						{ VK_IMAGE_TYPE_2D, VK_IMAGE_USAGE_SAMPLED_BIT,          0,                                   { BGFX_CAPS_FORMAT_TEXTURE_2D,          BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB     } },
1413 						{ VK_IMAGE_TYPE_3D, VK_IMAGE_USAGE_SAMPLED_BIT,          0,                                   { BGFX_CAPS_FORMAT_TEXTURE_3D,          BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB     } },
1414 						{ VK_IMAGE_TYPE_2D, VK_IMAGE_USAGE_SAMPLED_BIT,          VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, { BGFX_CAPS_FORMAT_TEXTURE_CUBE,        BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB   } },
1415 						{ VK_IMAGE_TYPE_2D, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0,                                   { BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER, BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER } },
1416 						{ VK_IMAGE_TYPE_2D, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0,                           { BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER, BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER } },
1417 					};
1418 
1419 					for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii)
1420 					{
1421 						uint16_t support = BGFX_CAPS_FORMAT_TEXTURE_NONE;
1422 
1423 						const bool depth = bimg::isDepth(bimg::TextureFormat::Enum(ii) );
1424 						VkFormat fmt = depth
1425 							? s_textureFormat[ii].m_fmtDsv
1426 							: s_textureFormat[ii].m_fmt
1427 							;
1428 
1429 						for (uint32_t jj = 0, num = depth ? 1 : 2; jj < num; ++jj)
1430 						{
1431 							if (VK_FORMAT_UNDEFINED != fmt)
1432 							{
1433 								for (uint32_t test = 0; test < BX_COUNTOF(imageTest); ++test)
1434 								{
1435 									const ImageTest& it = imageTest[test];
1436 
1437 									VkImageFormatProperties ifp;
1438 									result = vkGetPhysicalDeviceImageFormatProperties(m_physicalDevice
1439 										, fmt
1440 										, it.type
1441 										, VK_IMAGE_TILING_OPTIMAL
1442 										, it.usage
1443 										, it.flags
1444 										, &ifp
1445 										);
1446 
1447 									if (VK_SUCCESS == result)
1448 									{
1449 										support |= it.formatCaps[jj];
1450 										if (VK_SAMPLE_COUNT_1_BIT < ifp.sampleCounts)
1451 										{
1452 											support |= BGFX_CAPS_FORMAT_TEXTURE_MSAA;
1453 										}
1454 									}
1455 								}
1456 							}
1457 
1458 							fmt = s_textureFormat[ii].m_fmtSrgb;
1459 						}
1460 
1461 						g_caps.formats[ii] = support;
1462 					}
1463 				}
1464 
1465 				vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &m_memoryProperties);
1466 			}
1467 
1468 			{
1469 				BX_TRACE("---");
1470 
1471 				uint32_t queueFamilyPropertyCount = 0;
1472 				vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice
1473 					, &queueFamilyPropertyCount
1474 					, NULL
1475 					);
1476 
1477 				VkQueueFamilyProperties queueFamilyPropertices[10];
1478 				queueFamilyPropertyCount = bx::min<uint32_t>(queueFamilyPropertyCount, BX_COUNTOF(queueFamilyPropertices) );
1479 				vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice
1480 					, &queueFamilyPropertyCount
1481 					, queueFamilyPropertices
1482 					);
1483 
1484 				for (uint32_t ii = 0; ii < queueFamilyPropertyCount; ++ii)
1485 				{
1486 					const VkQueueFamilyProperties& qfp = queueFamilyPropertices[ii];
1487 					BX_UNUSED(qfp);
1488 					BX_TRACE("Queue family property %d:", ii);
1489 					BX_TRACE("\t  Queue flags: 0x%08x", qfp.queueFlags);
1490 					BX_TRACE("\t  Queue count: %d", qfp.queueCount);
1491 					BX_TRACE("\tTS valid bits: 0x%08x", qfp.timestampValidBits);
1492 					BX_TRACE("\t    Min image: %d x %d x %d"
1493 							, qfp.minImageTransferGranularity.width
1494 							, qfp.minImageTransferGranularity.height
1495 							, qfp.minImageTransferGranularity.depth
1496 							);
1497 				}
1498 
1499 				for (uint32_t ii = 0; ii < queueFamilyPropertyCount; ++ii)
1500 				{
1501 					const VkQueueFamilyProperties& qfp = queueFamilyPropertices[ii];
1502 					if (UINT32_MAX == m_qfiGraphics
1503 					&&  VK_QUEUE_GRAPHICS_BIT & qfp.queueFlags)
1504 					{
1505 						m_qfiGraphics = ii;
1506 					}
1507 
1508 					if (UINT32_MAX == m_qfiCompute
1509 					&&  VK_QUEUE_COMPUTE_BIT & qfp.queueFlags)
1510 					{
1511 						m_qfiCompute = ii;
1512 					}
1513 
1514 					if (UINT32_MAX != m_qfiGraphics
1515 					&&  UINT32_MAX != m_qfiCompute)
1516 					{
1517 						break;
1518 					}
1519 				}
1520 
1521 				if (UINT32_MAX == m_qfiGraphics)
1522 				{
1523 					BX_TRACE("Init error: Unable to find graphics queue.");
1524 					goto error;
1525 				}
1526 			}
1527 
1528 			if (m_qfiCompute != UINT32_MAX)
1529 			{
1530 				g_caps.supported |= BGFX_CAPS_COMPUTE;
1531 			}
1532 
1533 			{
1534 				const char* enabledLayerNames[] =
1535 				{
1536 #if BGFX_CONFIG_DEBUG
1537 					"VK_LAYER_GOOGLE_threading",
1538 //					"VK_LAYER_GOOGLE_unique_objects",
1539 					"VK_LAYER_LUNARG_device_limits",
1540 //					"VK_LAYER_LUNARG_standard_validation",
1541 					"VK_LAYER_LUNARG_image",
1542 					"VK_LAYER_LUNARG_object_tracker",
1543 					"VK_LAYER_LUNARG_parameter_validation",
1544 					"VK_LAYER_LUNARG_swapchain",
1545 //					"VK_LAYER_LUNARG_vktrace",
1546 //					"VK_LAYER_RENDERDOC_Capture",
1547 #endif // BGFX_CONFIG_DEBUG
1548 					/*not used*/ ""
1549 				};
1550 
1551 				uint32_t numEnabledExtensions = 1;
1552 
1553 				const char* enabledExtension[Extension::Count + 1] =
1554 				{
1555 					VK_KHR_SWAPCHAIN_EXTENSION_NAME,
1556 				};
1557 
1558 				for (uint32_t ii = 0; ii < Extension::Count; ++ii)
1559 				{
1560 					const Extension& extension = s_extension[ii];
1561 
1562 					if (extension.m_supported
1563 					&&  extension.m_initialize
1564 					&& !extension.m_instanceExt)
1565 					{
1566 						enabledExtension[numEnabledExtensions++] = extension.m_name;
1567 						BX_TRACE("%d: %s", numEnabledExtensions, extension.m_name);
1568 					}
1569 				}
1570 
1571 				float queuePriorities[1] = { 0.0f };
1572 				VkDeviceQueueCreateInfo dcqi;
1573 				dcqi.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
1574 				dcqi.pNext = NULL;
1575 				dcqi.flags = 0;
1576 				dcqi.queueFamilyIndex = m_qfiGraphics;
1577 				dcqi.queueCount       = 1;
1578 				dcqi.pQueuePriorities = queuePriorities;
1579 
1580 				VkDeviceCreateInfo dci;
1581 				dci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
1582 				dci.pNext = NULL;
1583 				dci.flags = 0;
1584 				dci.queueCreateInfoCount = 1;
1585 				dci.pQueueCreateInfos    = &dcqi;
1586 				dci.enabledLayerCount    = BX_COUNTOF(enabledLayerNames) - 1;
1587 				dci.ppEnabledLayerNames  = enabledLayerNames;
1588 				dci.enabledExtensionCount   = numEnabledExtensions;
1589 				dci.ppEnabledExtensionNames = enabledExtension;
1590 				dci.pEnabledFeatures = &m_deviceFeatures;
1591 
1592 				result = vkCreateDevice(
1593 					  m_physicalDevice
1594 					, &dci
1595 					, m_allocatorCb
1596 					, &m_device
1597 					);
1598 
1599 				if (VK_SUCCESS != result)
1600 				{
1601 					BX_TRACE("Init error: vkCreateDevice failed %d: %s.", result, getName(result) );
1602 					goto error;
1603 				}
1604 			}
1605 
1606 			errorState = ErrorState::DeviceCreated;
1607 
1608 			BX_TRACE("Device functions:");
1609 #define VK_IMPORT_DEVICE_FUNC(_optional, _func)                         \
1610 			_func = (PFN_##_func)vkGetDeviceProcAddr(m_device, #_func); \
1611 			BX_TRACE("\t%p " #_func, _func);                            \
1612 			imported &= _optional || NULL != _func
1613 VK_IMPORT_DEVICE
1614 #undef VK_IMPORT_DEVICE_FUNC
1615 
1616 			if (!imported)
1617 			{
1618 				BX_TRACE("Init error: Failed to load device functions.");
1619 				goto error;
1620 			}
1621 
1622 			vkGetDeviceQueue(m_device, m_qfiGraphics, 0, &m_queueGraphics);
1623 			vkGetDeviceQueue(m_device, m_qfiCompute,  0, &m_queueCompute);
1624 
1625 #if BX_PLATFORM_WINDOWS
1626 			{
1627 				VkWin32SurfaceCreateInfoKHR sci;
1628 				sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
1629 				sci.pNext = NULL;
1630 				sci.flags     = 0;
1631 				sci.hinstance = (HINSTANCE)GetModuleHandle(NULL);
1632 				sci.hwnd      = (HWND)g_platformData.nwh;
1633 				result = vkCreateWin32SurfaceKHR(m_instance, &sci, m_allocatorCb, &m_surface);
1634 			}
1635 #elif BX_PLATFORM_ANDROID
1636 			{
1637 				VkAndroidSurfaceCreateInfoKHR sci;
1638 				sci.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
1639 				sci.pNext = NULL;
1640 				sci.flags = 0;
1641 				sci.window = (ANativeWindow*)g_platformData.nwh;
1642 				result = vkCreateAndroidSurfaceKHR(m_instance, &sci, m_allocatorCb, &m_surface);
1643 			}
1644 #elif BX_PLATFORM_LINUX
1645 			{
1646 				if (NULL != vkCreateXlibSurfaceKHR)
1647 				{
1648 					VkXlibSurfaceCreateInfoKHR sci;
1649 					sci.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
1650 					sci.pNext = NULL;
1651 					sci.flags  = 0;
1652 					sci.dpy    = (Display*)g_platformData.ndt;
1653 					sci.window = (Window)g_platformData.nwh;
1654 					result = vkCreateXlibSurfaceKHR(m_instance, &sci, m_allocatorCb, &m_surface);
1655 				}
1656 				else
1657 				{
1658 					result = VK_RESULT_MAX_ENUM;
1659 				}
1660 
1661 				if (VK_SUCCESS != result)
1662 				{
1663 					void* xcbdll = bx::dlopen("libX11-xcb.so.1");
1664 					if (NULL != xcbdll)
1665 					{
1666 						typedef xcb_connection_t* (*PFN_XGETXCBCONNECTION)(Display*);
1667 						PFN_XGETXCBCONNECTION XGetXCBConnection = (PFN_XGETXCBCONNECTION)bx::dlsym(xcbdll, "XGetXCBConnection");
1668 
1669 						VkXcbSurfaceCreateInfoKHR sci;
1670 						sci.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
1671 						sci.pNext = NULL;
1672 						sci.flags      = 0;
1673 						sci.connection = XGetXCBConnection( (Display*)g_platformData.ndt);
1674 						union { void* ptr; xcb_window_t window; } cast = { g_platformData.nwh };
1675 						sci.window = cast.window;
1676 						result = vkCreateXcbSurfaceKHR(m_instance, &sci, m_allocatorCb, &m_surface);
1677 
1678 						bx::dlclose(xcbdll);
1679 					}
1680 				}
1681 			}
1682 #elif BX_PLATFORM_OSX
1683 			{
1684 				if (NULL != vkCreateMacOSSurfaceMVK)
1685 				{
1686 					NSWindow* window = (NSWindow*)(g_platformData.nwh);
1687 					NSView* contentView = (NSView*)window.contentView;
1688 					CAMetalLayer* layer = [CAMetalLayer layer];
1689 					if (_init.resolution.reset & BGFX_RESET_HIDPI)
1690 						layer.contentsScale = [window backingScaleFactor];
1691 					[contentView setWantsLayer : YES] ;
1692 					[contentView setLayer : layer] ;
1693 
1694 					VkMacOSSurfaceCreateInfoMVK sci;
1695 					sci.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
1696 					sci.pNext = NULL;
1697 					sci.flags = 0;
1698 					sci.pView = (__bridge void*)layer;
1699 					result = vkCreateMacOSSurfaceMVK(m_instance, &sci, m_allocatorCb, &m_surface);
1700 				}
1701 			}
1702 #else
1703 #	error "Figure out KHR surface..."
1704 #endif // BX_PLATFORM_
1705 
1706 			if (VK_SUCCESS != result)
1707 			{
1708 				BX_TRACE("Init error: vkCreateSurfaceKHR failed %d: %s.", result, getName(result) );
1709 				goto error;
1710 			}
1711 
1712 			errorState = ErrorState::SurfaceCreated;
1713 
1714 			{
1715 				VkBool32 surfaceSupported;
1716 				result = vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, m_qfiGraphics, m_surface, &surfaceSupported);
1717 
1718 				if (VK_SUCCESS != result)
1719 				{
1720 					BX_TRACE("Init error: vkGetPhysicalDeviceSurfaceSupportKHR failed %d: %s.", result, getName(result) );
1721 					goto error;
1722 				}
1723 
1724 				VkSurfaceCapabilitiesKHR surfaceCapabilities;
1725 				result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &surfaceCapabilities);
1726 
1727 				if (VK_SUCCESS != result)
1728 				{
1729 					BX_TRACE("Init error: vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed %d: %s.", result, getName(result) );
1730 					goto error;
1731 				}
1732 
1733 				uint32_t width = bx::clamp<uint32_t>(
1734 					  _init.resolution.width
1735 					, surfaceCapabilities.minImageExtent.width
1736 					, surfaceCapabilities.maxImageExtent.width
1737 					);
1738 				uint32_t height = bx::clamp<uint32_t>(
1739 					  _init.resolution.height
1740 					, surfaceCapabilities.minImageExtent.height
1741 					, surfaceCapabilities.maxImageExtent.height
1742 					);
1743 
1744 				uint32_t numSurfaceFormats;
1745 				result = vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &numSurfaceFormats, NULL);
1746 
1747 				if (VK_SUCCESS != result)
1748 				{
1749 					BX_TRACE("Init error: vkGetPhysicalDeviceSurfaceFormatsKHR failed %d: %s.", result, getName(result) );
1750 					goto error;
1751 				}
1752 
1753 				VkSurfaceFormatKHR surfaceFormats[10];
1754 				numSurfaceFormats = bx::min<uint32_t>(numSurfaceFormats, BX_COUNTOF(surfaceFormats) );
1755 				vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &numSurfaceFormats, surfaceFormats);
1756 
1757 				// find the best match...
1758 				VkFormat preferredSurfaceFormat[4] =
1759 				{
1760 					VK_FORMAT_R8G8B8A8_UNORM,
1761 					VK_FORMAT_B8G8R8A8_UNORM,
1762 					VK_FORMAT_R8G8B8A8_SRGB,
1763 					VK_FORMAT_B8G8R8A8_SRGB,
1764 				};
1765 
1766 				uint32_t surfaceFormatIdx = numSurfaceFormats;
1767 
1768 				for (uint32_t jj = 0; jj < BX_COUNTOF(preferredSurfaceFormat); jj++)
1769 				{
1770 					for (uint32_t ii = 0; ii < numSurfaceFormats; ii++)
1771 					{
1772 						BX_TRACE("Supported surface format: %d", surfaceFormats[ii].format);
1773 						if (preferredSurfaceFormat[jj] == surfaceFormats[ii].format)
1774 						{
1775 							surfaceFormatIdx = ii;
1776 							break;
1777 						}
1778 					}
1779 
1780 					if (surfaceFormatIdx < numSurfaceFormats)
1781 					{ // found
1782 						BX_TRACE("Preferred surface format found: %d", surfaceFormats[surfaceFormatIdx].format);
1783 						break;
1784 					}
1785 				}
1786 
1787 				BX_CHECK(surfaceFormatIdx < numSurfaceFormats, "cannot found preferred surface format from supported surface format");
1788 
1789 				uint32_t numPresentModes;
1790 				result = vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &numPresentModes, NULL);
1791 				if (VK_SUCCESS != result)
1792 				{
1793 					BX_TRACE("Init error: vkGetPhysicalDeviceSurfacePresentModesKHR failed %d: %s.", result, getName(result) );
1794 					goto error;
1795 				}
1796 
1797 				VkPresentModeKHR presentModes[10];
1798 				numPresentModes = bx::min<uint32_t>(numPresentModes, BX_COUNTOF(presentModes) );
1799 				vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &numPresentModes, presentModes);
1800 
1801 				// find the best match...
1802 				uint32_t presentModeIdx = numPresentModes;
1803 				VkPresentModeKHR preferredPresentMode[] = {
1804 					VK_PRESENT_MODE_FIFO_KHR,
1805 					VK_PRESENT_MODE_FIFO_RELAXED_KHR,
1806 					VK_PRESENT_MODE_MAILBOX_KHR,
1807 					VK_PRESENT_MODE_IMMEDIATE_KHR,
1808 				};
1809 				for (uint32_t ii = 0; ii < BX_COUNTOF(preferredPresentMode); ++ii)
1810 				{
1811 					for (uint32_t jj = 0; jj < numPresentModes; ++jj)
1812 					{
1813 						if (presentModes[jj] == preferredPresentMode[ii])
1814 						{
1815 							presentModeIdx = jj;
1816 							BX_TRACE("present mode: %d", (int)preferredPresentMode[ii]);
1817 							break;
1818 						}
1819 					}
1820 					if (presentModeIdx < numPresentModes)
1821 					{
1822 						break;
1823 					}
1824 				}
1825 				if (presentModeIdx == numPresentModes)
1826 				{
1827 					presentModeIdx = 0;
1828 				}
1829 
1830 				m_backBufferDepthStencilFormat = 0 != (g_caps.formats[TextureFormat::D24S8] & BGFX_CAPS_FORMAT_TEXTURE_2D)
1831 					? VK_FORMAT_D24_UNORM_S8_UINT
1832 					: VK_FORMAT_D32_SFLOAT_S8_UINT
1833 					;
1834 
1835 				VkCompositeAlphaFlagBitsKHR compositeAlpha = (VkCompositeAlphaFlagBitsKHR)0;
1836 				if (surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
1837 				{
1838 					compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
1839 				}
1840 				else if (surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
1841 				{
1842 					compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
1843 				}
1844 				else if (surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
1845 				{
1846 					compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
1847 				}
1848 				else if (surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
1849 				{
1850 					compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
1851 				}
1852 
1853 				m_sci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
1854 				m_sci.pNext = NULL;
1855 				m_sci.flags = 0;
1856 				m_sci.surface = m_surface;
1857 				m_sci.minImageCount   = 2;
1858 				m_sci.imageFormat     = surfaceFormats[surfaceFormatIdx].format;
1859 				m_sci.imageColorSpace = surfaceFormats[surfaceFormatIdx].colorSpace;
1860 				m_sci.imageExtent.width  = width;
1861 				m_sci.imageExtent.height = height;
1862 				m_sci.imageArrayLayers = 1;
1863 				m_sci.imageUsage       = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1864 				m_sci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
1865 				m_sci.queueFamilyIndexCount = 0;
1866 				m_sci.pQueueFamilyIndices   = NULL;
1867 				m_sci.preTransform   = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
1868 				m_sci.compositeAlpha = compositeAlpha;
1869 				m_sci.presentMode    = presentModes[presentModeIdx];
1870 				m_sci.clipped        = VK_TRUE;
1871 				m_sci.oldSwapchain   = VK_NULL_HANDLE;
1872 
1873 				for (uint32_t ii = 0; ii < BX_COUNTOF(m_backBufferColorImageView); ++ii)
1874 				{
1875 					m_backBufferColorImageView[ii] = VK_NULL_HANDLE;
1876 					m_backBufferColorImage[ii]     = VK_NULL_HANDLE;
1877 					m_backBufferColor[ii]          = VK_NULL_HANDLE;
1878 					m_presentDone[ii]              = VK_NULL_HANDLE;
1879 				}
1880 
1881 				result = createSwapchain();
1882 				if (VK_SUCCESS != result)
1883 				{
1884 					BX_TRACE("Init error: creating swapchain and image view failed %d: %s", result, getName(result));
1885 					goto error;
1886 				}
1887 
1888 				VkSemaphoreCreateInfo sci;
1889 				sci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
1890 				sci.pNext = NULL;
1891 				sci.flags = 0;
1892 
1893 				for (uint32_t ii = 0; ii < m_numSwapchainImages; ++ii)
1894 				{
1895 					result = vkCreateSemaphore(m_device, &sci, m_allocatorCb, &m_presentDone[ii]);
1896 					if (VK_SUCCESS != result)
1897 					{
1898 						BX_TRACE("Init error: vkCreateSemaphore failed %d: %s.", result, getName(result) );
1899 						goto error;
1900 					}
1901 				}
1902 			}
1903 
1904 			errorState = ErrorState::SwapchainCreated;
1905 
1906 			{
1907 				VkAttachmentDescription ad[2];
1908 				ad[0].flags          = 0;
1909 				ad[0].format         = m_sci.imageFormat;
1910 				ad[0].samples        = VK_SAMPLE_COUNT_1_BIT;
1911 				ad[0].loadOp         = VK_ATTACHMENT_LOAD_OP_LOAD;
1912 				ad[0].storeOp        = VK_ATTACHMENT_STORE_OP_STORE;
1913 				ad[0].stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1914 				ad[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1915 				ad[0].initialLayout  = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1916 				ad[0].finalLayout    = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1917 				ad[1].flags          = 0;
1918 				ad[1].format         = m_backBufferDepthStencilFormat;
1919 				ad[1].samples        = VK_SAMPLE_COUNT_1_BIT;
1920 				ad[1].loadOp         = VK_ATTACHMENT_LOAD_OP_LOAD;
1921 				ad[1].storeOp        = VK_ATTACHMENT_STORE_OP_STORE;
1922 				ad[1].stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_LOAD;
1923 				ad[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
1924 				ad[1].initialLayout  = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1925 				ad[1].finalLayout    = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1926 
1927 				VkAttachmentReference colorAr[1];
1928 				colorAr[0].attachment = 0;
1929 				colorAr[0].layout     = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1930 
1931 				VkAttachmentReference resolveAr[1];
1932 				resolveAr[0].attachment = VK_ATTACHMENT_UNUSED;
1933 				resolveAr[0].layout     = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1934 
1935 				VkAttachmentReference depthAr[1];
1936 				depthAr[0].attachment = 1;
1937 				depthAr[0].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1938 
1939 				VkSubpassDescription sd[1];
1940 				sd[0].flags                   = 0;
1941 				sd[0].pipelineBindPoint       = VK_PIPELINE_BIND_POINT_GRAPHICS;
1942 				sd[0].inputAttachmentCount    = 0;
1943 				sd[0].pInputAttachments       = NULL;
1944 				sd[0].colorAttachmentCount    = BX_COUNTOF(colorAr);
1945 				sd[0].pColorAttachments       = colorAr;
1946 				sd[0].pResolveAttachments     = resolveAr;
1947 				sd[0].pDepthStencilAttachment = depthAr;
1948 				sd[0].preserveAttachmentCount = 0;
1949 				sd[0].pPreserveAttachments    = NULL;
1950 
1951 				VkRenderPassCreateInfo rpi;
1952 				rpi.sType           = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1953 				rpi.pNext           = NULL;
1954 				rpi.flags           = 0;
1955 				rpi.attachmentCount = BX_COUNTOF(ad);
1956 				rpi.pAttachments    = ad;
1957 				rpi.subpassCount    = BX_COUNTOF(sd);
1958 				rpi.pSubpasses      = sd;
1959 				rpi.dependencyCount = 0;
1960 				rpi.pDependencies   = NULL;
1961 
1962 				result = vkCreateRenderPass(m_device, &rpi, m_allocatorCb, &m_renderPass);
1963 
1964 				if (VK_SUCCESS != result)
1965 				{
1966 					BX_TRACE("Init error: vkCreateRenderPass failed %d: %s.", result, getName(result));
1967 					goto error;
1968 				}
1969 			}
1970 
1971 			errorState = ErrorState::RenderPassCreated;
1972 
1973 			// framebuffer creation
1974 			result = createSwapchainFramebuffer();
1975 			if (VK_SUCCESS != result)
1976 			{
1977 				BX_TRACE("Init error: vkCreateFramebuffer failed %d: %s.", result, getName(result));
1978 				goto error;
1979 			}
1980 
1981 			errorState = ErrorState::FrameBufferCreated;
1982 
1983 			{
1984 				VkFenceCreateInfo fci;
1985 				fci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
1986 				fci.pNext = NULL;
1987 				fci.flags = 0;
1988 				result = vkCreateFence(m_device, &fci, m_allocatorCb, &m_fence);
1989 
1990 				if (VK_SUCCESS != result)
1991 				{
1992 					BX_TRACE("Init error: vkCreateFence failed %d: %s.", result, getName(result) );
1993 					goto error;
1994 				}
1995 
1996 				VkCommandPoolCreateInfo cpci;
1997 				cpci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
1998 				cpci.pNext = NULL;
1999 				cpci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
2000 				cpci.queueFamilyIndex = m_qfiGraphics;
2001 				result = vkCreateCommandPool(m_device, &cpci, m_allocatorCb, &m_commandPool);
2002 
2003 				if (VK_SUCCESS != result)
2004 				{
2005 					vkDestroy(m_fence);
2006 					BX_TRACE("Init error: vkCreateCommandPool failed %d: %s.", result, getName(result) );
2007 					goto error;
2008 				}
2009 
2010 				VkCommandBufferAllocateInfo cbai;
2011 				cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
2012 				cbai.pNext = NULL;
2013 				cbai.commandPool = m_commandPool;
2014 				cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
2015 				cbai.commandBufferCount = BX_COUNTOF(m_commandBuffers);
2016 
2017 				result = vkAllocateCommandBuffers(m_device, &cbai, m_commandBuffers);
2018 
2019 				if (VK_SUCCESS != result)
2020 				{
2021 					vkDestroy(m_commandPool);
2022 					vkDestroy(m_fence);
2023 					BX_TRACE("Init error: vkAllocateCommandBuffers failed %d: %s.", result, getName(result) );
2024 					goto error;
2025 				}
2026 
2027 				initSwapchainImageLayout();
2028 
2029 //				kick();
2030 //				finishAll();
2031 
2032 				VK_CHECK(vkResetCommandPool(m_device, m_commandPool, 0) );
2033 			}
2034 
2035 			errorState = ErrorState::CommandBuffersCreated;
2036 
2037 			{
2038 				VkDescriptorPoolSize dps[] =
2039 				{
2040 //					{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, (10 * BGFX_CONFIG_MAX_TEXTURE_SAMPLERS) << 10 },
2041 					{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,          (10 * BGFX_CONFIG_MAX_TEXTURE_SAMPLERS) << 10 },
2042 					{ VK_DESCRIPTOR_TYPE_SAMPLER,                (10 * BGFX_CONFIG_MAX_TEXTURE_SAMPLERS) << 10 },
2043 					{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 10<<10                           },
2044 					{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,         BGFX_CONFIG_MAX_TEXTURE_SAMPLERS << 10 },
2045 					{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,          BGFX_CONFIG_MAX_TEXTURE_SAMPLERS << 10 },
2046 				};
2047 
2048 // 				VkDescriptorSetLayoutBinding dslb[] =
2049 // 				{
2050 // //					{ DslBinding::CombinedImageSampler,  VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, VK_SHADER_STAGE_ALL,          NULL },
2051 // 					{ DslBinding::VertexUniformBuffer,   VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,         1,                                VK_SHADER_STAGE_ALL,          NULL },
2052 // 					{ DslBinding::FragmentUniformBuffer, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,         1,                                VK_SHADER_STAGE_FRAGMENT_BIT, NULL },
2053 // //					{ DslBinding::StorageBuffer,         VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,         BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, VK_SHADER_STAGE_ALL,          NULL },
2054 // 				};
2055 
2056 				VkDescriptorPoolCreateInfo dpci;
2057 				dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
2058 				dpci.pNext = NULL;
2059 				dpci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
2060 				dpci.maxSets       = 10<<10;
2061 				dpci.poolSizeCount = BX_COUNTOF(dps);
2062 				dpci.pPoolSizes    = dps;
2063 
2064 				result = vkCreateDescriptorPool(m_device, &dpci, m_allocatorCb, &m_descriptorPool);
2065 
2066 				if (VK_SUCCESS != result)
2067 				{
2068 					BX_TRACE("Init error: vkCreateDescriptorPool failed %d: %s.", result, getName(result) );
2069 					goto error;
2070 				}
2071 
2072 //				VkDescriptorSetLayoutCreateInfo dsl;
2073 //				dsl.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
2074 //				dsl.pNext = NULL;
2075 //				dsl.flags = 0;
2076 //				dsl.bindingCount = BX_COUNTOF(dslb);
2077 //				dsl.pBindings    = dslb;
2078 //				result = vkCreateDescriptorSetLayout(m_device, &dsl, m_allocatorCb, &m_descriptorSetLayout);
2079 //
2080 //				if (VK_SUCCESS != result)
2081 //				{
2082 //					BX_TRACE("Init error: vkCreateDescriptorSetLayout failed %d: %s.", result, getName(result) );
2083 //					goto error;
2084 //				}
2085 //
2086 //				VkPipelineLayoutCreateInfo pl;
2087 //				pl.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
2088 //				pl.pNext = NULL;
2089 //				pl.flags = 0;
2090 //				pl.setLayoutCount = 1;
2091 //				pl.pSetLayouts    = &m_descriptorSetLayout;
2092 //				pl.pushConstantRangeCount = 0;
2093 //				pl.pPushConstantRanges    = NULL;
2094 //				result = vkCreatePipelineLayout(m_device, &pl, m_allocatorCb, &m_pipelineLayout);
2095 //
2096 //				if (VK_SUCCESS != result)
2097 //				{
2098 //					BX_TRACE("Init error: vkCreatePipelineLayout failed %d: %s.", result, getName(result) );
2099 //					goto error;
2100 //				}
2101 
2102 				VkPipelineCacheCreateInfo pcci;
2103 				pcci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
2104 				pcci.pNext = NULL;
2105 				pcci.flags = 0;
2106 				pcci.initialDataSize = 0;
2107 				pcci.pInitialData    = NULL;
2108 				result = vkCreatePipelineCache(m_device, &pcci, m_allocatorCb, &m_pipelineCache);
2109 
2110 				if (VK_SUCCESS != result)
2111 				{
2112 					BX_TRACE("Init error: vkCreatePipelineCache failed %d: %s.", result, getName(result) );
2113 					goto error;
2114 				}
2115 			}
2116 
2117 			for (uint32_t ii = 0; ii < BX_COUNTOF(m_scratchBuffer); ++ii)
2118 			{
2119 				BX_TRACE("Create scratch buffer %d", ii);
2120 				m_scratchBuffer[ii].create(BGFX_CONFIG_MAX_DRAW_CALLS * 128, 1024);
2121 			}
2122 
2123 			errorState = ErrorState::DescriptorCreated;
2124 
2125 			if (NULL == vkSetDebugUtilsObjectNameEXT)
2126 			{
2127 				vkSetDebugUtilsObjectNameEXT = stubSetDebugUtilsObjectNameEXT;
2128 			}
2129 
2130 			if (NULL == vkCmdBeginDebugUtilsLabelEXT
2131 			||  NULL == vkCmdEndDebugUtilsLabelEXT)
2132 			{
2133 				vkCmdBeginDebugUtilsLabelEXT = stubCmdBeginDebugUtilsLabelEXT;
2134 				vkCmdEndDebugUtilsLabelEXT   = stubCmdEndDebugUtilsLabelEXT;
2135 			}
2136 
2137 			if (NULL == vkCmdInsertDebugUtilsLabelEXT)
2138 			{
2139 				vkCmdInsertDebugUtilsLabelEXT = stubCmdInsertDebugUtilsLabelEXT;
2140 			}
2141 
2142 			// Init reserved part of view name.
2143 			for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii)
2144 			{
2145 				bx::snprintf(s_viewName[ii], BGFX_CONFIG_MAX_VIEW_NAME_RESERVED+1, "%3d   ", ii);
2146 			}
2147 
2148 			g_internalData.context = m_device;
2149 			return true;
2150 
2151 		error:
2152 			BX_TRACE("errorState %d", errorState);
2153 			switch (errorState)
2154 			{
2155 			case ErrorState::DescriptorCreated:
2156 				vkDestroy(m_pipelineCache);
2157 //				vkDestroy(m_pipelineLayout);
2158 //				vkDestroy(m_descriptorSetLayout);
2159 				vkDestroy(m_descriptorPool);
2160 				BX_FALLTHROUGH;
2161 
2162 			case ErrorState::CommandBuffersCreated:
2163 				vkFreeCommandBuffers(m_device, m_commandPool, BX_COUNTOF(m_commandBuffers), m_commandBuffers);
2164 				vkDestroy(m_commandPool);
2165 				vkDestroy(m_fence);
2166 				BX_FALLTHROUGH;
2167 
2168 			case ErrorState::FrameBufferCreated:
2169 				releaseSwapchainFramebuffer();
2170 				BX_FALLTHROUGH;
2171 
2172 			case ErrorState::RenderPassCreated:
2173 				vkDestroy(m_renderPass);
2174 				BX_FALLTHROUGH;
2175 
2176 			case ErrorState::SwapchainCreated:
2177 				for (uint32_t ii = 0; ii < BX_COUNTOF(m_backBufferColorImageView); ++ii)
2178 				{
2179 					vkDestroy(m_presentDone[ii]);
2180 				}
2181 				releaseSwapchain();
2182 				BX_FALLTHROUGH;
2183 
2184 			case ErrorState::SurfaceCreated:
2185 				vkDestroySurfaceKHR(m_instance, m_surface, m_allocatorCb);
2186 				BX_FALLTHROUGH;
2187 
2188 			case ErrorState::DeviceCreated:
2189 				vkDestroyDevice(m_device, m_allocatorCb);
2190 				BX_FALLTHROUGH;
2191 
2192 			case ErrorState::InstanceCreated:
2193 				if (VK_NULL_HANDLE != m_debugReportCallback)
2194 				{
2195 					vkDestroyDebugReportCallbackEXT(m_instance, m_debugReportCallback, m_allocatorCb);
2196 				}
2197 
2198 				vkDestroyInstance(m_instance, m_allocatorCb);
2199 				BX_FALLTHROUGH;
2200 
2201 			case ErrorState::LoadedVulkan1:
2202 				bx::dlclose(m_vulkan1Dll);
2203 				m_vulkan1Dll  = NULL;
2204 				m_allocatorCb = NULL;
2205 				unloadRenderDoc(m_renderDocDll);
2206 				BX_FALLTHROUGH;
2207 
2208 			case ErrorState::Default:
2209 				break;
2210 			};
2211 
2212 			BX_CHECK(false, "Failed to initialize Vulkan.");
2213 			return false;
2214 		}
2215 
shutdownbgfx::vk::RendererContextVK2216 		void shutdown()
2217 		{
2218 			VK_CHECK(vkQueueWaitIdle(m_queueGraphics) );
2219 			VK_CHECK(vkDeviceWaitIdle(m_device) );
2220 
2221 			m_pipelineStateCache.invalidate();
2222 			m_descriptorSetLayoutCache.invalidate();
2223 			m_renderPassCache.invalidate();
2224 			m_samplerCache.invalidate();
2225 
2226 			for (uint32_t ii = 0; ii < BX_COUNTOF(m_scratchBuffer); ++ii)
2227 			{
2228 				m_scratchBuffer[ii].destroy();
2229 			}
2230 
2231 			for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii)
2232 			{
2233 				m_frameBuffers[ii].destroy();
2234 			}
2235 
2236 			for (uint32_t ii = 0; ii < BX_COUNTOF(m_indexBuffers); ++ii)
2237 			{
2238 				m_indexBuffers[ii].destroy();
2239 			}
2240 
2241 			for (uint32_t ii = 0; ii < BX_COUNTOF(m_vertexBuffers); ++ii)
2242 			{
2243 				m_vertexBuffers[ii].destroy();
2244 			}
2245 
2246 			for (uint32_t ii = 0; ii < BX_COUNTOF(m_shaders); ++ii)
2247 			{
2248 				m_shaders[ii].destroy();
2249 			}
2250 
2251 			for (uint32_t ii = 0; ii < BX_COUNTOF(m_textures); ++ii)
2252 			{
2253 				m_textures[ii].destroy();
2254 			}
2255 
2256 			vkDestroy(m_pipelineCache);
2257 //			vkDestroy(m_pipelineLayout);
2258 //			vkDestroy(m_descriptorSetLayout);
2259 			vkDestroy(m_descriptorPool);
2260 
2261 			vkFreeCommandBuffers(m_device, m_commandPool, BX_COUNTOF(m_commandBuffers), m_commandBuffers);
2262 			vkDestroy(m_commandPool);
2263 			vkDestroy(m_fence);
2264 
2265 			for (uint32_t ii = 0; ii < BX_COUNTOF(m_backBufferColorImageView); ++ii)
2266 			{
2267 				vkDestroy(m_presentDone[ii]);
2268 			}
2269 			releaseSwapchainFramebuffer();
2270 			releaseSwapchain();
2271 
2272 			vkDestroySurfaceKHR(m_instance, m_surface, m_allocatorCb);
2273 
2274 			vkDestroy(m_renderPass);
2275 
2276 			vkDestroyDevice(m_device, m_allocatorCb);
2277 
2278 			if (VK_NULL_HANDLE != m_debugReportCallback)
2279 			{
2280 				vkDestroyDebugReportCallbackEXT(m_instance, m_debugReportCallback, m_allocatorCb);
2281 			}
2282 
2283 			vkDestroyInstance(m_instance, m_allocatorCb);
2284 
2285 			bx::dlclose(m_vulkan1Dll);
2286 			m_vulkan1Dll  = NULL;
2287 			m_allocatorCb = NULL;
2288 			unloadRenderDoc(m_renderDocDll);
2289 		}
2290 
getRendererTypebgfx::vk::RendererContextVK2291 		RendererType::Enum getRendererType() const override
2292 		{
2293 			return RendererType::Vulkan;
2294 		}
2295 
getRendererNamebgfx::vk::RendererContextVK2296 		const char* getRendererName() const override
2297 		{
2298 			return BGFX_RENDERER_VULKAN_NAME;
2299 		}
2300 
isDeviceRemovedbgfx::vk::RendererContextVK2301 		bool isDeviceRemoved() override
2302 		{
2303 			return false;
2304 		}
2305 
flipbgfx::vk::RendererContextVK2306 		void flip() override
2307 		{
2308 			if (VK_NULL_HANDLE != m_swapchain)
2309 			{
2310 				VkPresentInfoKHR pi;
2311 				pi.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
2312 				pi.pNext = NULL;
2313 				pi.waitSemaphoreCount = 0;
2314 				pi.pWaitSemaphores    = NULL;
2315 				pi.swapchainCount = 1;
2316 				pi.pSwapchains    = &m_swapchain;
2317 				pi.pImageIndices  = &m_backBufferColorIdx;
2318 				pi.pResults       = NULL;
2319 				VkResult result = vkQueuePresentKHR(m_queueGraphics, &pi);
2320 				if (VK_ERROR_OUT_OF_DATE_KHR == result
2321 				||  VK_SUBOPTIMAL_KHR        == result)
2322 				{
2323 					m_needToRefreshSwapchain = true;
2324 				}
2325 			}
2326 		}
2327 
createIndexBufferbgfx::vk::RendererContextVK2328 		void createIndexBuffer(IndexBufferHandle _handle, const Memory* _mem, uint16_t _flags) override
2329 		{
2330 			m_indexBuffers[_handle.idx].create(_mem->size, _mem->data, _flags, false);
2331 		}
2332 
destroyIndexBufferbgfx::vk::RendererContextVK2333 		void destroyIndexBuffer(IndexBufferHandle _handle) override
2334 		{
2335 			m_indexBuffers[_handle.idx].destroy();
2336 		}
2337 
createVertexLayoutbgfx::vk::RendererContextVK2338 		void createVertexLayout(VertexLayoutHandle _handle, const VertexLayout& _layout) override
2339 		{
2340 			VertexLayout& layout = m_vertexLayouts[_handle.idx];
2341 			bx::memCopy(&layout, &_layout, sizeof(VertexLayout) );
2342 			dump(layout);
2343 		}
2344 
destroyVertexLayoutbgfx::vk::RendererContextVK2345 		void destroyVertexLayout(VertexLayoutHandle /*_handle*/) override
2346 		{
2347 		}
2348 
createVertexBufferbgfx::vk::RendererContextVK2349 		void createVertexBuffer(VertexBufferHandle _handle, const Memory* _mem, VertexLayoutHandle _layoutHandle, uint16_t _flags) override
2350 		{
2351 			m_vertexBuffers[_handle.idx].create(_mem->size, _mem->data, _layoutHandle, _flags);
2352 		}
2353 
destroyVertexBufferbgfx::vk::RendererContextVK2354 		void destroyVertexBuffer(VertexBufferHandle _handle) override
2355 		{
2356 			m_vertexBuffers[_handle.idx].destroy();
2357 		}
2358 
createDynamicIndexBufferbgfx::vk::RendererContextVK2359 		void createDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _size, uint16_t _flags) override
2360 		{
2361 			m_indexBuffers[_handle.idx].create(_size, NULL, _flags, false);
2362 		}
2363 
updateDynamicIndexBufferbgfx::vk::RendererContextVK2364 		void updateDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _offset, uint32_t _size, const Memory* _mem) override
2365 		{
2366 //			BX_UNUSED(_handle, _offset, _size, _mem);
2367 			m_indexBuffers[_handle.idx].update(/*m_commandBuffer*/NULL, _offset, bx::min<uint32_t>(_size, _mem->size), _mem->data);
2368 		}
2369 
destroyDynamicIndexBufferbgfx::vk::RendererContextVK2370 		void destroyDynamicIndexBuffer(IndexBufferHandle _handle) override
2371 		{
2372 			m_indexBuffers[_handle.idx].destroy();
2373 		}
2374 
createDynamicVertexBufferbgfx::vk::RendererContextVK2375 		void createDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _size, uint16_t _flags) override
2376 		{
2377 			VertexLayoutHandle layoutHandle = BGFX_INVALID_HANDLE;
2378 			m_vertexBuffers[_handle.idx].create(_size, NULL, layoutHandle, _flags);
2379 		}
2380 
updateDynamicVertexBufferbgfx::vk::RendererContextVK2381 		void updateDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _offset, uint32_t _size, const Memory* _mem) override
2382 		{
2383 //			BX_UNUSED(_handle, _offset, _size, _mem);
2384 			m_vertexBuffers[_handle.idx].update(/*m_commandBuffer*/NULL, _offset, bx::min<uint32_t>(_size, _mem->size), _mem->data);
2385 		}
2386 
destroyDynamicVertexBufferbgfx::vk::RendererContextVK2387 		void destroyDynamicVertexBuffer(VertexBufferHandle _handle) override
2388 		{
2389 			m_vertexBuffers[_handle.idx].destroy();
2390 		}
2391 
createShaderbgfx::vk::RendererContextVK2392 		void createShader(ShaderHandle _handle, const Memory* _mem) override
2393 		{
2394 			m_shaders[_handle.idx].create(_mem);
2395 		}
2396 
destroyShaderbgfx::vk::RendererContextVK2397 		void destroyShader(ShaderHandle _handle) override
2398 		{
2399 			m_shaders[_handle.idx].destroy();
2400 		}
2401 
createProgrambgfx::vk::RendererContextVK2402 		void createProgram(ProgramHandle _handle, ShaderHandle _vsh, ShaderHandle _fsh) override
2403 		{
2404 			m_program[_handle.idx].create(&m_shaders[_vsh.idx], isValid(_fsh) ? &m_shaders[_fsh.idx] : NULL);
2405 		}
2406 
destroyProgrambgfx::vk::RendererContextVK2407 		void destroyProgram(ProgramHandle _handle) override
2408 		{
2409 			m_program[_handle.idx].destroy();
2410 		}
2411 
createTexturebgfx::vk::RendererContextVK2412 		void* createTexture(TextureHandle _handle, const Memory* _mem, uint64_t _flags, uint8_t _skip) override
2413 		{
2414 			return m_textures[_handle.idx].create(_mem, _flags, _skip);
2415 		}
2416 
updateTextureBeginbgfx::vk::RendererContextVK2417 		void updateTextureBegin(TextureHandle /*_handle*/, uint8_t /*_side*/, uint8_t /*_mip*/) override
2418 		{
2419 		}
2420 
updateTexturebgfx::vk::RendererContextVK2421 		void updateTexture(TextureHandle _handle, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) override
2422 		{
2423 			m_textures[_handle.idx].update(m_commandPool, _side, _mip, _rect, _z, _depth, _pitch, _mem);
2424 		}
2425 
updateTextureEndbgfx::vk::RendererContextVK2426 		void updateTextureEnd() override
2427 		{
2428 		}
2429 
readTexturebgfx::vk::RendererContextVK2430 		void readTexture(TextureHandle /*_handle*/, void* /*_data*/, uint8_t /*_mip*/) override
2431 		{
2432 		}
2433 
resizeTexturebgfx::vk::RendererContextVK2434 		void resizeTexture(TextureHandle /*_handle*/, uint16_t /*_width*/, uint16_t /*_height*/, uint8_t /*_numMips*/, uint16_t /*_numLayers*/) override
2435 		{
2436 		}
2437 
overrideInternalbgfx::vk::RendererContextVK2438 		void overrideInternal(TextureHandle /*_handle*/, uintptr_t /*_ptr*/) override
2439 		{
2440 		}
2441 
getInternalbgfx::vk::RendererContextVK2442 		uintptr_t getInternal(TextureHandle /*_handle*/) override
2443 		{
2444 			return 0;
2445 		}
2446 
destroyTexturebgfx::vk::RendererContextVK2447 		void destroyTexture(TextureHandle _handle) override
2448 		{
2449 		    m_textures[_handle.idx].destroy();
2450 		}
2451 
createFrameBufferbgfx::vk::RendererContextVK2452 		void createFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const Attachment* _attachment) override
2453 		{
2454 			m_frameBuffers[_handle.idx].create(_num, _attachment);
2455 		}
2456 
createFrameBufferbgfx::vk::RendererContextVK2457 		void createFrameBuffer(FrameBufferHandle /*_handle*/, void* /*_nwh*/, uint32_t /*_width*/, uint32_t /*_height*/, TextureFormat::Enum /*_format*/, TextureFormat::Enum /*_depthFormat*/) override
2458 		{
2459 		}
2460 
destroyFrameBufferbgfx::vk::RendererContextVK2461 		void destroyFrameBuffer(FrameBufferHandle _handle) override
2462 		{
2463 			m_frameBuffers[_handle.idx].destroy();
2464 		}
2465 
createUniformbgfx::vk::RendererContextVK2466 		void createUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) override
2467 		{
2468 			if (NULL != m_uniforms[_handle.idx])
2469 			{
2470 				BX_FREE(g_allocator, m_uniforms[_handle.idx]);
2471 			}
2472 
2473 			uint32_t size = BX_ALIGN_16(g_uniformTypeSize[_type] * _num);
2474 			void* data = BX_ALLOC(g_allocator, size);
2475 			bx::memSet(data, 0, size);
2476 			m_uniforms[_handle.idx] = data;
2477 			m_uniformReg.add(_handle, _name);
2478 		}
2479 
destroyUniformbgfx::vk::RendererContextVK2480 		void destroyUniform(UniformHandle _handle) override
2481 		{
2482 			BX_FREE(g_allocator, m_uniforms[_handle.idx]);
2483 			m_uniforms[_handle.idx] = NULL;
2484 		}
2485 
requestScreenShotbgfx::vk::RendererContextVK2486 		void requestScreenShot(FrameBufferHandle /*_handle*/, const char* /*_filePath*/) override
2487 		{
2488 		}
2489 
updateViewNamebgfx::vk::RendererContextVK2490 		void updateViewName(ViewId _id, const char* _name) override
2491 		{
2492 			bx::strCopy(&s_viewName[_id][BGFX_CONFIG_MAX_VIEW_NAME_RESERVED]
2493 				, BX_COUNTOF(s_viewName[0]) - BGFX_CONFIG_MAX_VIEW_NAME_RESERVED
2494 				, _name
2495 				);
2496 		}
2497 
updateUniformbgfx::vk::RendererContextVK2498 		void updateUniform(uint16_t _loc, const void* _data, uint32_t _size) override
2499 		{
2500 			bx::memCopy(m_uniforms[_loc], _data, _size);
2501 		}
2502 
invalidateOcclusionQuerybgfx::vk::RendererContextVK2503 		void invalidateOcclusionQuery(OcclusionQueryHandle _handle) override
2504 		{
2505 			BX_UNUSED(_handle);
2506 		}
2507 
setMarkerbgfx::vk::RendererContextVK2508 		void setMarker(const char* _marker, uint16_t _len) override
2509 		{
2510 			if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) )
2511 			{
2512 				BX_UNUSED(_len);
2513 
2514 				VkDebugUtilsLabelEXT dul;
2515 				dul.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
2516 				dul.pNext = NULL;
2517 				dul.pLabelName = _marker;
2518 				dul.color[0] = 1.0f;
2519 				dul.color[1] = 0.0f;
2520 				dul.color[2] = 0.0f;
2521 				dul.color[3] = 1.0f;
2522 				vkCmdInsertDebugUtilsLabelEXT(m_commandBuffer, &dul);
2523 			}
2524 		}
2525 
setNamebgfx::vk::RendererContextVK2526 		virtual void setName(Handle _handle, const char* _name, uint16_t _len) override
2527 		{
2528 			switch (_handle.type)
2529 			{
2530 			case Handle::IndexBuffer:
2531 				setDebugObjectName(m_device, m_indexBuffers[_handle.idx].m_buffer, "%.*s", _len, _name);
2532 				break;
2533 
2534 			case Handle::Shader:
2535 				setDebugObjectName(m_device, m_shaders[_handle.idx].m_module, "%.*s", _len, _name);
2536 				break;
2537 
2538 			case Handle::Texture:
2539 //				setDebugObjectName(m_device, m_textures[_handle.idx].m_ptr, "%.*s", _len, _name);
2540 				break;
2541 
2542 			case Handle::VertexBuffer:
2543 				setDebugObjectName(m_device, m_vertexBuffers[_handle.idx].m_buffer, "%.*s", _len, _name);
2544 				break;
2545 
2546 			default:
2547 				BX_CHECK(false, "Invalid handle type?! %d", _handle.type);
2548 				break;
2549 			}
2550 		}
2551 
2552 		void submitBlit(BlitState& _bs, uint16_t _view);
2553 
2554 		void submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter) override;
2555 
blitSetupbgfx::vk::RendererContextVK2556 		void blitSetup(TextVideoMemBlitter& _blitter) override
2557 		{
2558 			const uint32_t width  = m_sci.imageExtent.width;
2559 			const uint32_t height = m_sci.imageExtent.height;
2560 
2561 			setFrameBuffer(BGFX_INVALID_HANDLE, false);
2562 
2563 			VkViewport vp;
2564 			vp.x        = 0;
2565 			vp.y        = 0;
2566 			vp.width    = (float)width;
2567 			vp.height   = (float)height;
2568 			vp.minDepth = 0.0f;
2569 			vp.maxDepth = 1.0f;
2570 			vkCmdSetViewport(m_commandBuffer, 0, 1, &vp);
2571 
2572 			VkRect2D rc;
2573 			rc.offset.x      = 0;
2574 			rc.offset.y      = 0;
2575 			rc.extent.width  = width;
2576 			rc.extent.height = height;
2577 			vkCmdSetScissor(m_commandBuffer, 0, 1, &rc);
2578 
2579 			const uint64_t state = 0
2580 				| BGFX_STATE_WRITE_RGB
2581 				| BGFX_STATE_WRITE_A
2582 				| BGFX_STATE_DEPTH_TEST_ALWAYS
2583 				;
2584 
2585 			const VertexLayout* layout = &m_vertexLayouts[_blitter.m_vb->layoutHandle.idx];
2586 			VkPipeline pso = getPipeline(state
2587 				, packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT)
2588 				, 1
2589 				, &layout
2590 				, _blitter.m_program
2591 				, 0
2592 				);
2593 			vkCmdBindPipeline(m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pso);
2594 
2595 			ProgramVK& program = m_program[_blitter.m_program.idx];
2596 			float proj[16];
2597 			bx::mtxOrtho(proj, 0.0f, (float)width, (float)height, 0.0f, 0.0f, 1000.0f, 0.0f, false);
2598 
2599 			PredefinedUniform& predefined = m_program[_blitter.m_program.idx].m_predefined[0];
2600 			uint8_t flags = predefined.m_type;
2601 			setShaderUniform(flags, predefined.m_loc, proj, 4);
2602 
2603 			UniformBuffer* vcb = program.m_vsh->m_constantBuffer;
2604 			if (NULL != vcb)
2605 			{
2606 				commit(*vcb);
2607 			}
2608 			ScratchBufferVK& scratchBuffer = m_scratchBuffer[m_backBufferColorIdx];
2609 			VkDescriptorSetLayout dsl = m_descriptorSetLayoutCache.find(program.m_descriptorSetLayoutHash);
2610 			VkDescriptorSetAllocateInfo dsai;
2611 			dsai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
2612 			dsai.pNext = NULL;
2613 			dsai.descriptorPool = m_descriptorPool;
2614 			dsai.descriptorSetCount = 1;
2615 			dsai.pSetLayouts = &dsl;
2616 			vkAllocateDescriptorSets(m_device, &dsai, &scratchBuffer.m_descriptorSet[scratchBuffer.m_currentDs]);
2617 
2618 			const uint32_t align = uint32_t(m_deviceProperties.limits.minUniformBufferOffsetAlignment);
2619 			TextureVK& texture = m_textures[_blitter.m_texture.idx];
2620 			uint32_t samplerFlags = (uint32_t)(texture.m_flags & BGFX_SAMPLER_BITS_MASK);
2621 			VkSampler sampler = getSampler(samplerFlags, 1);
2622 
2623 			const uint32_t size = bx::strideAlign(program.m_vsh->m_size, align);
2624 			uint32_t bufferOffset = scratchBuffer.m_pos;
2625 			VkDescriptorBufferInfo bufferInfo;
2626 			bufferInfo.buffer = scratchBuffer.m_buffer;
2627 			bufferInfo.offset = 0;
2628 			bufferInfo.range  = size;
2629 			bx::memCopy(&scratchBuffer.m_data[scratchBuffer.m_pos], m_vsScratch, program.m_vsh->m_size);
2630 			scratchBuffer.m_pos += size;
2631 
2632 			VkWriteDescriptorSet wds[3];
2633 			wds[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2634 			wds[0].pNext = NULL;
2635 			wds[0].dstSet = scratchBuffer.m_descriptorSet[scratchBuffer.m_currentDs];
2636 			wds[0].dstBinding = program.m_vsh->m_uniformBinding;
2637 			wds[0].dstArrayElement = 0;
2638 			wds[0].descriptorCount = 1;
2639 			wds[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
2640 			wds[0].pImageInfo = NULL;
2641 			wds[0].pBufferInfo = &bufferInfo;
2642 			wds[0].pTexelBufferView = NULL;
2643 
2644 			VkDescriptorImageInfo imageInfo;
2645 			imageInfo.imageLayout = texture.m_currentImageLayout;
2646 			imageInfo.imageView = texture.m_textureImageView;
2647 			imageInfo.sampler = sampler;
2648 
2649 			wds[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2650 			wds[1].pNext = NULL;
2651 			wds[1].dstSet = scratchBuffer.m_descriptorSet[scratchBuffer.m_currentDs];
2652 			wds[1].dstBinding = program.m_fsh->m_bindInfo[0].binding;
2653 			wds[1].dstArrayElement = 0;
2654 			wds[1].descriptorCount = 1;
2655 			wds[1].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
2656 			wds[1].pImageInfo = &imageInfo;
2657 			wds[1].pBufferInfo = NULL;
2658 			wds[1].pTexelBufferView = NULL;
2659 
2660 			wds[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2661 			wds[2].pNext = NULL;
2662 			wds[2].dstSet = scratchBuffer.m_descriptorSet[scratchBuffer.m_currentDs];
2663 			wds[2].dstBinding = program.m_fsh->m_bindInfo[0].samplerBinding;
2664 			wds[2].dstArrayElement = 0;
2665 			wds[2].descriptorCount = 1;
2666 			wds[2].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
2667 			wds[2].pImageInfo = &imageInfo;
2668 			wds[2].pBufferInfo = NULL;
2669 			wds[2].pTexelBufferView = NULL;
2670 
2671 			m_vsChanges = 0;
2672 			m_fsChanges = 0;
2673 
2674 			vkUpdateDescriptorSets(m_device, 3, wds, 0, NULL);
2675 			vkCmdBindDescriptorSets(
2676 				m_commandBuffer
2677 				, VK_PIPELINE_BIND_POINT_GRAPHICS
2678 				, program.m_pipelineLayout
2679 				, 0
2680 				, 1
2681 				, &scratchBuffer.m_descriptorSet[scratchBuffer.m_currentDs]
2682 				, 1
2683 				, &bufferOffset
2684 				);
2685 
2686 			scratchBuffer.m_currentDs++;
2687 
2688 			VertexBufferVK& vb  = m_vertexBuffers[_blitter.m_vb->handle.idx];
2689 			VkDeviceSize offset = 0;
2690 			vkCmdBindVertexBuffers(m_commandBuffer
2691 				, 0
2692 				, 1
2693 				, &vb.m_buffer
2694 				, &offset
2695 				);
2696 
2697 			BufferVK& ib = m_indexBuffers[_blitter.m_ib->handle.idx];
2698 			vkCmdBindIndexBuffer(m_commandBuffer
2699 				, ib.m_buffer
2700 				, 0
2701 				, VK_INDEX_TYPE_UINT16
2702 				);
2703 		}
2704 
blitRenderbgfx::vk::RendererContextVK2705 		void blitRender(TextVideoMemBlitter& _blitter, uint32_t _numIndices) override
2706 		{
2707 			const uint32_t numVertices = _numIndices*4/6;
2708 			if (0 < numVertices)
2709 			{
2710 				m_indexBuffers[_blitter.m_ib->handle.idx].update(m_commandBuffer, 0, _numIndices*2, _blitter.m_ib->data);
2711 				m_vertexBuffers[_blitter.m_vb->handle.idx].update(m_commandBuffer, 0, numVertices*_blitter.m_layout.m_stride, _blitter.m_vb->data, true);
2712 
2713 				vkCmdDrawIndexed(m_commandBuffer
2714 					, _numIndices
2715 					, 1
2716 					, 0
2717 					, 0
2718 					, 0
2719 					);
2720 			}
2721 		}
2722 
updateResolutionbgfx::vk::RendererContextVK2723 		void updateResolution(const Resolution& _resolution)
2724 		{
2725 			if (!!(_resolution.reset & BGFX_RESET_MAXANISOTROPY) )
2726 			{
2727 				m_maxAnisotropy = UINT32_MAX;
2728 			}
2729 			else
2730 			{
2731 				m_maxAnisotropy = 1;
2732 			}
2733 
2734 			bool depthClamp = !!(_resolution.reset & BGFX_RESET_DEPTH_CLAMP);
2735 
2736 			if (m_depthClamp != depthClamp)
2737 			{
2738 				m_depthClamp = depthClamp;
2739 				m_pipelineStateCache.invalidate();
2740 			}
2741 
2742 			uint32_t flags = _resolution.reset & ~(BGFX_RESET_MAXANISOTROPY | BGFX_RESET_DEPTH_CLAMP);
2743 
2744 			if (m_resolution.width  != _resolution.width
2745 			||  m_resolution.height != _resolution.height
2746 			||  m_resolution.reset  != flags)
2747 			{
2748 				flags &= ~BGFX_RESET_INTERNAL_FORCE;
2749 
2750 				bool resize = (m_resolution.reset&BGFX_RESET_MSAA_MASK) == (_resolution.reset&BGFX_RESET_MSAA_MASK);
2751 
2752 				m_resolution = _resolution;
2753 				m_resolution.reset = flags;
2754 
2755 				m_textVideoMem.resize(false, _resolution.width, _resolution.height);
2756 				m_textVideoMem.clear();
2757 
2758 				if (resize || m_needToRefreshSwapchain)
2759 				{
2760 					VK_CHECK(vkDeviceWaitIdle(m_device) );
2761 					releaseSwapchainFramebuffer();
2762 					releaseSwapchain();
2763 
2764 					uint32_t numPresentModes(10);
2765 					VkPresentModeKHR presentModes[10];
2766 					vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &numPresentModes, presentModes);
2767 
2768 					uint32_t presentModeIdx = numPresentModes;
2769 					static const VkPresentModeKHR preferredPresentMode[] =
2770 					{
2771 						VK_PRESENT_MODE_FIFO_KHR,
2772 						VK_PRESENT_MODE_FIFO_RELAXED_KHR,
2773 						VK_PRESENT_MODE_MAILBOX_KHR,
2774 						VK_PRESENT_MODE_IMMEDIATE_KHR,
2775 					};
2776 					static const bool hasVsync[] = { true, true, true, false };
2777 					BX_STATIC_ASSERT(BX_COUNTOF(preferredPresentMode) == BX_COUNTOF(hasVsync) );
2778 
2779 					const bool vsync = !!(flags & BGFX_RESET_VSYNC);
2780 
2781 					for (uint32_t ii = 0; ii < BX_COUNTOF(preferredPresentMode); ++ii)
2782 					{
2783 						for (uint32_t jj = 0; jj < numPresentModes; ++jj)
2784 						{
2785 							if (presentModes[jj] == preferredPresentMode[ii]
2786 							&&  vsync == hasVsync[ii])
2787 							{
2788 								presentModeIdx = jj;
2789 								BX_TRACE("present mode: %d", preferredPresentMode[ii]);
2790 								break;
2791 							}
2792 						}
2793 
2794 						if (presentModeIdx < numPresentModes)
2795 						{
2796 							break;
2797 						}
2798 					}
2799 
2800 					if (presentModeIdx == numPresentModes)
2801 					{
2802 						presentModeIdx = 0;
2803 					}
2804 
2805 					m_sci.presentMode = presentModes[presentModeIdx];
2806 
2807 					VkSurfaceCapabilitiesKHR surfaceCapabilities;
2808 					VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &surfaceCapabilities) );
2809 
2810 					m_sci.imageExtent.width  = bx::clamp<uint32_t>(m_resolution.width
2811 						, surfaceCapabilities.minImageExtent.width
2812 						, surfaceCapabilities.maxImageExtent.width
2813 						);
2814 					m_sci.imageExtent.height = bx::clamp<uint32_t>(m_resolution.height
2815 						, surfaceCapabilities.minImageExtent.height
2816 						, surfaceCapabilities.maxImageExtent.height
2817 						);
2818 
2819 					VK_CHECK(createSwapchain() );
2820 					VK_CHECK(createSwapchainFramebuffer() );
2821 					initSwapchainImageLayout();
2822 					BX_TRACE("refreshed swapchain: %d x %d", m_sci.imageExtent.width, m_sci.imageExtent.height);
2823 				}
2824 #if 1
2825 				BX_UNUSED(resize);
2826 #else
2827 				m_scd.BufferDesc.Width  = _resolution.m_width;
2828 				m_scd.BufferDesc.Height = _resolution.m_height;
2829 
2830 				preReset();
2831 
2832 				if (resize)
2833 				{
2834 					uint32_t nodeMask[] = { 1, 1, 1, 1 };
2835 					BX_STATIC_ASSERT(BX_COUNTOF(m_backBufferColor) == BX_COUNTOF(nodeMask) );
2836 					IUnknown* presentQueue[] ={ m_cmd.m_commandQueue, m_cmd.m_commandQueue, m_cmd.m_commandQueue, m_cmd.m_commandQueue };
2837 					BX_STATIC_ASSERT(BX_COUNTOF(m_backBufferColor) == BX_COUNTOF(presentQueue) );
2838 
2839 					DX_CHECK(m_swapChain->ResizeBuffers1(m_scd.BufferCount
2840 							, m_scd.BufferDesc.Width
2841 							, m_scd.BufferDesc.Height
2842 							, m_scd.BufferDesc.Format
2843 							, m_scd.Flags
2844 							, nodeMask
2845 							, presentQueue
2846 							) );
2847 				}
2848 				else
2849 				{
2850 					updateMsaa();
2851 					m_scd.SampleDesc = s_msaa[(m_resolution.m_flags&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT];
2852 
2853 					DX_RELEASE(m_swapChain, 0);
2854 
2855 					HRESULT hr;
2856 					hr = m_factory->CreateSwapChain(m_cmd.m_commandQueue
2857 							, &m_scd
2858 							, reinterpret_cast<IDXGISwapChain**>(&m_swapChain)
2859 							);
2860 					BGFX_FATAL(SUCCEEDED(hr), bgfx::Fatal::UnableToInitialize, "Failed to create swap chain.");
2861 				}
2862 
2863 				postReset();
2864 #endif // 0
2865 			}
2866 		}
2867 
setShaderUniformbgfx::vk::RendererContextVK2868 		void setShaderUniform(uint8_t _flags, uint32_t _regIndex, const void* _val, uint32_t _numRegs)
2869 		{
2870 			BX_UNUSED(_flags, _regIndex, _val, _numRegs);
2871 			if (_flags&BGFX_UNIFORM_FRAGMENTBIT)
2872 			{
2873 				bx::memCopy(&m_fsScratch[_regIndex], _val, _numRegs*16);
2874 				m_fsChanges += _numRegs;
2875 			}
2876 			else
2877 			{
2878 				bx::memCopy(&m_vsScratch[_regIndex], _val, _numRegs*16);
2879 				m_vsChanges += _numRegs;
2880 			}
2881 		}
2882 
setShaderUniform4fbgfx::vk::RendererContextVK2883 		void setShaderUniform4f(uint8_t _flags, uint32_t _regIndex, const void* _val, uint32_t _numRegs)
2884 		{
2885 			setShaderUniform(_flags, _regIndex, _val, _numRegs);
2886 		}
2887 
setShaderUniform4x4fbgfx::vk::RendererContextVK2888 		void setShaderUniform4x4f(uint8_t _flags, uint32_t _regIndex, const void* _val, uint32_t _numRegs)
2889 		{
2890 			setShaderUniform(_flags, _regIndex, _val, _numRegs);
2891 		}
2892 
2893 //		void commitShaderUniforms(VkCommandBuffer _commandBuffer, ProgramHandle _program)
2894 //		{
2895 //			ProgramVK& program = m_program[_program.idx];
2896 //
2897 //			const uint32_t align = uint32_t(m_deviceProperties.limits.minUniformBufferOffsetAlignment);
2898 //			const uint32_t vsize = bx::strideAlign(program.m_vsh->m_size, align);
2899 //			const uint32_t fsize = bx::strideAlign( (NULL != program.m_fsh ? program.m_fsh->m_size : 0), align);
2900 //			const uint32_t total = vsize + fsize;
2901 //
2902 //			if (0 < total)
2903 //			{
2904 //				ScratchBufferVK& sb = m_scratchBuffer[m_backBufferColorIdx];
2905 //
2906 //				uint8_t* data = (uint8_t*)sb.allocUbv(vsize, fsize);
2907 //
2908 //				bx::memCopy(data, m_vsScratch, program.m_vsh->m_size);
2909 //				data += vsize;
2910 //
2911 //				if (0 != fsize)
2912 //				{
2913 //					bx::memCopy(data, m_fsScratch, program.m_fsh->m_size);
2914 //				}
2915 //
2916 //				vkCmdBindDescriptorSets(_commandBuffer
2917 //					, VK_PIPELINE_BIND_POINT_GRAPHICS
2918 //					, m_pipelineLayout
2919 //					, program.m_pipelineLayout
2920 //					, 0
2921 //					, 1
2922 //					, &sb.m_descriptorSet[sb.m_currentDs - 1]
2923 //					, 0
2924 //					, NULL
2925 //					);
2926 //			}
2927 //
2928 //			m_vsChanges = 0;
2929 //			m_fsChanges = 0;
2930 //		}
2931 
setFrameBufferbgfx::vk::RendererContextVK2932 		void setFrameBuffer(FrameBufferHandle _fbh, bool _msaa = true)
2933 		{
2934 			BX_UNUSED(_msaa);
2935 
2936 			if (isValid(m_fbh)
2937 			&&  m_fbh.idx != _fbh.idx)
2938 			{
2939 				const FrameBufferVK& frameBuffer = m_frameBuffers[m_fbh.idx];
2940 				BX_UNUSED(frameBuffer);
2941 
2942 				for (uint8_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii)
2943 				{
2944 					TextureVK& texture = m_textures[frameBuffer.m_texture[ii].idx];
2945 					texture.setImageMemoryBarrier(m_commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2946 				}
2947 
2948 				if (isValid(frameBuffer.m_depth) )
2949 				{
2950 					TextureVK& texture = m_textures[frameBuffer.m_depth.idx];
2951 					const bool writeOnly  = 0 != (texture.m_flags&BGFX_TEXTURE_RT_WRITE_ONLY);
2952 					if (!writeOnly)
2953 					{
2954 						texture.setImageMemoryBarrier(m_commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2955 					}
2956 				}
2957 			}
2958 
2959 			if (!isValid(_fbh) )
2960 			{
2961 //				m_rtvHandle = m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
2962 //				uint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
2963 //				m_rtvHandle.ptr += m_backBufferColorIdx * rtvDescriptorSize;
2964 //				m_dsvHandle = m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
2965 //
2966 //				m_currentColor        = &m_rtvHandle;
2967 //				m_currentDepthStencil = &m_dsvHandle;
2968 //				m_commandList->OMSetRenderTargets(1, m_currentColor, true, m_currentDepthStencil);
2969 			}
2970 			else
2971 			{
2972 				const FrameBufferVK& frameBuffer = m_frameBuffers[_fbh.idx];
2973 				BX_UNUSED(frameBuffer);
2974 
2975 				if (0 < frameBuffer.m_num)
2976 				{
2977 //					D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
2978 //					uint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
2979 //					m_rtvHandle.ptr = rtvDescriptor.ptr + (BX_COUNTOF(m_backBufferColor) + _fbh.idx * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) * rtvDescriptorSize;
2980 //					m_currentColor  = &m_rtvHandle;
2981 				}
2982 				else
2983 				{
2984 //					m_currentColor = NULL;
2985 				}
2986 
2987 				if (isValid(frameBuffer.m_depth) )
2988 				{
2989 //					D3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
2990 //					uint32_t dsvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
2991 //					m_dsvHandle.ptr = dsvDescriptor.ptr + (1 + _fbh.idx) * dsvDescriptorSize;
2992 //					m_currentDepthStencil = &m_dsvHandle;
2993 				}
2994 				else
2995 				{
2996 //					m_currentDepthStencil = NULL;
2997 				}
2998 
2999 				for (uint8_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii)
3000 				{
3001 					TextureVK& texture = m_textures[frameBuffer.m_texture[ii].idx];
3002 					texture.setImageMemoryBarrier(m_commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
3003 				}
3004 
3005 				if (isValid(frameBuffer.m_depth) )
3006 				{
3007 					TextureVK& texture = m_textures[frameBuffer.m_depth.idx];
3008 					texture.setImageMemoryBarrier(m_commandBuffer, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
3009 				}
3010 
3011 //				m_commandList->OMSetRenderTargets(frameBuffer.m_num
3012 //												, m_currentColor
3013 //												, true
3014 //												, m_currentDepthStencil
3015 //												);
3016 			}
3017 
3018 			m_fbh = _fbh;
3019 //			m_rtMsaa = _msaa;
3020 		}
3021 
setBlendStatebgfx::vk::RendererContextVK3022 		void setBlendState(VkPipelineColorBlendStateCreateInfo& _desc, uint64_t _state, uint32_t _rgba = 0)
3023 		{
3024 			VkPipelineColorBlendAttachmentState* bas = const_cast<VkPipelineColorBlendAttachmentState*>(_desc.pAttachments);
3025 
3026 			uint8_t writeMask = 0;
3027 			writeMask |= (_state & BGFX_STATE_WRITE_R) ? VK_COLOR_COMPONENT_R_BIT : 0;
3028 			writeMask |= (_state & BGFX_STATE_WRITE_G) ? VK_COLOR_COMPONENT_G_BIT : 0;
3029 			writeMask |= (_state & BGFX_STATE_WRITE_B) ? VK_COLOR_COMPONENT_B_BIT : 0;
3030 			writeMask |= (_state & BGFX_STATE_WRITE_A) ? VK_COLOR_COMPONENT_A_BIT : 0;
3031 
3032 			bas->blendEnable = !!(BGFX_STATE_BLEND_MASK & _state);
3033 
3034 			{
3035 				const uint32_t blend    = uint32_t( (_state & BGFX_STATE_BLEND_MASK         ) >> BGFX_STATE_BLEND_SHIFT);
3036 				const uint32_t equation = uint32_t( (_state & BGFX_STATE_BLEND_EQUATION_MASK) >> BGFX_STATE_BLEND_EQUATION_SHIFT);
3037 
3038 				const uint32_t srcRGB = (blend      ) & 0xf;
3039 				const uint32_t dstRGB = (blend >>  4) & 0xf;
3040 				const uint32_t srcA   = (blend >>  8) & 0xf;
3041 				const uint32_t dstA   = (blend >> 12) & 0xf;
3042 
3043 				const uint32_t equRGB = (equation     ) & 0x7;
3044 				const uint32_t equA   = (equation >> 3) & 0x7;
3045 
3046 				bas->srcColorBlendFactor = s_blendFactor[srcRGB][0];
3047 				bas->dstColorBlendFactor = s_blendFactor[dstRGB][0];
3048 				bas->colorBlendOp        = s_blendEquation[equRGB];
3049 
3050 				bas->srcAlphaBlendFactor = s_blendFactor[srcA][1];
3051 				bas->dstAlphaBlendFactor = s_blendFactor[dstA][1];
3052 				bas->alphaBlendOp        = s_blendEquation[equA];
3053 
3054 				bas->colorWriteMask = writeMask;
3055 			}
3056 
3057 			uint32_t numAttachments = 1;
3058 			if (isValid(m_fbh) )
3059 			{
3060 				const FrameBufferVK& frameBuffer = m_frameBuffers[m_fbh.idx];
3061 				numAttachments = frameBuffer.m_num;
3062 			}
3063 
3064 			if (!!(BGFX_STATE_BLEND_INDEPENDENT & _state) && m_deviceFeatures.independentBlend )
3065 			{
3066 				for (uint32_t ii = 1, rgba = _rgba; ii < numAttachments; ++ii, rgba >>= 11)
3067 				{
3068 					++bas;
3069 					bas->blendEnable =  0 != (rgba & 0x7ff);
3070 
3071 					const uint32_t src      = (rgba     ) & 0xf;
3072 					const uint32_t dst      = (rgba >> 4) & 0xf;
3073 					const uint32_t equation = (rgba >> 8) & 0x7;
3074 
3075 					bas->srcColorBlendFactor = s_blendFactor[src][0];
3076 					bas->dstColorBlendFactor = s_blendFactor[dst][0];
3077 					bas->colorBlendOp        = s_blendEquation[equation];
3078 
3079 					bas->srcAlphaBlendFactor = s_blendFactor[src][1];
3080 					bas->dstAlphaBlendFactor = s_blendFactor[dst][1];
3081 					bas->alphaBlendOp        = s_blendEquation[equation];
3082 
3083 					bas->colorWriteMask = writeMask;
3084 				}
3085 			}
3086 			else
3087 			{
3088 				for (uint32_t ii = 1; ii < numAttachments; ++ii)
3089 				{
3090 					bx::memCopy(&bas[ii], bas, sizeof(VkPipelineColorBlendAttachmentState) );
3091 				}
3092 			}
3093 
3094 			_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
3095 			_desc.pNext = NULL;
3096 			_desc.flags = 0;
3097 			_desc.logicOpEnable = VK_FALSE;
3098 			_desc.logicOp       = VK_LOGIC_OP_CLEAR;
3099 			_desc.attachmentCount = numAttachments;
3100 			_desc.blendConstants[0] = 0.0f;
3101 			_desc.blendConstants[1] = 0.0f;
3102 			_desc.blendConstants[2] = 0.0f;
3103 			_desc.blendConstants[3] = 0.0f;
3104 		}
3105 
setRasterizerStatebgfx::vk::RendererContextVK3106 		void setRasterizerState(VkPipelineRasterizationStateCreateInfo& _desc, uint64_t _state, bool _wireframe = false)
3107 		{
3108 			const uint32_t cull = (_state&BGFX_STATE_CULL_MASK) >> BGFX_STATE_CULL_SHIFT;
3109 
3110 			_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
3111 			_desc.pNext = NULL;
3112 			_desc.flags = 0;
3113 			_desc.depthClampEnable = m_depthClamp;
3114 			_desc.rasterizerDiscardEnable = VK_FALSE;
3115 			_desc.polygonMode = _wireframe
3116 				? VK_POLYGON_MODE_LINE
3117 				: VK_POLYGON_MODE_FILL
3118 				;
3119 			_desc.cullMode  = s_cullMode[cull];
3120 			_desc.frontFace = (_state&BGFX_STATE_FRONT_CCW) ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
3121 			_desc.depthBiasEnable = VK_FALSE;
3122 			_desc.depthBiasConstantFactor = 0.0f;
3123 			_desc.depthBiasClamp          = 0.0f;
3124 			_desc.depthBiasSlopeFactor    = 0.0f;
3125 			_desc.lineWidth               = 1.0f;
3126 		}
3127 
setDepthStencilStatebgfx::vk::RendererContextVK3128 		void setDepthStencilState(VkPipelineDepthStencilStateCreateInfo& _desc, uint64_t _state, uint64_t _stencil = 0)
3129 		{
3130 			const uint32_t fstencil = unpackStencil(0, _stencil);
3131 			uint32_t func = (_state&BGFX_STATE_DEPTH_TEST_MASK)>>BGFX_STATE_DEPTH_TEST_SHIFT;
3132 
3133 			_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
3134 			_desc.pNext = NULL;
3135 			_desc.flags = 0;
3136 			_desc.depthTestEnable  = 0 != func;
3137 			_desc.depthWriteEnable = !!(BGFX_STATE_WRITE_Z & _state);
3138 			_desc.depthCompareOp   = s_cmpFunc[func];
3139 			_desc.depthBoundsTestEnable = VK_FALSE;
3140 
3141 			_desc.stencilTestEnable = 0 != _stencil;
3142 
3143 			uint32_t bstencil = unpackStencil(1, _stencil);
3144 			uint32_t frontAndBack = bstencil != BGFX_STENCIL_NONE && bstencil != fstencil;
3145 			bstencil = frontAndBack ? bstencil : fstencil;
3146 
3147 			_desc.front.failOp      = s_stencilOp[(fstencil & BGFX_STENCIL_OP_FAIL_S_MASK) >> BGFX_STENCIL_OP_FAIL_S_SHIFT];
3148 			_desc.front.passOp      = s_stencilOp[(fstencil & BGFX_STENCIL_OP_PASS_Z_MASK) >> BGFX_STENCIL_OP_PASS_Z_SHIFT];
3149 			_desc.front.depthFailOp = s_stencilOp[(fstencil & BGFX_STENCIL_OP_FAIL_Z_MASK) >> BGFX_STENCIL_OP_FAIL_Z_SHIFT];
3150 			_desc.front.compareOp   = s_cmpFunc[(fstencil & BGFX_STENCIL_TEST_MASK) >> BGFX_STENCIL_TEST_SHIFT];
3151 			_desc.front.compareMask = UINT32_MAX;
3152 			_desc.front.writeMask   = UINT32_MAX;
3153 			_desc.front.reference   = 0;
3154 
3155 			_desc.back.failOp       = s_stencilOp[(bstencil & BGFX_STENCIL_OP_FAIL_S_MASK) >> BGFX_STENCIL_OP_FAIL_S_SHIFT];
3156 			_desc.back.passOp       = s_stencilOp[(bstencil & BGFX_STENCIL_OP_PASS_Z_MASK) >> BGFX_STENCIL_OP_PASS_Z_SHIFT];
3157 			_desc.back.depthFailOp  = s_stencilOp[(bstencil & BGFX_STENCIL_OP_FAIL_Z_MASK) >> BGFX_STENCIL_OP_FAIL_Z_SHIFT];
3158 			_desc.back.compareOp    = s_cmpFunc[(bstencil&BGFX_STENCIL_TEST_MASK) >> BGFX_STENCIL_TEST_SHIFT];
3159 			_desc.back.compareMask  = UINT32_MAX;
3160 			_desc.back.writeMask    = UINT32_MAX;
3161 			_desc.back.reference    = 0;
3162 
3163 			_desc.minDepthBounds = 0.0f;
3164 			_desc.maxDepthBounds = 1.0f;
3165 		}
3166 
setInputLayoutbgfx::vk::RendererContextVK3167 		void setInputLayout(VkPipelineVertexInputStateCreateInfo& _vertexInputState, uint8_t _numStream, const VertexLayout** _layout, const ProgramVK& _program, uint8_t _numInstanceData)
3168 		{
3169 			_vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
3170 			_vertexInputState.pNext = NULL;
3171 			_vertexInputState.flags = 0;
3172 
3173 			_vertexInputState.vertexBindingDescriptionCount   = 0;
3174 			_vertexInputState.vertexAttributeDescriptionCount = 0;
3175 
3176 			uint16_t unsettedAttr[Attrib::Count];
3177 			bx::memCopy(unsettedAttr, _program.m_vsh->m_attrMask, sizeof(uint16_t) * Attrib::Count);
3178 			for (uint8_t stream = 0; stream < _numStream; ++stream)
3179 			{
3180 				VertexLayout layout;
3181 				bx::memCopy(&layout, _layout[stream], sizeof(VertexLayout) );
3182 				const uint16_t* attrMask = _program.m_vsh->m_attrMask;
3183 
3184 				for (uint32_t ii = 0; ii < Attrib::Count; ++ii)
3185 				{
3186 					uint16_t mask = attrMask[ii];
3187 					uint16_t attr = (layout.m_attributes[ii] & mask);
3188 					layout.m_attributes[ii] = attr == 0 || attr == UINT16_MAX ? UINT16_MAX : attr;
3189 					if (unsettedAttr[ii] && attr != UINT16_MAX)
3190 					{
3191 						unsettedAttr[ii] = 0;
3192 					}
3193 				}
3194 
3195 				fillVertexLayout(_program.m_vsh, _vertexInputState, layout);
3196 			}
3197 
3198 			for (uint32_t ii = 0; ii < Attrib::Count; ++ii)
3199 			{
3200 				if (0 < unsettedAttr[ii])
3201 				{
3202 					uint32_t numAttribs  = _vertexInputState.vertexAttributeDescriptionCount;
3203 					VkVertexInputAttributeDescription* inputAttrib = const_cast<VkVertexInputAttributeDescription*>(_vertexInputState.pVertexAttributeDescriptions + numAttribs);
3204 					inputAttrib->location = _program.m_vsh->m_attrRemap[ii];
3205 					inputAttrib->binding  = 0;
3206 					inputAttrib->format = VK_FORMAT_R32G32B32_SFLOAT;
3207 					inputAttrib->offset = 0;
3208 					_vertexInputState.vertexAttributeDescriptionCount++;
3209 				}
3210 			}
3211 
3212 			if (0 < _numInstanceData)
3213 			{
3214 				fillInstanceBinding(_program.m_vsh, _vertexInputState, _numInstanceData);
3215 			}
3216 		}
3217 
getRenderPassHashkeybgfx::vk::RendererContextVK3218 		uint32_t getRenderPassHashkey(uint8_t _num, const Attachment* attachments)
3219 		{
3220 			if (_num == 0)
3221 				return 0;
3222 			bx::HashMurmur2A hash;
3223 			hash.begin(0);
3224 			for (uint8_t ii = 0; ii < _num; ++ii)
3225 			{
3226 				hash.add(attachments[ii].access);
3227 				hash.add(attachments[ii].layer);
3228 				hash.add(attachments[ii].mip);
3229 				hash.add(attachments[ii].resolve);
3230 
3231 				TextureVK& texture = m_textures[attachments[ii].handle.idx];
3232 				hash.add(texture.m_textureFormat);
3233 			}
3234 			return hash.end();
3235 		}
3236 
getRenderPassbgfx::vk::RendererContextVK3237 		VkRenderPass getRenderPass(uint8_t _num, const Attachment* _attachments)
3238 		{
3239 			VkRenderPass renderPass = VK_NULL_HANDLE;
3240 			uint32_t hashKey = getRenderPassHashkey(_num, _attachments);
3241 			renderPass = (VkRenderPass)m_renderPassCache.find(hashKey);
3242 			if (renderPass != VK_NULL_HANDLE)
3243 				return renderPass;
3244 
3245 			// cache missed
3246 			VkAttachmentDescription ad[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
3247 			VkAttachmentReference colorAr[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
3248 			VkAttachmentReference resolveAr[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
3249 			VkAttachmentReference depthAr;
3250 			uint32_t numColorAr = 0;
3251 
3252 			depthAr.attachment   = VK_ATTACHMENT_UNUSED;
3253 			depthAr.layout		 = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
3254 
3255 			for (uint8_t ii = 0; ii < _num; ++ii)
3256 			{
3257 				TextureVK& texture = m_textures[_attachments[ii].handle.idx];
3258 				ad[ii].flags          = 0;
3259 				ad[ii].format         = texture.m_vkTextureFormat;
3260 				ad[ii].samples        = VK_SAMPLE_COUNT_1_BIT;
3261 
3262 				if (texture.m_vkTextureAspect & VK_IMAGE_ASPECT_COLOR_BIT)
3263 				{
3264 					ad[ii].loadOp                  = VK_ATTACHMENT_LOAD_OP_LOAD;
3265 					ad[ii].storeOp                 = VK_ATTACHMENT_STORE_OP_STORE;
3266 					ad[ii].stencilLoadOp           = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
3267 					ad[ii].stencilStoreOp          = VK_ATTACHMENT_STORE_OP_DONT_CARE;
3268 					ad[ii].initialLayout           = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
3269 					ad[ii].finalLayout             = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
3270 					colorAr[numColorAr].layout     = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
3271 					colorAr[numColorAr].attachment = ii;
3272 					numColorAr++;
3273 				}
3274 				else if (texture.m_vkTextureAspect & VK_IMAGE_ASPECT_DEPTH_BIT)
3275 				{
3276 					ad[ii].loadOp         = VK_ATTACHMENT_LOAD_OP_LOAD;
3277 					ad[ii].storeOp        = VK_ATTACHMENT_STORE_OP_STORE;
3278 					ad[ii].stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_LOAD;
3279 					ad[ii].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
3280 					ad[ii].initialLayout  = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
3281 					ad[ii].finalLayout    = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
3282 					depthAr.layout        = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
3283 					depthAr.attachment    = ii;
3284 				}
3285 
3286 				resolveAr[ii].attachment = VK_ATTACHMENT_UNUSED;
3287 				resolveAr[ii].layout     = ad[ii].initialLayout;
3288 			}
3289 
3290 			VkSubpassDescription sd[1];
3291 			sd[0].flags                   = 0;
3292 			sd[0].pipelineBindPoint       = VK_PIPELINE_BIND_POINT_GRAPHICS;
3293 			sd[0].inputAttachmentCount    = 0;
3294 			sd[0].pInputAttachments       = NULL;
3295 			sd[0].colorAttachmentCount    = numColorAr;
3296 			sd[0].pColorAttachments       = colorAr;
3297 			sd[0].pResolveAttachments     = resolveAr;
3298 			sd[0].pDepthStencilAttachment = &depthAr;
3299 			sd[0].preserveAttachmentCount = 0;
3300 			sd[0].pPreserveAttachments    = NULL;
3301 
3302 			VkRenderPassCreateInfo rpi;
3303 			rpi.sType           = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
3304 			rpi.pNext           = NULL;
3305 			rpi.flags           = 0;
3306 			rpi.attachmentCount = _num;
3307 			rpi.pAttachments    = ad;
3308 			rpi.subpassCount    = BX_COUNTOF(sd);
3309 			rpi.pSubpasses      = sd;
3310 			rpi.dependencyCount = 0;
3311 			rpi.pDependencies   = NULL;
3312 
3313 			VK_CHECK( vkCreateRenderPass(m_device, &rpi, m_allocatorCb, &renderPass) );
3314 
3315 			m_renderPassCache.add(hashKey, renderPass);
3316 			return renderPass;
3317 		}
3318 
getSamplerbgfx::vk::RendererContextVK3319 		VkSampler getSampler(uint32_t _samplerFlags, uint32_t _mipLevels)
3320 		{
3321 			bx::HashMurmur2A hash;
3322 			hash.begin();
3323 			hash.add(_samplerFlags);
3324 			hash.add(_mipLevels);
3325 			uint32_t hashKey = hash.end();
3326 
3327 			VkSampler sampler = m_samplerCache.find(hashKey);
3328 			if (sampler != VK_NULL_HANDLE)
3329 			{
3330 				return sampler;
3331 			}
3332 
3333 			const uint32_t cmpFunc = (_samplerFlags&BGFX_SAMPLER_COMPARE_MASK)>>BGFX_SAMPLER_COMPARE_SHIFT;
3334 
3335 			VkSamplerCreateInfo sci;
3336 			sci.sType            = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
3337 			sci.pNext            = NULL;
3338 			sci.flags            = 0;
3339 			sci.magFilter        = VK_FILTER_LINEAR;
3340 			sci.minFilter        = VK_FILTER_LINEAR;
3341 			sci.mipmapMode       = VK_SAMPLER_MIPMAP_MODE_LINEAR;
3342 			sci.addressModeU     = s_textureAddress[(_samplerFlags&BGFX_SAMPLER_U_MASK)>>BGFX_SAMPLER_U_SHIFT];
3343 			sci.addressModeV     = s_textureAddress[(_samplerFlags&BGFX_SAMPLER_V_MASK)>>BGFX_SAMPLER_V_SHIFT];
3344 			sci.addressModeW     = s_textureAddress[(_samplerFlags&BGFX_SAMPLER_W_MASK)>>BGFX_SAMPLER_W_SHIFT];
3345 			sci.mipLodBias       = 0.0f;
3346 			sci.anisotropyEnable = VK_FALSE;
3347 			sci.maxAnisotropy    = 4.0f;
3348 			sci.compareEnable    = 0 != cmpFunc;
3349 			sci.compareOp        = s_cmpFunc[cmpFunc];
3350 			sci.minLod           = 0.0f;
3351 			sci.maxLod           = (float)_mipLevels;
3352 			sci.borderColor      = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
3353 			sci.unnormalizedCoordinates = VK_FALSE;
3354 
3355 			switch (_samplerFlags & BGFX_SAMPLER_MAG_MASK)
3356 			{
3357 				case BGFX_SAMPLER_MAG_POINT:       sci.magFilter = VK_FILTER_NEAREST; break;
3358 				case BGFX_SAMPLER_MAG_ANISOTROPIC: sci.anisotropyEnable = VK_TRUE;    break;
3359 			}
3360 
3361 			switch (_samplerFlags & BGFX_SAMPLER_MIN_MASK)
3362 			{
3363 				case BGFX_SAMPLER_MIN_POINT:       sci.minFilter = VK_FILTER_NEAREST; break;
3364 				case BGFX_SAMPLER_MIN_ANISOTROPIC: sci.anisotropyEnable = VK_TRUE;    break;
3365 			}
3366 
3367 			uint32_t borderColor = ((_samplerFlags & BGFX_SAMPLER_BORDER_COLOR_MASK) >> BGFX_SAMPLER_BORDER_COLOR_SHIFT);
3368 			if (borderColor > 0)
3369 			{
3370 				sci.borderColor = VK_BORDER_COLOR_INT_OPAQUE_WHITE;
3371 			}
3372 
3373 			VK_CHECK(vkCreateSampler(m_device, &sci, m_allocatorCb, &sampler));
3374 
3375 			m_samplerCache.add(hashKey, sampler);
3376 			return sampler;
3377 		}
3378 
getPipelinebgfx::vk::RendererContextVK3379 		VkPipeline getPipeline(ProgramHandle _program)
3380 		{
3381 			ProgramVK& program = m_program[_program.idx];
3382 
3383 			bx::HashMurmur2A murmur;
3384 			murmur.begin();
3385 			murmur.add(program.m_vsh->m_hash);
3386 			const uint32_t hash = murmur.end();
3387 
3388 			VkPipeline pipeline = m_pipelineStateCache.find(hash);
3389 
3390 			if (VK_NULL_HANDLE != pipeline)
3391 			{
3392 				return pipeline;
3393 			}
3394 
3395 			VkComputePipelineCreateInfo cpci;
3396 			cpci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
3397 			cpci.pNext = NULL;
3398 			cpci.flags = 0;
3399 
3400 			cpci.stage.sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
3401 			cpci.stage.pNext  = NULL;
3402 			cpci.stage.flags  = 0;
3403 			cpci.stage.stage  = VK_SHADER_STAGE_COMPUTE_BIT;
3404 			cpci.stage.module = program.m_vsh->m_module;
3405 			cpci.stage.pName  = "main";
3406 			cpci.stage.pSpecializationInfo = NULL;
3407 
3408 			cpci.layout             = program.m_pipelineLayout;
3409 			cpci.basePipelineHandle = VK_NULL_HANDLE;
3410 			cpci.basePipelineIndex  = 0;
3411 
3412 			VK_CHECK( vkCreateComputePipelines(m_device, m_pipelineCache, 1, &cpci, m_allocatorCb, &pipeline) );
3413 
3414 			m_pipelineStateCache.add(hash, pipeline);
3415 
3416 			return pipeline;
3417 		}
3418 
getPipelinebgfx::vk::RendererContextVK3419 		VkPipeline getPipeline(uint64_t _state, uint64_t _stencil, uint8_t _numStreams, const VertexLayout** _layouts, ProgramHandle _program, uint8_t _numInstanceData)
3420 		{
3421 			ProgramVK& program = m_program[_program.idx];
3422 
3423 			_state &= 0
3424 				| BGFX_STATE_WRITE_RGB
3425 				| BGFX_STATE_WRITE_A
3426 				| BGFX_STATE_WRITE_Z
3427 				| BGFX_STATE_DEPTH_TEST_MASK
3428 				| BGFX_STATE_BLEND_MASK
3429 				| BGFX_STATE_BLEND_EQUATION_MASK
3430 				| BGFX_STATE_BLEND_INDEPENDENT
3431 				| BGFX_STATE_BLEND_ALPHA_TO_COVERAGE
3432 				| BGFX_STATE_CULL_MASK
3433 				| BGFX_STATE_MSAA
3434 				| BGFX_STATE_LINEAA
3435 				| BGFX_STATE_CONSERVATIVE_RASTER
3436 				| BGFX_STATE_PT_MASK
3437 				;
3438 
3439 			_stencil &= packStencil(~BGFX_STENCIL_FUNC_REF_MASK, ~BGFX_STENCIL_FUNC_REF_MASK);
3440 
3441 			VertexLayout layout;
3442 			if (0 < _numStreams)
3443 			{
3444 				bx::memCopy(&layout, _layouts[0], sizeof(VertexLayout) );
3445 				const uint16_t* attrMask = program.m_vsh->m_attrMask;
3446 
3447 				for (uint32_t ii = 0; ii < Attrib::Count; ++ii)
3448 				{
3449 					uint16_t mask = attrMask[ii];
3450 					uint16_t attr = (layout.m_attributes[ii] & mask);
3451 					layout.m_attributes[ii] = attr == 0 ? UINT16_MAX : attr == UINT16_MAX ? 0 : attr;
3452 				}
3453 			}
3454 
3455 			bx::HashMurmur2A murmur;
3456 			murmur.begin();
3457 			murmur.add(_state);
3458 			murmur.add(_stencil);
3459 			murmur.add(program.m_vsh->m_hash);
3460 			murmur.add(program.m_vsh->m_attrMask, sizeof(program.m_vsh->m_attrMask) );
3461 			murmur.add(program.m_fsh->m_hash);
3462 			for (uint8_t ii = 0; ii < _numStreams; ++ii)
3463 			{
3464 				murmur.add(_layouts[ii]->m_hash);
3465 			}
3466 			murmur.add(layout.m_attributes, sizeof(layout.m_attributes) );
3467 			murmur.add(m_fbh.idx);
3468 			murmur.add(_numInstanceData);
3469 			const uint32_t hash = murmur.end();
3470 
3471 			VkPipeline pipeline = m_pipelineStateCache.find(hash);
3472 
3473 			if (VK_NULL_HANDLE != pipeline)
3474 			{
3475 				return pipeline;
3476 			}
3477 
3478 			VkPipelineColorBlendAttachmentState blendAttachmentState[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
3479 			VkPipelineColorBlendStateCreateInfo colorBlendState;
3480 			colorBlendState.pAttachments = blendAttachmentState;
3481 			setBlendState(colorBlendState, _state);
3482 
3483 			VkPipelineInputAssemblyStateCreateInfo inputAssemblyState;
3484 			inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
3485 			inputAssemblyState.pNext = NULL;
3486 			inputAssemblyState.flags = 0;
3487 			inputAssemblyState.topology = s_primInfo[(_state&BGFX_STATE_PT_MASK) >> BGFX_STATE_PT_SHIFT].m_topology;
3488 			inputAssemblyState.primitiveRestartEnable = VK_FALSE;
3489 
3490 			VkPipelineRasterizationStateCreateInfo rasterizationState;
3491 			setRasterizerState(rasterizationState, _state);
3492 
3493 			VkPipelineDepthStencilStateCreateInfo depthStencilState;
3494 			setDepthStencilState(depthStencilState, _state, _stencil);
3495 
3496 			VkVertexInputBindingDescription  inputBinding[Attrib::Count + 1 + BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT];
3497 			VkVertexInputAttributeDescription inputAttrib[Attrib::Count + 1 + BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT];
3498 
3499 			VkPipelineVertexInputStateCreateInfo vertexInputState;
3500 			vertexInputState.pVertexBindingDescriptions   = inputBinding;
3501 			vertexInputState.pVertexAttributeDescriptions = inputAttrib;
3502 			setInputLayout(vertexInputState, _numStreams, _layouts, program, _numInstanceData);
3503 
3504 			const VkDynamicState dynamicStates[] =
3505 			{
3506 				VK_DYNAMIC_STATE_VIEWPORT,
3507 				VK_DYNAMIC_STATE_SCISSOR,
3508 				VK_DYNAMIC_STATE_BLEND_CONSTANTS,
3509 				VK_DYNAMIC_STATE_STENCIL_REFERENCE,
3510 			};
3511 
3512 			VkPipelineDynamicStateCreateInfo dynamicState;
3513 			dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
3514 			dynamicState.pNext = NULL;
3515 			dynamicState.flags = 0;
3516 			dynamicState.dynamicStateCount = BX_COUNTOF(dynamicStates);
3517 			dynamicState.pDynamicStates    = dynamicStates;
3518 
3519 			VkPipelineShaderStageCreateInfo shaderStages[2];
3520 			shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
3521 			shaderStages[0].pNext = NULL;
3522 			shaderStages[0].flags = 0;
3523 			shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
3524 			shaderStages[0].module = program.m_vsh->m_module;
3525 			shaderStages[0].pName  = "main";
3526 			shaderStages[0].pSpecializationInfo = NULL;
3527 			shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
3528 			shaderStages[1].pNext = NULL;
3529 			shaderStages[1].flags = 0;
3530 			shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
3531 			shaderStages[1].module = program.m_fsh->m_module;
3532 			shaderStages[1].pName  = "main";
3533 			shaderStages[1].pSpecializationInfo = NULL;
3534 
3535 			VkPipelineViewportStateCreateInfo viewportState;
3536 			viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
3537 			viewportState.pNext = NULL;
3538 			viewportState.flags = 0;
3539 			viewportState.viewportCount = 1;
3540 			viewportState.pViewports    = NULL;
3541 			viewportState.scissorCount  = 1;
3542 			viewportState.pScissors     = NULL;
3543 
3544 			VkPipelineMultisampleStateCreateInfo multisampleState;
3545 			multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
3546 			multisampleState.pNext = NULL;
3547 			multisampleState.flags = 0;
3548 			multisampleState.rasterizationSamples  = VK_SAMPLE_COUNT_1_BIT;
3549 			multisampleState.sampleShadingEnable   = VK_FALSE;
3550 			multisampleState.minSampleShading      = !!(BGFX_STATE_CONSERVATIVE_RASTER & _state) ? 1.0f : 0.0f;
3551 			multisampleState.pSampleMask           = NULL;
3552 			multisampleState.alphaToCoverageEnable = !!(BGFX_STATE_BLEND_ALPHA_TO_COVERAGE & _state);
3553 			multisampleState.alphaToOneEnable      = VK_FALSE;
3554 
3555 			VkGraphicsPipelineCreateInfo graphicsPipeline;
3556 			graphicsPipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
3557 			graphicsPipeline.pNext = NULL;
3558 			graphicsPipeline.flags = 0;
3559 			graphicsPipeline.stageCount = BX_COUNTOF(shaderStages);
3560 			graphicsPipeline.pStages    = shaderStages;
3561 			graphicsPipeline.pVertexInputState   = &vertexInputState;
3562 			graphicsPipeline.pInputAssemblyState = &inputAssemblyState;
3563 			graphicsPipeline.pTessellationState  = NULL;
3564 			graphicsPipeline.pViewportState      = &viewportState;
3565 			graphicsPipeline.pRasterizationState = &rasterizationState;
3566 			graphicsPipeline.pMultisampleState   = &multisampleState;
3567 			graphicsPipeline.pDepthStencilState  = &depthStencilState;
3568 			graphicsPipeline.pColorBlendState    = &colorBlendState;
3569 			graphicsPipeline.pDynamicState       = &dynamicState;
3570 //			graphicsPipeline.layout     = m_pipelineLayout;
3571 			graphicsPipeline.layout     = program.m_pipelineLayout;
3572 			graphicsPipeline.renderPass = isValid(m_fbh) ? m_frameBuffers[m_fbh.idx].m_renderPass : m_renderPass;
3573 			graphicsPipeline.subpass    = 0;
3574 			graphicsPipeline.basePipelineHandle = VK_NULL_HANDLE;
3575 			graphicsPipeline.basePipelineIndex  = 0;
3576 
3577 			uint32_t length = g_callback->cacheReadSize(hash);
3578 			bool cached = length > 0;
3579 
3580 			void* cachedData = NULL;
3581 
3582 			VkPipelineCacheCreateInfo pcci;
3583 			pcci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
3584 			pcci.pNext = NULL;
3585 			pcci.flags = 0;
3586 			pcci.initialDataSize = 0;
3587 			pcci.pInitialData    = NULL;
3588 
3589 			if (cached)
3590 			{
3591 				cachedData = BX_ALLOC(g_allocator, length);
3592 				if (g_callback->cacheRead(hash, cachedData, length) )
3593 				{
3594 					BX_TRACE("Loading cached pipeline state (size %d).", length);
3595 					bx::MemoryReader reader(cachedData, length);
3596 
3597 					pcci.initialDataSize = (size_t)reader.remaining();
3598 					pcci.pInitialData    = reader.getDataPtr();
3599 				}
3600 			}
3601 
3602 			VkPipelineCache cache;
3603 			VK_CHECK(vkCreatePipelineCache(m_device, &pcci, m_allocatorCb, &cache) );
3604 
3605 			VK_CHECK(vkCreateGraphicsPipelines(m_device
3606 				, cache
3607 				, 1
3608 				, &graphicsPipeline
3609 				, m_allocatorCb
3610 				, &pipeline
3611 				) );
3612 			m_pipelineStateCache.add(hash, pipeline);
3613 
3614 			size_t dataSize;
3615 			VK_CHECK(vkGetPipelineCacheData(m_device, cache, &dataSize, NULL) );
3616 
3617 			if (0 < dataSize)
3618 			{
3619 				if (length < dataSize)
3620 				{
3621 					cachedData = BX_REALLOC(g_allocator, cachedData, dataSize);
3622 				}
3623 				VK_CHECK(vkGetPipelineCacheData(m_device, cache, &dataSize, cachedData) );
3624 				g_callback->cacheWrite(hash, cachedData, (uint32_t)dataSize);
3625 			}
3626 
3627 			VK_CHECK(vkMergePipelineCaches(m_device, m_pipelineCache, 1, &cache) );
3628 			vkDestroy(cache);
3629 
3630 			if (NULL != cachedData)
3631 			{
3632 				BX_FREE(g_allocator, cachedData);
3633 			}
3634 
3635 			return pipeline;
3636 		}
3637 
allocDescriptorSetbgfx::vk::RendererContextVK3638 		void allocDescriptorSet(ProgramVK& program, const RenderBind& renderBind, ScratchBufferVK& scratchBuffer)
3639 		{
3640 			VkDescriptorSetLayout dsl = m_descriptorSetLayoutCache.find(program.m_descriptorSetLayoutHash);
3641 			VkDescriptorSetAllocateInfo dsai;
3642 			dsai.sType              = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
3643 			dsai.pNext              = NULL;
3644 			dsai.descriptorPool     = m_descriptorPool;
3645 			dsai.descriptorSetCount = 1;
3646 			dsai.pSetLayouts        = &dsl;
3647 
3648 			VkDescriptorSet& descriptorSet = scratchBuffer.m_descriptorSet[scratchBuffer.m_currentDs];
3649 			vkAllocateDescriptorSets(m_device, &dsai, &descriptorSet);
3650 			scratchBuffer.m_currentDs++;
3651 
3652 			VkDescriptorImageInfo imageInfo[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
3653 			VkDescriptorBufferInfo bufferInfo[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
3654 			VkWriteDescriptorSet wds[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
3655 			bx::memSet(wds, 0, sizeof(VkWriteDescriptorSet) * BGFX_CONFIG_MAX_TEXTURE_SAMPLERS);
3656 			uint32_t wdsCount    = 0;
3657 			uint32_t bufferCount = 0;
3658 			uint32_t imageCount  = 0;
3659 
3660 			for (uint32_t stage = 0; stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++stage)
3661 			{
3662 				const Binding& bind = renderBind.m_bind[stage];
3663 				if (kInvalidHandle != bind.m_idx)
3664 				{
3665 					const ShaderVK::BindInfo* bindInfo = NULL;
3666 					if (isValid(program.m_vsh->m_bindInfo[stage].uniformHandle))
3667 					{
3668 						bindInfo = &(program.m_vsh->m_bindInfo[stage]);
3669 					}
3670 					else if (NULL != program.m_fsh && isValid(program.m_fsh->m_bindInfo[stage].uniformHandle))
3671 					{
3672 						bindInfo = &(program.m_fsh->m_bindInfo[stage]);
3673 					}
3674 
3675 					if (NULL == bindInfo)
3676 					{
3677 						continue;
3678 					}
3679 
3680 					if (ShaderVK::BindType::Storage == bindInfo->type)
3681 					{
3682 						VkDescriptorType descriptorType = (VkDescriptorType)bindInfo->samplerBinding;
3683 						wds[wdsCount].sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3684 						wds[wdsCount].pNext            = NULL;
3685 						wds[wdsCount].dstSet           = descriptorSet;
3686 						wds[wdsCount].dstBinding       = bindInfo->binding;
3687 						wds[wdsCount].dstArrayElement  = 0;
3688 						wds[wdsCount].descriptorCount  = 1;
3689 						wds[wdsCount].descriptorType   = descriptorType;
3690 						wds[wdsCount].pImageInfo       = NULL;
3691 						wds[wdsCount].pBufferInfo      = NULL;
3692 						wds[wdsCount].pTexelBufferView = NULL;
3693 
3694 						if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == descriptorType)
3695 						{
3696 							VertexBufferVK& vb = m_vertexBuffers[bind.m_idx];
3697 							bufferInfo[bufferCount].buffer = vb.m_buffer;
3698 							bufferInfo[bufferCount].offset = 0;
3699 							bufferInfo[bufferCount].range  = vb.m_size;
3700 							wds[wdsCount].pBufferInfo = &bufferInfo[bufferCount];
3701 							++bufferCount;
3702 						}
3703 						else if (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE == descriptorType)
3704 						{
3705 							TextureVK& texture = m_textures[bind.m_idx];
3706 							VkSampler sampler = getSampler(
3707 								(0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags)
3708 									? bind.m_samplerFlags
3709 									: (uint32_t)texture.m_flags
3710 								) & (BGFX_SAMPLER_BITS_MASK | BGFX_SAMPLER_BORDER_COLOR_MASK)
3711 								, (uint32_t)texture.m_numMips);
3712 
3713 							if (VK_IMAGE_LAYOUT_GENERAL != texture.m_currentImageLayout
3714 							&&  VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL != texture.m_currentImageLayout)
3715 							{
3716 								texture.setImageMemoryBarrier(m_commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
3717 							}
3718 
3719 							imageInfo[imageCount].imageLayout = texture.m_currentImageLayout;
3720 							imageInfo[imageCount].imageView   = VK_NULL_HANDLE != texture.m_textureImageStorageView
3721 								? texture.m_textureImageStorageView
3722 								: texture.m_textureImageView
3723 								;
3724 							imageInfo[imageCount].sampler     = sampler;
3725 							wds[wdsCount].pImageInfo = &imageInfo[imageCount];
3726 							++imageCount;
3727 						}
3728 
3729 						++wdsCount;
3730 					}
3731 					else if (ShaderVK::BindType::Sampler == bindInfo->type)
3732 					{
3733 						TextureVK& texture = m_textures[bind.m_idx];
3734 						VkSampler sampler = getSampler(
3735 							(0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags)
3736 								? bind.m_samplerFlags
3737 								: (uint32_t)texture.m_flags
3738 							) & (BGFX_SAMPLER_BITS_MASK | BGFX_SAMPLER_BORDER_COLOR_MASK)
3739 							, (uint32_t)texture.m_numMips);
3740 
3741 						if (VK_IMAGE_LAYOUT_GENERAL != texture.m_currentImageLayout
3742 						&&  VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL != texture.m_currentImageLayout)
3743 						{
3744 							texture.setImageMemoryBarrier(m_commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
3745 						}
3746 
3747 						imageInfo[imageCount].imageLayout = texture.m_currentImageLayout;
3748 						imageInfo[imageCount].imageView   = VK_NULL_HANDLE != texture.m_textureImageDepthView
3749 							? texture.m_textureImageDepthView
3750 							: texture.m_textureImageView
3751 							;
3752 						imageInfo[imageCount].sampler     = sampler;
3753 
3754 						wds[wdsCount].sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3755 						wds[wdsCount].pNext            = NULL;
3756 						wds[wdsCount].dstSet           = descriptorSet;
3757 						wds[wdsCount].dstBinding       = bindInfo->binding;
3758 						wds[wdsCount].dstArrayElement  = 0;
3759 						wds[wdsCount].descriptorCount  = 1;
3760 						wds[wdsCount].descriptorType   = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3761 						wds[wdsCount].pImageInfo       = &imageInfo[imageCount];
3762 						wds[wdsCount].pBufferInfo      = NULL;
3763 						wds[wdsCount].pTexelBufferView = NULL;
3764 						++wdsCount;
3765 
3766 						wds[wdsCount].sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3767 						wds[wdsCount].pNext            = NULL;
3768 						wds[wdsCount].dstSet           = descriptorSet;
3769 						wds[wdsCount].dstBinding       = bindInfo->samplerBinding;
3770 						wds[wdsCount].dstArrayElement  = 0;
3771 						wds[wdsCount].descriptorCount  = 1;
3772 						wds[wdsCount].descriptorType   = VK_DESCRIPTOR_TYPE_SAMPLER;
3773 						wds[wdsCount].pImageInfo       = &imageInfo[imageCount];
3774 						wds[wdsCount].pBufferInfo      = NULL;
3775 						wds[wdsCount].pTexelBufferView = NULL;
3776 						++wdsCount;
3777 
3778 						++imageCount;
3779 					}
3780 				}
3781 			}
3782 
3783 			const uint32_t align = uint32_t(m_deviceProperties.limits.minUniformBufferOffsetAlignment);
3784 			const uint32_t vsize = bx::strideAlign(program.m_vsh->m_size, align);
3785 			const uint32_t fsize = bx::strideAlign((NULL != program.m_fsh ? program.m_fsh->m_size : 0), align);
3786 			const uint32_t total = vsize + fsize;
3787 
3788 			if (0 < total)
3789 			{
3790 				uint32_t vsUniformBinding = program.m_vsh->m_uniformBinding;
3791 				uint32_t fsUniformBinding = program.m_fsh ? program.m_fsh->m_uniformBinding : 0;
3792 
3793 				if (vsize > 0)
3794 				{
3795 					bufferInfo[bufferCount].buffer = scratchBuffer.m_buffer;
3796 					bufferInfo[bufferCount].offset = 0;
3797 					bufferInfo[bufferCount].range  = vsize;
3798 
3799 					wds[wdsCount].sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3800 					wds[wdsCount].pNext            = NULL;
3801 					wds[wdsCount].dstSet           = descriptorSet;
3802 					wds[wdsCount].dstBinding       = vsUniformBinding;
3803 					wds[wdsCount].dstArrayElement  = 0;
3804 					wds[wdsCount].descriptorCount  = 1;
3805 					wds[wdsCount].descriptorType   = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
3806 					wds[wdsCount].pImageInfo       = NULL;
3807 					wds[wdsCount].pBufferInfo      = &bufferInfo[bufferCount];
3808 					wds[wdsCount].pTexelBufferView = NULL;
3809 					++wdsCount;
3810 					++bufferCount;
3811 				}
3812 
3813 				if (fsize > 0)
3814 				{
3815 					bufferInfo[bufferCount].buffer = scratchBuffer.m_buffer;
3816 					bufferInfo[bufferCount].offset = 0;
3817 					bufferInfo[bufferCount].range  = fsize;
3818 
3819 					wds[wdsCount].sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3820 					wds[wdsCount].pNext            = NULL;
3821 					wds[wdsCount].dstSet           = descriptorSet;
3822 					wds[wdsCount].dstBinding       = fsUniformBinding;
3823 					wds[wdsCount].dstArrayElement  = 0;
3824 					wds[wdsCount].descriptorCount  = 1;
3825 					wds[wdsCount].descriptorType   = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
3826 					wds[wdsCount].pImageInfo       = NULL;
3827 					wds[wdsCount].pBufferInfo      = &bufferInfo[bufferCount];
3828 					wds[wdsCount].pTexelBufferView = NULL;
3829 					++wdsCount;
3830 					++bufferCount;
3831 				}
3832 			}
3833 
3834 			vkUpdateDescriptorSets(m_device, wdsCount, wds, 0, NULL);
3835 		}
3836 
commitbgfx::vk::RendererContextVK3837 		void commit(UniformBuffer& _uniformBuffer)
3838 		{
3839 			_uniformBuffer.reset();
3840 
3841 			for (;;)
3842 			{
3843 				uint32_t opcode = _uniformBuffer.read();
3844 
3845 				if (UniformType::End == opcode)
3846 				{
3847 					break;
3848 				}
3849 
3850 				UniformType::Enum type;
3851 				uint16_t loc;
3852 				uint16_t num;
3853 				uint16_t copy;
3854 				UniformBuffer::decodeOpcode(opcode, type, loc, num, copy);
3855 
3856 				const char* data;
3857 				if (copy)
3858 				{
3859 					data = _uniformBuffer.read(g_uniformTypeSize[type]*num);
3860 				}
3861 				else
3862 				{
3863 					UniformHandle handle;
3864 					bx::memCopy(&handle, _uniformBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) );
3865 					data = (const char*)m_uniforms[handle.idx];
3866 				}
3867 
3868 #define CASE_IMPLEMENT_UNIFORM(_uniform, _dxsuffix, _type)                   \
3869 				case UniformType::_uniform:                                  \
3870 				case UniformType::_uniform|BGFX_UNIFORM_FRAGMENTBIT:         \
3871 						{                                                    \
3872 							setShaderUniform(uint8_t(type), loc, data, num); \
3873 						}                                                    \
3874 						break;
3875 
3876 				switch ( (uint32_t)type)
3877 				{
3878 				case UniformType::Mat3:
3879 				case UniformType::Mat3|BGFX_UNIFORM_FRAGMENTBIT:
3880 					 {
3881 						 float* value = (float*)data;
3882 						 for (uint32_t ii = 0, count = num/3; ii < count; ++ii,  loc += 3*16, value += 9)
3883 						 {
3884 							 Matrix4 mtx;
3885 							 mtx.un.val[ 0] = value[0];
3886 							 mtx.un.val[ 1] = value[1];
3887 							 mtx.un.val[ 2] = value[2];
3888 							 mtx.un.val[ 3] = 0.0f;
3889 							 mtx.un.val[ 4] = value[3];
3890 							 mtx.un.val[ 5] = value[4];
3891 							 mtx.un.val[ 6] = value[5];
3892 							 mtx.un.val[ 7] = 0.0f;
3893 							 mtx.un.val[ 8] = value[6];
3894 							 mtx.un.val[ 9] = value[7];
3895 							 mtx.un.val[10] = value[8];
3896 							 mtx.un.val[11] = 0.0f;
3897 							 setShaderUniform(uint8_t(type), loc, &mtx.un.val[0], 3);
3898 						 }
3899 					}
3900 					break;
3901 
3902 				case UniformType::Sampler:
3903 				case UniformType::Sampler|BGFX_UNIFORM_FRAGMENTBIT:
3904 					// do nothing, but VkDescriptorSetImageInfo would be set before drawing
3905 					break;
3906 //				CASE_IMPLEMENT_UNIFORM(Sampler, I, int);
3907 				CASE_IMPLEMENT_UNIFORM(Vec4,    F, float);
3908 				CASE_IMPLEMENT_UNIFORM(Mat4,    F, float);
3909 
3910 				case UniformType::End:
3911 					break;
3912 
3913 				default:
3914 					BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _uniformBuffer.getPos(), opcode, type, loc, num, copy);
3915 					break;
3916 				}
3917 #undef CASE_IMPLEMENT_UNIFORM
3918 			}
3919 		}
3920 
clearQuadbgfx::vk::RendererContextVK3921 		void clearQuad(const Rect& _rect, const Clear& _clear, const float _palette[][4])
3922 		{
3923 			VkClearRect rect[1];
3924 			rect[0].rect.offset.x      = _rect.m_x;
3925 			rect[0].rect.offset.y      = _rect.m_y;
3926 			rect[0].rect.extent.width  = _rect.m_width;
3927 			rect[0].rect.extent.height = _rect.m_height;
3928 			rect[0].baseArrayLayer = 0;
3929 			rect[0].layerCount     = 1;
3930 
3931 			uint32_t numMrt = 1;
3932 			FrameBufferHandle fbh = m_fbh;
3933 			if (isValid(fbh) )
3934 			{
3935 				const FrameBufferVK& fb = m_frameBuffers[fbh.idx];
3936 				numMrt = bx::max((uint8_t)1, fb.m_num);
3937 			}
3938 
3939 			VkClearAttachment attachments[BGFX_CONFIG_MAX_FRAME_BUFFERS];
3940 			uint32_t mrt = 0;
3941 
3942 			if (true //NULL != m_currentColor
3943 			&&  BGFX_CLEAR_COLOR & _clear.m_flags)
3944 			{
3945 				if (BGFX_CLEAR_COLOR_USE_PALETTE & _clear.m_flags)
3946 				{
3947 					for (uint32_t ii = 0; ii < numMrt; ++ii)
3948 					{
3949 						attachments[mrt].colorAttachment = mrt;
3950 						attachments[mrt].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3951 						uint8_t index = bx::min<uint8_t>(BGFX_CONFIG_MAX_COLOR_PALETTE-1, _clear.m_index[ii]);
3952 						bx::memCopy(&attachments[mrt].clearValue.color.float32, _palette[index], 16);
3953 						++mrt;
3954 					}
3955 				}
3956 				else
3957 				{
3958 					float frgba[4] =
3959 					{
3960 						_clear.m_index[0] * 1.0f / 255.0f,
3961 						_clear.m_index[1] * 1.0f / 255.0f,
3962 						_clear.m_index[2] * 1.0f / 255.0f,
3963 						_clear.m_index[3] * 1.0f / 255.0f,
3964 					};
3965 
3966 					for (uint32_t ii = 0; ii < numMrt; ++ii)
3967 					{
3968 						attachments[mrt].colorAttachment = mrt;
3969 						attachments[mrt].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3970 						bx::memCopy(&attachments[mrt].clearValue.color.float32, frgba, 16);
3971 						++mrt;
3972 					}
3973 				}
3974 			}
3975 
3976 			if (true //NULL != m_currentDepthStencil
3977 			&& (BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL) & _clear.m_flags)
3978 			{
3979 				attachments[mrt].colorAttachment = mrt;
3980 				attachments[mrt].aspectMask = 0;
3981 				attachments[mrt].aspectMask |= (_clear.m_flags & BGFX_CLEAR_DEPTH  ) ? VK_IMAGE_ASPECT_DEPTH_BIT   : 0;
3982 				attachments[mrt].aspectMask |= (_clear.m_flags & BGFX_CLEAR_STENCIL) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0;
3983 
3984 				attachments[mrt].clearValue.depthStencil.stencil = _clear.m_stencil;
3985 				attachments[mrt].clearValue.depthStencil.depth   = _clear.m_depth;
3986 				++mrt;
3987 			}
3988 
3989 			if (mrt > 0)
3990 			{
3991 				vkCmdClearAttachments(m_commandBuffer
3992 					, mrt
3993 					, attachments
3994 					, BX_COUNTOF(rect)
3995 					, rect
3996 					);
3997 			}
3998 		}
3999 
kickbgfx::vk::RendererContextVK4000 		uint64_t kick(VkSemaphore _wait = VK_NULL_HANDLE, VkSemaphore _signal = VK_NULL_HANDLE)
4001 		{
4002 			VkPipelineStageFlags stageFlags = 0
4003 				| VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
4004 				;
4005 
4006 			VkSubmitInfo si;
4007 			si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
4008 			si.pNext = NULL;
4009 			si.waitSemaphoreCount = VK_NULL_HANDLE != _wait;
4010 			si.pWaitSemaphores    = &_wait;
4011 			si.pWaitDstStageMask  = &stageFlags;
4012 			si.commandBufferCount = 1;
4013 			si.pCommandBuffers    = &m_commandBuffers[m_backBufferColorIdx];
4014 			si.signalSemaphoreCount = VK_NULL_HANDLE != _signal;
4015 			si.pSignalSemaphores    = &_signal;
4016 
4017 //			VK_CHECK(vkResetFences(m_device, 1, &m_fence) );
4018 			VK_CHECK(vkQueueSubmit(m_queueGraphics, 1, &si, VK_NULL_HANDLE) );
4019 			return 0;
4020 		}
4021 
finishbgfx::vk::RendererContextVK4022 		void finish()
4023 		{
4024 			finishAll();
4025 		}
4026 
finishAllbgfx::vk::RendererContextVK4027 		void finishAll()
4028 		{
4029 			VK_CHECK(vkQueueWaitIdle(m_queueGraphics) );
4030 //			VK_CHECK(vkWaitForFences(m_device, 1, &m_fence, true, INT64_MAX) );
4031 		}
4032 
selectMemoryTypebgfx::vk::RendererContextVK4033 		uint32_t selectMemoryType(uint32_t _memoryTypeBits, uint32_t _propertyFlags) const
4034 		{
4035 			for (uint32_t ii = 0, num = m_memoryProperties.memoryTypeCount; ii < num; ++ii)
4036 			{
4037 				const VkMemoryType& memType = m_memoryProperties.memoryTypes[ii];
4038 				if ( (0 != ( (1<<ii) & _memoryTypeBits) )
4039 				&& ( (memType.propertyFlags & _propertyFlags) == _propertyFlags) )
4040 				{
4041 					return ii;
4042 				}
4043 			}
4044 
4045 			BX_TRACE("Failed to find memory that supports flags 0x%08x.", _propertyFlags);
4046 			return 0;
4047 		}
4048 
beginNewCommandbgfx::vk::RendererContextVK4049 		VkCommandBuffer beginNewCommand(VkCommandBufferUsageFlagBits commandBufferUsageFlag = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)
4050 		{
4051 			VkCommandBufferAllocateInfo cbai;
4052 			cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
4053 			cbai.pNext = NULL;
4054 			cbai.commandPool = m_commandPool;
4055 			cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
4056 			cbai.commandBufferCount = 1;
4057 
4058 			VkCommandBuffer commandBuffer;
4059 			VK_CHECK(vkAllocateCommandBuffers(m_device, &cbai, &commandBuffer));
4060 
4061 			VkCommandBufferBeginInfo cbbi;
4062 			cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
4063 			cbbi.pNext = NULL;
4064 			cbbi.flags = commandBufferUsageFlag;
4065 			cbbi.pInheritanceInfo = NULL;
4066 			VK_CHECK(vkBeginCommandBuffer(commandBuffer, &cbbi));
4067 
4068 			return commandBuffer;
4069 		}
4070 
submitCommandAndWaitbgfx::vk::RendererContextVK4071 		void submitCommandAndWait(VkCommandBuffer commandBuffer)
4072 		{
4073 			vkEndCommandBuffer(commandBuffer);
4074 
4075 			VkSubmitInfo submitInfo;
4076 			submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
4077 			submitInfo.pNext = NULL;
4078 			submitInfo.commandBufferCount = 1;
4079 			submitInfo.pCommandBuffers = &commandBuffer;
4080 			submitInfo.waitSemaphoreCount = 0;
4081 			submitInfo.pWaitSemaphores = NULL;
4082 			submitInfo.signalSemaphoreCount = 0;
4083 			submitInfo.pSignalSemaphores = NULL;
4084 			submitInfo.pWaitDstStageMask = NULL;
4085 
4086 			VK_CHECK(vkQueueSubmit(m_queueGraphics, 1, &submitInfo, VK_NULL_HANDLE));
4087 			VK_CHECK(vkQueueWaitIdle(m_queueGraphics));
4088 
4089 			vkFreeCommandBuffers(m_device, m_commandPool, 1, &commandBuffer);
4090 		}
4091 
4092 #define NUM_SWAPCHAIN_IMAGE 4
4093 		VkAllocationCallbacks*   m_allocatorCb;
4094 		VkDebugReportCallbackEXT m_debugReportCallback;
4095 		VkInstance       m_instance;
4096 		VkPhysicalDevice m_physicalDevice;
4097 
4098 		VkPhysicalDeviceProperties       m_deviceProperties;
4099 		VkPhysicalDeviceMemoryProperties m_memoryProperties;
4100 		VkPhysicalDeviceFeatures         m_deviceFeatures;
4101 
4102 		VkSwapchainCreateInfoKHR m_sci;
4103 		VkSurfaceKHR     m_surface;
4104 		VkSwapchainKHR   m_swapchain;
4105 		uint32_t         m_numSwapchainImages;
4106 		VkImageLayout    m_backBufferColorImageLayout[NUM_SWAPCHAIN_IMAGE];
4107 		VkImage          m_backBufferColorImage[NUM_SWAPCHAIN_IMAGE];
4108 		VkImageView      m_backBufferColorImageView[NUM_SWAPCHAIN_IMAGE];
4109 		VkFramebuffer    m_backBufferColor[NUM_SWAPCHAIN_IMAGE];
4110 		VkCommandBuffer  m_commandBuffers[NUM_SWAPCHAIN_IMAGE];
4111 		VkCommandBuffer  m_commandBuffer;
4112 		bool             m_needToRefreshSwapchain;
4113 
4114 		VkFormat         m_backBufferDepthStencilFormat;
4115 		VkDeviceMemory   m_backBufferDepthStencilMemory;
4116 		VkImage          m_backBufferDepthStencilImage;
4117 		VkImageView      m_backBufferDepthStencilImageView;
4118 
4119 		ScratchBufferVK  m_scratchBuffer[NUM_SWAPCHAIN_IMAGE];
4120 		VkSemaphore      m_presentDone[NUM_SWAPCHAIN_IMAGE];
4121 
4122 		uint32_t m_qfiGraphics;
4123 		uint32_t m_qfiCompute;
4124 
4125 		VkDevice m_device;
4126 		VkQueue  m_queueGraphics;
4127 		VkQueue  m_queueCompute;
4128 		VkFence  m_fence;
4129 		VkRenderPass m_renderPass;
4130 		VkDescriptorPool m_descriptorPool;
4131 //		VkDescriptorSetLayout m_descriptorSetLayout;
4132 //		VkPipelineLayout m_pipelineLayout;
4133 		VkPipelineCache m_pipelineCache;
4134 		VkCommandPool m_commandPool;
4135 
4136 		void* m_renderDocDll;
4137 		void* m_vulkan1Dll;
4138 
4139 		IndexBufferVK m_indexBuffers[BGFX_CONFIG_MAX_INDEX_BUFFERS];
4140 		VertexBufferVK m_vertexBuffers[BGFX_CONFIG_MAX_VERTEX_BUFFERS];
4141 		ShaderVK m_shaders[BGFX_CONFIG_MAX_SHADERS];
4142 		ProgramVK m_program[BGFX_CONFIG_MAX_PROGRAMS];
4143 		TextureVK m_textures[BGFX_CONFIG_MAX_TEXTURES];
4144 		VertexLayout m_vertexLayouts[BGFX_CONFIG_MAX_VERTEX_LAYOUTS];
4145 		FrameBufferVK m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS];
4146 		void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS];
4147 		Matrix4 m_predefinedUniforms[PredefinedUniform::Count];
4148 		UniformRegistry m_uniformReg;
4149 
4150 		StateCacheT<VkPipeline> m_pipelineStateCache;
4151 		StateCacheT<VkDescriptorSetLayout> m_descriptorSetLayoutCache;
4152 		StateCacheT<VkRenderPass> m_renderPassCache;
4153 		StateCacheT<VkSampler> m_samplerCache;
4154 
4155 		Resolution m_resolution;
4156 		uint32_t m_maxAnisotropy;
4157 		bool m_depthClamp;
4158 		bool m_wireframe;
4159 
4160 		TextVideoMem m_textVideoMem;
4161 
4162 		uint8_t m_fsScratch[64<<10];
4163 		uint8_t m_vsScratch[64<<10];
4164 		uint32_t m_fsChanges;
4165 		uint32_t m_vsChanges;
4166 
4167 		uint32_t m_backBufferColorIdx;
4168 		FrameBufferHandle m_fbh;
4169 	};
4170 
4171 	static RendererContextVK* s_renderVK;
4172 
rendererCreate(const Init & _init)4173 	RendererContextI* rendererCreate(const Init& _init)
4174 	{
4175 		s_renderVK = BX_NEW(g_allocator, RendererContextVK);
4176 		if (!s_renderVK->init(_init) )
4177 		{
4178 			BX_DELETE(g_allocator, s_renderVK);
4179 			s_renderVK = NULL;
4180 		}
4181 		return s_renderVK;
4182 	}
4183 
rendererDestroy()4184 	void rendererDestroy()
4185 	{
4186 		s_renderVK->shutdown();
4187 		BX_DELETE(g_allocator, s_renderVK);
4188 		s_renderVK = NULL;
4189 	}
4190 
4191 #define VK_DESTROY_FUNC(_name)                                                               \
4192 			void vkDestroy(Vk##_name& _obj)                                                  \
4193 			{                                                                                \
4194 				if (VK_NULL_HANDLE != _obj)                                                  \
4195 				{                                                                            \
4196 					vkDestroy##_name(s_renderVK->m_device, _obj, s_renderVK->m_allocatorCb); \
4197 					_obj = VK_NULL_HANDLE;                                                   \
4198 				}                                                                            \
4199 			}
4200 VK_DESTROY
4201 #undef VK_DESTROY_FUNC
4202 
create(uint32_t _size,uint32_t _maxDescriptors)4203 	void ScratchBufferVK::create(uint32_t _size, uint32_t _maxDescriptors)
4204 	{
4205 		m_maxDescriptors = _maxDescriptors;
4206 		m_currentDs = 0;
4207 		m_descriptorSet  = (VkDescriptorSet*)BX_ALLOC(g_allocator, m_maxDescriptors * sizeof(VkDescriptorSet) );
4208 		bx::memSet(m_descriptorSet, 0, sizeof(VkDescriptorSet) * m_maxDescriptors);
4209 
4210 		VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
4211 		VkDevice device = s_renderVK->m_device;
4212 
4213 		VkBufferCreateInfo bci;
4214 		bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
4215 		bci.pNext = NULL;
4216 		bci.flags = 0;
4217 		bci.size  = _size;
4218 		bci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
4219 		bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
4220 		bci.queueFamilyIndexCount = 0;
4221 		bci.pQueueFamilyIndices   = NULL;
4222 
4223 		VK_CHECK(vkCreateBuffer(
4224 			  device
4225 			, &bci
4226 			, allocatorCb
4227 			, &m_buffer
4228 			) );
4229 
4230 		VkMemoryRequirements mr;
4231 		vkGetBufferMemoryRequirements(
4232 			  device
4233 			, m_buffer
4234 			, &mr
4235 			);
4236 
4237 		VkMemoryAllocateInfo ma;
4238 		ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
4239 		ma.pNext = NULL;
4240 		ma.allocationSize  = mr.size;
4241 		ma.memoryTypeIndex = s_renderVK->selectMemoryType(mr.memoryTypeBits
4242 			, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
4243 			);
4244 		VK_CHECK(vkAllocateMemory(device
4245 			, &ma
4246 			, allocatorCb
4247 			, &m_deviceMem
4248 			) );
4249 
4250 		m_size = (uint32_t)mr.size;
4251 		m_pos  = 0;
4252 
4253 		VK_CHECK(vkBindBufferMemory(device, m_buffer, m_deviceMem, 0) );
4254 
4255 		VK_CHECK(vkMapMemory(device, m_deviceMem, 0, ma.allocationSize, 0, (void**)&m_data) );
4256 	}
4257 
destroy()4258 	void ScratchBufferVK::destroy()
4259 	{
4260 		VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
4261 		VkDevice device = s_renderVK->m_device;
4262 
4263 		reset();
4264 		BX_FREE(g_allocator, m_descriptorSet);
4265 
4266 		vkUnmapMemory(device, m_deviceMem);
4267 		vkDestroy(m_buffer);
4268 		vkFreeMemory(device
4269 			, m_deviceMem
4270 			, allocatorCb
4271 			);
4272 	}
4273 
reset()4274 	void ScratchBufferVK::reset()
4275 	{
4276 		if (m_currentDs > 0)
4277 		{
4278 			vkFreeDescriptorSets(
4279 				  s_renderVK->m_device
4280 				, s_renderVK->m_descriptorPool
4281 				, m_currentDs
4282 				, m_descriptorSet
4283 				);
4284 		}
4285 
4286 		bx::memSet(m_descriptorSet, 0, sizeof(VkDescriptorSet) * m_maxDescriptors);
4287 		m_pos = 0;
4288 		m_currentDs = 0;
4289 	}
4290 
create(VkFormat _format,const VkExtent3D & _extent)4291 	VkResult ImageVK::create(VkFormat _format, const VkExtent3D& _extent)
4292 	{
4293 		VkResult result;
4294 
4295 		VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
4296 		VkDevice device = s_renderVK->m_device;
4297 
4298 		VkImageCreateInfo ici;
4299 		ici.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
4300 		ici.pNext = NULL;
4301 		ici.flags = 0;
4302 		ici.imageType = VK_IMAGE_TYPE_2D;
4303 		ici.format = _format;
4304 		ici.extent = _extent;
4305 		ici.mipLevels   = 1;
4306 		ici.arrayLayers = 1;
4307 		ici.samples = VK_SAMPLE_COUNT_1_BIT;
4308 		ici.tiling  = VK_IMAGE_TILING_OPTIMAL;
4309 		ici.usage   = 0
4310 			| VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
4311 			| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
4312 			;
4313 		ici.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
4314 		ici.queueFamilyIndexCount = 0;
4315 		ici.pQueueFamilyIndices   = 0;
4316 		ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
4317 		result = vkCreateImage(device, &ici, allocatorCb, &m_image);
4318 
4319 		if (VK_SUCCESS != result)
4320 		{
4321 			BX_TRACE("vkCreateImage failed %d: %s.", result, getName(result) );
4322 			return result;
4323 		}
4324 
4325 		VkMemoryRequirements mr;
4326 		vkGetImageMemoryRequirements(device, m_image, &mr);
4327 
4328 		VkMemoryAllocateInfo ma;
4329 		ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
4330 		ma.pNext = NULL;
4331 		ma.allocationSize  = mr.size;
4332 		ma.memoryTypeIndex = s_renderVK->selectMemoryType(
4333 			  mr.memoryTypeBits
4334 			, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
4335 			);
4336 		result = vkAllocateMemory(device, &ma, allocatorCb, &m_memory);
4337 
4338 		if (VK_SUCCESS != result)
4339 		{
4340 			BX_TRACE("vkAllocateMemory failed %d: %s.", result, getName(result) );
4341 			destroy();
4342 			return result;
4343 		}
4344 
4345 		result = vkBindImageMemory(device, m_image, m_memory, 0);
4346 
4347 		if (VK_SUCCESS != result)
4348 		{
4349 			BX_TRACE("vkBindImageMemory failed %d: %s.", result, getName(result) );
4350 			destroy();
4351 			return result;
4352 		}
4353 
4354 		VkImageViewCreateInfo ivci;
4355 		ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
4356 		ivci.pNext = NULL;
4357 		ivci.flags = 0;
4358 		ivci.image    = m_image;
4359 		ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
4360 		ivci.format   = _format;
4361 		ivci.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
4362 		ivci.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
4363 		ivci.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
4364 		ivci.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
4365 		ivci.subresourceRange.aspectMask = 0
4366 			| VK_IMAGE_ASPECT_DEPTH_BIT
4367 			| VK_IMAGE_ASPECT_STENCIL_BIT
4368 			;
4369 		ivci.subresourceRange.baseMipLevel   = 0;
4370 		ivci.subresourceRange.levelCount     = 1;
4371 		ivci.subresourceRange.baseArrayLayer = 0;
4372 		ivci.subresourceRange.layerCount     = 1;
4373 		result = vkCreateImageView(device, &ivci, allocatorCb, &m_imageView);
4374 
4375 		if (VK_SUCCESS != result)
4376 		{
4377 			BX_TRACE("vkCreateImageView failed %d: %s.", result, getName(result) );
4378 			destroy();
4379 			return result;
4380 		}
4381 
4382 		return VK_SUCCESS;
4383 	}
4384 
destroy()4385 	void ImageVK::destroy()
4386 	{
4387 		vkDestroy(m_imageView);
4388 		vkDestroy(m_image);
4389 		if (VK_NULL_HANDLE != m_memory)
4390 		{
4391 			vkFreeMemory(s_renderVK->m_device, m_memory, s_renderVK->m_allocatorCb);
4392 			m_memory = VK_NULL_HANDLE;
4393 		}
4394 	}
4395 
create(uint32_t _size,void * _data,uint16_t _flags,bool _vertex,uint32_t _stride)4396 	void BufferVK::create(uint32_t _size, void* _data, uint16_t _flags, bool _vertex, uint32_t _stride)
4397 	{
4398 		BX_UNUSED(_stride);
4399 
4400 		m_size    = _size;
4401 		m_flags   = _flags;
4402 		m_dynamic = NULL == _data;
4403 
4404 		bool storage  = m_flags & BGFX_BUFFER_COMPUTE_READ_WRITE;
4405 		bool indirect = m_flags & BGFX_BUFFER_DRAW_INDIRECT;
4406 		VkBufferCreateInfo bci;
4407 		bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
4408 		bci.pNext = NULL;
4409 		bci.flags = 0;
4410 		bci.size  = _size;
4411 		bci.usage = 0
4412 //			| (m_dynamic            ? VK_BUFFER_USAGE_TRANSFER_DST_BIT    : 0)
4413 			| (_vertex              ? VK_BUFFER_USAGE_VERTEX_BUFFER_BIT   : VK_BUFFER_USAGE_INDEX_BUFFER_BIT)
4414 			| (storage || indirect  ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT  : 0)
4415 			| (indirect             ? VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT : 0)
4416 			| VK_BUFFER_USAGE_TRANSFER_DST_BIT
4417 			;
4418 		bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
4419 		bci.queueFamilyIndexCount = 0;
4420 		bci.pQueueFamilyIndices   = NULL;
4421 
4422 		VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
4423 		VkDevice device = s_renderVK->m_device;
4424 		VK_CHECK(vkCreateBuffer(device
4425 			, &bci
4426 			, allocatorCb
4427 			, &m_buffer
4428 			) );
4429 
4430 		VkMemoryRequirements mr;
4431 		vkGetBufferMemoryRequirements(device, m_buffer, &mr);
4432 
4433 		VkMemoryAllocateInfo ma;
4434 		ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
4435 		ma.pNext = NULL;
4436 		ma.allocationSize  = mr.size;
4437 		ma.memoryTypeIndex = s_renderVK->selectMemoryType(
4438 			  mr.memoryTypeBits
4439 			, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
4440 			);
4441 		VK_CHECK(vkAllocateMemory(device, &ma, allocatorCb, &m_deviceMem) );
4442 
4443 		VK_CHECK(vkBindBufferMemory(device, m_buffer, m_deviceMem, 0));
4444 
4445 		if (!m_dynamic)
4446 		{
4447 //			void* dst;
4448 //			VK_CHECK(vkMapMemory(device, m_deviceMem, 0, ma.allocationSize, 0, &dst) );
4449 //			bx::memCopy(dst, _data, _size);
4450 //			vkUnmapMemory(device, m_deviceMem);
4451 
4452 			// staging buffer
4453 			VkBuffer stagingBuffer;
4454 			VkDeviceMemory stagingMem;
4455 			bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
4456 			bci.pNext = NULL;
4457 			bci.flags = 0;
4458 			bci.size = _size;
4459 			bci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
4460 			bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
4461 			bci.queueFamilyIndexCount = 0;
4462 			bci.pQueueFamilyIndices = NULL;
4463 
4464 			VK_CHECK(vkCreateBuffer(device
4465 				, &bci
4466 				, allocatorCb
4467 				, &stagingBuffer
4468 			));
4469 
4470 			vkGetBufferMemoryRequirements(device, stagingBuffer, &mr);
4471 
4472 			ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
4473 			ma.pNext = NULL;
4474 			ma.allocationSize = mr.size;
4475 			ma.memoryTypeIndex = s_renderVK->selectMemoryType(mr.memoryTypeBits
4476 				, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
4477 			);
4478 			VK_CHECK(vkAllocateMemory(device
4479 				, &ma
4480 				, allocatorCb
4481 				, &stagingMem
4482 			));
4483 
4484 			VK_CHECK(vkBindBufferMemory(device, stagingBuffer, stagingMem, 0));
4485 
4486 			void* dst;
4487 			VK_CHECK(vkMapMemory(device, stagingMem, 0, ma.allocationSize, 0, &dst));
4488 			bx::memCopy(dst, _data, _size);
4489 			vkUnmapMemory(device, stagingMem);
4490 
4491 			VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand();
4492 			// copy buffer to buffer
4493 			{
4494 				VkBufferCopy region;
4495 				region.srcOffset = 0;
4496 				region.dstOffset = 0;
4497 				region.size      = _size;
4498 
4499 				vkCmdCopyBuffer(commandBuffer, stagingBuffer, m_buffer, 1, &region);
4500 			}
4501 			s_renderVK->submitCommandAndWait(commandBuffer);
4502 
4503 			vkFreeMemory(device, stagingMem, allocatorCb);
4504 			vkDestroy(stagingBuffer);
4505 		}
4506 	}
4507 
update(VkCommandBuffer _commandBuffer,uint32_t _offset,uint32_t _size,void * _data,bool _discard)4508 	void BufferVK::update(VkCommandBuffer _commandBuffer, uint32_t _offset, uint32_t _size, void* _data, bool _discard)
4509 	{
4510 		BX_UNUSED(_commandBuffer, _discard);
4511 //		void* dst;
4512 //		VkDevice device = s_renderVK->m_device;
4513 //		VK_CHECK(vkMapMemory(device, m_deviceMem, _offset, _size, 0, &dst) );
4514 //		bx::memCopy(dst, _data, _size);
4515 //		vkUnmapMemory(device, m_deviceMem);
4516 
4517 		// staging buffer
4518 		VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
4519 		VkDevice device = s_renderVK->m_device;
4520 		VkBuffer stagingBuffer;
4521 		VkDeviceMemory stagingMem;
4522 		VkBufferCreateInfo bci;
4523 		bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
4524 		bci.pNext = NULL;
4525 		bci.flags = 0;
4526 		bci.size = _size;
4527 		bci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
4528 		bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
4529 		bci.queueFamilyIndexCount = 0;
4530 		bci.pQueueFamilyIndices = NULL;
4531 
4532 		VK_CHECK(vkCreateBuffer(device
4533 			, &bci
4534 			, allocatorCb
4535 			, &stagingBuffer
4536 		));
4537 
4538 		VkMemoryRequirements mr;
4539 		vkGetBufferMemoryRequirements(device
4540 			, stagingBuffer
4541 			, &mr
4542 		);
4543 
4544 		VkMemoryAllocateInfo ma;
4545 		ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
4546 		ma.pNext = NULL;
4547 		ma.allocationSize = mr.size;
4548 		ma.memoryTypeIndex = s_renderVK->selectMemoryType(mr.memoryTypeBits
4549 			, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
4550 		);
4551 		VK_CHECK(vkAllocateMemory(device
4552 			, &ma
4553 			, allocatorCb
4554 			, &stagingMem
4555 		));
4556 
4557 		VK_CHECK(vkBindBufferMemory(device, stagingBuffer, stagingMem, 0));
4558 
4559 		void* dst;
4560 		VK_CHECK(vkMapMemory(device, stagingMem, 0, ma.allocationSize, 0, &dst));
4561 		bx::memCopy(dst, _data, _size);
4562 		vkUnmapMemory(device, stagingMem);
4563 
4564 		VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand();
4565 
4566 		// copy buffer to buffer
4567 		{
4568 			VkBufferCopy region;
4569 			region.srcOffset = 0;
4570 			region.dstOffset = _offset;
4571 			region.size      = _size;
4572 
4573 			vkCmdCopyBuffer(commandBuffer, stagingBuffer, m_buffer, 1, &region);
4574 		}
4575 
4576 		s_renderVK->submitCommandAndWait(commandBuffer);
4577 
4578 		vkFreeMemory(device, stagingMem, allocatorCb);
4579 		vkDestroy(stagingBuffer);
4580 	}
4581 
destroy()4582 	void BufferVK::destroy()
4583 	{
4584 		if (VK_NULL_HANDLE != m_buffer)
4585 		{
4586 			VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
4587 			VkDevice device = s_renderVK->m_device;
4588 
4589 			vkDestroy(m_buffer);
4590 			vkFreeMemory(device
4591 				, m_deviceMem
4592 				, allocatorCb
4593 				);
4594 			m_dynamic = false;
4595 		}
4596 	}
4597 
create(uint32_t _size,void * _data,VertexLayoutHandle _layoutHandle,uint16_t _flags)4598 	void VertexBufferVK::create(uint32_t _size, void* _data, VertexLayoutHandle _layoutHandle, uint16_t _flags)
4599 	{
4600 		BufferVK::create(_size, _data, _flags, true);
4601 		m_layoutHandle = _layoutHandle;
4602 	}
4603 
create(const Memory * _mem)4604 	void ShaderVK::create(const Memory* _mem)
4605 	{
4606 		bx::MemoryReader reader(_mem->data, _mem->size);
4607 
4608 		uint32_t magic;
4609 		bx::read(&reader, magic);
4610 
4611 		VkShaderStageFlagBits shaderStage;
4612 		BX_UNUSED(shaderStage);
4613 
4614 		if (isShaderType(magic, 'C') )
4615 		{
4616 			shaderStage = VK_SHADER_STAGE_COMPUTE_BIT;
4617 		}
4618 		else if (isShaderType(magic, 'F') )
4619 		{
4620 			shaderStage = VK_SHADER_STAGE_FRAGMENT_BIT;
4621 		}
4622 		else if (isShaderType(magic, 'V') )
4623 		{
4624 			shaderStage = VK_SHADER_STAGE_VERTEX_BIT;
4625 		}
4626 
4627 		const bool fragment = isShaderType(magic, 'F');
4628 
4629 		uint32_t hashIn;
4630 		bx::read(&reader, hashIn);
4631 
4632 		uint32_t hashOut;
4633 
4634 		if (isShaderVerLess(magic, 6) )
4635 		{
4636 			hashOut = hashIn;
4637 		}
4638 		else
4639 		{
4640 			bx::read(&reader, hashOut);
4641 		}
4642 
4643 		uint16_t count;
4644 		bx::read(&reader, count);
4645 
4646 		m_numPredefined = 0;
4647 		m_numUniforms = count;
4648 
4649 		BX_TRACE("%s Shader consts %d"
4650 			, getShaderTypeName(magic)
4651 			, count
4652 			);
4653 
4654 		uint8_t fragmentBit = fragment ? BGFX_UNIFORM_FRAGMENTBIT : 0;
4655 
4656 		for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++ii)
4657 		{
4658 			m_bindInfo[ii].uniformHandle  = BGFX_INVALID_HANDLE;
4659 			m_bindInfo[ii].type           = BindType::Count;
4660 			m_bindInfo[ii].binding        = 0;
4661 			m_bindInfo[ii].samplerBinding = 0;
4662 		}
4663 
4664 		if (0 < count)
4665 		{
4666 			for (uint32_t ii = 0; ii < count; ++ii)
4667 			{
4668 				uint8_t nameSize = 0;
4669 				bx::read(&reader, nameSize);
4670 
4671 				char name[256];
4672 				bx::read(&reader, &name, nameSize);
4673 				name[nameSize] = '\0';
4674 
4675 				uint8_t type = 0;
4676 				bx::read(&reader, type);
4677 
4678 				uint8_t num;
4679 				bx::read(&reader, num);
4680 
4681 				uint16_t regIndex;
4682 				bx::read(&reader, regIndex);
4683 
4684 				uint16_t regCount;
4685 				bx::read(&reader, regCount);
4686 
4687 				const char* kind = "invalid";
4688 
4689 				PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name);
4690 				if (PredefinedUniform::Count != predefined)
4691 				{
4692 					kind = "predefined";
4693 					m_predefined[m_numPredefined].m_loc   = regIndex;
4694 					m_predefined[m_numPredefined].m_count = regCount;
4695 					m_predefined[m_numPredefined].m_type  = uint8_t(predefined|fragmentBit);
4696 					m_numPredefined++;
4697 				}
4698 				else if (UniformType::End == (~BGFX_UNIFORM_MASK & type))
4699 				{
4700 					m_bindInfo[num].uniformHandle  = { 0 };
4701 					m_bindInfo[num].type           = BindType::Storage;
4702 					m_bindInfo[num].binding        = regCount; // regCount is used for buffer binding index
4703 					m_bindInfo[num].samplerBinding = regIndex; // regIndex is used for descriptor type
4704 
4705 					kind = "storage";
4706 				}
4707 				else if (UniformType::Sampler == (~BGFX_UNIFORM_MASK & type) )
4708 				{
4709 					const UniformRegInfo* info = s_renderVK->m_uniformReg.find(name);
4710 					BX_CHECK(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name);
4711 
4712 					m_bindInfo[num].uniformHandle  = info->m_handle;
4713 					m_bindInfo[num].type           = BindType::Sampler;
4714 					m_bindInfo[num].binding        = regIndex; // regIndex is used for image binding index
4715 					m_bindInfo[num].samplerBinding = regCount; // regCount is used for sampler binding index
4716 
4717 					kind = "sampler";
4718 				}
4719 				else
4720 				{
4721 					const UniformRegInfo* info = s_renderVK->m_uniformReg.find(name);
4722 					BX_CHECK(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name);
4723 
4724 					if (NULL != info)
4725 					{
4726 						if (NULL == m_constantBuffer)
4727 						{
4728 							m_constantBuffer = UniformBuffer::create(1024);
4729 						}
4730 
4731 						kind = "user";
4732 						m_constantBuffer->writeUniformHandle( (UniformType::Enum)(type|fragmentBit), regIndex, info->m_handle, regCount);
4733 					}
4734 				}
4735 
4736 
4737 				BX_TRACE("\t%s: %s (%s), num %2d, r.index %3d, r.count %2d"
4738 					, kind
4739 					, name
4740 					, getUniformTypeName(UniformType::Enum(type&~BGFX_UNIFORM_MASK) )
4741 					, num
4742 					, regIndex
4743 					, regCount
4744 					);
4745 				BX_UNUSED(kind);
4746 			}
4747 
4748 			if (NULL != m_constantBuffer)
4749 			{
4750 				m_constantBuffer->finish();
4751 			}
4752 		}
4753 
4754 		uint32_t shaderSize;
4755 		bx::read(&reader, shaderSize);
4756 
4757 		const void* code = reader.getDataPtr();
4758 		bx::skip(&reader, shaderSize+1);
4759 
4760 		m_code = alloc(shaderSize);
4761 		bx::memCopy(m_code->data, code, shaderSize);
4762 
4763 		VkShaderModuleCreateInfo smci;
4764 		smci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
4765 		smci.pNext = NULL;
4766 		smci.flags = 0;
4767 		smci.codeSize = m_code->size;
4768 		smci.pCode    = (const uint32_t*)m_code->data;
4769 
4770 //		disassemble(bx::getDebugOut(), m_code->data, m_code->size);
4771 
4772 		VK_CHECK(vkCreateShaderModule(
4773 			  s_renderVK->m_device
4774 			, &smci
4775 			, s_renderVK->m_allocatorCb
4776 			, &m_module
4777 			) );
4778 
4779 		bx::memSet(m_attrMask,  0, sizeof(m_attrMask) );
4780 		bx::memSet(m_attrRemap, 0, sizeof(m_attrRemap) );
4781 
4782 		bx::read(&reader, m_numAttrs);
4783 
4784 		for (uint8_t ii = 0; ii < m_numAttrs; ++ii)
4785 		{
4786 			uint16_t id;
4787 			bx::read(&reader, id);
4788 
4789 			Attrib::Enum attr = idToAttrib(id);
4790 
4791 			if (Attrib::Count != attr)
4792 			{
4793 				m_attrMask[attr]  = UINT16_MAX;
4794 				m_attrRemap[attr] = ii;
4795 			}
4796 		}
4797 
4798 		bx::HashMurmur2A murmur;
4799 		murmur.begin();
4800 		murmur.add(hashIn);
4801 		murmur.add(hashOut);
4802 		murmur.add(m_code->data, m_code->size);
4803 		murmur.add(m_numAttrs);
4804 		murmur.add(m_attrMask,  m_numAttrs);
4805 		murmur.add(m_attrRemap, m_numAttrs);
4806 		m_hash = murmur.end();
4807 
4808 		bx::read(&reader, m_size);
4809 
4810 		// fill binding description with uniform informations
4811 		{
4812 			uint16_t bidx = 0;
4813 			if (m_size > 0)
4814 			{
4815 				m_uniformBinding = fragment ? 48 : 0;
4816 				m_bindings[bidx].stageFlags = VK_SHADER_STAGE_ALL;
4817 				m_bindings[bidx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
4818 				m_bindings[bidx].binding = m_uniformBinding;
4819 				m_bindings[bidx].pImmutableSamplers = NULL;
4820 				m_bindings[bidx].descriptorCount = 1;
4821 				bidx++;
4822 			}
4823 
4824 			for (uint32_t ii = 0; ii < BX_COUNTOF(m_bindInfo); ++ii)
4825 			{
4826 				switch (m_bindInfo[ii].type)
4827 				{
4828 					case BindType::Storage:
4829 						m_bindings[bidx].stageFlags = VK_SHADER_STAGE_ALL;
4830 						m_bindings[bidx].descriptorType = (VkDescriptorType)m_bindInfo[ii].samplerBinding;
4831 						m_bindings[bidx].binding = m_bindInfo[ii].binding;
4832 						m_bindings[bidx].pImmutableSamplers = NULL;
4833 						m_bindings[bidx].descriptorCount = 1;
4834 						bidx++;
4835 						break;
4836 
4837 					case BindType::Sampler:
4838 						m_bindings[bidx].stageFlags = VK_SHADER_STAGE_ALL;
4839 						m_bindings[bidx].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
4840 						m_bindings[bidx].binding = m_bindInfo[ii].binding;
4841 						m_bindings[bidx].pImmutableSamplers = NULL;
4842 						m_bindings[bidx].descriptorCount = 1;
4843 						bidx++;
4844 
4845 						m_bindings[bidx].stageFlags = VK_SHADER_STAGE_ALL;
4846 						m_bindings[bidx].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
4847 						m_bindings[bidx].binding = m_bindInfo[ii].samplerBinding;
4848 						m_bindings[bidx].pImmutableSamplers = NULL;
4849 						m_bindings[bidx].descriptorCount = 1;
4850 						bidx++;
4851 						break;
4852 
4853 					default:
4854 						break;
4855 				}
4856 			}
4857 
4858 			m_numBindings = bidx;
4859 		}
4860 	}
4861 
destroy()4862 	void ShaderVK::destroy()
4863 	{
4864 		if (NULL != m_constantBuffer)
4865 		{
4866 			UniformBuffer::destroy(m_constantBuffer);
4867 			m_constantBuffer = NULL;
4868 		}
4869 
4870 		m_numPredefined = 0;
4871 
4872 		if (NULL != m_code)
4873 		{
4874 			release(m_code);
4875 			m_code = NULL;
4876 			m_hash = 0;
4877 		}
4878 
4879 		if (VK_NULL_HANDLE != m_module)
4880 		{
4881 			vkDestroy(m_module);
4882 		}
4883 	}
4884 
create(const ShaderVK * _vsh,const ShaderVK * _fsh)4885 	void ProgramVK::create(const ShaderVK* _vsh, const ShaderVK* _fsh)
4886 	{
4887 		BX_CHECK(NULL != _vsh->m_code, "Vertex shader doesn't exist.");
4888 		m_vsh = _vsh;
4889 		bx::memCopy(
4890 			  &m_predefined[0]
4891 			, _vsh->m_predefined
4892 			, _vsh->m_numPredefined * sizeof(PredefinedUniform)
4893 			);
4894 		m_numPredefined = _vsh->m_numPredefined;
4895 
4896 		if (NULL != _fsh)
4897 		{
4898 			BX_CHECK(NULL != _fsh->m_code, "Fragment shader doesn't exist.");
4899 			m_fsh = _fsh;
4900 			bx::memCopy(
4901 				  &m_predefined[m_numPredefined]
4902 				, _fsh->m_predefined
4903 				, _fsh->m_numPredefined * sizeof(PredefinedUniform)
4904 				);
4905 			m_numPredefined += _fsh->m_numPredefined;
4906 		}
4907 
4908 		// create exact pipeline layout
4909 		VkDescriptorSetLayout dsl = VK_NULL_HANDLE;
4910 
4911 		uint32_t numBindings = m_vsh->m_numBindings + (m_fsh ? m_fsh->m_numBindings : 0);
4912 		if (0 < numBindings)
4913 		{
4914 			// generate descriptor set layout hash
4915 			bx::HashMurmur2A murmur;
4916 			murmur.begin();
4917 			murmur.add(m_vsh->m_bindings, sizeof(VkDescriptorSetLayoutBinding) * m_vsh->m_numBindings);
4918 			if (NULL != m_fsh)
4919 			{
4920 				murmur.add(m_fsh->m_bindings, sizeof(VkDescriptorSetLayoutBinding) * m_fsh->m_numBindings);
4921 			}
4922 			m_descriptorSetLayoutHash = murmur.end();
4923 
4924 			dsl = s_renderVK->m_descriptorSetLayoutCache.find(m_descriptorSetLayoutHash);
4925 
4926 			if (VK_NULL_HANDLE == dsl)
4927 			{
4928 				VkDescriptorSetLayoutBinding bindings[64];
4929 				bx::memCopy(
4930 					  bindings
4931 					, m_vsh->m_bindings
4932 					, sizeof(VkDescriptorSetLayoutBinding) * m_vsh->m_numBindings
4933 					);
4934 				if (NULL != m_fsh)
4935 				{
4936 					bx::memCopy(
4937 						  bindings + m_vsh->m_numBindings
4938 						, m_fsh->m_bindings
4939 						, sizeof(VkDescriptorSetLayoutBinding) * m_fsh->m_numBindings
4940 						);
4941 				}
4942 
4943 				VkDescriptorSetLayoutCreateInfo dslci;
4944 				dslci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
4945 				dslci.pNext = NULL;
4946 				dslci.flags = 0;
4947 				dslci.bindingCount = numBindings;
4948 				dslci.pBindings = bindings;
4949 
4950 				VK_CHECK(vkCreateDescriptorSetLayout(
4951 					  s_renderVK->m_device
4952 					, &dslci
4953 					, s_renderVK->m_allocatorCb
4954 					, &dsl
4955 					));
4956 
4957 				s_renderVK->m_descriptorSetLayoutCache.add(m_descriptorSetLayoutHash, dsl);
4958 			}
4959 		}
4960 
4961 		VkPipelineLayoutCreateInfo plci;
4962 		plci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
4963 		plci.pNext = NULL;
4964 		plci.flags = 0;
4965 		plci.pushConstantRangeCount = 0;
4966 		plci.pPushConstantRanges = NULL;
4967 		plci.setLayoutCount = (dsl == VK_NULL_HANDLE ? 0 : 1);
4968 		plci.pSetLayouts = &dsl;
4969 
4970 		VK_CHECK(vkCreatePipelineLayout(
4971 			  s_renderVK->m_device
4972 			, &plci
4973 			, s_renderVK->m_allocatorCb
4974 			, &m_pipelineLayout
4975 			));
4976 	}
4977 
destroy()4978 	void ProgramVK::destroy()
4979 	{
4980 		vkDestroy(m_pipelineLayout);
4981 		m_numPredefined = 0;
4982 		m_vsh = NULL;
4983 		m_fsh = NULL;
4984 	}
4985 
create(const Memory * _mem,uint64_t _flags,uint8_t _skip)4986 	void* TextureVK::create(const Memory* _mem, uint64_t _flags, uint8_t _skip)
4987 	{
4988 		bimg::ImageContainer imageContainer;
4989 
4990 		if (bimg::imageParse(imageContainer, _mem->data, _mem->size))
4991 		{
4992 			VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
4993 			VkDevice device = s_renderVK->m_device;
4994 
4995 			const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(imageContainer.m_format);
4996 			const uint8_t startLod = bx::min<uint8_t>(_skip, imageContainer.m_numMips - 1);
4997 
4998 			bimg::TextureInfo ti;
4999 			bimg::imageGetSize(
5000 				  &ti
5001 				, uint16_t(imageContainer.m_width >> startLod)
5002 				, uint16_t(imageContainer.m_height >> startLod)
5003 				, uint16_t(imageContainer.m_depth >> startLod)
5004 				, imageContainer.m_cubeMap
5005 				, 1 < imageContainer.m_numMips
5006 				, imageContainer.m_numLayers
5007 				, imageContainer.m_format
5008 				);
5009 
5010 			ti.numMips = bx::min<uint8_t>(imageContainer.m_numMips - startLod, ti.numMips);
5011 
5012 			m_flags     = _flags;
5013 			m_width     = ti.width;
5014 			m_height    = ti.height;
5015 			m_depth     = ti.depth;
5016 			m_numLayers = ti.numLayers;
5017 			m_requestedFormat = uint8_t(imageContainer.m_format);
5018 			m_textureFormat = uint8_t(getViableTextureFormat(imageContainer));
5019 			m_vkTextureFormat = bimg::isDepth(bimg::TextureFormat::Enum(m_textureFormat) )
5020 				? s_textureFormat[m_textureFormat].m_fmtDsv
5021 				: s_textureFormat[m_textureFormat].m_fmt
5022 				;
5023 
5024 			const bool convert = m_textureFormat != m_requestedFormat;
5025 			const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat));
5026 			m_vkTextureAspect = bimg::isDepth((bimg::TextureFormat::Enum)m_textureFormat)
5027 				? VK_IMAGE_ASPECT_DEPTH_BIT
5028 				: VK_IMAGE_ASPECT_COLOR_BIT
5029 				;
5030 
5031 			if (m_vkTextureFormat == VK_FORMAT_S8_UINT
5032 			||  m_vkTextureFormat == VK_FORMAT_D16_UNORM_S8_UINT
5033 			||  m_vkTextureFormat == VK_FORMAT_D24_UNORM_S8_UINT
5034 			||  m_vkTextureFormat == VK_FORMAT_D32_SFLOAT_S8_UINT)
5035 			{
5036 				m_vkTextureAspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
5037 			}
5038 
5039 			if (imageContainer.m_cubeMap)
5040 			{
5041 				m_type = VK_IMAGE_VIEW_TYPE_CUBE;
5042 			}
5043 			else if (imageContainer.m_depth > 1)
5044 			{
5045 				m_type = VK_IMAGE_VIEW_TYPE_3D;
5046 			}
5047 			else
5048 			{
5049 				m_type = VK_IMAGE_VIEW_TYPE_2D;
5050 			}
5051 
5052 			m_numMips = ti.numMips;
5053 			m_numSides = ti.numLayers * (imageContainer.m_cubeMap ? 6 : 1);
5054 			const uint16_t numSides = ti.numLayers * (imageContainer.m_cubeMap ? 6 : 1);
5055 			const uint32_t numSrd = numSides * ti.numMips;
5056 
5057 			uint32_t kk = 0;
5058 
5059 			const bool compressed = bimg::isCompressed(bimg::TextureFormat::Enum(m_textureFormat));
5060 			const bool swizzle = TextureFormat::BGRA8 == m_textureFormat && 0 != (m_flags & BGFX_TEXTURE_COMPUTE_WRITE);
5061 
5062 			const bool writeOnly    = 0 != (m_flags & BGFX_TEXTURE_RT_WRITE_ONLY);
5063 			const bool computeWrite = 0 != (m_flags & BGFX_TEXTURE_COMPUTE_WRITE);
5064 			const bool renderTarget = 0 != (m_flags & BGFX_TEXTURE_RT_MASK);
5065 			const bool blit         = 0 != (m_flags & BGFX_TEXTURE_BLIT_DST);
5066 
5067 			BX_UNUSED(swizzle, writeOnly, computeWrite, renderTarget, blit);
5068 
5069 			BX_TRACE(
5070 				  "Texture %3d: %s (requested: %s), %dx%d%s RT[%c], BO[%c], CW[%c]%s."
5071 				, (int)(this - s_renderVK->m_textures)
5072 				, getName((TextureFormat::Enum)m_textureFormat)
5073 				, getName((TextureFormat::Enum)m_requestedFormat)
5074 				, ti.width
5075 				, ti.height
5076 				, imageContainer.m_cubeMap ? "x6" : ""
5077 				, renderTarget ? 'x' : ' '
5078 				, writeOnly ? 'x' : ' '
5079 				, computeWrite ? 'x' : ' '
5080 				, swizzle ? " (swizzle BGRA8 -> RGBA8)" : ""
5081 				);
5082 
5083 			// decode images
5084 			struct ImageInfo
5085 			{
5086 				uint8_t* data;
5087 				uint32_t width;
5088 				uint32_t height;
5089 				uint32_t depth;
5090 				uint32_t pitch;
5091 				uint32_t slice;
5092 				uint32_t size;
5093 				uint8_t mipLevel;
5094 				uint8_t layer;
5095 			};
5096 
5097 			ImageInfo* imageInfos = (ImageInfo*)BX_ALLOC(g_allocator, sizeof(ImageInfo) * numSrd);
5098 			bx::memSet(imageInfos, 0, sizeof(ImageInfo) * numSrd);
5099 			uint32_t alignment = 1; // tightly aligned buffer
5100 			for (uint8_t side = 0; side < numSides; ++side)
5101 			{
5102 				for (uint8_t lod = 0; lod < ti.numMips; ++lod)
5103 				{
5104 					bimg::ImageMip mip;
5105 					if (bimg::imageGetRawData(imageContainer, side, lod + startLod, _mem->data, _mem->size, mip))
5106 					{
5107 						if (convert)
5108 						{
5109 							const uint32_t pitch = bx::strideAlign(bx::max<uint32_t>(mip.m_width, 4) * bpp / 8, alignment);
5110 							const uint32_t slice = bx::strideAlign(bx::max<uint32_t>(mip.m_height, 4) * pitch, alignment);
5111 							const uint32_t size = slice * mip.m_depth;
5112 
5113 							uint8_t* temp = (uint8_t*)BX_ALLOC(g_allocator, size);
5114 							bimg::imageDecodeToBgra8(
5115 								  g_allocator
5116 								, temp
5117 								, mip.m_data
5118 								, mip.m_width
5119 								, mip.m_height
5120 								, pitch
5121 								, mip.m_format
5122 								);
5123 
5124 							imageInfos[kk].data = temp;
5125 							imageInfos[kk].width = mip.m_width;
5126 							imageInfos[kk].height = mip.m_height;
5127 							imageInfos[kk].depth = mip.m_depth;
5128 							imageInfos[kk].pitch = pitch;
5129 							imageInfos[kk].slice = slice;
5130 							imageInfos[kk].size = size;
5131 							imageInfos[kk].mipLevel = lod;
5132 							imageInfos[kk].layer = side;
5133 						}
5134 						else if (compressed)
5135 						{
5136 							const uint32_t pitch = bx::strideAlign((mip.m_width / blockInfo.blockWidth) * mip.m_blockSize, alignment);
5137 							const uint32_t slice = bx::strideAlign((mip.m_height / blockInfo.blockHeight) * pitch, alignment);
5138 							const uint32_t size = slice * mip.m_depth;
5139 
5140 							uint8_t* temp = (uint8_t*)BX_ALLOC(g_allocator, size);
5141 							bimg::imageCopy(
5142 								  temp
5143 								, mip.m_height / blockInfo.blockHeight
5144 								, (mip.m_width / blockInfo.blockWidth) * mip.m_blockSize
5145 								, mip.m_depth
5146 								, mip.m_data
5147 								, pitch
5148 								);
5149 
5150 							imageInfos[kk].data = temp;
5151 							imageInfos[kk].width = mip.m_width;
5152 							imageInfos[kk].height = mip.m_height;
5153 							imageInfos[kk].depth = mip.m_depth;
5154 							imageInfos[kk].pitch = pitch;
5155 							imageInfos[kk].slice = slice;
5156 							imageInfos[kk].size = size;
5157 							imageInfos[kk].mipLevel = lod;
5158 							imageInfos[kk].layer = side;
5159 						}
5160 						else
5161 						{
5162 							const uint32_t pitch = bx::strideAlign(mip.m_width * mip.m_bpp / 8, alignment);
5163 							const uint32_t slice = bx::strideAlign(mip.m_height * pitch, alignment);
5164 
5165 							uint8_t* temp = (uint8_t*)BX_ALLOC(g_allocator, slice);
5166 							bimg::imageCopy(temp
5167 								, mip.m_height
5168 								, mip.m_width * mip.m_bpp / 8
5169 								, mip.m_depth
5170 								, mip.m_data
5171 								, pitch
5172 							);
5173 
5174 							imageInfos[kk].data = temp;
5175 							imageInfos[kk].width = mip.m_width;
5176 							imageInfos[kk].height = mip.m_height;
5177 							imageInfos[kk].depth = mip.m_depth;
5178 							imageInfos[kk].pitch = pitch;
5179 							imageInfos[kk].slice = slice;
5180 							imageInfos[kk].size = slice;
5181 							imageInfos[kk].mipLevel = lod;
5182 							imageInfos[kk].layer = side;
5183 						}
5184 					}
5185 					++kk;
5186 				}
5187 			}
5188 
5189 			uint32_t totalMemSize = 0;
5190 			VkBufferImageCopy* bufferCopyInfo = (VkBufferImageCopy*)BX_ALLOC(g_allocator, sizeof(VkBufferImageCopy) * numSrd);
5191 			for (uint32_t ii = 0; ii < numSrd; ++ii)
5192 			{
5193 				uint32_t idealWidth  = bx::max<uint32_t>(1, m_width  >> imageInfos[ii].mipLevel);
5194 				uint32_t idealHeight = bx::max<uint32_t>(1, m_height >> imageInfos[ii].mipLevel);
5195 				bufferCopyInfo[ii].bufferOffset      = totalMemSize;
5196 				bufferCopyInfo[ii].bufferRowLength   = 0; // assume that image data are tightly aligned
5197 				bufferCopyInfo[ii].bufferImageHeight = 0; // assume that image data are tightly aligned
5198 				bufferCopyInfo[ii].imageSubresource.aspectMask     = m_vkTextureAspect;
5199 				bufferCopyInfo[ii].imageSubresource.mipLevel       = imageInfos[ii].mipLevel;
5200 				bufferCopyInfo[ii].imageSubresource.baseArrayLayer = imageInfos[ii].layer;
5201 				bufferCopyInfo[ii].imageSubresource.layerCount     = 1;
5202 				bufferCopyInfo[ii].imageOffset = { 0, 0, 0 };
5203 				bufferCopyInfo[ii].imageExtent = { idealWidth, idealHeight, imageInfos[ii].depth };
5204 				totalMemSize += imageInfos[ii].size;
5205 			}
5206 
5207 			VkBuffer stagingBuffer = VK_NULL_HANDLE;
5208 			VkDeviceMemory stagingDeviceMem = VK_NULL_HANDLE;
5209 			if (totalMemSize > 0)
5210 			{
5211 				// staging buffer creation
5212 				VkBufferCreateInfo bci;
5213 				bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
5214 				bci.pNext = NULL;
5215 				bci.flags = 0;
5216 				bci.size = totalMemSize;
5217 				bci.queueFamilyIndexCount = 0;
5218 				bci.pQueueFamilyIndices = NULL;
5219 				bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
5220 				bci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
5221 				VK_CHECK(vkCreateBuffer(
5222 					  device
5223 					, &bci
5224 					, allocatorCb
5225 					, &stagingBuffer
5226 					));
5227 
5228 				VkMemoryRequirements mr;
5229 				vkGetBufferMemoryRequirements(
5230 					  device
5231 					, stagingBuffer
5232 					, &mr
5233 					);
5234 
5235 				VkMemoryAllocateInfo ma;
5236 				ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
5237 				ma.pNext = NULL;
5238 				ma.allocationSize = mr.size;
5239 				ma.memoryTypeIndex = s_renderVK->selectMemoryType(
5240 					  mr.memoryTypeBits
5241 					, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
5242 					);
5243 				VK_CHECK(vkAllocateMemory(
5244 					  device
5245 					, &ma
5246 					, allocatorCb
5247 					, &stagingDeviceMem
5248 					));
5249 
5250 				VK_CHECK(vkBindBufferMemory(
5251 					  device
5252 					, stagingBuffer
5253 					, stagingDeviceMem
5254 					, 0
5255 					));
5256 				VK_CHECK(vkMapMemory(
5257 					  device
5258 					, stagingDeviceMem
5259 					, 0
5260 					, ma.allocationSize
5261 					, 0
5262 					, (void**)& m_directAccessPtr
5263 					));
5264 
5265 				uint8_t* mappedMemory = (uint8_t*)m_directAccessPtr;
5266 
5267 				// copy image to staging buffer
5268 				for (uint32_t ii = 0; ii < numSrd; ++ii)
5269 				{
5270 					bx::memCopy(mappedMemory, imageInfos[ii].data, imageInfos[ii].size);
5271 					mappedMemory += imageInfos[ii].size;
5272 				}
5273 
5274 				vkUnmapMemory(device, stagingDeviceMem);
5275 			}
5276 
5277 			// create texture and allocate its device memory
5278 			VkImageCreateInfo ici;
5279 			ici.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
5280 			ici.pNext = NULL;
5281 			ici.flags = VK_IMAGE_VIEW_TYPE_CUBE == m_type
5282 				? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
5283 				: 0
5284 				;
5285 			ici.pQueueFamilyIndices = NULL;
5286 			ici.queueFamilyIndexCount = 0;
5287 			ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
5288 			ici.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
5289 			ici.usage = 0
5290 				| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
5291 				| VK_IMAGE_USAGE_TRANSFER_DST_BIT
5292 				| VK_IMAGE_USAGE_SAMPLED_BIT
5293 				| (_flags & BGFX_TEXTURE_RT_MASK
5294 					? (bimg::isDepth((bimg::TextureFormat::Enum)m_textureFormat)
5295 						? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
5296 						: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
5297 					: 0
5298 					)
5299 				| (_flags & BGFX_TEXTURE_COMPUTE_WRITE ? VK_IMAGE_USAGE_STORAGE_BIT : 0)
5300 				;
5301 			ici.format = bimg::isDepth(bimg::TextureFormat::Enum(m_textureFormat) )
5302 				? s_textureFormat[m_textureFormat].m_fmtDsv
5303 				: s_textureFormat[m_textureFormat].m_fmt
5304 				;
5305 			ici.samples = VK_SAMPLE_COUNT_1_BIT;
5306 			ici.mipLevels = m_numMips;
5307 			ici.arrayLayers = m_numSides;
5308 			ici.extent.width = m_width;
5309 			ici.extent.height = m_height;
5310 			ici.extent.depth = m_depth;
5311 			ici.imageType = VK_IMAGE_VIEW_TYPE_3D == m_type
5312 				? VK_IMAGE_TYPE_3D
5313 				: VK_IMAGE_TYPE_2D
5314 				;
5315 			ici.tiling = VK_IMAGE_TILING_OPTIMAL;
5316 
5317 			VK_CHECK(vkCreateImage(device, &ici, allocatorCb, &m_textureImage));
5318 
5319 			VkMemoryRequirements imageMemReq;
5320 			vkGetImageMemoryRequirements(device, m_textureImage, &imageMemReq);
5321 
5322 			VkMemoryAllocateInfo imai;
5323 			imai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
5324 			imai.pNext = NULL;
5325 			imai.allocationSize = imageMemReq.size;
5326 			imai.memoryTypeIndex = s_renderVK->selectMemoryType(
5327 				  imageMemReq.memoryTypeBits
5328 				, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
5329 				);
5330 
5331 			VK_CHECK(vkAllocateMemory(device, &imai, allocatorCb, &m_textureDeviceMem));
5332 
5333 			vkBindImageMemory(device, m_textureImage, m_textureDeviceMem, 0);
5334 
5335 			if (stagingBuffer)
5336 			{
5337 				copyBufferToTexture(stagingBuffer, numSrd, bufferCopyInfo);
5338 			}
5339 			else
5340 			{
5341 				VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand();
5342 				setImageMemoryBarrier(
5343 					  commandBuffer
5344 					, (m_flags & BGFX_TEXTURE_COMPUTE_WRITE
5345 						? VK_IMAGE_LAYOUT_GENERAL
5346 						: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
5347 					  )
5348 					);
5349 				s_renderVK->submitCommandAndWait(commandBuffer);
5350 			}
5351 
5352 			vkFreeMemory(device, stagingDeviceMem, allocatorCb);
5353 			vkDestroy(stagingBuffer);
5354 
5355 			BX_FREE(g_allocator, bufferCopyInfo);
5356 			for (uint32_t ii = 0; ii < numSrd; ++ii)
5357 			{
5358 				BX_FREE(g_allocator, imageInfos[ii].data);
5359 			}
5360 			BX_FREE(g_allocator, imageInfos);
5361 
5362 			// image view creation
5363 			{
5364 				VkImageViewCreateInfo viewInfo;
5365 				viewInfo.sType        = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
5366 				viewInfo.pNext        = NULL;
5367 				viewInfo.flags        = 0;
5368 				viewInfo.image        = m_textureImage;
5369 				viewInfo.viewType     = m_type;
5370 				viewInfo.format       = m_vkTextureFormat;
5371 				viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
5372 				viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
5373 				viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
5374 				viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
5375 				viewInfo.subresourceRange.aspectMask     = m_vkTextureAspect;
5376 				viewInfo.subresourceRange.baseMipLevel   = 0;
5377 				viewInfo.subresourceRange.levelCount     = m_numMips; //m_numMips;
5378 				viewInfo.subresourceRange.baseArrayLayer = 0;
5379 				viewInfo.subresourceRange.layerCount     = m_numSides; //(m_type == VK_IMAGE_VIEW_TYPE_CUBE ? 6 : m_numLayers);
5380 				VK_CHECK(vkCreateImageView(
5381 					  device
5382 					, &viewInfo
5383 					, allocatorCb
5384 					, &m_textureImageView
5385 					));
5386 			}
5387 
5388 			if ((m_vkTextureAspect & VK_IMAGE_ASPECT_DEPTH_BIT)
5389 			&&  (m_vkTextureAspect & VK_IMAGE_ASPECT_STENCIL_BIT))
5390 			{
5391 				VkImageViewCreateInfo viewInfo;
5392 				viewInfo.sType        = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
5393 				viewInfo.pNext        = NULL;
5394 				viewInfo.flags        = 0;
5395 				viewInfo.image        = m_textureImage;
5396 				viewInfo.viewType     = m_type;
5397 				viewInfo.format       = m_vkTextureFormat;
5398 				viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
5399 				viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
5400 				viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
5401 				viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
5402 				viewInfo.subresourceRange.aspectMask     = VK_IMAGE_ASPECT_DEPTH_BIT;
5403 				viewInfo.subresourceRange.baseMipLevel   = 0;
5404 				viewInfo.subresourceRange.levelCount     = m_numMips; //m_numMips;
5405 				viewInfo.subresourceRange.baseArrayLayer = 0;
5406 				viewInfo.subresourceRange.layerCount     = m_numSides; //(m_type == VK_IMAGE_VIEW_TYPE_CUBE ? 6 : m_numLayers);
5407 				VK_CHECK(vkCreateImageView(
5408 					device
5409 					, &viewInfo
5410 					, allocatorCb
5411 					, &m_textureImageDepthView
5412 					));
5413 			}
5414 
5415 			// image view creation for storage if needed
5416 			if (m_flags & BGFX_TEXTURE_COMPUTE_WRITE)
5417 			{
5418 				VkImageViewCreateInfo viewInfo;
5419 				viewInfo.sType        = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
5420 				viewInfo.pNext        = NULL;
5421 				viewInfo.flags        = 0;
5422 				viewInfo.image        = m_textureImage;
5423 				viewInfo.viewType     = (m_type == VK_IMAGE_VIEW_TYPE_CUBE ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : m_type);
5424 				viewInfo.format       = m_vkTextureFormat;
5425 				viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
5426 				viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
5427 				viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
5428 				viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
5429 				viewInfo.subresourceRange.aspectMask     = m_vkTextureAspect;
5430 				viewInfo.subresourceRange.baseMipLevel   = 0;
5431 				viewInfo.subresourceRange.levelCount     = m_numMips; //m_numMips;
5432 				viewInfo.subresourceRange.baseArrayLayer = 0;
5433 				viewInfo.subresourceRange.layerCount     = m_numSides; //(m_type == VK_IMAGE_VIEW_TYPE_CUBE ? 6 : m_numLayers);
5434 				VK_CHECK(vkCreateImageView(
5435 					  device
5436 					, &viewInfo
5437 					, allocatorCb
5438 					, &m_textureImageStorageView
5439 					));
5440 			}
5441 		}
5442 
5443 		return m_directAccessPtr;
5444 	}
5445 
destroy()5446 	void TextureVK::destroy()
5447 	{
5448 		if (m_textureImage)
5449 		{
5450 			VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
5451 			VkDevice device = s_renderVK->m_device;
5452 
5453 			vkFreeMemory(device, m_textureDeviceMem, allocatorCb);
5454 
5455 			vkDestroy(m_textureImageStorageView);
5456 			vkDestroy(m_textureImageDepthView);
5457 			vkDestroy(m_textureImageView);
5458 			vkDestroy(m_textureImage);
5459 
5460 			m_currentImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
5461 		}
5462 	}
5463 
update(VkCommandPool _commandPool,uint8_t _side,uint8_t _mip,const Rect & _rect,uint16_t _z,uint16_t _depth,uint16_t _pitch,const Memory * _mem)5464 	void TextureVK::update(VkCommandPool _commandPool, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem)
5465 	{
5466 		BX_UNUSED(_commandPool);
5467 
5468 		VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
5469 		VkDevice device = s_renderVK->m_device;
5470 
5471 		VkBuffer stagingBuffer = VK_NULL_HANDLE;
5472 		VkDeviceMemory stagingDeviceMem = VK_NULL_HANDLE;
5473 
5474 		// staging buffer creation
5475 		VkBufferCreateInfo bci;
5476 		bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
5477 		bci.pNext = NULL;
5478 		bci.flags = 0;
5479 		bci.size = (_pitch == UINT16_MAX ? _mem->size :_rect.m_height * _pitch * _depth);
5480 		bci.queueFamilyIndexCount = 0;
5481 		bci.pQueueFamilyIndices = NULL;
5482 		bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
5483 		bci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
5484 		VK_CHECK(vkCreateBuffer(
5485 			  device
5486 			, &bci
5487 			, allocatorCb
5488 			, &stagingBuffer
5489 			));
5490 
5491 		VkMemoryRequirements mr;
5492 		vkGetBufferMemoryRequirements(
5493 			  device
5494 			, stagingBuffer
5495 			, &mr
5496 			);
5497 
5498 		VkMemoryAllocateInfo ma;
5499 		ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
5500 		ma.pNext = NULL;
5501 		ma.allocationSize = mr.size;
5502 		ma.memoryTypeIndex = s_renderVK->selectMemoryType(
5503 			  mr.memoryTypeBits
5504 			, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
5505 			);
5506 		VK_CHECK(vkAllocateMemory(
5507 			  device
5508 			, &ma
5509 			, allocatorCb
5510 			, &stagingDeviceMem
5511 			));
5512 
5513 		void* directAccessPtr = NULL;
5514 		VK_CHECK(vkBindBufferMemory(device, stagingBuffer, stagingDeviceMem, 0));
5515 		VK_CHECK(vkMapMemory(device, stagingDeviceMem, 0, ma.allocationSize, 0, (void**)&directAccessPtr));
5516 		bx::memCopy(directAccessPtr, _mem->data, size_t(bci.size));
5517 		vkUnmapMemory(device, stagingDeviceMem);
5518 
5519 		const uint32_t bpp    = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) );
5520 		VkBufferImageCopy region;
5521 		region.bufferOffset      = 0;
5522 		region.bufferRowLength   = (_pitch == UINT16_MAX ? 0 : _pitch * 8 / bpp);
5523 		region.bufferImageHeight = 0;
5524 		region.imageSubresource.aspectMask     = m_vkTextureAspect;
5525 		region.imageSubresource.mipLevel       = _mip;
5526 		region.imageSubresource.baseArrayLayer = _side;
5527 		region.imageSubresource.layerCount     = 1;
5528 		region.imageOffset = { _rect.m_x, _rect.m_y, _z };
5529 		region.imageExtent = { _rect.m_width, _rect.m_height, _depth };
5530 
5531 		copyBufferToTexture(stagingBuffer, 1, &region);
5532 
5533 		vkFreeMemory(device, stagingDeviceMem, allocatorCb);
5534 		vkDestroy(stagingBuffer);
5535 	}
5536 
copyBufferToTexture(VkBuffer stagingBuffer,uint32_t bufferImageCopyCount,VkBufferImageCopy * bufferImageCopy)5537 	void TextureVK::copyBufferToTexture(VkBuffer stagingBuffer, uint32_t bufferImageCopyCount, VkBufferImageCopy* bufferImageCopy)
5538 	{
5539 		VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand();
5540 
5541 		// image Layout transition into destination optimal
5542 		setImageMemoryBarrier(commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
5543 
5544 		// copy buffer to image
5545 		vkCmdCopyBufferToImage(
5546 			  commandBuffer
5547 			, stagingBuffer
5548 			, m_textureImage
5549 			, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
5550 			, bufferImageCopyCount
5551 			, bufferImageCopy
5552 			);
5553 
5554 		setImageMemoryBarrier(commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
5555 		s_renderVK->submitCommandAndWait(commandBuffer);
5556 	}
5557 
setImageMemoryBarrier(VkCommandBuffer commandBuffer,VkImageLayout newImageLayout)5558 	void TextureVK::setImageMemoryBarrier(VkCommandBuffer commandBuffer, VkImageLayout newImageLayout)
5559 	{
5560 		if (m_currentImageLayout == newImageLayout)
5561 			return;
5562 		bgfx::vk::setImageMemoryBarrier(commandBuffer
5563 			, m_textureImage
5564 			, m_vkTextureAspect
5565 			, m_currentImageLayout
5566 			, newImageLayout
5567 			, m_numMips
5568 			, m_numSides
5569 			);
5570 		m_currentImageLayout = newImageLayout;
5571 	}
5572 
create(uint8_t _num,const Attachment * _attachment)5573 	void FrameBufferVK::create(uint8_t _num, const Attachment* _attachment)
5574 	{
5575 		// create frame buffer object
5576 		m_numAttachment = _num;
5577 		bx::memCopy(m_attachment, _attachment, sizeof(Attachment) * _num);
5578 
5579 		VkDevice device = s_renderVK->m_device;
5580 		VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb;
5581 		VkRenderPass renderPass = s_renderVK->getRenderPass(_num, _attachment);
5582 
5583 		TextureVK& firstTexture = s_renderVK->m_textures[m_attachment[0].handle.idx];
5584 		::VkImageView textureImageViews[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
5585 
5586 		m_num = 0;
5587 		for (uint8_t ii = 0; ii < m_numAttachment; ++ii)
5588 		{
5589 			TextureVK& texture = s_renderVK->m_textures[m_attachment[ii].handle.idx];
5590 			textureImageViews[ii] = texture.m_textureImageView;
5591 			if (texture.m_vkTextureAspect & VK_IMAGE_ASPECT_COLOR_BIT)
5592 			{
5593 				m_texture[m_num] = m_attachment[ii].handle;
5594 				m_num++;
5595 			}
5596 			else if (texture.m_vkTextureAspect & VK_IMAGE_ASPECT_DEPTH_BIT)
5597 			{
5598 				m_depth = m_attachment[ii].handle;
5599 			}
5600 		}
5601 
5602 		VkFramebufferCreateInfo fci;
5603 		fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
5604 		fci.pNext = NULL;
5605 		fci.flags = 0;
5606 		fci.renderPass      = renderPass;
5607 		fci.attachmentCount = m_numAttachment;
5608 		fci.pAttachments    = textureImageViews;
5609 		fci.width  = firstTexture.m_width >> m_attachment[0].mip;
5610 		fci.height = firstTexture.m_height >> m_attachment[0].mip;
5611 		fci.layers = firstTexture.m_numSides;
5612 		VK_CHECK( vkCreateFramebuffer(device, &fci, allocatorCb, &m_framebuffer) );
5613 		m_renderPass = renderPass;
5614 	}
5615 
destroy()5616 	void FrameBufferVK::destroy()
5617 	{
5618 		vkDestroy(m_framebuffer);
5619 	}
5620 
submitBlit(BlitState & _bs,uint16_t _view)5621 	void RendererContextVK::submitBlit(BlitState& _bs, uint16_t _view)
5622 	{
5623 		TextureHandle currentSrc = { kInvalidHandle };
5624 		TextureHandle currentDst = { kInvalidHandle };
5625 		VkImageLayout oldSrcLayout = VK_IMAGE_LAYOUT_UNDEFINED;
5626 		VkImageLayout oldDstLayout = VK_IMAGE_LAYOUT_UNDEFINED;
5627 
5628 		VkCommandBuffer commandBuffer = beginNewCommand();
5629 		while (_bs.hasItem(_view) )
5630 		{
5631 			const BlitItem& blit = _bs.advance();
5632 
5633 			TextureVK& src = m_textures[blit.m_src.idx];
5634 			TextureVK& dst = m_textures[blit.m_dst.idx];
5635 
5636 			if (currentSrc.idx != blit.m_src.idx)
5637 			{
5638 				if (oldSrcLayout != VK_IMAGE_LAYOUT_UNDEFINED)
5639 				{
5640 					m_textures[currentSrc.idx].setImageMemoryBarrier(commandBuffer, oldSrcLayout);
5641 				}
5642 				oldSrcLayout = src.m_currentImageLayout;
5643 				src.setImageMemoryBarrier(commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
5644 				currentSrc = blit.m_src;
5645 			}
5646 
5647 			if (currentDst.idx != blit.m_dst.idx)
5648 			{
5649 				if (oldDstLayout != VK_IMAGE_LAYOUT_UNDEFINED)
5650 				{
5651 					m_textures[currentDst.idx].setImageMemoryBarrier(commandBuffer, oldDstLayout);
5652 				}
5653 				oldDstLayout = dst.m_currentImageLayout;
5654 				dst.setImageMemoryBarrier(commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
5655 				currentDst = blit.m_dst;
5656 			}
5657 
5658 			uint32_t srcZ = (VK_IMAGE_VIEW_TYPE_CUBE == src.m_type ? 0 : blit.m_srcZ);
5659 			uint32_t dstZ = (VK_IMAGE_VIEW_TYPE_CUBE == dst.m_type ? 0 : blit.m_dstZ);
5660 			uint32_t srcLayer = (VK_IMAGE_VIEW_TYPE_CUBE == src.m_type ? blit.m_srcZ : 0);
5661 			uint32_t dstLayer = (VK_IMAGE_VIEW_TYPE_CUBE == dst.m_type ? blit.m_dstZ : 0);
5662 			uint32_t depth = (blit.m_depth == UINT16_MAX ? 1 : blit.m_depth);
5663 
5664 			VkImageBlit blitInfo;
5665 			blitInfo.srcSubresource.aspectMask     = src.m_vkTextureAspect;
5666 			blitInfo.srcSubresource.mipLevel       = blit.m_srcMip;
5667 			blitInfo.srcSubresource.baseArrayLayer = srcLayer;
5668 			blitInfo.srcSubresource.layerCount     = 1;
5669 			blitInfo.srcOffsets[0].x = blit.m_srcX;
5670 			blitInfo.srcOffsets[0].y = blit.m_srcY;
5671 			blitInfo.srcOffsets[0].z = srcZ;
5672 			blitInfo.srcOffsets[1].x = blit.m_srcX + blit.m_width;
5673 			blitInfo.srcOffsets[1].y = blit.m_srcY + blit.m_height;
5674 			blitInfo.srcOffsets[1].z = srcZ + depth;
5675 			blitInfo.dstSubresource.aspectMask     = dst.m_vkTextureAspect;
5676 			blitInfo.dstSubresource.mipLevel       = blit.m_dstMip;
5677 			blitInfo.dstSubresource.baseArrayLayer = dstLayer;
5678 			blitInfo.dstSubresource.layerCount     = 1;
5679 			blitInfo.dstOffsets[0].x = blit.m_dstX;
5680 			blitInfo.dstOffsets[0].y = blit.m_dstY;
5681 			blitInfo.dstOffsets[0].z = dstZ;
5682 			blitInfo.dstOffsets[1].x = blit.m_dstX + blit.m_width;
5683 			blitInfo.dstOffsets[1].y = blit.m_dstY + blit.m_height;
5684 			blitInfo.dstOffsets[1].z = dstZ + depth;
5685 			vkCmdBlitImage(
5686 				  commandBuffer
5687 				, src.m_textureImage
5688 				, src.m_currentImageLayout
5689 				, dst.m_textureImage
5690 				, dst.m_currentImageLayout
5691 				, 1
5692 				, &blitInfo
5693 				, VK_FILTER_LINEAR
5694 				);
5695 		}
5696 
5697 		if (oldSrcLayout != VK_IMAGE_LAYOUT_UNDEFINED)
5698 		{
5699 			m_textures[currentSrc.idx].setImageMemoryBarrier(commandBuffer, oldSrcLayout);
5700 		}
5701 		if (oldDstLayout != VK_IMAGE_LAYOUT_UNDEFINED)
5702 		{
5703 			m_textures[currentDst.idx].setImageMemoryBarrier(commandBuffer, oldDstLayout);
5704 		}
5705 		submitCommandAndWait(commandBuffer);
5706 	}
5707 
submit(Frame * _render,ClearQuad & _clearQuad,TextVideoMemBlitter & _textVideoMemBlitter)5708 	void RendererContextVK::submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter)
5709 	{
5710 		BX_UNUSED(_render, _clearQuad, _textVideoMemBlitter);
5711 
5712 		updateResolution(_render->m_resolution);
5713 
5714 		int64_t timeBegin = bx::getHPCounter();
5715 		int64_t captureElapsed = 0;
5716 
5717 //		m_gpuTimer.begin(m_commandList);
5718 
5719 		if (0 < _render->m_iboffset)
5720 		{
5721 			BGFX_PROFILER_SCOPE("bgfx/Update transient index buffer", kColorResource);
5722 			TransientIndexBuffer* ib = _render->m_transientIb;
5723 			m_indexBuffers[ib->handle.idx].update(/*m_commandList*/NULL, 0, _render->m_iboffset, ib->data);
5724 		}
5725 
5726 		if (0 < _render->m_vboffset)
5727 		{
5728 			BGFX_PROFILER_SCOPE("bgfx/Update transient vertex buffer", kColorResource);
5729 			TransientVertexBuffer* vb = _render->m_transientVb;
5730 			m_vertexBuffers[vb->handle.idx].update(/*m_commandList*/NULL, 0, _render->m_vboffset, vb->data);
5731 		}
5732 
5733 		_render->sort();
5734 
5735 		RenderDraw currentState;
5736 		currentState.clear();
5737 		currentState.m_stateFlags = BGFX_STATE_NONE;
5738 		currentState.m_stencil    = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE);
5739 
5740 		static ViewState viewState;
5741 		viewState.reset(_render);
5742 
5743 // 		bool wireframe = !!(_render->m_debug&BGFX_DEBUG_WIREFRAME);
5744 // 		setDebugWireframe(wireframe);
5745 
5746 		uint16_t currentSamplerStateIdx = kInvalidHandle;
5747 		ProgramHandle currentProgram    = BGFX_INVALID_HANDLE;
5748 		uint32_t currentBindHash        = 0;
5749 		uint32_t currentDslHash         = 0;
5750 		bool     hasPredefined          = false;
5751 		bool     commandListChanged     = false;
5752 		VkPipeline currentPipeline = VK_NULL_HANDLE;
5753 		SortKey key;
5754 		uint16_t view = UINT16_MAX;
5755 		FrameBufferHandle fbh = { BGFX_CONFIG_MAX_FRAME_BUFFERS };
5756 
5757 		BlitState bs(_render);
5758 
5759 		uint32_t blendFactor = 0;
5760 
5761 		const uint64_t primType = _render->m_debug&BGFX_DEBUG_WIREFRAME ? BGFX_STATE_PT_LINES : 0;
5762 		uint8_t primIndex = uint8_t(primType >> BGFX_STATE_PT_SHIFT);
5763 		PrimInfo prim = s_primInfo[primIndex];
5764 
5765 		bool wasCompute     = false;
5766 		bool viewHasScissor = false;
5767 		bool restoreScissor = false;
5768 		Rect viewScissorRect;
5769 		viewScissorRect.clear();
5770 
5771 		const uint32_t maxComputeBindings = g_caps.limits.maxComputeBindings;
5772 		BX_UNUSED(maxComputeBindings);
5773 
5774 		uint32_t statsNumPrimsSubmitted[BX_COUNTOF(s_primInfo)] = {};
5775 		uint32_t statsNumPrimsRendered[BX_COUNTOF(s_primInfo)] = {};
5776 		uint32_t statsNumInstances[BX_COUNTOF(s_primInfo)] = {};
5777 		uint32_t statsNumIndices = 0;
5778 		uint32_t statsKeyType[2] = {};
5779 
5780 		VkSemaphore renderWait = m_presentDone[m_backBufferColorIdx];
5781 		VkResult result = vkAcquireNextImageKHR(
5782 			  m_device
5783 			, m_swapchain
5784 			, UINT64_MAX
5785 			, renderWait
5786 			, VK_NULL_HANDLE
5787 			, &m_backBufferColorIdx
5788 			);
5789 
5790 		if (VK_ERROR_OUT_OF_DATE_KHR == result
5791 		||  VK_SUBOPTIMAL_KHR        == result)
5792 		{
5793 			m_needToRefreshSwapchain = true;
5794 			return;
5795 		}
5796 
5797 //		const uint64_t f0 = BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_FACTOR, BGFX_STATE_BLEND_FACTOR);
5798 //		const uint64_t f1 = BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_INV_FACTOR, BGFX_STATE_BLEND_INV_FACTOR);
5799 		const uint64_t f0 = BGFX_STATE_BLEND_FACTOR;
5800 		const uint64_t f1 = BGFX_STATE_BLEND_INV_FACTOR;
5801 		const uint64_t f2 = BGFX_STATE_BLEND_FACTOR<<4;
5802 		const uint64_t f3 = BGFX_STATE_BLEND_INV_FACTOR<<4;
5803 
5804 		ScratchBufferVK& scratchBuffer = m_scratchBuffer[m_backBufferColorIdx];
5805 		scratchBuffer.reset();
5806 
5807 		VkCommandBufferBeginInfo cbbi;
5808 		cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
5809 		cbbi.pNext = NULL;
5810 		cbbi.flags = 0
5811 			| VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
5812 //			| VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
5813 			;
5814 		cbbi.pInheritanceInfo = NULL;
5815 
5816 		m_commandBuffer = m_commandBuffers[m_backBufferColorIdx];
5817 		VK_CHECK(vkBeginCommandBuffer(m_commandBuffer, &cbbi) );
5818 
5819 		setImageMemoryBarrier(m_commandBuffer
5820 			, m_backBufferColorImage[m_backBufferColorIdx]
5821 			, VK_IMAGE_ASPECT_COLOR_BIT
5822 			, m_backBufferColorImageLayout[m_backBufferColorIdx]
5823 			, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
5824 			, 1, 1);
5825 		m_backBufferColorImageLayout[m_backBufferColorIdx] = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
5826 
5827 		VkRenderPassBeginInfo rpbi;
5828 		rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
5829 		rpbi.pNext = NULL;
5830 		rpbi.renderPass  = m_renderPass;
5831 		rpbi.framebuffer = m_backBufferColor[m_backBufferColorIdx];
5832 		rpbi.renderArea.offset.x = 0;
5833 		rpbi.renderArea.offset.y = 0;
5834 		rpbi.renderArea.extent = m_sci.imageExtent;
5835 		rpbi.clearValueCount = 0;
5836 		rpbi.pClearValues    = NULL;
5837 
5838 		bool beginRenderPass = false;
5839 
5840 		if (0 == (_render->m_debug&BGFX_DEBUG_IFH) )
5841 		{
5842 //			m_batch.begin();
5843 
5844 			viewState.m_rect = _render->m_view[0].m_rect;
5845 
5846 			int32_t numItems = _render->m_numRenderItems;
5847 			for (int32_t item = 0; item < numItems;)
5848 			{
5849 				const uint64_t encodedKey = _render->m_sortKeys[item];
5850 				const bool isCompute = key.decode(encodedKey, _render->m_viewRemap);
5851 				statsKeyType[isCompute]++;
5852 
5853 				const bool viewChanged = 0
5854 					|| key.m_view != view
5855 					|| item == numItems
5856 					;
5857 
5858 				const uint32_t itemIdx       = _render->m_sortValues[item];
5859 				const RenderItem& renderItem = _render->m_renderItem[itemIdx];
5860 				const RenderBind& renderBind = _render->m_renderItemBind[itemIdx];
5861 				++item;
5862 
5863 				if (viewChanged || isCompute || wasCompute)
5864 				{
5865 					if (beginRenderPass)
5866 					{
5867 						vkCmdEndRenderPass(m_commandBuffer);
5868 						beginRenderPass = false;
5869 
5870 						if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) && s_extension[Extension::EXT_debug_utils].m_supported )
5871 						{
5872 							vkCmdEndDebugUtilsLabelEXT(m_commandBuffer);
5873 						}
5874 					}
5875 
5876 					VK_CHECK(vkEndCommandBuffer(m_commandBuffer) );
5877 
5878 //					m_batch.flush(m_commandList, true);
5879 					kick(renderWait);
5880 					renderWait = VK_NULL_HANDLE;
5881 					finishAll();
5882 
5883 					view = key.m_view;
5884 					currentPipeline = VK_NULL_HANDLE;
5885 					currentSamplerStateIdx = kInvalidHandle;
5886 					BX_UNUSED(currentSamplerStateIdx);
5887 					currentProgram         = BGFX_INVALID_HANDLE;
5888 					hasPredefined          = false;
5889 
5890 					VK_CHECK(vkBeginCommandBuffer(m_commandBuffer, &cbbi) );
5891 					fbh = _render->m_view[view].m_fbh;
5892 					setFrameBuffer(fbh);
5893 
5894 					viewState.m_rect = _render->m_view[view].m_rect;
5895 					const Rect& rect        = _render->m_view[view].m_rect;
5896 					const Rect& scissorRect = _render->m_view[view].m_scissor;
5897 					viewHasScissor  = !scissorRect.isZero();
5898 					viewScissorRect = viewHasScissor ? scissorRect : rect;
5899 
5900 					rpbi.framebuffer = isValid(m_fbh) ? m_frameBuffers[m_fbh.idx].m_framebuffer : m_backBufferColor[m_backBufferColorIdx];
5901 					rpbi.renderPass = isValid(m_fbh) ? m_frameBuffers[m_fbh.idx].m_renderPass : m_renderPass;
5902 					rpbi.renderArea.offset.x = rect.m_x;
5903 					rpbi.renderArea.offset.y = rect.m_y;
5904 					rpbi.renderArea.extent.width  = rect.m_width;
5905 					rpbi.renderArea.extent.height = rect.m_height;
5906 
5907 					if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) && s_extension[Extension::EXT_debug_utils].m_supported )
5908 					{
5909 						VkDebugUtilsLabelEXT dul;
5910 						dul.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
5911 						dul.pNext = NULL;
5912 						dul.pLabelName = s_viewName[view];
5913 						dul.color[0] = 1.0f;
5914 						dul.color[1] = 1.0f;
5915 						dul.color[2] = 1.0f;
5916 						dul.color[3] = 1.0f;
5917 						vkCmdBeginDebugUtilsLabelEXT(m_commandBuffer, &dul);
5918 					}
5919 
5920 					if (!isCompute && !beginRenderPass)
5921 					{
5922 						vkCmdBeginRenderPass(m_commandBuffer, &rpbi, VK_SUBPASS_CONTENTS_INLINE);
5923 						beginRenderPass = true;
5924 
5925 						VkViewport vp;
5926 						vp.x        = rect.m_x;
5927 						vp.y        = rect.m_y;
5928 						vp.width    = rect.m_width;
5929 						vp.height   = rect.m_height;
5930 						vp.minDepth = 0.0f;
5931 						vp.maxDepth = 1.0f;
5932 						vkCmdSetViewport(m_commandBuffer, 0, 1, &vp);
5933 
5934 						VkRect2D rc;
5935 						rc.offset.x      = viewScissorRect.m_x;
5936 						rc.offset.y      = viewScissorRect.m_y;
5937 						rc.extent.width  = viewScissorRect.m_width;
5938 						rc.extent.height = viewScissorRect.m_height;
5939 						vkCmdSetScissor(m_commandBuffer, 0, 1, &rc);
5940 
5941 						restoreScissor = false;
5942 
5943 						Clear& clr = _render->m_view[view].m_clear;
5944 						if (BGFX_CLEAR_NONE != clr.m_flags)
5945 						{
5946 							Rect clearRect = rect;
5947 							clearRect.setIntersect(rect, viewScissorRect);
5948 							clearQuad(clearRect, clr, _render->m_colorPalette);
5949 						}
5950 
5951 						prim = s_primInfo[Topology::Count]; // Force primitive type update.
5952 
5953 						submitBlit(bs, view);
5954 					}
5955 				}
5956 
5957 				if (isCompute)
5958 				{
5959 					if (!wasCompute)
5960 					{
5961 						wasCompute = true;
5962 
5963 //						m_commandList->SetComputeRootSignature(m_rootSignature);
5964 //						ID3D12DescriptorHeap* heaps[] = {
5965 //							m_samplerAllocator.getHeap(),
5966 //							scratchBuffer.getHeap(),
5967 //						};
5968 //						m_commandList->SetDescriptorHeaps(BX_COUNTOF(heaps), heaps);
5969 					}
5970 
5971 					const RenderCompute& compute = renderItem.compute;
5972 
5973 					VkPipeline pipeline = getPipeline(key.m_program);
5974 					if (pipeline != currentPipeline)
5975 					{
5976 						currentPipeline = pipeline;
5977 						vkCmdBindPipeline(m_commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
5978 						currentBindHash = 0;
5979 						currentDslHash = 0;
5980 					}
5981 
5982 					bool constantsChanged = false;
5983 					if (compute.m_uniformBegin < compute.m_uniformEnd
5984 					||  currentProgram.idx != key.m_program.idx)
5985 					{
5986 						rendererUpdateUniforms(this, _render->m_uniformBuffer[compute.m_uniformIdx], compute.m_uniformBegin, compute.m_uniformEnd);
5987 
5988 						currentProgram = key.m_program;
5989 						ProgramVK& program = m_program[currentProgram.idx];
5990 
5991 						UniformBuffer* vcb = program.m_vsh->m_constantBuffer;
5992 						if (NULL != vcb)
5993 						{
5994 							commit(*vcb);
5995 						}
5996 
5997 						hasPredefined = 0 < program.m_numPredefined;
5998 						constantsChanged = true;
5999 					}
6000 
6001 					ProgramVK& program = m_program[currentProgram.idx];
6002 					if (constantsChanged
6003 					||  hasPredefined)
6004 					{
6005 						viewState.setPredefined<4>(this, view, program, _render, compute);
6006 //						commitShaderConstants(key.m_program, gpuAddress);
6007 //						m_commandList->SetComputeRootConstantBufferView(Rdt::CBV, gpuAddress);
6008 					}
6009 
6010 					uint32_t bindHash = bx::hash<bx::HashMurmur2A>(renderBind.m_bind, sizeof(renderBind.m_bind) );
6011 					if (currentBindHash != bindHash
6012 					||  currentDslHash != program.m_descriptorSetLayoutHash)
6013 					{
6014 						currentBindHash = bindHash;
6015 						currentDslHash = program.m_descriptorSetLayoutHash;
6016 
6017 						allocDescriptorSet(program, renderBind, scratchBuffer);
6018 					}
6019 
6020 					uint32_t offset = 0;
6021 
6022 					if (constantsChanged
6023 					||  hasPredefined)
6024 					{
6025 						const uint32_t align = uint32_t(m_deviceProperties.limits.minUniformBufferOffsetAlignment);
6026 						const uint32_t vsize = bx::strideAlign(program.m_vsh->m_size, align);
6027 
6028 						offset = scratchBuffer.m_pos;
6029 
6030 						m_vsChanges = 0;
6031 						m_fsChanges = 0;
6032 
6033 						bx::memCopy(&scratchBuffer.m_data[scratchBuffer.m_pos], m_vsScratch, program.m_vsh->m_size);
6034 
6035 						scratchBuffer.m_pos += vsize;
6036 					}
6037 
6038 					vkCmdBindDescriptorSets(
6039 						m_commandBuffer
6040 						, VK_PIPELINE_BIND_POINT_COMPUTE
6041 						, program.m_pipelineLayout
6042 						, 0
6043 						, 1
6044 						, &scratchBuffer.getCurrentDS()
6045 						, constantsChanged || hasPredefined ? 1 : 0
6046 						, &offset
6047 						);
6048 
6049 					if (isValid(compute.m_indirectBuffer) )
6050 					{
6051 						const VertexBufferVK& vb = m_vertexBuffers[compute.m_indirectBuffer.idx];
6052 
6053 						uint32_t numDrawIndirect = UINT16_MAX == compute.m_numIndirect
6054 							? vb.m_size/BGFX_CONFIG_DRAW_INDIRECT_STRIDE
6055 							: compute.m_numIndirect
6056 							;
6057 
6058 						uint32_t args = compute.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE;
6059 						for (uint32_t ii = 0; ii < numDrawIndirect; ++ii)
6060 						{
6061 							vkCmdDispatchIndirect(m_commandBuffer, vb.m_buffer, args);
6062 							args += BGFX_CONFIG_DRAW_INDIRECT_STRIDE;
6063 						}
6064 					}
6065 					else
6066 					{
6067 						vkCmdDispatch(m_commandBuffer, compute.m_numX, compute.m_numY, compute.m_numZ);
6068 					}
6069 
6070 					continue;
6071 				}
6072 
6073 				const RenderDraw& draw = renderItem.draw;
6074 
6075 				const bool hasOcclusionQuery = false; //0 != (draw.m_stateFlags & BGFX_STATE_INTERNAL_OCCLUSION_QUERY);
6076 				{
6077 					const bool occluded = false //true
6078 //						&& isValid(draw.m_occlusionQuery)
6079 //						&& !hasOcclusionQuery
6080 //						&& !isVisible(_render, draw.m_occlusionQuery, 0 != (draw.m_submitFlags&BGFX_SUBMIT_INTERNAL_OCCLUSION_VISIBLE) )
6081 						;
6082 
6083 					if (occluded
6084 					||  _render->m_frameCache.isZeroArea(viewScissorRect, draw.m_scissor) )
6085 					{
6086 //						if (resetState)
6087 //						{
6088 //							currentState.clear();
6089 //							currentState.m_scissor = !draw.m_scissor;
6090 //							currentBind.clear();
6091 //						}
6092 
6093 						continue;
6094 					}
6095 				}
6096 
6097 				const uint64_t newFlags = draw.m_stateFlags;
6098 				uint64_t changedFlags = currentState.m_stateFlags ^ draw.m_stateFlags;
6099 				currentState.m_stateFlags = newFlags;
6100 
6101 				const uint64_t newStencil = draw.m_stencil;
6102 				uint64_t changedStencil = (currentState.m_stencil ^ draw.m_stencil) & BGFX_STENCIL_FUNC_REF_MASK;
6103 				currentState.m_stencil = newStencil;
6104 
6105 				if (viewChanged
6106 				||  wasCompute)
6107 				{
6108 					if (wasCompute)
6109 					{
6110 						wasCompute = false;
6111 					}
6112 
6113 					if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) )
6114 					{
6115 						BX_UNUSED(s_viewName);
6116 // 						wchar_t* viewNameW = s_viewNameW[view];
6117 // 						viewNameW[3] = L' ';
6118 // 						PIX_ENDEVENT();
6119 // 						PIX_BEGINEVENT(toRgba8(0xff, 0x00, 0x00, 0xff), viewNameW);
6120 					}
6121 
6122 					commandListChanged = true;
6123 				}
6124 
6125 				if (commandListChanged)
6126 				{
6127 					commandListChanged = false;
6128 
6129 //					m_commandList->SetGraphicsRootSignature(m_rootSignature);
6130 //					ID3D12DescriptorHeap* heaps[] = {
6131 //						m_samplerAllocator.getHeap(),
6132 //						scratchBuffer.getHeap(),
6133 //					};
6134 //					m_commandList->SetDescriptorHeaps(BX_COUNTOF(heaps), heaps);
6135 
6136 					currentPipeline        = VK_NULL_HANDLE;
6137 					currentBindHash        = 0;
6138 					currentDslHash         = 0;
6139 					currentSamplerStateIdx = kInvalidHandle;
6140 					currentProgram         = BGFX_INVALID_HANDLE;
6141 					currentState.clear();
6142 					currentState.m_scissor = !draw.m_scissor;
6143 					changedFlags = BGFX_STATE_MASK;
6144 					changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
6145 					currentState.m_stateFlags = newFlags;
6146 					currentState.m_stencil    = newStencil;
6147 
6148 					const uint64_t pt = newFlags&BGFX_STATE_PT_MASK;
6149 					primIndex = uint8_t(pt>>BGFX_STATE_PT_SHIFT);
6150 				}
6151 
6152 				rendererUpdateUniforms(this, _render->m_uniformBuffer[draw.m_uniformIdx], draw.m_uniformBegin, draw.m_uniformEnd);
6153 
6154 				if (0 != draw.m_streamMask)
6155 				{
6156 					currentState.m_streamMask			= draw.m_streamMask;
6157 
6158 					const uint64_t state = draw.m_stateFlags;
6159 					bool hasFactor = 0
6160 						|| f0 == (state & f0)
6161 						|| f1 == (state & f1)
6162 						|| f2 == (state & f2)
6163 						|| f3 == (state & f3)
6164 						;
6165 
6166 					const VertexLayout* layouts[BGFX_CONFIG_MAX_VERTEX_STREAMS];
6167 					uint8_t numStreams = 0;
6168 					if (UINT8_MAX != draw.m_streamMask)
6169 					{
6170 						for (uint32_t idx = 0, streamMask = draw.m_streamMask
6171 							; 0 != streamMask
6172 							; streamMask >>= 1, idx += 1, ++numStreams
6173 							)
6174 						{
6175 							const uint32_t ntz = bx::uint32_cnttz(streamMask);
6176 							streamMask >>= ntz;
6177 							idx         += ntz;
6178 
6179 							currentState.m_stream[idx].m_layoutHandle   = draw.m_stream[idx].m_layoutHandle;
6180 							currentState.m_stream[idx].m_handle         = draw.m_stream[idx].m_handle;
6181 							currentState.m_stream[idx].m_startVertex    = draw.m_stream[idx].m_startVertex;
6182 
6183 							uint16_t handle = draw.m_stream[idx].m_handle.idx;
6184 							const VertexBufferVK& vb = m_vertexBuffers[handle];
6185 							const uint16_t decl = isValid(draw.m_stream[idx].m_layoutHandle)
6186 												  ? draw.m_stream[idx].m_layoutHandle.idx
6187 												  : vb.m_layoutHandle.idx;
6188 							const VertexLayout& layout = m_vertexLayouts[decl];
6189 
6190 							layouts[numStreams] = &layout;
6191 						}
6192 					}
6193 
6194 					VkPipeline pipeline =
6195 						getPipeline(state
6196 							, draw.m_stencil
6197 							, numStreams
6198 							, layouts
6199 							, key.m_program
6200 							, uint8_t(draw.m_instanceDataStride/16)
6201 							);
6202 
6203 					uint16_t scissor = draw.m_scissor;
6204 					uint32_t bindHash = bx::hash<bx::HashMurmur2A>(renderBind.m_bind, sizeof(renderBind.m_bind) );
6205 
6206 					if (pipeline != currentPipeline
6207 					||  0 != changedStencil)
6208 					{
6209 						const uint32_t fstencil = unpackStencil(0, draw.m_stencil);
6210 						const uint32_t ref = (fstencil&BGFX_STENCIL_FUNC_REF_MASK)>>BGFX_STENCIL_FUNC_REF_SHIFT;
6211 						vkCmdSetStencilReference(m_commandBuffer, VK_STENCIL_FRONT_AND_BACK, ref);
6212 					}
6213 
6214 					if (pipeline != currentPipeline
6215 					|| (hasFactor && blendFactor != draw.m_rgba) )
6216 					{
6217 						blendFactor = draw.m_rgba;
6218 
6219 						float bf[4];
6220 						bf[0] = ( (draw.m_rgba>>24)     )/255.0f;
6221 						bf[1] = ( (draw.m_rgba>>16)&0xff)/255.0f;
6222 						bf[2] = ( (draw.m_rgba>> 8)&0xff)/255.0f;
6223 						bf[3] = ( (draw.m_rgba    )&0xff)/255.0f;
6224 						vkCmdSetBlendConstants(m_commandBuffer, bf);
6225 					}
6226 
6227 					if (0 != (BGFX_STATE_PT_MASK & changedFlags)
6228 					||  prim.m_topology != s_primInfo[primIndex].m_topology)
6229 					{
6230 						const uint64_t pt = newFlags&BGFX_STATE_PT_MASK;
6231 						primIndex = uint8_t(pt>>BGFX_STATE_PT_SHIFT);
6232 						prim = s_primInfo[primIndex];
6233 //						m_commandList->IASetPrimitiveTopology(prim.m_topology);
6234 					}
6235 
6236 					if (currentState.m_scissor != scissor)
6237 					{
6238 						currentState.m_scissor = scissor;
6239 
6240 						if (UINT16_MAX == scissor)
6241 						{
6242 							if (restoreScissor
6243 							||  viewHasScissor)
6244 							{
6245 								restoreScissor = false;
6246 								VkRect2D rc;
6247 								rc.offset.x      = viewScissorRect.m_x;
6248 								rc.offset.y      = viewScissorRect.m_y;
6249 								rc.extent.width  = viewScissorRect.m_width;
6250 								rc.extent.height = viewScissorRect.m_height;
6251 								vkCmdSetScissor(m_commandBuffer, 0, 1, &rc);
6252 							}
6253 						}
6254 						else
6255 						{
6256 							restoreScissor = true;
6257 							Rect scissorRect;
6258 							scissorRect.setIntersect(viewScissorRect, _render->m_frameCache.m_rectCache.m_cache[scissor]);
6259 
6260 							VkRect2D rc;
6261 							rc.offset.x      = scissorRect.m_x;
6262 							rc.offset.y      = scissorRect.m_y;
6263 							rc.extent.width  = scissorRect.m_width;
6264 							rc.extent.height = scissorRect.m_height;
6265 							vkCmdSetScissor(m_commandBuffer, 0, 1, &rc);
6266 						}
6267 					}
6268 
6269 					if (pipeline != currentPipeline)
6270 					{
6271 						currentPipeline = pipeline;
6272 						vkCmdBindPipeline(m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
6273 					}
6274 
6275 					bool constantsChanged = false;
6276 					if (draw.m_uniformBegin < draw.m_uniformEnd
6277 					||  currentProgram.idx != key.m_program.idx
6278 					||  BGFX_STATE_ALPHA_REF_MASK & changedFlags)
6279 					{
6280 						currentProgram = key.m_program;
6281 						ProgramVK& program = m_program[currentProgram.idx];
6282 
6283 						UniformBuffer* vcb = program.m_vsh->m_constantBuffer;
6284 						if (NULL != vcb)
6285 						{
6286 							commit(*vcb);
6287 						}
6288 
6289 						UniformBuffer* fcb = program.m_fsh->m_constantBuffer;
6290 						if (NULL != fcb)
6291 						{
6292 							commit(*fcb);
6293 						}
6294 
6295 						hasPredefined = 0 < program.m_numPredefined;
6296 						constantsChanged = true;
6297 					}
6298 
6299 					ProgramVK& program = m_program[currentProgram.idx];
6300 					if (hasPredefined)
6301 					{
6302 						uint32_t ref = (newFlags & BGFX_STATE_ALPHA_REF_MASK) >> BGFX_STATE_ALPHA_REF_SHIFT;
6303 						viewState.m_alphaRef = ref / 255.0f;
6304 						viewState.setPredefined<4>(this, view, program, _render, draw);
6305 					}
6306 
6307 					if (currentBindHash != bindHash
6308 					||  currentDslHash != program.m_descriptorSetLayoutHash)
6309 					{
6310 						currentBindHash = bindHash;
6311 						currentDslHash = program.m_descriptorSetLayoutHash;
6312 
6313 						allocDescriptorSet(program, renderBind, scratchBuffer);
6314 					}
6315 
6316 					uint32_t numOffset = 0;
6317 					uint32_t offsets[2] = {0, 0};
6318 					if (constantsChanged
6319 					||  hasPredefined)
6320 					{
6321 						const uint32_t align = uint32_t(m_deviceProperties.limits.minUniformBufferOffsetAlignment);
6322 						const uint32_t vsize = bx::strideAlign(program.m_vsh->m_size, align);
6323 						const uint32_t fsize = bx::strideAlign((NULL != program.m_fsh ? program.m_fsh->m_size : 0), align);
6324 						const uint32_t total = vsize + fsize;
6325 						if (vsize > 0)
6326 						{
6327 							offsets[numOffset++] = scratchBuffer.m_pos;
6328 							bx::memCopy(&scratchBuffer.m_data[scratchBuffer.m_pos], m_vsScratch, program.m_vsh->m_size);
6329 						}
6330 						if (fsize > 0)
6331 						{
6332 							offsets[numOffset++] = scratchBuffer.m_pos + vsize;
6333 							bx::memCopy(&scratchBuffer.m_data[scratchBuffer.m_pos + vsize], m_fsScratch, program.m_fsh->m_size);
6334 						}
6335 
6336 						m_vsChanges = 0;
6337 						m_fsChanges = 0;
6338 						scratchBuffer.m_pos += total;
6339 					}
6340 
6341 					vkCmdBindDescriptorSets(
6342 						m_commandBuffer
6343 						, VK_PIPELINE_BIND_POINT_GRAPHICS
6344 						, program.m_pipelineLayout
6345 						, 0
6346 						, 1
6347 						, &scratchBuffer.getCurrentDS()
6348 						, numOffset
6349 						, offsets
6350 						);
6351 
6352 
6353 //					if (constantsChanged
6354 //					||  hasPredefined)
6355 //					{
6356 //						ProgramVK& program = m_program[currentProgram.idx];
6357 //						uint32_t ref = (newFlags&BGFX_STATE_ALPHA_REF_MASK)>>BGFX_STATE_ALPHA_REF_SHIFT;
6358 //						viewState.m_alphaRef = ref/255.0f;
6359 //						viewState.setPredefined<4>(this, view, program, _render, draw);
6360 //						commitShaderUniforms(m_commandBuffer, key.m_program); //, gpuAddress);
6361 //					}
6362 
6363 //					vb.setState(_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);
6364 
6365 					uint32_t numIndices = 0;
6366 					for (uint32_t ii = 0; ii < numStreams; ++ii)
6367 					{
6368 						VkDeviceSize offset = 0;
6369 						vkCmdBindVertexBuffers(m_commandBuffer
6370 							, ii
6371 							, 1
6372 							, &m_vertexBuffers[draw.m_stream[ii].m_handle.idx].m_buffer
6373 							, &offset
6374 							);
6375 					}
6376 
6377 					if (isValid(draw.m_instanceDataBuffer))
6378 					{
6379 						VkDeviceSize instanceOffset = draw.m_instanceDataOffset;
6380 						VertexBufferVK& instanceBuffer = m_vertexBuffers[draw.m_instanceDataBuffer.idx];
6381 						vkCmdBindVertexBuffers(m_commandBuffer
6382 							, numStreams
6383 							, 1
6384 							, &instanceBuffer.m_buffer
6385 							, &instanceOffset
6386 							);
6387 					}
6388 
6389 					if (!isValid(draw.m_indexBuffer) )
6390 					{
6391 						const VertexBufferVK& vertexBuffer = m_vertexBuffers[draw.m_stream[0].m_handle.idx];
6392 						const VertexLayout& layout = m_vertexLayouts[draw.m_stream[0].m_layoutHandle.idx];
6393 
6394 						const uint32_t numVertices = UINT32_MAX == draw.m_numVertices
6395 							? vertexBuffer.m_size / layout.m_stride
6396 							: draw.m_numVertices
6397 							;
6398 						vkCmdDraw(m_commandBuffer
6399 							, numVertices
6400 							, draw.m_numInstances
6401 							, draw.m_stream[0].m_startVertex
6402 							, 0
6403 							);
6404 					}
6405 					else
6406 					{
6407 						BufferVK& ib = m_indexBuffers[draw.m_indexBuffer.idx];
6408 
6409 						const bool hasIndex16 = 0 == (ib.m_flags & BGFX_BUFFER_INDEX32);
6410 						const uint32_t indexSize = hasIndex16 ? 2 : 4;
6411 
6412 						numIndices = UINT32_MAX == draw.m_numIndices
6413 							? ib.m_size / indexSize
6414 							: draw.m_numIndices
6415 							;
6416 
6417 						vkCmdBindIndexBuffer(m_commandBuffer
6418 							, ib.m_buffer
6419 							, 0
6420 							, hasIndex16
6421 								? VK_INDEX_TYPE_UINT16
6422 								: VK_INDEX_TYPE_UINT32
6423 							);
6424 						vkCmdDrawIndexed(m_commandBuffer
6425 							, numIndices
6426 							, draw.m_numInstances
6427 							, draw.m_startIndex
6428 							, draw.m_stream[0].m_startVertex
6429 							, 0
6430 							);
6431 					}
6432 
6433 					uint32_t numPrimsSubmitted = numIndices / prim.m_div - prim.m_sub;
6434 					uint32_t numPrimsRendered  = numPrimsSubmitted*draw.m_numInstances;
6435 
6436 					statsNumPrimsSubmitted[primIndex] += numPrimsSubmitted;
6437 					statsNumPrimsRendered[primIndex]  += numPrimsRendered;
6438 					statsNumInstances[primIndex]      += draw.m_numInstances;
6439 					statsNumIndices                   += numIndices;
6440 
6441 					if (hasOcclusionQuery)
6442 					{
6443 //						m_occlusionQuery.begin(m_commandList, _render, draw.m_occlusionQuery);
6444 //						m_batch.flush(m_commandList);
6445 //						m_occlusionQuery.end(m_commandList);
6446 					}
6447 				}
6448 			}
6449 
6450 			submitBlit(bs, BGFX_CONFIG_MAX_VIEWS);
6451 
6452 //			m_batch.end(m_commandList);
6453 		}
6454 
6455 		int64_t timeEnd = bx::getHPCounter();
6456 		int64_t frameTime = timeEnd - timeBegin;
6457 
6458 		static int64_t min = frameTime;
6459 		static int64_t max = frameTime;
6460 		min = bx::min<int64_t>(min, frameTime);
6461 		max = bx::max<int64_t>(max, frameTime);
6462 
6463 		static uint32_t maxGpuLatency = 0;
6464 		static double   maxGpuElapsed = 0.0f;
6465 		double elapsedGpuMs = 0.0;
6466 BX_UNUSED(maxGpuLatency, maxGpuElapsed, elapsedGpuMs);
6467 
6468 		static int64_t presentMin = 0; //m_presentElapsed;
6469 		static int64_t presentMax = 0; //m_presentElapsed;
6470 BX_UNUSED(presentMin, presentMax);
6471 //		presentMin = bx::min<int64_t>(presentMin, m_presentElapsed);
6472 //		presentMax = bx::max<int64_t>(presentMax, m_presentElapsed);
6473 
6474 //		m_gpuTimer.end(m_commandList);
6475 
6476 //		while (m_gpuTimer.get() )
6477 //		{
6478 //			double toGpuMs = 1000.0 / double(m_gpuTimer.m_frequency);
6479 //			elapsedGpuMs   = m_gpuTimer.m_elapsed * toGpuMs;
6480 //			maxGpuElapsed  = elapsedGpuMs > maxGpuElapsed ? elapsedGpuMs : maxGpuElapsed;
6481 //		}
6482 //		maxGpuLatency = bx::uint32_imax(maxGpuLatency, m_gpuTimer.m_control.available()-1);
6483 
6484 		const int64_t timerFreq = bx::getHPFrequency();
6485 
6486 		Stats& perfStats = _render->m_perfStats;
6487 		perfStats.cpuTimeBegin  = timeBegin;
6488 		perfStats.cpuTimeEnd    = timeEnd;
6489 		perfStats.cpuTimerFreq  = timerFreq;
6490 //		perfStats.gpuTimeBegin  = m_gpuTimer.m_begin;
6491 //		perfStats.gpuTimeEnd    = m_gpuTimer.m_end;
6492 //		perfStats.gpuTimerFreq  = m_gpuTimer.m_frequency;
6493 //		perfStats.numDraw       = statsKeyType[0];
6494 //		perfStats.numCompute    = statsKeyType[1];
6495 		perfStats.numBlit       = _render->m_numBlitItems;
6496 //		perfStats.maxGpuLatency = maxGpuLatency;
6497 		bx::memCopy(perfStats.numPrims, statsNumPrimsRendered, sizeof(perfStats.numPrims) );
6498 		perfStats.gpuMemoryMax  = -INT64_MAX;
6499 		perfStats.gpuMemoryUsed = -INT64_MAX;
6500 
6501 		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
6502 		{
6503 //			PIX_BEGINEVENT(toRgba8(0x40, 0x40, 0x40, 0xff), L"debugstats");
6504 
6505 //			m_needPresent = true;
6506 			TextVideoMem& tvm = m_textVideoMem;
6507 
6508 			static int64_t next = timeEnd;
6509 
6510 			if (timeEnd >= next)
6511 			{
6512 				next = timeEnd + timerFreq;
6513 
6514 				double freq = double(timerFreq);
6515 				double toMs = 1000.0 / freq;
6516 
6517 				tvm.clear();
6518 				uint16_t pos = 0;
6519 				tvm.printf(0, pos++, BGFX_CONFIG_DEBUG ? 0x8c : 0x8f
6520 					, " %s / " BX_COMPILER_NAME " / " BX_CPU_NAME " / " BX_ARCH_NAME " / " BX_PLATFORM_NAME " "
6521 					, getRendererName()
6522 					);
6523 
6524 				const VkPhysicalDeviceProperties& pdp = m_deviceProperties;
6525 				tvm.printf(0, pos++, 0x8f, " Device: %s (%s)"
6526 					, pdp.deviceName
6527 					, getName(pdp.deviceType)
6528 					);
6529 
6530 				if (s_extension[Extension::EXT_memory_budget].m_supported)
6531 				{
6532 					VkPhysicalDeviceMemoryBudgetPropertiesEXT dmbp;
6533 					dmbp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
6534 					dmbp.pNext = NULL;
6535 
6536 					VkPhysicalDeviceMemoryProperties2 pdmp2;
6537 					pdmp2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
6538 					pdmp2.pNext = &dmbp;
6539 
6540 					vkGetPhysicalDeviceMemoryProperties2KHR(m_physicalDevice, &pdmp2);
6541 
6542 					for (uint32_t ii = 0; ii < VK_MAX_MEMORY_HEAPS; ++ii)
6543 					{
6544 						if (dmbp.heapBudget[ii] == 0)
6545 						{
6546 							continue;
6547 						}
6548 
6549 						char budget[16];
6550 						bx::prettify(budget, BX_COUNTOF(budget), dmbp.heapBudget[ii]);
6551 
6552 						char usage[16];
6553 						bx::prettify(usage, BX_COUNTOF(usage), dmbp.heapUsage[ii]);
6554 
6555 						tvm.printf(0, pos++, 0x8f, " Memory %d - Budget: %12s, Usage: %12s"
6556 							, ii
6557 							, budget
6558 							, usage
6559 							);
6560 					}
6561 				}
6562 
6563 				pos = 10;
6564 				tvm.printf(10, pos++, 0x8b, "       Frame: % 7.3f, % 7.3f \x1f, % 7.3f \x1e [ms] / % 6.2f FPS "
6565 					, double(frameTime)*toMs
6566 					, double(min)*toMs
6567 					, double(max)*toMs
6568 					, freq/frameTime
6569 					);
6570 //				tvm.printf(10, pos++, 0x8b, "     Present: % 7.3f, % 7.3f \x1f, % 7.3f \x1e [ms] "
6571 //					, double(m_presentElapsed)*toMs
6572 //					, double(presentMin)*toMs
6573 //					, double(presentMax)*toMs
6574 //					);
6575 
6576 				const uint32_t msaa = (m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT;
6577 				tvm.printf(10, pos++, 0x8b, " Reset flags: [%c] vsync, [%c] MSAAx%d, [%c] MaxAnisotropy "
6578 					, !!(m_resolution.reset&BGFX_RESET_VSYNC) ? '\xfe' : ' '
6579 					, 0 != msaa ? '\xfe' : ' '
6580 					, 1<<msaa
6581 					, !!(m_resolution.reset&BGFX_RESET_MAXANISOTROPY) ? '\xfe' : ' '
6582 					);
6583 
6584 				double elapsedCpuMs = double(frameTime)*toMs;
6585 				tvm.printf(10, pos++, 0x8b, "   Submitted: %5d (draw %5d, compute %4d) / CPU %7.4f [ms] "
6586 					, _render->m_numRenderItems
6587 					, statsKeyType[0]
6588 					, statsKeyType[1]
6589 					, elapsedCpuMs
6590 					);
6591 
6592 				for (uint32_t ii = 0; ii < Topology::Count; ++ii)
6593 				{
6594 					tvm.printf(10, pos++, 0x8b, "   %9s: %7d (#inst: %5d), submitted: %7d "
6595 						, getName(Topology::Enum(ii) )
6596 						, statsNumPrimsRendered[ii]
6597 						, statsNumInstances[ii]
6598 						, statsNumPrimsSubmitted[ii]
6599 						);
6600 				}
6601 
6602 //				tvm.printf(10, pos++, 0x8b, "       Batch: %7dx%d indirect, %7d immediate "
6603 //					, m_batch.m_stats.m_numIndirect[BatchD3D12::Draw]
6604 //					, m_batch.m_maxDrawPerBatch
6605 //					, m_batch.m_stats.m_numImmediate[BatchD3D12::Draw]
6606 //					);
6607 
6608 //				tvm.printf(10, pos++, 0x8b, "              %7dx%d indirect, %7d immediate "
6609 //					, m_batch.m_stats.m_numIndirect[BatchD3D12::DrawIndexed]
6610 //					, m_batch.m_maxDrawPerBatch
6611 //					, m_batch.m_stats.m_numImmediate[BatchD3D12::DrawIndexed]
6612 //					);
6613 
6614 				if (NULL != m_renderDocDll)
6615 				{
6616 					tvm.printf(tvm.m_width-27, 0, 0x4f, " [F11 - RenderDoc capture] ");
6617 				}
6618 
6619 				tvm.printf(10, pos++, 0x8b, "      Indices: %7d ", statsNumIndices);
6620 //				tvm.printf(10, pos++, 0x8b, " Uniform size: %7d, Max: %7d ", _render->m_uniformEnd, _render->m_uniformMax);
6621 				tvm.printf(10, pos++, 0x8b, "     DVB size: %7d ", _render->m_vboffset);
6622 				tvm.printf(10, pos++, 0x8b, "     DIB size: %7d ", _render->m_iboffset);
6623 
6624 				pos++;
6625 				tvm.printf(10, pos++, 0x8b, " State cache:                        ");
6626 				tvm.printf(10, pos++, 0x8b, " PSO    | DSL     | DS     | Queued  ");
6627 				tvm.printf(10, pos++, 0x8b, " %6d | %6d | %6d | %6d  "
6628 					, m_pipelineStateCache.getCount()
6629 					, m_descriptorSetLayoutCache.getCount()
6630 					, scratchBuffer.m_currentDs
6631 //					, m_cmd.m_control.available()
6632 					);
6633 				pos++;
6634 
6635 				double captureMs = double(captureElapsed)*toMs;
6636 				tvm.printf(10, pos++, 0x8b, "     Capture: %7.4f [ms] ", captureMs);
6637 
6638 				uint8_t attr[2] = { 0x8c, 0x8a };
6639 				uint8_t attrIndex = _render->m_waitSubmit < _render->m_waitRender;
6640 
6641 				tvm.printf(10, pos++, attr[attrIndex&1], " Submit wait: %7.4f [ms] ", _render->m_waitSubmit*toMs);
6642 				tvm.printf(10, pos++, attr[(attrIndex+1)&1], " Render wait: %7.4f [ms] ", _render->m_waitRender*toMs);
6643 
6644 				min = frameTime;
6645 				max = frameTime;
6646 //				presentMin = m_presentElapsed;
6647 //				presentMax = m_presentElapsed;
6648 			}
6649 
6650 			blit(this, _textVideoMemBlitter, tvm);
6651 
6652 //			PIX_ENDEVENT();
6653 		}
6654 		else if (_render->m_debug & BGFX_DEBUG_TEXT)
6655 		{
6656 //			PIX_BEGINEVENT(toRgba8(0x40, 0x40, 0x40, 0xff), L"debugtext");
6657 
6658 			blit(this, _textVideoMemBlitter, _render->m_textVideoMem);
6659 
6660 //			PIX_ENDEVENT();
6661 		}
6662 
6663 		VkMappedMemoryRange range;
6664 		range.sType  = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
6665 		range.pNext  = NULL;
6666 		range.memory = scratchBuffer.m_deviceMem;
6667 		range.offset = 0;
6668 		range.size   = scratchBuffer.m_pos;
6669 		vkFlushMappedMemoryRanges(m_device, 1, &range);
6670 
6671 		if (beginRenderPass)
6672 		{
6673 			vkCmdEndRenderPass(m_commandBuffer);
6674 			beginRenderPass = false;
6675 
6676 			if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) && s_extension[Extension::EXT_debug_utils].m_supported )
6677 			{
6678 				vkCmdEndDebugUtilsLabelEXT(m_commandBuffer);
6679 			}
6680 		}
6681 
6682 		setImageMemoryBarrier(m_commandBuffer
6683 			, m_backBufferColorImage[m_backBufferColorIdx]
6684 			, VK_IMAGE_ASPECT_COLOR_BIT
6685 			, m_backBufferColorImageLayout[m_backBufferColorIdx]
6686 			, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
6687 			, 1, 1);
6688 		m_backBufferColorImageLayout[m_backBufferColorIdx] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
6689 
6690 		VK_CHECK(vkEndCommandBuffer(m_commandBuffer) );
6691 
6692 		kick(renderWait); //, m_presentDone[m_backBufferColorIdx]);
6693 		finishAll();
6694 
6695 		VK_CHECK(vkResetCommandPool(m_device, m_commandPool, 0) );
6696 	}
6697 
6698 } /* namespace vk */ } // namespace bgfx
6699 
6700 #else
6701 
6702 namespace bgfx { namespace vk
6703 {
rendererCreate(const Init & _init)6704 	RendererContextI* rendererCreate(const Init& _init)
6705 	{
6706 		BX_UNUSED(_init);
6707 		return NULL;
6708 	}
6709 
rendererDestroy()6710 	void rendererDestroy()
6711 	{
6712 	}
6713 } /* namespace vk */ } // namespace bgfx
6714 
6715 #endif // BGFX_CONFIG_RENDERER_VULKAN
6716