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 #pragma once
19 
20 // The Descriptor Set used for the majority of PSP rendering looks like this:
21 //
22 // * binding 0: Texture/Sampler (the PSP texture)
23 // * binding 1: Secondary texture sampler for shader blending
24 // * binding 2: Depal palette
25 // * binding 3: Base Uniform Buffer (includes fragment state)
26 // * binding 4: Light uniform buffer
27 // * binding 5: Bone uniform buffer
28 // * binding 6: Tess data storage buffer
29 //
30 // All shaders conform to this layout, so they are all compatible with the same descriptor set.
31 // The format of the various uniform buffers may vary though - vertex shaders that don't skin
32 // won't get any bone data, etc.
33 
34 #include "Common/Data/Collections/Hashmaps.h"
35 
36 #include "GPU/Vulkan/VulkanUtil.h"
37 
38 #include "GPU/GPUState.h"
39 #include "GPU/Common/GPUDebugInterface.h"
40 #include "GPU/Common/IndexGenerator.h"
41 #include "GPU/Common/VertexDecoderCommon.h"
42 #include "GPU/Common/DrawEngineCommon.h"
43 #include "GPU/Common/GPUStateUtils.h"
44 #include "GPU/Vulkan/StateMappingVulkan.h"
45 
46 struct DecVtxFormat;
47 struct UVScale;
48 
49 class ShaderManagerVulkan;
50 class PipelineManagerVulkan;
51 class TextureCacheVulkan;
52 class FramebufferManagerVulkan;
53 
54 class VulkanContext;
55 class VulkanPushBuffer;
56 struct VulkanPipeline;
57 
58 struct DrawEngineVulkanStats {
59 	int pushUBOSpaceUsed;
60 	int pushVertexSpaceUsed;
61 	int pushIndexSpaceUsed;
62 };
63 
64 enum {
65 	VAIVULKAN_FLAG_VERTEXFULLALPHA = 1,
66 };
67 
68 // Try to keep this POD.
69 class VertexArrayInfoVulkan {
70 public:
VertexArrayInfoVulkan()71 	VertexArrayInfoVulkan() {
72 		lastFrame = gpuStats.numFlips;
73 	}
74 	// No destructor needed - we always fully wipe.
75 
76 	enum VAIStatus : uint8_t {
77 		VAI_NEW,
78 		VAI_HASHING,
79 		VAI_RELIABLE,  // cache, don't hash
80 		VAI_UNRELIABLE,  // never cache
81 	};
82 
83 	uint64_t hash;
84 	u32 minihash;
85 
86 	// These will probably always be the same, but whatever.
87 	VkBuffer vb = VK_NULL_HANDLE;
88 	VkBuffer ib = VK_NULL_HANDLE;
89 	// Offsets into the cache buffer.
90 	uint32_t vbOffset = 0;
91 	uint32_t ibOffset = 0;
92 
93 	// Precalculated parameter for vkDrawIndexed
94 	u16 numVerts = 0;
95 	u16 maxIndex = 0;
96 	s8 prim = GE_PRIM_INVALID;
97 	VAIStatus status = VAI_NEW;
98 
99 	// ID information
100 	int numDraws = 0;
101 	int numFrames = 0;
102 	int lastFrame;  // So that we can forget.
103 	u16 drawsUntilNextFullHash = 0;
104 	u8 flags = 0;
105 };
106 
107 class VulkanRenderManager;
108 
109 class TessellationDataTransferVulkan : public TessellationDataTransfer  {
110 public:
TessellationDataTransferVulkan(VulkanContext * vulkan)111 	TessellationDataTransferVulkan(VulkanContext *vulkan) : vulkan_(vulkan) {}
112 
SetPushBuffer(VulkanPushBuffer * push)113 	void SetPushBuffer(VulkanPushBuffer *push) { push_ = push; }
114 	// Send spline/bezier's control points and weights to vertex shader through structured shader buffer.
115 	void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) override;
GetBufferInfo()116 	const VkDescriptorBufferInfo *GetBufferInfo() { return bufInfo_; }
117 private:
118 	VulkanContext *vulkan_;
119 	VulkanPushBuffer *push_;  // Updated each frame.
120 	VkDescriptorBufferInfo bufInfo_[3]{};
121 };
122 
123 // Handles transform, lighting and drawing.
124 class DrawEngineVulkan : public DrawEngineCommon {
125 public:
126 	DrawEngineVulkan(VulkanContext *vulkan, Draw::DrawContext *draw);
127 	virtual ~DrawEngineVulkan();
128 
SetShaderManager(ShaderManagerVulkan * shaderManager)129 	void SetShaderManager(ShaderManagerVulkan *shaderManager) {
130 		shaderManager_ = shaderManager;
131 	}
SetPipelineManager(PipelineManagerVulkan * pipelineManager)132 	void SetPipelineManager(PipelineManagerVulkan *pipelineManager) {
133 		pipelineManager_ = pipelineManager;
134 	}
SetTextureCache(TextureCacheVulkan * textureCache)135 	void SetTextureCache(TextureCacheVulkan *textureCache) {
136 		textureCache_ = textureCache;
137 	}
SetFramebufferManager(FramebufferManagerVulkan * fbManager)138 	void SetFramebufferManager(FramebufferManagerVulkan *fbManager) {
139 		framebufferManager_ = fbManager;
140 	}
141 
142 	void DeviceLost();
143 	void DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw);
144 
145 	// So that this can be inlined
Flush()146 	void Flush() {
147 		if (!numDrawCalls)
148 			return;
149 		DoFlush();
150 	}
151 
FinishDeferred()152 	void FinishDeferred() {
153 		if (!numDrawCalls)
154 			return;
155 		// Decode any pending vertices. And also flush while we're at it, for simplicity.
156 		// It might be possible to only decode like in the other backends, but meh, it can't matter.
157 		// Issue #10095 has a nice example of where this is required.
158 		DoFlush();
159 	}
160 
DispatchFlush()161 	void DispatchFlush() override { Flush(); }
162 
GetPipelineLayout()163 	VkPipelineLayout GetPipelineLayout() const {
164 		return pipelineLayout_;
165 	}
166 
167 	void BeginFrame();
168 	void EndFrame();
169 
170 	void DirtyAllUBOs();
171 
DirtyPipeline()172 	void DirtyPipeline() {
173 		lastPipeline_ = nullptr;
174 	}
175 
GetPushBufferForTextureData()176 	VulkanPushBuffer *GetPushBufferForTextureData() {
177 		return frame_[vulkan_->GetCurFrame()].pushUBO;
178 	}
179 
180 	// Only use Allocate on this one.
GetPushBufferLocal()181 	VulkanPushBuffer *GetPushBufferLocal() {
182 		return frame_[vulkan_->GetCurFrame()].pushLocal;
183 	}
184 
GetStats()185 	const DrawEngineVulkanStats &GetStats() const {
186 		return stats_;
187 	}
188 
189 	void SetLineWidth(float lineWidth);
SetDepalTexture(VkImageView depal)190 	void SetDepalTexture(VkImageView depal) {
191 		if (boundDepal_ != depal) {
192 			boundDepal_ = depal;
193 			gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
194 		}
195 	}
196 
197 private:
198 	struct FrameData;
199 	void ApplyDrawStateLate(VulkanRenderManager *renderManager, bool applyStencilRef, uint8_t stencilRef, bool useBlendConstant);
200 	void ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManager, ShaderManagerVulkan *shaderManager, int prim, VulkanPipelineRasterStateKey &key, VulkanDynamicState &dynState);
201 	void BindShaderBlendTex();
202 	void ResetFramebufferRead();
203 
204 	void InitDeviceObjects();
205 	void DestroyDeviceObjects();
206 
207 	void DecodeVertsToPushBuffer(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf);
208 	VkResult RecreateDescriptorPool(FrameData &frame, int newSize);
209 
210 	void DoFlush();
211 	void UpdateUBOs(FrameData *frame);
212 
213 	VkDescriptorSet GetOrCreateDescriptorSet(VkImageView imageView, VkSampler sampler, VkBuffer base, VkBuffer light, VkBuffer bone, bool tess);
214 
215 	VulkanContext *vulkan_;
216 	Draw::DrawContext *draw_;
217 
218 	// We use a single descriptor set layout for all PSP draws.
219 	VkDescriptorSetLayout descriptorSetLayout_;
220 	VkPipelineLayout pipelineLayout_;
221 	VulkanPipeline *lastPipeline_;
222 	VkDescriptorSet lastDs_ = VK_NULL_HANDLE;
223 
224 	// Secondary texture for shader blending
225 	VkImageView boundSecondary_ = VK_NULL_HANDLE;
226 	VkImageView boundDepal_ = VK_NULL_HANDLE;
227 	VkSampler samplerSecondary_ = VK_NULL_HANDLE;  // This one is actually never used since we use fetch.
228 
229 	PrehashMap<VertexArrayInfoVulkan *, nullptr> vai_;
230 	VulkanPushBuffer *vertexCache_;
231 	int descDecimationCounter_ = 0;
232 
233 	struct DescriptorSetKey {
234 		VkImageView imageView_;
235 		VkImageView secondaryImageView_;
236 		VkImageView depalImageView_;
237 		VkSampler sampler_;
238 		VkBuffer base_, light_, bone_;  // All three UBO slots will be set to this. This will usually be identical
239 		// for all draws in a frame, except when the buffer has to grow.
240 	};
241 
242 	// We alternate between these.
243 	struct FrameData {
FrameDataFrameData244 		FrameData() : descSets(512) {}
245 
246 		VkDescriptorPool descPool = VK_NULL_HANDLE;
247 		int descCount = 0;
248 		int descPoolSize = 256;  // We double this before we allocate so we initialize this to half the size we want.
249 
250 		VulkanPushBuffer *pushUBO = nullptr;
251 		VulkanPushBuffer *pushVertex = nullptr;
252 		VulkanPushBuffer *pushIndex = nullptr;
253 
254 		// Special push buffer in GPU local memory, for texture data conversion and similar tasks.
255 		VulkanPushBuffer *pushLocal;
256 
257 		// We do rolling allocation and reset instead of caching across frames. That we might do later.
258 		DenseHashMap<DescriptorSetKey, VkDescriptorSet, (VkDescriptorSet)VK_NULL_HANDLE> descSets;
259 
260 		void Destroy(VulkanContext *vulkan);
261 	};
262 
263 	GEPrimitiveType lastPrim_ = GE_PRIM_INVALID;
264 	FrameData frame_[VulkanContext::MAX_INFLIGHT_FRAMES];
265 
266 	// Other
267 	ShaderManagerVulkan *shaderManager_ = nullptr;
268 	PipelineManagerVulkan *pipelineManager_ = nullptr;
269 	TextureCacheVulkan *textureCache_ = nullptr;
270 	FramebufferManagerVulkan *framebufferManager_ = nullptr;
271 
272 	// State cache
273 	uint64_t dirtyUniforms_;
274 	uint32_t baseUBOOffset;
275 	uint32_t lightUBOOffset;
276 	uint32_t boneUBOOffset;
277 	VkBuffer baseBuf, lightBuf, boneBuf;
278 	VkImageView imageView = VK_NULL_HANDLE;
279 	VkSampler sampler = VK_NULL_HANDLE;
280 
281 	// For null texture
282 	VkSampler nullSampler_ = VK_NULL_HANDLE;
283 
284 	DrawEngineVulkanStats stats_{};
285 
286 	VulkanPipelineRasterStateKey pipelineKey_{};
287 	VulkanDynamicState dynState_{};
288 
289 	int tessOffset_ = 0;
290 
291 	// Hardware tessellation
292 	TessellationDataTransferVulkan *tessDataTransferVulkan;
293 
294 	int lastRenderStepId_ = -1;
295 };
296