1 // Copyright (c) 2015- PPSSPP Project.
2 
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6 
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License 2.0 for more details.
11 
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14 
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17 
18 #include <cstdio>
19 #include <vector>
20 #include <string>
21 #include <map>
22 
23 #include "Common/System/Display.h"
24 #include "Common/Math/lin/matrix4x4.h"
25 #include "Common/Data/Convert/SmallDataConvert.h"
26 #include "Common/GPU/thin3d.h"
27 #include "Common/GPU/Vulkan/VulkanRenderManager.h"
28 
29 #include "Common/Log.h"
30 #include "Common/StringUtils.h"
31 #include "Common/GPU/Vulkan/VulkanContext.h"
32 #include "Common/GPU/Vulkan/VulkanImage.h"
33 #include "Common/GPU/Vulkan/VulkanMemory.h"
34 
35 #include "Core/Config.h"
36 
37 // We use a simple descriptor set for all rendering: 1 sampler, 1 texture, 1 UBO binding point.
38 // binding 0 - uniform data
39 // binding 1 - sampler
40 // binding 2 - sampler
41 //
42 // Vertex data lives in a separate namespace (location = 0, 1, etc)
43 
44 #include "Common/GPU/Vulkan/VulkanLoader.h"
45 
46 using namespace PPSSPP_VK;
47 
48 namespace Draw {
49 
50 // This can actually be replaced with a cast as the values are in the right order.
51 static const VkCompareOp compToVK[] = {
52 	VK_COMPARE_OP_NEVER,
53 	VK_COMPARE_OP_LESS,
54 	VK_COMPARE_OP_EQUAL,
55 	VK_COMPARE_OP_LESS_OR_EQUAL,
56 	VK_COMPARE_OP_GREATER,
57 	VK_COMPARE_OP_NOT_EQUAL,
58 	VK_COMPARE_OP_GREATER_OR_EQUAL,
59 	VK_COMPARE_OP_ALWAYS
60 };
61 
62 // So can this.
63 static const VkBlendOp blendEqToVk[] = {
64 	VK_BLEND_OP_ADD,
65 	VK_BLEND_OP_SUBTRACT,
66 	VK_BLEND_OP_REVERSE_SUBTRACT,
67 	VK_BLEND_OP_MIN,
68 	VK_BLEND_OP_MAX,
69 };
70 
71 static const VkBlendFactor blendFactorToVk[] = {
72 	VK_BLEND_FACTOR_ZERO,
73 	VK_BLEND_FACTOR_ONE,
74 	VK_BLEND_FACTOR_SRC_COLOR,
75 	VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
76 	VK_BLEND_FACTOR_DST_COLOR,
77 	VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
78 	VK_BLEND_FACTOR_SRC_ALPHA,
79 	VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
80 	VK_BLEND_FACTOR_DST_ALPHA,
81 	VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
82 	VK_BLEND_FACTOR_CONSTANT_COLOR,
83 	VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
84 	VK_BLEND_FACTOR_CONSTANT_ALPHA,
85 	VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
86 	VK_BLEND_FACTOR_SRC1_COLOR,
87 	VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR,
88 	VK_BLEND_FACTOR_SRC1_ALPHA,
89 	VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
90 };
91 
92 static const VkLogicOp logicOpToVK[] = {
93 	VK_LOGIC_OP_CLEAR,
94 	VK_LOGIC_OP_SET,
95 	VK_LOGIC_OP_COPY,
96 	VK_LOGIC_OP_COPY_INVERTED,
97 	VK_LOGIC_OP_NO_OP,
98 	VK_LOGIC_OP_INVERT,
99 	VK_LOGIC_OP_AND,
100 	VK_LOGIC_OP_NAND,
101 	VK_LOGIC_OP_OR,
102 	VK_LOGIC_OP_NOR,
103 	VK_LOGIC_OP_XOR,
104 	VK_LOGIC_OP_EQUIVALENT,
105 	VK_LOGIC_OP_AND_REVERSE,
106 	VK_LOGIC_OP_AND_INVERTED,
107 	VK_LOGIC_OP_OR_REVERSE,
108 	VK_LOGIC_OP_OR_INVERTED,
109 };
110 
111 static const VkPrimitiveTopology primToVK[] = {
112 	VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
113 	VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
114 	VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
115 	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
116 	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
117 	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
118 	// Tesselation shader primitive.
119 	VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
120 	// The rest are for geometry shaders only.
121 	VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
122 	VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
123 	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
124 	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
125 };
126 
127 
128 static const VkStencilOp stencilOpToVK[8] = {
129 	VK_STENCIL_OP_KEEP,
130 	VK_STENCIL_OP_ZERO,
131 	VK_STENCIL_OP_REPLACE,
132 	VK_STENCIL_OP_INCREMENT_AND_CLAMP,
133 	VK_STENCIL_OP_DECREMENT_AND_CLAMP,
134 	VK_STENCIL_OP_INVERT,
135 	VK_STENCIL_OP_INCREMENT_AND_WRAP,
136 	VK_STENCIL_OP_DECREMENT_AND_WRAP,
137 };
138 
139 class VKBlendState : public BlendState {
140 public:
141 	VkPipelineColorBlendStateCreateInfo info{ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
142 	std::vector<VkPipelineColorBlendAttachmentState> attachments;
143 };
144 
145 class VKDepthStencilState : public DepthStencilState {
146 public:
147 	VkPipelineDepthStencilStateCreateInfo info{ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
148 };
149 
150 class VKRasterState : public RasterState {
151 public:
VKRasterState(VulkanContext * vulkan,const RasterStateDesc & desc)152 	VKRasterState(VulkanContext *vulkan, const RasterStateDesc &desc) {
153 		cullFace = desc.cull;
154 		frontFace = desc.frontFace;
155 	}
156 	Facing frontFace;
157 	CullMode cullFace;
158 
ToVulkan(VkPipelineRasterizationStateCreateInfo * info) const159 	void ToVulkan(VkPipelineRasterizationStateCreateInfo *info) const {
160 		memset(info, 0, sizeof(*info));
161 		info->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
162 		info->frontFace = frontFace == Facing::CCW ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
163 		switch (cullFace) {
164 		case CullMode::BACK: info->cullMode = VK_CULL_MODE_BACK_BIT; break;
165 		case CullMode::FRONT: info->cullMode = VK_CULL_MODE_FRONT_BIT; break;
166 		case CullMode::FRONT_AND_BACK: info->cullMode = VK_CULL_MODE_FRONT_AND_BACK; break;
167 		case CullMode::NONE: info->cullMode = VK_CULL_MODE_NONE; break;
168 		}
169 		info->polygonMode = VK_POLYGON_MODE_FILL;
170 		info->lineWidth = 1.0f;
171 	}
172 };
173 
StageToVulkan(ShaderStage stage)174 VkShaderStageFlagBits StageToVulkan(ShaderStage stage) {
175 	switch (stage) {
176 	case ShaderStage::Vertex: return VK_SHADER_STAGE_VERTEX_BIT;
177 	case ShaderStage::Geometry: return VK_SHADER_STAGE_GEOMETRY_BIT;
178 	case ShaderStage::Compute: return VK_SHADER_STAGE_COMPUTE_BIT;
179 	default:
180 	case ShaderStage::Fragment: return VK_SHADER_STAGE_FRAGMENT_BIT;
181 	}
182 }
183 
184 // Not registering this as a resource holder, instead the pipeline is registered. It will
185 // invoke Compile again to recreate the shader then link them together.
186 class VKShaderModule : public ShaderModule {
187 public:
VKShaderModule(ShaderStage stage,const std::string & tag)188 	VKShaderModule(ShaderStage stage, const std::string &tag) : stage_(stage), tag_(tag) {
189 		vkstage_ = StageToVulkan(stage);
190 	}
191 	bool Compile(VulkanContext *vulkan, ShaderLanguage language, const uint8_t *data, size_t size);
GetSource() const192 	const std::string &GetSource() const { return source_; }
~VKShaderModule()193 	~VKShaderModule() {
194 		if (module_) {
195 			vulkan_->Delete().QueueDeleteShaderModule(module_);
196 		}
197 	}
Get() const198 	VkShaderModule Get() const { return module_; }
GetStage() const199 	ShaderStage GetStage() const override {
200 		return stage_;
201 	}
202 
203 private:
204 	VulkanContext *vulkan_;
205 	VkShaderModule module_ = VK_NULL_HANDLE;
206 	VkShaderStageFlagBits vkstage_;
207 	bool ok_ = false;
208 	ShaderStage stage_;
209 	std::string source_;  // So we can recompile in case of context loss.
210 	std::string tag_;
211 };
212 
Compile(VulkanContext * vulkan,ShaderLanguage language,const uint8_t * data,size_t size)213 bool VKShaderModule::Compile(VulkanContext *vulkan, ShaderLanguage language, const uint8_t *data, size_t size) {
214 	vulkan_ = vulkan;
215 	// We'll need this to free it later.
216 	source_ = (const char *)data;
217 	std::vector<uint32_t> spirv;
218 	std::string errorMessage;
219 	if (!GLSLtoSPV(vkstage_, source_.c_str(), GLSLVariant::VULKAN, spirv, &errorMessage)) {
220 		WARN_LOG(G3D, "Shader compile to module failed: %s", errorMessage.c_str());
221 		return false;
222 	}
223 
224 	// Just for kicks, sanity check the SPIR-V. The disasm isn't perfect
225 	// but gives you some idea of what's going on.
226 #if 0
227 	std::string disasm;
228 	if (DisassembleSPIRV(spirv, &disasm)) {
229 		OutputDebugStringA(disasm.c_str());
230 	}
231 #endif
232 
233 	if (vulkan->CreateShaderModule(spirv, &module_)) {
234 		ok_ = true;
235 	} else {
236 		WARN_LOG(G3D, "vkCreateShaderModule failed");
237 		ok_ = false;
238 	}
239 	return ok_;
240 }
241 
242 class VKInputLayout : public InputLayout {
243 public:
244 	std::vector<VkVertexInputBindingDescription> bindings;
245 	std::vector<VkVertexInputAttributeDescription> attributes;
246 	VkPipelineVertexInputStateCreateInfo visc;
247 };
248 
249 class VKPipeline : public Pipeline {
250 public:
VKPipeline(VulkanContext * vulkan,size_t size,PipelineFlags _flags)251 	VKPipeline(VulkanContext *vulkan, size_t size, PipelineFlags _flags) : flags(_flags), vulkan_(vulkan) {
252 		uboSize_ = (int)size;
253 		ubo_ = new uint8_t[uboSize_];
254 	}
~VKPipeline()255 	~VKPipeline() {
256 		vulkan_->Delete().QueueDeletePipeline(backbufferPipeline);
257 		vulkan_->Delete().QueueDeletePipeline(framebufferPipeline);
258 		delete[] ubo_;
259 	}
260 
SetDynamicUniformData(const void * data,size_t size)261 	void SetDynamicUniformData(const void *data, size_t size) {
262 		memcpy(ubo_, data, size);
263 	}
264 
265 	// Returns the binding offset, and the VkBuffer to bind.
PushUBO(VulkanPushBuffer * buf,VulkanContext * vulkan,VkBuffer * vkbuf)266 	size_t PushUBO(VulkanPushBuffer *buf, VulkanContext *vulkan, VkBuffer *vkbuf) {
267 		return buf->PushAligned(ubo_, uboSize_, vulkan->GetPhysicalDeviceProperties().properties.limits.minUniformBufferOffsetAlignment, vkbuf);
268 	}
269 
270 	int GetUniformLoc(const char *name);
GetUBOSize() const271 	int GetUBOSize() const {
272 		return uboSize_;
273 	}
RequiresBuffer()274 	bool RequiresBuffer() override {
275 		return false;
276 	}
277 
278 	VkPipeline backbufferPipeline = VK_NULL_HANDLE;
279 	VkPipeline framebufferPipeline = VK_NULL_HANDLE;
280 
281 	PipelineFlags flags;
282 	int stride[4]{};
283 	int dynamicUniformSize = 0;
284 
285 	bool usesStencil = false;
286 	uint8_t stencilWriteMask = 0xFF;
287 	uint8_t stencilTestMask = 0xFF;
288 
289 private:
290 	VulkanContext *vulkan_;
291 	uint8_t *ubo_;
292 	int uboSize_;
293 };
294 
295 class VKTexture;
296 class VKBuffer;
297 class VKSamplerState;
298 
299 enum {
300 	MAX_BOUND_TEXTURES = MAX_TEXTURE_SLOTS,
301 };
302 
303 struct DescriptorSetKey {
304 	VkImageView imageViews_[MAX_BOUND_TEXTURES];
305 	VKSamplerState *samplers_[MAX_BOUND_TEXTURES];
306 	VkBuffer buffer_;
307 
operator <Draw::DescriptorSetKey308 	bool operator < (const DescriptorSetKey &other) const {
309 		for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) {
310 			if (imageViews_[i] < other.imageViews_[i]) return true; else if (imageViews_[i] > other.imageViews_[i]) return false;
311 			if (samplers_[i] < other.samplers_[i]) return true; else if (samplers_[i] > other.samplers_[i]) return false;
312 		}
313 		if (buffer_ < other.buffer_) return true; else if (buffer_ > other.buffer_) return false;
314 		return false;
315 	}
316 };
317 
318 class VKTexture : public Texture {
319 public:
VKTexture(VulkanContext * vulkan,VkCommandBuffer cmd,VulkanPushBuffer * pushBuffer,const TextureDesc & desc)320 	VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc)
321 		: vulkan_(vulkan), mipLevels_(desc.mipLevels), format_(desc.format) {}
322 	bool Create(VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc, VulkanDeviceAllocator *alloc);
323 
~VKTexture()324 	~VKTexture() {
325 		Destroy();
326 	}
327 
GetImageView()328 	VkImageView GetImageView() {
329 		if (vkTex_) {
330 			vkTex_->Touch();
331 			return vkTex_->GetImageView();
332 		} else {
333 			// This would be bad.
334 			return VK_NULL_HANDLE;
335 		}
336 	}
337 
338 private:
Destroy()339 	void Destroy() {
340 		if (vkTex_) {
341 			vkTex_->Destroy();
342 			delete vkTex_;
343 			vkTex_ = nullptr;
344 		}
345 	}
346 
347 	VulkanContext *vulkan_;
348 	VulkanTexture *vkTex_ = nullptr;
349 
350 	int mipLevels_ = 0;
351 
352 	DataFormat format_ = DataFormat::UNDEFINED;
353 };
354 
355 class VKFramebuffer;
356 
357 class VKContext : public DrawContext {
358 public:
359 	VKContext(VulkanContext *vulkan, bool splitSubmit);
360 	virtual ~VKContext();
361 
GetDeviceCaps() const362 	const DeviceCaps &GetDeviceCaps() const override {
363 		return caps_;
364 	}
GetDeviceList() const365 	std::vector<std::string> GetDeviceList() const override {
366 		std::vector<std::string> list;
367 		for (int i = 0; i < vulkan_->GetNumPhysicalDevices(); i++) {
368 			list.push_back(vulkan_->GetPhysicalDeviceProperties(i).properties.deviceName);
369 		}
370 		return list;
371 	}
GetSupportedShaderLanguages() const372 	uint32_t GetSupportedShaderLanguages() const override {
373 		return (uint32_t)ShaderLanguage::GLSL_VULKAN;
374 	}
375 	uint32_t GetDataFormatSupport(DataFormat fmt) const override;
376 
377 	DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) override;
378 	BlendState *CreateBlendState(const BlendStateDesc &desc) override;
379 	InputLayout *CreateInputLayout(const InputLayoutDesc &desc) override;
380 	SamplerState *CreateSamplerState(const SamplerStateDesc &desc) override;
381 	RasterState *CreateRasterState(const RasterStateDesc &desc) override;
382 	Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc) override;
383 	ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const std::string &tag) override;
384 
385 	Texture *CreateTexture(const TextureDesc &desc) override;
386 	Buffer *CreateBuffer(size_t size, uint32_t usageFlags) override;
387 	Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) override;
388 
389 	void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override;
390 
391 	void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override;
392 	bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override;
393 	bool CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, const char *tag) override;
394 	DataFormat PreferredFramebufferReadbackFormat(Framebuffer *src) override;
395 
396 	// These functions should be self explanatory.
397 	void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override;
GetCurrentRenderTarget()398 	Framebuffer *GetCurrentRenderTarget() override {
399 		return curFramebuffer_;
400 	}
401 	void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override;
402 
403 	uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) override;
404 
405 	void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
406 
407 	void SetScissorRect(int left, int top, int width, int height) override;
408 	void SetViewports(int count, Viewport *viewports) override;
409 	void SetBlendFactor(float color[4]) override;
410 	void SetStencilRef(uint8_t stencilRef) override;
411 
412 	void BindSamplerStates(int start, int count, SamplerState **state) override;
413 	void BindTextures(int start, int count, Texture **textures) override;
414 
BindPipeline(Pipeline * pipeline)415 	void BindPipeline(Pipeline *pipeline) override {
416 		curPipeline_ = (VKPipeline *)pipeline;
417 	}
418 
419 	// TODO: Make VKBuffers proper buffers, and do a proper binding model. This is just silly.
BindVertexBuffers(int start,int count,Buffer ** buffers,const int * offsets)420 	void BindVertexBuffers(int start, int count, Buffer **buffers, const int *offsets) override {
421 		_assert_(start + count <= ARRAY_SIZE(curVBuffers_));
422 		for (int i = 0; i < count; i++) {
423 			curVBuffers_[i + start] = (VKBuffer *)buffers[i];
424 			curVBufferOffsets_[i + start] = offsets ? offsets[i] : 0;
425 		}
426 	}
BindIndexBuffer(Buffer * indexBuffer,int offset)427 	void BindIndexBuffer(Buffer *indexBuffer, int offset) override {
428 		curIBuffer_ = (VKBuffer *)indexBuffer;
429 		curIBufferOffset_ = offset;
430 	}
431 
432 	void UpdateDynamicUniformBuffer(const void *ub, size_t size) override;
433 
434 	// TODO: Add more sophisticated draws.
435 	void Draw(int vertexCount, int offset) override;
436 	void DrawIndexed(int vertexCount, int offset) override;
437 	void DrawUP(const void *vdata, int vertexCount) override;
438 
439 	void BindCompatiblePipeline();
440 	void ApplyDynamicState();
441 
442 	void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
443 
444 	void BeginFrame() override;
445 	void EndFrame() override;
446 	void WipeQueue() override;
447 
FlushState()448 	void FlushState() override {}
449 
GetInfoString(InfoField info) const450 	std::string GetInfoString(InfoField info) const override {
451 		// TODO: Make these actually query the right information
452 		switch (info) {
453 		case APINAME: return "Vulkan";
454 		case VENDORSTRING: return vulkan_->GetPhysicalDeviceProperties().properties.deviceName;
455 		case VENDOR: return VulkanVendorString(vulkan_->GetPhysicalDeviceProperties().properties.vendorID);
456 		case DRIVER: return FormatDriverVersion(vulkan_->GetPhysicalDeviceProperties().properties);
457 		case SHADELANGVERSION: return "N/A";;
458 		case APIVERSION:
459 		{
460 			uint32_t ver = vulkan_->GetPhysicalDeviceProperties().properties.apiVersion;
461 			return StringFromFormat("%d.%d.%d", ver >> 22, (ver >> 12) & 0x3ff, ver & 0xfff);
462 		}
463 		default: return "?";
464 		}
465 	}
466 
467 	VkDescriptorSet GetOrCreateDescriptorSet(VkBuffer buffer);
468 
469 	std::vector<std::string> GetFeatureList() const override;
470 	std::vector<std::string> GetExtensionList() const override;
471 
GetNativeObject(NativeObject obj)472 	uint64_t GetNativeObject(NativeObject obj) override {
473 		switch (obj) {
474 		case NativeObject::CONTEXT:
475 			return (uint64_t)vulkan_;
476 		case NativeObject::FRAMEBUFFER_RENDERPASS:
477 			// Return a representative renderpass.
478 			return (uint64_t)renderManager_.GetFramebufferRenderPass();
479 		case NativeObject::BACKBUFFER_RENDERPASS:
480 			return (uint64_t)renderManager_.GetBackbufferRenderPass();
481 		case NativeObject::COMPATIBLE_RENDERPASS:
482 			return (uint64_t)renderManager_.GetCompatibleRenderPass();
483 		case NativeObject::INIT_COMMANDBUFFER:
484 			return (uint64_t)renderManager_.GetInitCmd();
485 		case NativeObject::BOUND_TEXTURE0_IMAGEVIEW:
486 			return (uint64_t)boundImageView_[0];
487 		case NativeObject::BOUND_TEXTURE1_IMAGEVIEW:
488 			return (uint64_t)boundImageView_[1];
489 		case NativeObject::RENDER_MANAGER:
490 			return (uint64_t)(uintptr_t)&renderManager_;
491 		case NativeObject::NULL_IMAGEVIEW:
492 			return (uint64_t)GetNullTexture()->GetImageView();
493 		default:
494 			Crash();
495 			return 0;
496 		}
497 	}
498 
499 	void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override;
500 
GetCurrentStepId() const501 	int GetCurrentStepId() const override {
502 		return renderManager_.GetCurrentStepId();
503 	}
504 
505 	void InvalidateCachedState() override;
506 
507 private:
508 	VulkanTexture *GetNullTexture();
509 	VulkanContext *vulkan_ = nullptr;
510 
511 	VulkanRenderManager renderManager_;
512 
513 	VulkanDeviceAllocator *allocator_ = nullptr;
514 
515 	VulkanTexture *nullTexture_ = nullptr;
516 
517 	AutoRef<VKPipeline> curPipeline_;
518 	AutoRef<VKBuffer> curVBuffers_[4];
519 	int curVBufferOffsets_[4]{};
520 	AutoRef<VKBuffer> curIBuffer_;
521 	int curIBufferOffset_ = 0;
522 
523 	VkDescriptorSetLayout descriptorSetLayout_ = VK_NULL_HANDLE;
524 	VkPipelineLayout pipelineLayout_ = VK_NULL_HANDLE;
525 	VkPipelineCache pipelineCache_ = VK_NULL_HANDLE;
526 	AutoRef<Framebuffer> curFramebuffer_;
527 
528 	VkDevice device_;
529 	VkQueue queue_;
530 	int queueFamilyIndex_;
531 
532 	enum {
533 		MAX_FRAME_COMMAND_BUFFERS = 256,
534 	};
535 	AutoRef<VKTexture> boundTextures_[MAX_BOUND_TEXTURES];
536 	AutoRef<VKSamplerState> boundSamplers_[MAX_BOUND_TEXTURES];
537 	VkImageView boundImageView_[MAX_BOUND_TEXTURES]{};
538 
539 	struct FrameData {
540 		VulkanPushBuffer *pushBuffer;
541 		// Per-frame descriptor set cache. As it's per frame and reset every frame, we don't need to
542 		// worry about invalidating descriptors pointing to deleted textures.
543 		// However! ARM is not a fan of doing it this way.
544 		std::map<DescriptorSetKey, VkDescriptorSet> descSets_;
545 		VkDescriptorPool descriptorPool;
546 	};
547 
548 	VkResult RecreateDescriptorPool(FrameData *frame);
549 
550 	FrameData frame_[VulkanContext::MAX_INFLIGHT_FRAMES]{};
551 
552 	VulkanPushBuffer *push_ = nullptr;
553 
554 	DeviceCaps caps_{};
555 
556 	uint8_t stencilRef_ = 0;
557 };
558 
GetBpp(VkFormat format)559 static int GetBpp(VkFormat format) {
560 	switch (format) {
561 	case VK_FORMAT_R8G8B8A8_UNORM:
562 	case VK_FORMAT_B8G8R8A8_UNORM:
563 		return 32;
564 	case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
565 	case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
566 	case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
567 	case VK_FORMAT_R5G6B5_UNORM_PACK16:
568 	case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
569 	case VK_FORMAT_B5G6R5_UNORM_PACK16:
570 	case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
571 		return 16;
572 	case VK_FORMAT_D24_UNORM_S8_UINT:
573 		return 32;
574 	case VK_FORMAT_D16_UNORM:
575 		return 16;
576 	default:
577 		return 0;
578 	}
579 }
580 
DataFormatToVulkan(DataFormat format)581 VkFormat DataFormatToVulkan(DataFormat format) {
582 	switch (format) {
583 	case DataFormat::D16: return VK_FORMAT_D16_UNORM;
584 	case DataFormat::D32F: return VK_FORMAT_D32_SFLOAT;
585 	case DataFormat::D32F_S8: return VK_FORMAT_D32_SFLOAT_S8_UINT;
586 	case DataFormat::S8: return VK_FORMAT_S8_UINT;
587 	case DataFormat::R16_FLOAT: return VK_FORMAT_R16_SFLOAT;
588 	case DataFormat::R16G16_FLOAT: return VK_FORMAT_R16G16_SFLOAT;
589 	case DataFormat::R16G16B16A16_FLOAT: return VK_FORMAT_R16G16B16A16_SFLOAT;
590 	case DataFormat::R8_UNORM: return VK_FORMAT_R8_UNORM;
591 	case DataFormat::R8G8_UNORM: return VK_FORMAT_R8G8_UNORM;
592 	case DataFormat::R8G8B8_UNORM: return VK_FORMAT_R8G8B8_UNORM;
593 	case DataFormat::R8G8B8A8_UNORM: return VK_FORMAT_R8G8B8A8_UNORM;
594 	case DataFormat::R4G4_UNORM_PACK8: return VK_FORMAT_R4G4_UNORM_PACK8;
595 
596 	// Note: A4R4G4B4_UNORM_PACK16 is not supported.
597 	case DataFormat::R4G4B4A4_UNORM_PACK16: return VK_FORMAT_R4G4B4A4_UNORM_PACK16;
598 	case DataFormat::B4G4R4A4_UNORM_PACK16: return VK_FORMAT_B4G4R4A4_UNORM_PACK16;
599 	case DataFormat::R5G5B5A1_UNORM_PACK16: return VK_FORMAT_R5G5B5A1_UNORM_PACK16;
600 	case DataFormat::B5G5R5A1_UNORM_PACK16: return VK_FORMAT_B5G5R5A1_UNORM_PACK16;
601 	case DataFormat::R5G6B5_UNORM_PACK16: return VK_FORMAT_R5G6B5_UNORM_PACK16;
602 	case DataFormat::B5G6R5_UNORM_PACK16: return VK_FORMAT_B5G6R5_UNORM_PACK16;
603 	case DataFormat::A1R5G5B5_UNORM_PACK16: return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
604 
605 	case DataFormat::R32_FLOAT: return VK_FORMAT_R32_SFLOAT;
606 	case DataFormat::R32G32_FLOAT: return VK_FORMAT_R32G32_SFLOAT;
607 	case DataFormat::R32G32B32_FLOAT: return VK_FORMAT_R32G32B32_SFLOAT;
608 	case DataFormat::R32G32B32A32_FLOAT: return VK_FORMAT_R32G32B32A32_SFLOAT;
609 
610 	case DataFormat::BC1_RGBA_UNORM_BLOCK: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
611 	case DataFormat::BC2_UNORM_BLOCK: return VK_FORMAT_BC2_UNORM_BLOCK;
612 	case DataFormat::BC3_UNORM_BLOCK: return VK_FORMAT_BC3_UNORM_BLOCK;
613 	case DataFormat::BC4_UNORM_BLOCK: return VK_FORMAT_BC4_UNORM_BLOCK;
614 	case DataFormat::BC4_SNORM_BLOCK: return VK_FORMAT_BC4_SNORM_BLOCK;
615 	case DataFormat::BC5_UNORM_BLOCK: return VK_FORMAT_BC5_UNORM_BLOCK;
616 	case DataFormat::BC5_SNORM_BLOCK: return VK_FORMAT_BC5_SNORM_BLOCK;
617 	case DataFormat::BC6H_SFLOAT_BLOCK: return VK_FORMAT_BC6H_SFLOAT_BLOCK;
618 	case DataFormat::BC6H_UFLOAT_BLOCK: return VK_FORMAT_BC6H_UFLOAT_BLOCK;
619 	case DataFormat::BC7_UNORM_BLOCK: return VK_FORMAT_BC7_UNORM_BLOCK;
620 	case DataFormat::BC7_SRGB_BLOCK:  return VK_FORMAT_BC7_SRGB_BLOCK;
621 	default:
622 		return VK_FORMAT_UNDEFINED;
623 	}
624 }
625 
AddressModeToVulkan(Draw::TextureAddressMode mode)626 static inline VkSamplerAddressMode AddressModeToVulkan(Draw::TextureAddressMode mode) {
627 	switch (mode) {
628 	case TextureAddressMode::CLAMP_TO_BORDER: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
629 	case TextureAddressMode::CLAMP_TO_EDGE: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
630 	case TextureAddressMode::REPEAT_MIRROR: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
631 	default:
632 	case TextureAddressMode::REPEAT: return VK_SAMPLER_ADDRESS_MODE_REPEAT;
633 	}
634 }
635 
GetNullTexture()636 VulkanTexture *VKContext::GetNullTexture() {
637 	if (!nullTexture_) {
638 		VkCommandBuffer cmdInit = renderManager_.GetInitCmd();
639 		nullTexture_ = new VulkanTexture(vulkan_);
640 		nullTexture_->SetTag("Null");
641 		int w = 8;
642 		int h = 8;
643 		nullTexture_->CreateDirect(cmdInit, allocator_, w, h, 1, VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
644 			VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
645 		uint32_t bindOffset;
646 		VkBuffer bindBuf;
647 		uint32_t *data = (uint32_t *)push_->Push(w * h * 4, &bindOffset, &bindBuf);
648 		for (int y = 0; y < h; y++) {
649 			for (int x = 0; x < w; x++) {
650 				// data[y*w + x] = ((x ^ y) & 1) ? 0xFF808080 : 0xFF000000;   // gray/black checkerboard
651 				data[y*w + x] = 0;  // black
652 			}
653 		}
654 		nullTexture_->UploadMip(cmdInit, 0, w, h, bindBuf, bindOffset, w);
655 		nullTexture_->EndCreate(cmdInit, false, VK_PIPELINE_STAGE_TRANSFER_BIT);
656 	} else {
657 		nullTexture_->Touch();
658 	}
659 	return nullTexture_;
660 }
661 
662 class VKSamplerState : public SamplerState {
663 public:
VKSamplerState(VulkanContext * vulkan,const SamplerStateDesc & desc)664 	VKSamplerState(VulkanContext *vulkan, const SamplerStateDesc &desc) : vulkan_(vulkan) {
665 		VkSamplerCreateInfo s = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
666 		s.addressModeU = AddressModeToVulkan(desc.wrapU);
667 		s.addressModeV = AddressModeToVulkan(desc.wrapV);
668 		s.addressModeW = AddressModeToVulkan(desc.wrapW);
669 		s.anisotropyEnable = desc.maxAniso > 1.0f;
670 		s.magFilter = desc.magFilter == TextureFilter::LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
671 		s.minFilter = desc.minFilter == TextureFilter::LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
672 		s.mipmapMode = desc.mipFilter == TextureFilter::LINEAR ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
673 		s.maxLod = desc.maxLod;
674 		VkResult res = vkCreateSampler(vulkan_->GetDevice(), &s, nullptr, &sampler_);
675 		_assert_(VK_SUCCESS == res);
676 	}
~VKSamplerState()677 	~VKSamplerState() {
678 		vulkan_->Delete().QueueDeleteSampler(sampler_);
679 	}
680 
GetSampler()681 	VkSampler GetSampler() { return sampler_; }
682 
683 private:
684 	VulkanContext *vulkan_;
685 	VkSampler sampler_;
686 };
687 
CreateSamplerState(const SamplerStateDesc & desc)688 SamplerState *VKContext::CreateSamplerState(const SamplerStateDesc &desc) {
689 	return new VKSamplerState(vulkan_, desc);
690 }
691 
CreateRasterState(const RasterStateDesc & desc)692 RasterState *VKContext::CreateRasterState(const RasterStateDesc &desc) {
693 	return new VKRasterState(vulkan_, desc);
694 }
695 
BindSamplerStates(int start,int count,SamplerState ** state)696 void VKContext::BindSamplerStates(int start, int count, SamplerState **state) {
697 	_assert_(start + count <= MAX_BOUND_TEXTURES);
698 	for (int i = start; i < start + count; i++) {
699 		boundSamplers_[i] = (VKSamplerState *)state[i - start];
700 	}
701 }
702 
703 enum class TextureState {
704 	UNINITIALIZED,
705 	STAGED,
706 	INITIALIZED,
707 	PENDING_DESTRUCTION,
708 };
709 
Create(VkCommandBuffer cmd,VulkanPushBuffer * push,const TextureDesc & desc,VulkanDeviceAllocator * alloc)710 bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const TextureDesc &desc, VulkanDeviceAllocator *alloc) {
711 	// Zero-sized textures not allowed.
712 	_assert_(desc.width * desc.height * desc.depth > 0);  // remember to set depth to 1!
713 	if (desc.width * desc.height * desc.depth <= 0) {
714 		ERROR_LOG(G3D,  "Bad texture dimensions %dx%dx%d", desc.width, desc.height, desc.depth);
715 		return false;
716 	}
717 	_assert_(push);
718 	format_ = desc.format;
719 	mipLevels_ = desc.mipLevels;
720 	width_ = desc.width;
721 	height_ = desc.height;
722 	depth_ = desc.depth;
723 	vkTex_ = new VulkanTexture(vulkan_);
724 	if (desc.tag) {
725 		vkTex_->SetTag(desc.tag);
726 	}
727 	VkFormat vulkanFormat = DataFormatToVulkan(format_);
728 	int bpp = GetBpp(vulkanFormat);
729 	int bytesPerPixel = bpp / 8;
730 	int usageBits = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
731 	if (mipLevels_ > (int)desc.initData.size()) {
732 		// Gonna have to generate some, which requires TRANSFER_SRC
733 		usageBits |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
734 	}
735 
736 	if (!vkTex_->CreateDirect(cmd, alloc, width_, height_, mipLevels_, vulkanFormat, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, usageBits)) {
737 		ERROR_LOG(G3D,  "Failed to create VulkanTexture: %dx%dx%d fmt %d, %d levels", width_, height_, depth_, (int)vulkanFormat, mipLevels_);
738 		return false;
739 	}
740 	VkImageLayout layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
741 	if (desc.initData.size()) {
742 		int w = width_;
743 		int h = height_;
744 		int d = depth_;
745 		int i;
746 		for (i = 0; i < (int)desc.initData.size(); i++) {
747 			uint32_t offset;
748 			VkBuffer buf;
749 			size_t size = w * h * d * bytesPerPixel;
750 			if (desc.initDataCallback) {
751 				uint8_t *dest = (uint8_t *)push->PushAligned(size, &offset, &buf, 16);
752 				if (!desc.initDataCallback(dest, desc.initData[i], w, h, d, w * bytesPerPixel, h * w * bytesPerPixel)) {
753 					memcpy(dest, desc.initData[i], size);
754 				}
755 			} else {
756 				offset = push->PushAligned((const void *)desc.initData[i], size, 16, &buf);
757 			}
758 			vkTex_->UploadMip(cmd, i, w, h, buf, offset, w);
759 			w = (w + 1) / 2;
760 			h = (h + 1) / 2;
761 			d = (d + 1) / 2;
762 		}
763 		// Generate the rest of the mips automatically.
764 		if (i < mipLevels_) {
765 			vkTex_->GenerateMips(cmd, i, false);
766 			layout = VK_IMAGE_LAYOUT_GENERAL;
767 		}
768 	}
769 	vkTex_->EndCreate(cmd, false, VK_PIPELINE_STAGE_TRANSFER_BIT, layout);
770 	return true;
771 }
772 
VKContext(VulkanContext * vulkan,bool splitSubmit)773 VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
774 	: vulkan_(vulkan), renderManager_(vulkan) {
775 	shaderLanguageDesc_.Init(GLSL_VULKAN);
776 
777 	caps_.anisoSupported = vulkan->GetDeviceFeatures().enabled.samplerAnisotropy != 0;
778 	caps_.geometryShaderSupported = vulkan->GetDeviceFeatures().enabled.geometryShader != 0;
779 	caps_.tesselationShaderSupported = vulkan->GetDeviceFeatures().enabled.tessellationShader != 0;
780 	caps_.multiViewport = vulkan->GetDeviceFeatures().enabled.multiViewport != 0;
781 	caps_.dualSourceBlend = vulkan->GetDeviceFeatures().enabled.dualSrcBlend != 0;
782 	caps_.depthClampSupported = vulkan->GetDeviceFeatures().enabled.depthClamp != 0;
783 	caps_.framebufferBlitSupported = true;
784 	caps_.framebufferCopySupported = true;
785 	caps_.framebufferDepthBlitSupported = false;  // Can be checked for.
786 	caps_.framebufferDepthCopySupported = true;   // Will pretty much always be the case.
787 	caps_.preferredDepthBufferFormat = DataFormat::D24_S8;  // TODO: Ask vulkan.
788 
789 	auto deviceProps = vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDeviceIndex()).properties;
790 	switch (deviceProps.vendorID) {
791 	case VULKAN_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break;
792 	case VULKAN_VENDOR_ARM: caps_.vendor = GPUVendor::VENDOR_ARM; break;
793 	case VULKAN_VENDOR_IMGTEC: caps_.vendor = GPUVendor::VENDOR_IMGTEC; break;
794 	case VULKAN_VENDOR_NVIDIA: caps_.vendor = GPUVendor::VENDOR_NVIDIA; break;
795 	case VULKAN_VENDOR_QUALCOMM: caps_.vendor = GPUVendor::VENDOR_QUALCOMM; break;
796 	case VULKAN_VENDOR_INTEL: caps_.vendor = GPUVendor::VENDOR_INTEL; break;
797 	default: caps_.vendor = GPUVendor::VENDOR_UNKNOWN; break;
798 	}
799 
800 	if (caps_.vendor == GPUVendor::VENDOR_QUALCOMM) {
801 		// Adreno 5xx devices, all known driver versions, fail to discard stencil when depth write is off.
802 		// See: https://github.com/hrydgard/ppsspp/pull/11684
803 		if (deviceProps.deviceID >= 0x05000000 && deviceProps.deviceID < 0x06000000) {
804 			if (deviceProps.driverVersion < 0x80180000) {
805 				bugs_.Infest(Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL);
806 			}
807 		}
808 		// Color write mask not masking write in certain scenarios with a depth test, see #10421.
809 		// Known still present on driver 0x80180000 and Adreno 5xx (possibly more.)
810 		bugs_.Infest(Bugs::COLORWRITEMASK_BROKEN_WITH_DEPTHTEST);
811 	} else if (caps_.vendor == GPUVendor::VENDOR_AMD) {
812 		// See issue #10074, and also #10065 (AMD) and #10109 for the choice of the driver version to check for.
813 		if (deviceProps.driverVersion < 0x00407000) {
814 			bugs_.Infest(Bugs::DUAL_SOURCE_BLENDING_BROKEN);
815 		}
816 	} else if (caps_.vendor == GPUVendor::VENDOR_INTEL) {
817 		// Workaround for Intel driver bug. TODO: Re-enable after some driver version
818 		bugs_.Infest(Bugs::DUAL_SOURCE_BLENDING_BROKEN);
819 	}
820 
821 	caps_.deviceID = deviceProps.deviceID;
822 	device_ = vulkan->GetDevice();
823 
824 	queue_ = vulkan->GetGraphicsQueue();
825 	queueFamilyIndex_ = vulkan->GetGraphicsQueueFamilyIndex();
826 
827 	VkCommandPoolCreateInfo p{ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
828 	p.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
829 	p.queueFamilyIndex = vulkan->GetGraphicsQueueFamilyIndex();
830 
831 	for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
832 		VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
833 		frame_[i].pushBuffer = new VulkanPushBuffer(vulkan_, 1024 * 1024, usage);
834 		VkResult res = RecreateDescriptorPool(&frame_[i]);
835 		_assert_(res == VK_SUCCESS);
836 	}
837 
838 	// binding 0 - uniform data
839 	// binding 1 - combined sampler/image 0
840 	// binding 2 - combined sampler/image 1
841 	VkDescriptorSetLayoutBinding bindings[MAX_BOUND_TEXTURES + 1];
842 	bindings[0].descriptorCount = 1;
843 	bindings[0].pImmutableSamplers = nullptr;
844 	bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
845 	bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
846 	bindings[0].binding = 0;
847 	for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) {
848 		bindings[i + 1].descriptorCount = 1;
849 		bindings[i + 1].pImmutableSamplers = nullptr;
850 		bindings[i + 1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
851 		bindings[i + 1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
852 		bindings[i + 1].binding = i + 1;
853 	}
854 
855 	VkDescriptorSetLayoutCreateInfo dsl = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
856 	dsl.bindingCount = ARRAY_SIZE(bindings);
857 	dsl.pBindings = bindings;
858 	VkResult res = vkCreateDescriptorSetLayout(device_, &dsl, nullptr, &descriptorSetLayout_);
859 	_assert_(VK_SUCCESS == res);
860 
861 	VkPipelineLayoutCreateInfo pl = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
862 	pl.pPushConstantRanges = nullptr;
863 	pl.pushConstantRangeCount = 0;
864 	pl.setLayoutCount = 1;
865 	pl.pSetLayouts = &descriptorSetLayout_;
866 	res = vkCreatePipelineLayout(device_, &pl, nullptr, &pipelineLayout_);
867 	_assert_(VK_SUCCESS == res);
868 
869 	VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO };
870 	res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_);
871 	_assert_(VK_SUCCESS == res);
872 
873 	renderManager_.SetSplitSubmit(splitSubmit);
874 
875 	allocator_ = new VulkanDeviceAllocator(vulkan_, 256 * 1024, 2048 * 1024);
876 }
877 
~VKContext()878 VKContext::~VKContext() {
879 	delete nullTexture_;
880 	allocator_->Destroy();
881 	// We have to delete on queue, so this can free its queued deletions.
882 	vulkan_->Delete().QueueCallback([](void *ptr) {
883 		auto allocator = static_cast<VulkanDeviceAllocator *>(ptr);
884 		delete allocator;
885 	}, allocator_);
886 	allocator_ = nullptr;
887 	// This also destroys all descriptor sets.
888 	for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
889 		frame_[i].descSets_.clear();
890 		vulkan_->Delete().QueueDeleteDescriptorPool(frame_[i].descriptorPool);
891 		frame_[i].pushBuffer->Destroy(vulkan_);
892 		delete frame_[i].pushBuffer;
893 	}
894 	vulkan_->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout_);
895 	vulkan_->Delete().QueueDeletePipelineLayout(pipelineLayout_);
896 	vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_);
897 }
898 
BeginFrame()899 void VKContext::BeginFrame() {
900 	renderManager_.BeginFrame(g_Config.bShowGpuProfile);
901 
902 	FrameData &frame = frame_[vulkan_->GetCurFrame()];
903 	push_ = frame.pushBuffer;
904 
905 	// OK, we now know that nothing is reading from this frame's data pushbuffer,
906 	push_->Reset();
907 	push_->Begin(vulkan_);
908 	allocator_->Begin();
909 
910 	frame.descSets_.clear();
911 	VkResult result = vkResetDescriptorPool(device_, frame.descriptorPool, 0);
912 	_assert_(result == VK_SUCCESS);
913 }
914 
EndFrame()915 void VKContext::EndFrame() {
916 	// Stop collecting data in the frame's data pushbuffer.
917 	push_->End();
918 	allocator_->End();
919 
920 	renderManager_.Finish();
921 
922 	push_ = nullptr;
923 
924 	// Unbind stuff, to avoid accidentally relying on it across frames (and provide some protection against forgotten unbinds of deleted things).
925 	InvalidateCachedState();
926 }
927 
InvalidateCachedState()928 void VKContext::InvalidateCachedState() {
929 	curPipeline_ = nullptr;
930 
931 	for (auto &view : boundImageView_) {
932 		view = VK_NULL_HANDLE;
933 	}
934 	for (auto &sampler : boundSamplers_) {
935 		sampler = nullptr;
936 	}
937 	for (auto &texture : boundTextures_) {
938 		texture = nullptr;
939 	}
940 }
941 
WipeQueue()942 void VKContext::WipeQueue() {
943 	renderManager_.Wipe();
944 }
945 
RecreateDescriptorPool(FrameData * frame)946 VkResult VKContext::RecreateDescriptorPool(FrameData *frame) {
947 	if (frame->descriptorPool) {
948 		WARN_LOG(G3D, "Reallocating Draw desc pool");
949 		vulkan_->Delete().QueueDeleteDescriptorPool(frame->descriptorPool);
950 		frame->descSets_.clear();
951 	}
952 
953 	VkDescriptorPoolSize dpTypes[2];
954 	dpTypes[0].descriptorCount = 200;
955 	dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
956 	dpTypes[1].descriptorCount = 200 * MAX_BOUND_TEXTURES;
957 	dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
958 
959 	VkDescriptorPoolCreateInfo dp{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
960 	dp.flags = 0;   // Don't want to mess around with individually freeing these, let's go dynamic each frame.
961 	dp.maxSets = 4096;  // 200 textures per frame was not enough for the UI.
962 	dp.pPoolSizes = dpTypes;
963 	dp.poolSizeCount = ARRAY_SIZE(dpTypes);
964 
965 	return vkCreateDescriptorPool(device_, &dp, nullptr, &frame->descriptorPool);
966 }
967 
GetOrCreateDescriptorSet(VkBuffer buf)968 VkDescriptorSet VKContext::GetOrCreateDescriptorSet(VkBuffer buf) {
969 	DescriptorSetKey key;
970 
971 	FrameData *frame = &frame_[vulkan_->GetCurFrame()];
972 
973 	for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) {
974 		key.imageViews_[i] = boundTextures_[i] ? boundTextures_[i]->GetImageView() : boundImageView_[i];
975 		key.samplers_[i] = boundSamplers_[i];
976 	}
977 	key.buffer_ = buf;
978 
979 	auto iter = frame->descSets_.find(key);
980 	if (iter != frame->descSets_.end()) {
981 		return iter->second;
982 	}
983 
984 	VkDescriptorSet descSet;
985 	VkDescriptorSetAllocateInfo alloc = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
986 	alloc.descriptorPool = frame->descriptorPool;
987 	alloc.pSetLayouts = &descriptorSetLayout_;
988 	alloc.descriptorSetCount = 1;
989 	VkResult res = vkAllocateDescriptorSets(device_, &alloc, &descSet);
990 	if (res != VK_SUCCESS) {
991 		// First, try to reallocate the pool.
992 		res = RecreateDescriptorPool(frame);
993 		alloc.descriptorPool = frame->descriptorPool;
994 
995 		res = vkAllocateDescriptorSets(device_, &alloc, &descSet);
996 		if (res != VK_SUCCESS) {
997 			ERROR_LOG(G3D, "GetOrCreateDescriptorSet failed: %08x", res);
998 			return VK_NULL_HANDLE;
999 		}
1000 	}
1001 
1002 	VkDescriptorBufferInfo bufferDesc;
1003 	bufferDesc.buffer = buf;
1004 	bufferDesc.offset = 0;
1005 	bufferDesc.range = curPipeline_->GetUBOSize();
1006 
1007 	VkDescriptorImageInfo imageDesc[MAX_BOUND_TEXTURES]{};
1008 	VkWriteDescriptorSet writes[1 + MAX_BOUND_TEXTURES]{};
1009 
1010 	// If handles are NULL for whatever buggy reason, it's best to leave the descriptors
1011 	// unwritten instead of trying to write a zero, which is not legal.
1012 
1013 	int numWrites = 0;
1014 	if (buf) {
1015 		writes[numWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1016 		writes[numWrites].dstSet = descSet;
1017 		writes[numWrites].dstArrayElement = 0;
1018 		writes[numWrites].dstBinding = 0;
1019 		writes[numWrites].pBufferInfo = &bufferDesc;
1020 		writes[numWrites].pImageInfo = nullptr;
1021 		writes[numWrites].pTexelBufferView = nullptr;
1022 		writes[numWrites].descriptorCount = 1;
1023 		writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
1024 		numWrites++;
1025 	}
1026 
1027 	for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) {
1028 		if (key.imageViews_[i] && key.samplers_[i] && key.samplers_[i]->GetSampler()) {
1029 			imageDesc[i].imageView = key.imageViews_[i];
1030 			imageDesc[i].sampler = key.samplers_[i]->GetSampler();
1031 			imageDesc[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1032 			writes[numWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1033 			writes[numWrites].dstSet = descSet;
1034 			writes[numWrites].dstArrayElement = 0;
1035 			writes[numWrites].dstBinding = i + 1;
1036 			writes[numWrites].pBufferInfo = nullptr;
1037 			writes[numWrites].pImageInfo = &imageDesc[i];
1038 			writes[numWrites].pTexelBufferView = nullptr;
1039 			writes[numWrites].descriptorCount = 1;
1040 			writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1041 			numWrites++;
1042 		}
1043 	}
1044 
1045 	vkUpdateDescriptorSets(device_, numWrites, writes, 0, nullptr);
1046 
1047 	frame->descSets_[key] = descSet;
1048 	return descSet;
1049 }
1050 
CreateGraphicsPipeline(const PipelineDesc & desc)1051 Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
1052 	VKInputLayout *input = (VKInputLayout *)desc.inputLayout;
1053 	VKBlendState *blend = (VKBlendState *)desc.blend;
1054 	VKDepthStencilState *depth = (VKDepthStencilState *)desc.depthStencil;
1055 	VKRasterState *raster = (VKRasterState *)desc.raster;
1056 
1057 	u32 pipelineFlags = 0;
1058 	if (depth->info.depthTestEnable || depth->info.stencilTestEnable) {
1059 		pipelineFlags |= PIPELINE_FLAG_USES_DEPTH_STENCIL;
1060 	}
1061 
1062 	VKPipeline *pipeline = new VKPipeline(vulkan_, desc.uniformDesc ? desc.uniformDesc->uniformBufferSize : 16 * sizeof(float), (PipelineFlags)pipelineFlags);
1063 
1064 	if (input) {
1065 		for (int i = 0; i < (int)input->bindings.size(); i++) {
1066 			pipeline->stride[i] = input->bindings[i].stride;
1067 		}
1068 	} else {
1069 		pipeline->stride[0] = 0;
1070 	}
1071 
1072 	std::vector<VkPipelineShaderStageCreateInfo> stages;
1073 	stages.resize(desc.shaders.size());
1074 	int i = 0;
1075 	for (auto &iter : desc.shaders) {
1076 		VKShaderModule *vkshader = (VKShaderModule *)iter;
1077 		if (!vkshader) {
1078 			ERROR_LOG(G3D,  "CreateGraphicsPipeline got passed a null shader");
1079 			return nullptr;
1080 		}
1081 		VkPipelineShaderStageCreateInfo &stage = stages[i++];
1082 		stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1083 		stage.pNext = nullptr;
1084 		stage.pSpecializationInfo = nullptr;
1085 		stage.stage = StageToVulkan(vkshader->GetStage());
1086 		stage.module = vkshader->Get();
1087 		stage.pName = "main";
1088 		stage.flags = 0;
1089 	}
1090 
1091 	VkPipelineInputAssemblyStateCreateInfo inputAssembly = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
1092 	inputAssembly.topology = primToVK[(int)desc.prim];
1093 	inputAssembly.primitiveRestartEnable = false;
1094 
1095 	// We treat the three stencil states as a unit in other places, so let's do that here too.
1096 	VkDynamicState dynamics[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE, VK_DYNAMIC_STATE_STENCIL_WRITE_MASK };
1097 	VkPipelineDynamicStateCreateInfo dynamicInfo = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
1098 	dynamicInfo.dynamicStateCount = depth->info.stencilTestEnable ? ARRAY_SIZE(dynamics) : 2;
1099 	dynamicInfo.pDynamicStates = dynamics;
1100 
1101 	VkPipelineMultisampleStateCreateInfo ms{ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
1102 	ms.pSampleMask = nullptr;
1103 	ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
1104 
1105 	VkPipelineViewportStateCreateInfo vs{ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
1106 	vs.viewportCount = 1;
1107 	vs.scissorCount = 1;
1108 	vs.pViewports = nullptr;  // dynamic
1109 	vs.pScissors = nullptr;  // dynamic
1110 
1111 	VkPipelineRasterizationStateCreateInfo rs{ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
1112 	raster->ToVulkan(&rs);
1113 
1114 	VkPipelineVertexInputStateCreateInfo emptyVisc{ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
1115 
1116 	VkGraphicsPipelineCreateInfo createInfo[2]{};
1117 	for (auto &info : createInfo) {
1118 		info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1119 		info.flags = 0;
1120 		info.stageCount = (uint32_t)stages.size();
1121 		info.pStages = stages.data();
1122 		info.pColorBlendState = &blend->info;
1123 		info.pDepthStencilState = &depth->info;
1124 		info.pDynamicState = &dynamicInfo;
1125 		info.pInputAssemblyState = &inputAssembly;
1126 		info.pTessellationState = nullptr;
1127 		info.pMultisampleState = &ms;
1128 		info.pVertexInputState = input ? &input->visc : &emptyVisc;
1129 		info.pRasterizationState = &rs;
1130 		info.pViewportState = &vs;  // Must set viewport and scissor counts even if we set the actual state dynamically.
1131 		info.layout = pipelineLayout_;
1132 		info.subpass = 0;
1133 	}
1134 
1135 	createInfo[0].renderPass = renderManager_.GetBackbufferRenderPass();
1136 	createInfo[1].renderPass = renderManager_.GetFramebufferRenderPass();
1137 
1138 	// OK, need to create new pipelines.
1139 	VkPipeline pipelines[2]{};
1140 	VkResult result = vkCreateGraphicsPipelines(device_, pipelineCache_, 2, createInfo, nullptr, pipelines);
1141 	if (result != VK_SUCCESS) {
1142 		ERROR_LOG(G3D,  "Failed to create graphics pipeline");
1143 		delete pipeline;
1144 		return nullptr;
1145 	}
1146 
1147 	pipeline->backbufferPipeline = pipelines[0];
1148 	pipeline->framebufferPipeline = pipelines[1];
1149 
1150 	if (desc.uniformDesc) {
1151 		pipeline->dynamicUniformSize = (int)desc.uniformDesc->uniformBufferSize;
1152 	}
1153 	if (depth->info.stencilTestEnable) {
1154 		pipeline->usesStencil = true;
1155 		pipeline->stencilTestMask = depth->info.front.compareMask;
1156 		pipeline->stencilWriteMask = depth->info.front.writeMask;
1157 	}
1158 	return pipeline;
1159 }
1160 
SetScissorRect(int left,int top,int width,int height)1161 void VKContext::SetScissorRect(int left, int top, int width, int height) {
1162 	VkRect2D scissor{ {(int32_t)left, (int32_t)top}, {(uint32_t)width, (uint32_t)height} };
1163 	renderManager_.SetScissor(scissor);
1164 }
1165 
SetViewports(int count,Viewport * viewports)1166 void VKContext::SetViewports(int count, Viewport *viewports) {
1167 	if (count > 0) {
1168 		// Ignore viewports more than the first.
1169 		VkViewport viewport;
1170 		viewport.x = viewports[0].TopLeftX;
1171 		viewport.y = viewports[0].TopLeftY;
1172 		viewport.width = viewports[0].Width;
1173 		viewport.height = viewports[0].Height;
1174 		viewport.minDepth = viewports[0].MinDepth;
1175 		viewport.maxDepth = viewports[0].MaxDepth;
1176 		renderManager_.SetViewport(viewport);
1177 	}
1178 }
1179 
SetBlendFactor(float color[4])1180 void VKContext::SetBlendFactor(float color[4]) {
1181 	uint32_t col = Float4ToUint8x4(color);
1182 	renderManager_.SetBlendFactor(col);
1183 }
1184 
SetStencilRef(uint8_t stencilRef)1185 void VKContext::SetStencilRef(uint8_t stencilRef) {
1186 	if (curPipeline_->usesStencil)
1187 		renderManager_.SetStencilParams(curPipeline_->stencilWriteMask, curPipeline_->stencilTestMask, stencilRef);
1188 	stencilRef_ = stencilRef;
1189 }
1190 
CreateInputLayout(const InputLayoutDesc & desc)1191 InputLayout *VKContext::CreateInputLayout(const InputLayoutDesc &desc) {
1192 	VKInputLayout *vl = new VKInputLayout();
1193 	vl->visc = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
1194 	vl->visc.flags = 0;
1195 	vl->visc.vertexAttributeDescriptionCount = (uint32_t)desc.attributes.size();
1196 	vl->visc.vertexBindingDescriptionCount = (uint32_t)desc.bindings.size();
1197 	vl->bindings.resize(vl->visc.vertexBindingDescriptionCount);
1198 	vl->attributes.resize(vl->visc.vertexAttributeDescriptionCount);
1199 	vl->visc.pVertexBindingDescriptions = vl->bindings.data();
1200 	vl->visc.pVertexAttributeDescriptions = vl->attributes.data();
1201 	for (size_t i = 0; i < desc.attributes.size(); i++) {
1202 		vl->attributes[i].binding = (uint32_t)desc.attributes[i].binding;
1203 		vl->attributes[i].format = DataFormatToVulkan(desc.attributes[i].format);
1204 		vl->attributes[i].location = desc.attributes[i].location;
1205 		vl->attributes[i].offset = desc.attributes[i].offset;
1206 	}
1207 	for (size_t i = 0; i < desc.bindings.size(); i++) {
1208 		vl->bindings[i].inputRate = desc.bindings[i].instanceRate ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
1209 		vl->bindings[i].binding = (uint32_t)i;
1210 		vl->bindings[i].stride = desc.bindings[i].stride;
1211 	}
1212 	return vl;
1213 }
1214 
CreateTexture(const TextureDesc & desc)1215 Texture *VKContext::CreateTexture(const TextureDesc &desc) {
1216 	VkCommandBuffer initCmd = renderManager_.GetInitCmd();
1217 	if (!push_ || !initCmd) {
1218 		// Too early! Fail.
1219 		ERROR_LOG(G3D,  "Can't create textures before the first frame has started.");
1220 		return nullptr;
1221 	}
1222 	VKTexture *tex = new VKTexture(vulkan_, initCmd, push_, desc);
1223 	if (tex->Create(initCmd, push_, desc, allocator_)) {
1224 		return tex;
1225 	} else {
1226 		ERROR_LOG(G3D,  "Failed to create texture");
1227 		delete tex;
1228 		return nullptr;
1229 	}
1230 }
1231 
CopySide(VkStencilOpState & dest,const StencilSide & src)1232 static inline void CopySide(VkStencilOpState &dest, const StencilSide &src) {
1233 	dest.compareMask = src.compareMask;
1234 	dest.writeMask = src.writeMask;
1235 	dest.compareOp = compToVK[(int)src.compareOp];
1236 	dest.failOp = stencilOpToVK[(int)src.failOp];
1237 	dest.passOp = stencilOpToVK[(int)src.passOp];
1238 	dest.depthFailOp = stencilOpToVK[(int)src.depthFailOp];
1239 }
1240 
CreateDepthStencilState(const DepthStencilStateDesc & desc)1241 DepthStencilState *VKContext::CreateDepthStencilState(const DepthStencilStateDesc &desc) {
1242 	VKDepthStencilState *ds = new VKDepthStencilState();
1243 	ds->info.depthCompareOp = compToVK[(int)desc.depthCompare];
1244 	ds->info.depthTestEnable = desc.depthTestEnabled;
1245 	ds->info.depthWriteEnable = desc.depthWriteEnabled;
1246 	ds->info.stencilTestEnable = desc.stencilEnabled;
1247 	ds->info.depthBoundsTestEnable = false;
1248 	if (ds->info.stencilTestEnable) {
1249 		CopySide(ds->info.front, desc.front);
1250 		CopySide(ds->info.back, desc.back);
1251 	}
1252 	return ds;
1253 }
1254 
CreateBlendState(const BlendStateDesc & desc)1255 BlendState *VKContext::CreateBlendState(const BlendStateDesc &desc) {
1256 	VKBlendState *bs = new VKBlendState();
1257 	bs->info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1258 	bs->info.attachmentCount = 1;
1259 	bs->info.logicOp = logicOpToVK[(int)desc.logicOp];
1260 	bs->info.logicOpEnable = desc.logicEnabled;
1261 	bs->attachments.resize(1);
1262 	bs->attachments[0].blendEnable = desc.enabled;
1263 	bs->attachments[0].colorBlendOp = blendEqToVk[(int)desc.eqCol];
1264 	bs->attachments[0].alphaBlendOp = blendEqToVk[(int)desc.eqAlpha];
1265 	bs->attachments[0].colorWriteMask = desc.colorMask;
1266 	bs->attachments[0].dstAlphaBlendFactor = blendFactorToVk[(int)desc.dstAlpha];
1267 	bs->attachments[0].dstColorBlendFactor = blendFactorToVk[(int)desc.dstCol];
1268 	bs->attachments[0].srcAlphaBlendFactor = blendFactorToVk[(int)desc.srcAlpha];
1269 	bs->attachments[0].srcColorBlendFactor = blendFactorToVk[(int)desc.srcCol];
1270 	bs->info.pAttachments = bs->attachments.data();
1271 	return bs;
1272 }
1273 
1274 // Very simplistic buffer that will simply copy its contents into our "pushbuffer" when it's time to draw,
1275 // to avoid synchronization issues.
1276 class VKBuffer : public Buffer {
1277 public:
VKBuffer(size_t size,uint32_t flags)1278 	VKBuffer(size_t size, uint32_t flags) : dataSize_(size) {
1279 		data_ = new uint8_t[size];
1280 	}
~VKBuffer()1281 	~VKBuffer() override {
1282 		delete[] data_;
1283 	}
1284 
GetSize() const1285 	size_t GetSize() const { return dataSize_; }
GetData() const1286 	const uint8_t *GetData() const { return data_; }
1287 
1288 	uint8_t *data_;
1289 	size_t dataSize_;
1290 };
1291 
CreateBuffer(size_t size,uint32_t usageFlags)1292 Buffer *VKContext::CreateBuffer(size_t size, uint32_t usageFlags) {
1293 	return new VKBuffer(size, usageFlags);
1294 }
1295 
UpdateBuffer(Buffer * buffer,const uint8_t * data,size_t offset,size_t size,UpdateBufferFlags flags)1296 void VKContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) {
1297 	VKBuffer *buf = (VKBuffer *)buffer;
1298 	memcpy(buf->data_ + offset, data, size);
1299 }
1300 
BindTextures(int start,int count,Texture ** textures)1301 void VKContext::BindTextures(int start, int count, Texture **textures) {
1302 	_assert_(start + count <= MAX_BOUND_TEXTURES);
1303 	for (int i = start; i < start + count; i++) {
1304 		boundTextures_[i] = static_cast<VKTexture *>(textures[i - start]);
1305 		boundImageView_[i] = boundTextures_[i] ? boundTextures_[i]->GetImageView() : GetNullTexture()->GetImageView();
1306 	}
1307 }
1308 
CreateShaderModule(ShaderStage stage,ShaderLanguage language,const uint8_t * data,size_t size,const std::string & tag)1309 ShaderModule *VKContext::CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t size, const std::string &tag) {
1310 	VKShaderModule *shader = new VKShaderModule(stage, tag);
1311 	if (shader->Compile(vulkan_, language, data, size)) {
1312 		return shader;
1313 	} else {
1314 		ERROR_LOG(G3D,  "Failed to compile shader:\n%s", (const char *)data);
1315 		shader->Release();
1316 		return nullptr;
1317 	}
1318 }
1319 
GetUniformLoc(const char * name)1320 int VKPipeline::GetUniformLoc(const char *name) {
1321 	int loc = -1;
1322 
1323 	// HACK! As we only use one uniform we hardcode it.
1324 	if (!strcmp(name, "WorldViewProj")) {
1325 		return 0;
1326 	}
1327 
1328 	return loc;
1329 }
1330 
UpdateDynamicUniformBuffer(const void * ub,size_t size)1331 void VKContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
1332 	curPipeline_->SetDynamicUniformData(ub, size);
1333 }
1334 
ApplyDynamicState()1335 void VKContext::ApplyDynamicState() {
1336 	// TODO: blend constants, stencil, viewports should be here, after bindpipeline..
1337 	if (curPipeline_->usesStencil) {
1338 		renderManager_.SetStencilParams(curPipeline_->stencilWriteMask, curPipeline_->stencilTestMask, stencilRef_);
1339 	}
1340 }
1341 
Draw(int vertexCount,int offset)1342 void VKContext::Draw(int vertexCount, int offset) {
1343 	VKBuffer *vbuf = curVBuffers_[0];
1344 
1345 	VkBuffer vulkanVbuf;
1346 	VkBuffer vulkanUBObuf;
1347 	uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf);
1348 	size_t vbBindOffset = push_->Push(vbuf->GetData(), vbuf->GetSize(), &vulkanVbuf);
1349 
1350 	VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf);
1351 	if (descSet == VK_NULL_HANDLE) {
1352 		ERROR_LOG(G3D, "GetOrCreateDescriptorSet failed, skipping %s", __FUNCTION__);
1353 		return;
1354 	}
1355 
1356 	BindCompatiblePipeline();
1357 	ApplyDynamicState();
1358 	renderManager_.Draw(pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vertexCount, offset);
1359 }
1360 
DrawIndexed(int vertexCount,int offset)1361 void VKContext::DrawIndexed(int vertexCount, int offset) {
1362 	VKBuffer *ibuf = curIBuffer_;
1363 	VKBuffer *vbuf = curVBuffers_[0];
1364 
1365 	VkBuffer vulkanVbuf, vulkanIbuf, vulkanUBObuf;
1366 	uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf);
1367 	size_t vbBindOffset = push_->Push(vbuf->GetData(), vbuf->GetSize(), &vulkanVbuf);
1368 	size_t ibBindOffset = push_->Push(ibuf->GetData(), ibuf->GetSize(), &vulkanIbuf);
1369 
1370 	VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf);
1371 	if (descSet == VK_NULL_HANDLE) {
1372 		ERROR_LOG(G3D, "GetOrCreateDescriptorSet failed, skipping %s", __FUNCTION__);
1373 		return;
1374 	}
1375 
1376 	BindCompatiblePipeline();
1377 	ApplyDynamicState();
1378 	renderManager_.DrawIndexed(pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vulkanIbuf, (int)ibBindOffset + offset * sizeof(uint32_t), vertexCount, 1, VK_INDEX_TYPE_UINT16);
1379 }
1380 
DrawUP(const void * vdata,int vertexCount)1381 void VKContext::DrawUP(const void *vdata, int vertexCount) {
1382 	VkBuffer vulkanVbuf, vulkanUBObuf;
1383 	size_t vbBindOffset = push_->Push(vdata, vertexCount * curPipeline_->stride[0], &vulkanVbuf);
1384 	uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf);
1385 
1386 	VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf);
1387 	if (descSet == VK_NULL_HANDLE) {
1388 		ERROR_LOG(G3D, "GetOrCreateDescriptorSet failed, skipping %s", __FUNCTION__);
1389 		return;
1390 	}
1391 
1392 	BindCompatiblePipeline();
1393 	ApplyDynamicState();
1394 	renderManager_.Draw(pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset + curVBufferOffsets_[0], vertexCount);
1395 }
1396 
BindCompatiblePipeline()1397 void VKContext::BindCompatiblePipeline() {
1398 	VkRenderPass renderPass = renderManager_.GetCompatibleRenderPass();
1399 	if (renderPass == renderManager_.GetBackbufferRenderPass()) {
1400 		renderManager_.BindPipeline(curPipeline_->backbufferPipeline, curPipeline_->flags);
1401 	} else {
1402 		renderManager_.BindPipeline(curPipeline_->framebufferPipeline, curPipeline_->flags);
1403 	}
1404 }
1405 
Clear(int clearMask,uint32_t colorval,float depthVal,int stencilVal)1406 void VKContext::Clear(int clearMask, uint32_t colorval, float depthVal, int stencilVal) {
1407 	int mask = 0;
1408 	if (clearMask & FBChannel::FB_COLOR_BIT)
1409 		mask |= VK_IMAGE_ASPECT_COLOR_BIT;
1410 	if (clearMask & FBChannel::FB_DEPTH_BIT)
1411 		mask |= VK_IMAGE_ASPECT_DEPTH_BIT;
1412 	if (clearMask & FBChannel::FB_STENCIL_BIT)
1413 		mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
1414 	renderManager_.Clear(colorval, depthVal, stencilVal, mask);
1415 }
1416 
T3DCreateVulkanContext(VulkanContext * vulkan,bool split)1417 DrawContext *T3DCreateVulkanContext(VulkanContext *vulkan, bool split) {
1418 	return new VKContext(vulkan, split);
1419 }
1420 
AddFeature(std::vector<std::string> & features,const char * name,VkBool32 available,VkBool32 enabled)1421 void AddFeature(std::vector<std::string> &features, const char *name, VkBool32 available, VkBool32 enabled) {
1422 	char buf[512];
1423 	snprintf(buf, sizeof(buf), "%s: Available: %d Enabled: %d", name, (int)available, (int)enabled);
1424 	features.push_back(buf);
1425 }
1426 
1427 // Limited to depth buffer formats as that's what we need right now.
VulkanFormatToString(VkFormat fmt)1428 static const char *VulkanFormatToString(VkFormat fmt) {
1429 	switch (fmt) {
1430 	case VkFormat::VK_FORMAT_D24_UNORM_S8_UINT: return "D24S8";
1431 	case VkFormat::VK_FORMAT_D16_UNORM: return "D16";
1432 	case VkFormat::VK_FORMAT_D16_UNORM_S8_UINT: return "D16S8";
1433 	case VkFormat::VK_FORMAT_D32_SFLOAT: return "D32f";
1434 	case VkFormat::VK_FORMAT_D32_SFLOAT_S8_UINT: return "D32fS8";
1435 	case VkFormat::VK_FORMAT_S8_UINT: return "S8";
1436 	case VkFormat::VK_FORMAT_UNDEFINED: return "UNDEFINED (BAD!)";
1437 	default: return "UNKNOWN";
1438 	}
1439 }
1440 
GetFeatureList() const1441 std::vector<std::string> VKContext::GetFeatureList() const {
1442 	const VkPhysicalDeviceFeatures &available = vulkan_->GetDeviceFeatures().available;
1443 	const VkPhysicalDeviceFeatures &enabled = vulkan_->GetDeviceFeatures().enabled;
1444 
1445 	std::vector<std::string> features;
1446 	AddFeature(features, "dualSrcBlend", available.dualSrcBlend, enabled.dualSrcBlend);
1447 	AddFeature(features, "logicOp", available.logicOp, enabled.logicOp);
1448 	AddFeature(features, "geometryShader", available.geometryShader, enabled.geometryShader);
1449 	AddFeature(features, "depthBounds", available.depthBounds, enabled.depthBounds);
1450 	AddFeature(features, "depthClamp", available.depthClamp, enabled.depthClamp);
1451 	AddFeature(features, "fillModeNonSolid", available.fillModeNonSolid, enabled.fillModeNonSolid);
1452 	AddFeature(features, "largePoints", available.largePoints, enabled.largePoints);
1453 	AddFeature(features, "wideLines", available.wideLines, enabled.wideLines);
1454 	AddFeature(features, "pipelineStatisticsQuery", available.pipelineStatisticsQuery, enabled.pipelineStatisticsQuery);
1455 	AddFeature(features, "samplerAnisotropy", available.samplerAnisotropy, enabled.samplerAnisotropy);
1456 	AddFeature(features, "textureCompressionBC", available.textureCompressionBC, enabled.textureCompressionBC);
1457 	AddFeature(features, "textureCompressionETC2", available.textureCompressionETC2, enabled.textureCompressionETC2);
1458 	AddFeature(features, "textureCompressionASTC_LDR", available.textureCompressionASTC_LDR, enabled.textureCompressionASTC_LDR);
1459 	AddFeature(features, "shaderClipDistance", available.shaderClipDistance, enabled.shaderClipDistance);
1460 	AddFeature(features, "shaderCullDistance", available.shaderCullDistance, enabled.shaderCullDistance);
1461 	AddFeature(features, "occlusionQueryPrecise", available.occlusionQueryPrecise, enabled.occlusionQueryPrecise);
1462 	AddFeature(features, "multiDrawIndirect", available.multiDrawIndirect, enabled.multiDrawIndirect);
1463 
1464 	features.push_back(std::string("Preferred depth buffer format: ") + VulkanFormatToString(vulkan_->GetDeviceInfo().preferredDepthStencilFormat));
1465 
1466 	return features;
1467 }
1468 
GetExtensionList() const1469 std::vector<std::string> VKContext::GetExtensionList() const {
1470 	std::vector<std::string> extensions;
1471 	for (auto &iter : vulkan_->GetDeviceExtensionsAvailable()) {
1472 		extensions.push_back(iter.extensionName);
1473 	}
1474 	return extensions;
1475 }
1476 
GetDataFormatSupport(DataFormat fmt) const1477 uint32_t VKContext::GetDataFormatSupport(DataFormat fmt) const {
1478 	VkFormat vulkan_format = DataFormatToVulkan(fmt);
1479 	VkFormatProperties properties;
1480 	vkGetPhysicalDeviceFormatProperties(vulkan_->GetCurrentPhysicalDevice(), vulkan_format, &properties);
1481 	uint32_t flags = 0;
1482 	if (properties.optimalTilingFeatures & VkFormatFeatureFlagBits::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
1483 		flags |= FMT_RENDERTARGET;
1484 	}
1485 	if (properties.optimalTilingFeatures & VkFormatFeatureFlagBits::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
1486 		flags |= FMT_DEPTHSTENCIL;
1487 	}
1488 	if (properties.optimalTilingFeatures & VkFormatFeatureFlagBits::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
1489 		flags |= FMT_TEXTURE;
1490 	}
1491 	if (properties.bufferFeatures & VkFormatFeatureFlagBits::VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) {
1492 		flags |= FMT_INPUTLAYOUT;
1493 	}
1494 	return flags;
1495 }
1496 
1497 // A VKFramebuffer is a VkFramebuffer (note caps difference) plus all the textures it owns.
1498 // It also has a reference to the command buffer that it was last rendered to with.
1499 // If it needs to be transitioned, and the frame number matches, use it, otherwise
1500 // use this frame's init command buffer.
1501 class VKFramebuffer : public Framebuffer {
1502 public:
VKFramebuffer(VKRFramebuffer * fb)1503 	VKFramebuffer(VKRFramebuffer *fb) : buf_(fb) {
1504 		_assert_msg_(fb, "Null fb in VKFramebuffer constructor");
1505 		width_ = fb->width;
1506 		height_ = fb->height;
1507 	}
~VKFramebuffer()1508 	~VKFramebuffer() {
1509 		_assert_msg_(buf_, "Null buf_ in VKFramebuffer - double delete?");
1510 		buf_->vulkan_->Delete().QueueCallback([](void *fb) {
1511 			VKRFramebuffer *vfb = static_cast<VKRFramebuffer *>(fb);
1512 			delete vfb;
1513 		}, buf_);
1514 		buf_ = nullptr;
1515 	}
GetFB() const1516 	VKRFramebuffer *GetFB() const { return buf_; }
1517 private:
1518 	VKRFramebuffer *buf_;
1519 };
1520 
CreateFramebuffer(const FramebufferDesc & desc)1521 Framebuffer *VKContext::CreateFramebuffer(const FramebufferDesc &desc) {
1522 	VkCommandBuffer cmd = renderManager_.GetInitCmd();
1523 	// TODO: We always create with depth here, even when it's not needed (such as color temp FBOs).
1524 	// Should optimize those away.
1525 	VKRFramebuffer *vkrfb = new VKRFramebuffer(vulkan_, cmd, renderManager_.GetFramebufferRenderPass(), desc.width, desc.height, desc.tag);
1526 	return new VKFramebuffer(vkrfb);
1527 }
1528 
CopyFramebufferImage(Framebuffer * srcfb,int level,int x,int y,int z,Framebuffer * dstfb,int dstLevel,int dstX,int dstY,int dstZ,int width,int height,int depth,int channelBits,const char * tag)1529 void VKContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x, int y, int z, Framebuffer *dstfb, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) {
1530 	VKFramebuffer *src = (VKFramebuffer *)srcfb;
1531 	VKFramebuffer *dst = (VKFramebuffer *)dstfb;
1532 
1533 	int aspectMask = 0;
1534 	if (channelBits & FBChannel::FB_COLOR_BIT) aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
1535 	if (channelBits & FBChannel::FB_DEPTH_BIT) aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
1536 	if (channelBits & FBChannel::FB_STENCIL_BIT) aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
1537 
1538 	renderManager_.CopyFramebuffer(src->GetFB(), VkRect2D{ {x, y}, {(uint32_t)width, (uint32_t)height } }, dst->GetFB(), VkOffset2D{ dstX, dstY }, aspectMask, tag);
1539 }
1540 
BlitFramebuffer(Framebuffer * srcfb,int srcX1,int srcY1,int srcX2,int srcY2,Framebuffer * dstfb,int dstX1,int dstY1,int dstX2,int dstY2,int channelBits,FBBlitFilter filter,const char * tag)1541 bool VKContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dstfb, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) {
1542 	VKFramebuffer *src = (VKFramebuffer *)srcfb;
1543 	VKFramebuffer *dst = (VKFramebuffer *)dstfb;
1544 
1545 	int aspectMask = 0;
1546 	if (channelBits & FBChannel::FB_COLOR_BIT) aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
1547 	if (channelBits & FBChannel::FB_DEPTH_BIT) aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
1548 	if (channelBits & FBChannel::FB_STENCIL_BIT) aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
1549 
1550 	renderManager_.BlitFramebuffer(src->GetFB(), VkRect2D{ {srcX1, srcY1}, {(uint32_t)(srcX2 - srcX1), (uint32_t)(srcY2 - srcY1) } }, dst->GetFB(), VkRect2D{ {dstX1, dstY1}, {(uint32_t)(dstX2 - dstX1), (uint32_t)(dstY2 - dstY1) } }, aspectMask, filter == FB_BLIT_LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST, tag);
1551 	return true;
1552 }
1553 
CopyFramebufferToMemorySync(Framebuffer * srcfb,int channelBits,int x,int y,int w,int h,Draw::DataFormat format,void * pixels,int pixelStride,const char * tag)1554 bool VKContext::CopyFramebufferToMemorySync(Framebuffer *srcfb, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, const char *tag) {
1555 	VKFramebuffer *src = (VKFramebuffer *)srcfb;
1556 
1557 	int aspectMask = 0;
1558 	if (channelBits & FBChannel::FB_COLOR_BIT) aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
1559 	if (channelBits & FBChannel::FB_DEPTH_BIT) aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
1560 	if (channelBits & FBChannel::FB_STENCIL_BIT) aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
1561 
1562 	return renderManager_.CopyFramebufferToMemorySync(src ? src->GetFB() : nullptr, aspectMask, x, y, w, h, format, (uint8_t *)pixels, pixelStride, tag);
1563 }
1564 
PreferredFramebufferReadbackFormat(Framebuffer * src)1565 DataFormat VKContext::PreferredFramebufferReadbackFormat(Framebuffer *src) {
1566 	if (src) {
1567 		return DrawContext::PreferredFramebufferReadbackFormat(src);
1568 	}
1569 
1570 	if (vulkan_->GetSwapchainFormat() == VK_FORMAT_B8G8R8A8_UNORM) {
1571 		return Draw::DataFormat::B8G8R8A8_UNORM;
1572 	}
1573 	return DrawContext::PreferredFramebufferReadbackFormat(src);
1574 }
1575 
BindFramebufferAsRenderTarget(Framebuffer * fbo,const RenderPassInfo & rp,const char * tag)1576 void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) {
1577 	VKFramebuffer *fb = (VKFramebuffer *)fbo;
1578 	VKRRenderPassAction color = (VKRRenderPassAction)rp.color;
1579 	VKRRenderPassAction depth = (VKRRenderPassAction)rp.depth;
1580 	VKRRenderPassAction stencil = (VKRRenderPassAction)rp.stencil;
1581 
1582 	renderManager_.BindFramebufferAsRenderTarget(fb ? fb->GetFB() : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil, tag);
1583 	curFramebuffer_ = fb;
1584 }
1585 
BindFramebufferAsTexture(Framebuffer * fbo,int binding,FBChannel channelBit,int attachment)1586 void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) {
1587 	VKFramebuffer *fb = (VKFramebuffer *)fbo;
1588 	_assert_(binding < MAX_BOUND_TEXTURES);
1589 
1590 	// TODO: There are cases where this is okay, actually. But requires layout transitions and stuff -
1591 	// we're not ready for this.
1592 	_assert_(fb != curFramebuffer_);
1593 
1594 	int aspect = 0;
1595 	switch (channelBit) {
1596 	case FBChannel::FB_COLOR_BIT:
1597 		aspect = VK_IMAGE_ASPECT_COLOR_BIT;
1598 		break;
1599 	case FBChannel::FB_DEPTH_BIT:
1600 		aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
1601 		break;
1602 	default:
1603 		_assert_(false);
1604 		break;
1605 	}
1606 	boundTextures_[binding] = nullptr;
1607 	boundImageView_[binding] = renderManager_.BindFramebufferAsTexture(fb->GetFB(), binding, aspect, attachment);
1608 }
1609 
GetFramebufferAPITexture(Framebuffer * fbo,int channelBit,int attachment)1610 uintptr_t VKContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) {
1611 	if (!fbo)
1612 		return 0;
1613 
1614 	VKFramebuffer *fb = (VKFramebuffer *)fbo;
1615 	VkImageView view = VK_NULL_HANDLE;
1616 	switch (channelBit) {
1617 	case FB_COLOR_BIT:
1618 		view = fb->GetFB()->color.imageView;
1619 		break;
1620 	case FB_DEPTH_BIT:
1621 	case FB_STENCIL_BIT:
1622 		view = fb->GetFB()->depth.imageView;
1623 		break;
1624 	}
1625 	return (uintptr_t)view;
1626 }
1627 
GetFramebufferDimensions(Framebuffer * fbo,int * w,int * h)1628 void VKContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
1629 	VKFramebuffer *fb = (VKFramebuffer *)fbo;
1630 	if (fb) {
1631 		*w = fb->GetFB()->width;
1632 		*h = fb->GetFB()->height;
1633 	} else {
1634 		*w = vulkan_->GetBackbufferWidth();
1635 		*h = vulkan_->GetBackbufferHeight();
1636 	}
1637 }
1638 
HandleEvent(Event ev,int width,int height,void * param1,void * param2)1639 void VKContext::HandleEvent(Event ev, int width, int height, void *param1, void *param2) {
1640 	switch (ev) {
1641 	case Event::LOST_BACKBUFFER:
1642 		renderManager_.DestroyBackbuffers();
1643 		break;
1644 	case Event::GOT_BACKBUFFER:
1645 		renderManager_.CreateBackbuffers();
1646 		break;
1647 	default:
1648 		_assert_(false);
1649 		break;
1650 	}
1651 }
1652 
1653 }  // namespace Draw
1654