1 // Copyright (c) 2012- 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 <algorithm>
19 
20 #include "Common/MemoryUtil.h"
21 #include "Common/TimeUtil.h"
22 #include "Core/MemMap.h"
23 #include "Core/System.h"
24 #include "Core/Reporting.h"
25 #include "Core/Config.h"
26 #include "Core/CoreTiming.h"
27 
28 #include "Common/GPU/OpenGL/GLDebugLog.h"
29 #include "Common/Profiler/Profiler.h"
30 
31 #include "GPU/Math3D.h"
32 #include "GPU/GPUState.h"
33 #include "GPU/ge_constants.h"
34 
35 #include "GPU/Common/TextureDecoder.h"
36 #include "GPU/Common/SplineCommon.h"
37 #include "GPU/Common/VertexDecoderCommon.h"
38 #include "GPU/Common/SoftwareTransformCommon.h"
39 #include "GPU/Debugger/Debugger.h"
40 #include "GPU/GLES/FragmentTestCacheGLES.h"
41 #include "GPU/GLES/StateMappingGLES.h"
42 #include "GPU/GLES/TextureCacheGLES.h"
43 #include "GPU/GLES/DrawEngineGLES.h"
44 #include "GPU/GLES/ShaderManagerGLES.h"
45 #include "GPU/GLES/GPU_GLES.h"
46 
47 const GLuint glprim[8] = {
48 	GL_POINTS,
49 	GL_LINES,
50 	GL_LINE_STRIP,
51 	GL_TRIANGLES,
52 	GL_TRIANGLE_STRIP,
53 	GL_TRIANGLE_FAN,
54 	GL_TRIANGLES,
55 	// Rectangles need to be expanded into triangles.
56 };
57 
58 enum {
59 	TRANSFORMED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * sizeof(TransformedVertex)
60 };
61 
62 #define VERTEXCACHE_DECIMATION_INTERVAL 17
63 #define VERTEXCACHE_NAME_DECIMATION_INTERVAL 41
64 #define VERTEXCACHE_NAME_DECIMATION_MAX 100
65 #define VERTEXCACHE_NAME_CACHE_SIZE 64
66 #define VERTEXCACHE_NAME_CACHE_FULL_BYTES (1024 * 1024)
67 #define VERTEXCACHE_NAME_CACHE_MAX_AGE 120
68 
69 enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 };
70 
DrawEngineGLES(Draw::DrawContext * draw)71 DrawEngineGLES::DrawEngineGLES(Draw::DrawContext *draw) : vai_(256), inputLayoutMap_(16), draw_(draw) {
72 	render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
73 
74 	decOptions_.expandAllWeightsToFloat = false;
75 	decOptions_.expand8BitNormalsToFloat = false;
76 
77 	decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL;
78 	bufferDecimationCounter_ = VERTEXCACHE_NAME_DECIMATION_INTERVAL;
79 	// Allocate nicely aligned memory. Maybe graphics drivers will
80 	// appreciate it.
81 	// All this is a LOT of memory, need to see if we can cut down somehow.
82 	decoded = (u8 *)AllocateMemoryPages(DECODED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
83 	decIndex = (u16 *)AllocateMemoryPages(DECODED_INDEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
84 
85 	indexGen.Setup(decIndex);
86 
87 	InitDeviceObjects();
88 
89 	tessDataTransferGLES = new TessellationDataTransferGLES(render_);
90 	tessDataTransfer = tessDataTransferGLES;
91 }
92 
~DrawEngineGLES()93 DrawEngineGLES::~DrawEngineGLES() {
94 	DestroyDeviceObjects();
95 	FreeMemoryPages(decoded, DECODED_VERTEX_BUFFER_SIZE);
96 	FreeMemoryPages(decIndex, DECODED_INDEX_BUFFER_SIZE);
97 
98 	delete tessDataTransferGLES;
99 }
100 
DeviceLost()101 void DrawEngineGLES::DeviceLost() {
102 	DestroyDeviceObjects();
103 }
104 
DeviceRestore(Draw::DrawContext * draw)105 void DrawEngineGLES::DeviceRestore(Draw::DrawContext *draw) {
106 	draw_ = draw;
107 	render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
108 	InitDeviceObjects();
109 }
110 
InitDeviceObjects()111 void DrawEngineGLES::InitDeviceObjects() {
112 	_assert_msg_(render_ != nullptr, "Render manager must be set");
113 
114 	for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) {
115 		frameData_[i].pushVertex = render_->CreatePushBuffer(i, GL_ARRAY_BUFFER, 1024 * 1024);
116 		frameData_[i].pushIndex = render_->CreatePushBuffer(i, GL_ELEMENT_ARRAY_BUFFER, 256 * 1024);
117 	}
118 
119 	int vertexSize = sizeof(TransformedVertex);
120 	std::vector<GLRInputLayout::Entry> entries;
121 	entries.push_back({ ATTR_POSITION, 4, GL_FLOAT, GL_FALSE, vertexSize, 0 });
122 	entries.push_back({ ATTR_TEXCOORD, 3, GL_FLOAT, GL_FALSE, vertexSize, offsetof(TransformedVertex, u) });
123 	entries.push_back({ ATTR_COLOR0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, offsetof(TransformedVertex, color0) });
124 	entries.push_back({ ATTR_COLOR1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, offsetof(TransformedVertex, color1) });
125 	softwareInputLayout_ = render_->CreateInputLayout(entries);
126 }
127 
DestroyDeviceObjects()128 void DrawEngineGLES::DestroyDeviceObjects() {
129 	// Beware: this could be called twice in a row, sometimes.
130 	for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) {
131 		if (!frameData_[i].pushVertex && !frameData_[i].pushIndex)
132 			continue;
133 
134 		if (frameData_[i].pushVertex)
135 			render_->DeletePushBuffer(frameData_[i].pushVertex);
136 		if (frameData_[i].pushIndex)
137 			render_->DeletePushBuffer(frameData_[i].pushIndex);
138 		frameData_[i].pushVertex = nullptr;
139 		frameData_[i].pushIndex = nullptr;
140 	}
141 
142 	ClearTrackedVertexArrays();
143 
144 	if (softwareInputLayout_)
145 		render_->DeleteInputLayout(softwareInputLayout_);
146 	softwareInputLayout_ = nullptr;
147 
148 	ClearInputLayoutMap();
149 }
150 
ClearInputLayoutMap()151 void DrawEngineGLES::ClearInputLayoutMap() {
152 	inputLayoutMap_.Iterate([&](const uint32_t &key, GLRInputLayout *il) {
153 		render_->DeleteInputLayout(il);
154 	});
155 	inputLayoutMap_.Clear();
156 }
157 
BeginFrame()158 void DrawEngineGLES::BeginFrame() {
159 	DecimateTrackedVertexArrays();
160 
161 	FrameData &frameData = frameData_[render_->GetCurFrame()];
162 	render_->BeginPushBuffer(frameData.pushIndex);
163 	render_->BeginPushBuffer(frameData.pushVertex);
164 
165 	lastRenderStepId_ = -1;
166 }
167 
EndFrame()168 void DrawEngineGLES::EndFrame() {
169 	FrameData &frameData = frameData_[render_->GetCurFrame()];
170 	render_->EndPushBuffer(frameData.pushIndex);
171 	render_->EndPushBuffer(frameData.pushVertex);
172 	tessDataTransferGLES->EndFrame();
173 }
174 
175 struct GlTypeInfo {
176 	u16 type;
177 	u8 count;
178 	u8 normalized;
179 };
180 
181 static const GlTypeInfo GLComp[] = {
182 	{0}, // 	DEC_NONE,
183 	{GL_FLOAT, 1, GL_FALSE}, // 	DEC_FLOAT_1,
184 	{GL_FLOAT, 2, GL_FALSE}, // 	DEC_FLOAT_2,
185 	{GL_FLOAT, 3, GL_FALSE}, // 	DEC_FLOAT_3,
186 	{GL_FLOAT, 4, GL_FALSE}, // 	DEC_FLOAT_4,
187 	{GL_BYTE, 4, GL_TRUE}, // 	DEC_S8_3,
188 	{GL_SHORT, 4, GL_TRUE},// 	DEC_S16_3,
189 	{GL_UNSIGNED_BYTE, 1, GL_TRUE},// 	DEC_U8_1,
190 	{GL_UNSIGNED_BYTE, 2, GL_TRUE},// 	DEC_U8_2,
191 	{GL_UNSIGNED_BYTE, 3, GL_TRUE},// 	DEC_U8_3,
192 	{GL_UNSIGNED_BYTE, 4, GL_TRUE},// 	DEC_U8_4,
193 	{GL_UNSIGNED_SHORT, 1, GL_TRUE},// 	DEC_U16_1,
194 	{GL_UNSIGNED_SHORT, 2, GL_TRUE},// 	DEC_U16_2,
195 	{GL_UNSIGNED_SHORT, 3, GL_TRUE},// 	DEC_U16_3,
196 	{GL_UNSIGNED_SHORT, 4, GL_TRUE},// 	DEC_U16_4,
197 };
198 
VertexAttribSetup(int attrib,int fmt,int stride,int offset,std::vector<GLRInputLayout::Entry> & entries)199 static inline void VertexAttribSetup(int attrib, int fmt, int stride, int offset, std::vector<GLRInputLayout::Entry> &entries) {
200 	if (fmt) {
201 		const GlTypeInfo &type = GLComp[fmt];
202 		GLRInputLayout::Entry entry;
203 		entry.offset = offset;
204 		entry.location = attrib;
205 		entry.normalized = type.normalized;
206 		entry.type = type.type;
207 		entry.stride = stride;
208 		entry.count = type.count;
209 		entries.push_back(entry);
210 	}
211 }
212 
213 // TODO: Use VBO and get rid of the vertexData pointers - with that, we will supply only offsets
SetupDecFmtForDraw(LinkedShader * program,const DecVtxFormat & decFmt)214 GLRInputLayout *DrawEngineGLES::SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt) {
215 	uint32_t key = decFmt.id;
216 	GLRInputLayout *inputLayout = inputLayoutMap_.Get(key);
217 	if (inputLayout) {
218 		return inputLayout;
219 	}
220 
221 	std::vector<GLRInputLayout::Entry> entries;
222 	VertexAttribSetup(ATTR_W1, decFmt.w0fmt, decFmt.stride, decFmt.w0off, entries);
223 	VertexAttribSetup(ATTR_W2, decFmt.w1fmt, decFmt.stride, decFmt.w1off, entries);
224 	VertexAttribSetup(ATTR_TEXCOORD, decFmt.uvfmt, decFmt.stride, decFmt.uvoff, entries);
225 	VertexAttribSetup(ATTR_COLOR0, decFmt.c0fmt, decFmt.stride, decFmt.c0off, entries);
226 	VertexAttribSetup(ATTR_COLOR1, decFmt.c1fmt, decFmt.stride, decFmt.c1off, entries);
227 	VertexAttribSetup(ATTR_NORMAL, decFmt.nrmfmt, decFmt.stride, decFmt.nrmoff, entries);
228 	VertexAttribSetup(ATTR_POSITION, decFmt.posfmt, decFmt.stride, decFmt.posoff, entries);
229 
230 	inputLayout = render_->CreateInputLayout(entries);
231 	inputLayoutMap_.Insert(key, inputLayout);
232 	return inputLayout;
233 }
234 
DecodeVertsToPushBuffer(GLPushBuffer * push,uint32_t * bindOffset,GLRBuffer ** buf)235 void *DrawEngineGLES::DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindOffset, GLRBuffer **buf) {
236 	u8 *dest = decoded;
237 
238 	// Figure out how much pushbuffer space we need to allocate.
239 	if (push) {
240 		int vertsToDecode = ComputeNumVertsToDecode();
241 		dest = (u8 *)push->Push(vertsToDecode * dec_->GetDecVtxFmt().stride, bindOffset, buf);
242 	}
243 	DecodeVerts(dest);
244 	return dest;
245 }
246 
MarkUnreliable(VertexArrayInfo * vai)247 void DrawEngineGLES::MarkUnreliable(VertexArrayInfo *vai) {
248 	vai->status = VertexArrayInfo::VAI_UNRELIABLE;
249 	if (vai->vbo) {
250 		render_->DeleteBuffer(vai->vbo);
251 		vai->vbo = 0;
252 	}
253 	if (vai->ebo) {
254 		render_->DeleteBuffer(vai->ebo);
255 		vai->ebo = 0;
256 	}
257 }
258 
ClearTrackedVertexArrays()259 void DrawEngineGLES::ClearTrackedVertexArrays() {
260 	vai_.Iterate([&](uint32_t hash, VertexArrayInfo *vai){
261 		FreeVertexArray(vai);
262 		delete vai;
263 	});
264 	vai_.Clear();
265 }
266 
DecimateTrackedVertexArrays()267 void DrawEngineGLES::DecimateTrackedVertexArrays() {
268 	if (--decimationCounter_ <= 0) {
269 		decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL;
270 	} else {
271 		return;
272 	}
273 
274 	const int threshold = gpuStats.numFlips - VAI_KILL_AGE;
275 	const int unreliableThreshold = gpuStats.numFlips - VAI_UNRELIABLE_KILL_AGE;
276 	int unreliableLeft = VAI_UNRELIABLE_KILL_MAX;
277 	vai_.Iterate([&](uint32_t hash, VertexArrayInfo *vai) {
278 		bool kill;
279 		if (vai->status == VertexArrayInfo::VAI_UNRELIABLE) {
280 			// We limit killing unreliable so we don't rehash too often.
281 			kill = vai->lastFrame < unreliableThreshold && --unreliableLeft >= 0;
282 		} else {
283 			kill = vai->lastFrame < threshold;
284 		}
285 		if (kill) {
286 			FreeVertexArray(vai);
287 			delete vai;
288 			vai_.Remove(hash);
289 		}
290 	});
291 	vai_.Maintain();
292 }
293 
FreeVertexArray(VertexArrayInfo * vai)294 void DrawEngineGLES::FreeVertexArray(VertexArrayInfo *vai) {
295 	if (vai->vbo) {
296 		render_->DeleteBuffer(vai->vbo);
297 		vai->vbo = nullptr;
298 	}
299 	if (vai->ebo) {
300 		render_->DeleteBuffer(vai->ebo);
301 		vai->ebo = nullptr;
302 	}
303 }
304 
DoFlush()305 void DrawEngineGLES::DoFlush() {
306 	PROFILE_THIS_SCOPE("flush");
307 
308 	FrameData &frameData = frameData_[render_->GetCurFrame()];
309 
310 	gpuStats.numFlushes++;
311 	gpuStats.numTrackedVertexArrays = (int)vai_.size();
312 
313 	// A new render step means we need to flush any dynamic state. Really, any state that is reset in
314 	// GLQueueRunner::PerformRenderPass.
315 	int curRenderStepId = render_->GetCurrentStepId();
316 	if (lastRenderStepId_ != curRenderStepId) {
317 		// Dirty everything that has dynamic state that will need re-recording.
318 		gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
319 		textureCache_->ForgetLastTexture();
320 		lastRenderStepId_ = curRenderStepId;
321 	}
322 
323 	bool textureNeedsApply = false;
324 	if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) {
325 		textureCache_->SetTexture();
326 		gstate_c.Clean(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
327 		textureNeedsApply = true;
328 	} else if (gstate.getTextureAddress(0) == ((gstate.getFrameBufRawAddress() | 0x04000000) & 0x3FFFFFFF)) {
329 		// This catches the case of clearing a texture. (#10957)
330 		gstate_c.Dirty(DIRTY_TEXTURE_IMAGE);
331 	}
332 
333 	GEPrimitiveType prim = prevPrim_;
334 
335 	VShaderID vsid;
336 	Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat, &vsid);
337 
338 	GLRBuffer *vertexBuffer = nullptr;
339 	GLRBuffer *indexBuffer = nullptr;
340 	uint32_t vertexBufferOffset = 0;
341 	uint32_t indexBufferOffset = 0;
342 
343 	if (vshader->UseHWTransform()) {
344 		int vertexCount = 0;
345 		bool useElements = true;
346 		bool populateCache = false;
347 		VertexArrayInfo *vai = nullptr;
348 
349 		// Cannot cache vertex data with morph enabled.
350 		bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK);
351 		// Also avoid caching when software skinning.
352 		if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK))
353 			useCache = false;
354 
355 		// TEMPORARY
356 		useCache = false;
357 
358 		if (useCache) {
359 			u32 id = dcid_ ^ gstate.getUVGenMode();  // This can have an effect on which UV decoder we need to use! And hence what the decoded data will look like. See #9263
360 			vai = vai_.Get(id);
361 			if (!vai) {
362 				vai = new VertexArrayInfo();
363 				vai_.Insert(id, vai);
364 			}
365 
366 			switch (vai->status) {
367 			case VertexArrayInfo::VAI_NEW:
368 				{
369 					// Haven't seen this one before.
370 					uint64_t dataHash = ComputeHash();
371 					vai->hash = dataHash;
372 					vai->minihash = ComputeMiniHash();
373 					vai->status = VertexArrayInfo::VAI_HASHING;
374 					vai->drawsUntilNextFullHash = 0;
375 					useCache = false;
376 					break;
377 				}
378 
379 				// Hashing - still gaining confidence about the buffer.
380 				// But if we get this far it's likely to be worth creating a vertex buffer.
381 			case VertexArrayInfo::VAI_HASHING:
382 				{
383 					vai->numDraws++;
384 					if (vai->lastFrame != gpuStats.numFlips) {
385 						vai->numFrames++;
386 					}
387 					if (vai->drawsUntilNextFullHash == 0) {
388 						// Let's try to skip a full hash if mini would fail.
389 						const u32 newMiniHash = ComputeMiniHash();
390 						uint64_t newHash = vai->hash;
391 						if (newMiniHash == vai->minihash) {
392 							newHash = ComputeHash();
393 						}
394 						if (newMiniHash != vai->minihash || newHash != vai->hash) {
395 							MarkUnreliable(vai);
396 							useCache = false;
397 							break;
398 						}
399 						if (vai->numVerts > 64) {
400 							// exponential backoff up to 16 draws, then every 32
401 							vai->drawsUntilNextFullHash = std::min(32, vai->numFrames);
402 						} else {
403 							// Lower numbers seem much more likely to change.
404 							vai->drawsUntilNextFullHash = 0;
405 						}
406 						// TODO: tweak
407 						//if (vai->numFrames > 1000) {
408 						//	vai->status = VertexArrayInfo::VAI_RELIABLE;
409 						//}
410 					} else {
411 						vai->drawsUntilNextFullHash--;
412 						u32 newMiniHash = ComputeMiniHash();
413 						if (newMiniHash != vai->minihash) {
414 							MarkUnreliable(vai);
415 							break;
416 						}
417 					}
418 
419 					if (vai->vbo == nullptr) {
420 						_dbg_assert_msg_(gstate_c.vertBounds.minV >= gstate_c.vertBounds.maxV, "Should not have checked UVs when caching.");
421 
422 						// We'll populate the cache this time around, use it next time.
423 						populateCache = true;
424 						useCache = false;
425 					} else {
426 						gpuStats.numCachedDrawCalls++;
427 						useElements = vai->ebo ? true : false;
428 						gpuStats.numCachedVertsDrawn += vai->numVerts;
429 						gstate_c.vertexFullAlpha = vai->flags & VAI_FLAG_VERTEXFULLALPHA;
430 
431 						vertexBuffer = vai->vbo;
432 						indexBuffer = vai->ebo;
433 						vertexCount = vai->numVerts;
434 						prim = static_cast<GEPrimitiveType>(vai->prim);
435 					}
436 					break;
437 				}
438 
439 				// Reliable - we don't even bother hashing anymore. Right now we don't go here until after a very long time.
440 			case VertexArrayInfo::VAI_RELIABLE:
441 				{
442 					vai->numDraws++;
443 					if (vai->lastFrame != gpuStats.numFlips) {
444 						vai->numFrames++;
445 					}
446 					gpuStats.numCachedDrawCalls++;
447 					gpuStats.numCachedVertsDrawn += vai->numVerts;
448 					vertexBuffer = vai->vbo;
449 					indexBuffer = vai->ebo;
450 					vertexCount = vai->numVerts;
451 					prim = static_cast<GEPrimitiveType>(vai->prim);
452 
453 					gstate_c.vertexFullAlpha = vai->flags & VAI_FLAG_VERTEXFULLALPHA;
454 					break;
455 				}
456 
457 			case VertexArrayInfo::VAI_UNRELIABLE:
458 				{
459 					vai->numDraws++;
460 					if (vai->lastFrame != gpuStats.numFlips) {
461 						vai->numFrames++;
462 					}
463 					useCache = false;
464 					break;
465 				}
466 			}
467 
468 			if (useCache) {
469 				vai->lastFrame = gpuStats.numFlips;
470 			}
471 		}
472 
473 		if (!useCache) {
474 			if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) {
475 				// If software skinning, we've already predecoded into "decoded". So push that content.
476 				size_t size = decodedVerts_ * dec_->GetDecVtxFmt().stride;
477 				u8 *dest = (u8 *)frameData.pushVertex->Push(size, &vertexBufferOffset, &vertexBuffer);
478 				memcpy(dest, decoded, size);
479 			} else {
480 				// Decode directly into the pushbuffer
481 				u8 *dest = (u8 *)DecodeVertsToPushBuffer(frameData.pushVertex, &vertexBufferOffset, &vertexBuffer);
482 				if (populateCache) {
483 					size_t size = decodedVerts_ * dec_->GetDecVtxFmt().stride;
484 					vai->vbo = render_->CreateBuffer(GL_ARRAY_BUFFER, size, GL_STATIC_DRAW);
485 					render_->BufferSubdata(vai->vbo, 0, size, dest, false);
486 				}
487 			}
488 
489 			if (populateCache || (vai && vai->status == VertexArrayInfo::VAI_NEW)) {
490 				vai->numVerts = indexGen.VertexCount();
491 				vai->prim = indexGen.Prim();
492 				vai->maxIndex = indexGen.MaxIndex();
493 				vai->flags = gstate_c.vertexFullAlpha ? VAI_FLAG_VERTEXFULLALPHA : 0;
494 			}
495 
496 			gpuStats.numUncachedVertsDrawn += indexGen.VertexCount();
497 			// If there's only been one primitive type, and it's either TRIANGLES, LINES or POINTS,
498 			// there is no need for the index buffer we built. We can then use glDrawArrays instead
499 			// for a very minor speed boost.
500 			useElements = !indexGen.SeenOnlyPurePrims();
501 			vertexCount = indexGen.VertexCount();
502 			if (!useElements && indexGen.PureCount()) {
503 				vertexCount = indexGen.PureCount();
504 			}
505 			prim = indexGen.Prim();
506 		}
507 
508 		VERBOSE_LOG(G3D, "Flush prim %i! %i verts in one go", prim, vertexCount);
509 		bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
510 		if (gstate.isModeThrough()) {
511 			gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && (hasColor || gstate.getMaterialAmbientA() == 255);
512 		} else {
513 			gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && ((hasColor && (gstate.materialupdate & 1)) || gstate.getMaterialAmbientA() == 255) && (!gstate.isLightingEnabled() || gstate.getAmbientA() == 255);
514 		}
515 
516 		if (textureNeedsApply)
517 			textureCache_->ApplyTexture();
518 
519 		// Need to ApplyDrawState after ApplyTexture because depal can launch a render pass and that wrecks the state.
520 		ApplyDrawState(prim);
521 		ApplyDrawStateLate(false, 0);
522 
523 		LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, framebufferManager_->UseBufferedRendering());
524 		GLRInputLayout *inputLayout = SetupDecFmtForDraw(program, dec_->GetDecVtxFmt());
525 		render_->BindVertexBuffer(inputLayout, vertexBuffer, vertexBufferOffset);
526 		if (useElements) {
527 			if (!indexBuffer) {
528 				size_t esz = sizeof(uint16_t) * indexGen.VertexCount();
529 				void *dest = frameData.pushIndex->Push(esz, &indexBufferOffset, &indexBuffer);
530 				memcpy(dest, decIndex, esz);
531 
532 				if (populateCache) {
533 					vai->ebo = render_->CreateBuffer(GL_ELEMENT_ARRAY_BUFFER, esz, GL_STATIC_DRAW);
534 					render_->BufferSubdata(vai->ebo, 0, esz, (uint8_t *)dest, false);
535 				}
536 			}
537 			render_->BindIndexBuffer(indexBuffer);
538 			render_->DrawIndexed(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset);
539 		} else {
540 			render_->Draw(glprim[prim], 0, vertexCount);
541 		}
542 	} else {
543 		DecodeVerts(decoded);
544 		bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
545 		if (gstate.isModeThrough()) {
546 			gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && (hasColor || gstate.getMaterialAmbientA() == 255);
547 		} else {
548 			gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && ((hasColor && (gstate.materialupdate & 1)) || gstate.getMaterialAmbientA() == 255) && (!gstate.isLightingEnabled() || gstate.getAmbientA() == 255);
549 		}
550 
551 		gpuStats.numUncachedVertsDrawn += indexGen.VertexCount();
552 		prim = indexGen.Prim();
553 		// Undo the strip optimization, not supported by the SW code yet.
554 		if (prim == GE_PRIM_TRIANGLE_STRIP)
555 			prim = GE_PRIM_TRIANGLES;
556 
557 		u16 *inds = decIndex;
558 		SoftwareTransformResult result{};
559 		// TODO: Keep this static?  Faster than repopulating?
560 		SoftwareTransformParams params{};
561 		params.decoded = decoded;
562 		params.transformed = transformed;
563 		params.transformedExpanded = transformedExpanded;
564 		params.fbman = framebufferManager_;
565 		params.texCache = textureCache_;
566 		params.allowClear = true;
567 		params.allowSeparateAlphaClear = true;
568 		params.provokeFlatFirst = false;
569 
570 		int maxIndex = indexGen.MaxIndex();
571 		int vertexCount = indexGen.VertexCount();
572 
573 		// TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts.
574 #if defined(MOBILE_DEVICE)
575 		if (vertexCount > 0x10000 / 3)
576 			vertexCount = 0x10000 / 3;
577 #endif
578 
579 		SoftwareTransform swTransform(params);
580 		swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result);
581 		if (result.action == SW_NOT_READY)
582 			swTransform.DetectOffsetTexture(maxIndex);
583 
584 		if (textureNeedsApply)
585 			textureCache_->ApplyTexture();
586 
587 		// Need to ApplyDrawState after ApplyTexture because depal can launch a render pass and that wrecks the state.
588 		ApplyDrawState(prim);
589 
590 		if (result.action == SW_NOT_READY)
591 			swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, maxIndex, &result);
592 		if (result.setSafeSize)
593 			framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);
594 
595 		ApplyDrawStateLate(result.setStencil, result.stencilValue);
596 
597 		shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, framebufferManager_->UseBufferedRendering());
598 
599 		if (result.action == SW_DRAW_PRIMITIVES) {
600 			if (result.drawIndexed) {
601 				vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), &vertexBuffer);
602 				indexBufferOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(uint16_t) * result.drawNumTrans, &indexBuffer);
603 				render_->BindVertexBuffer(softwareInputLayout_, vertexBuffer, vertexBufferOffset);
604 				render_->BindIndexBuffer(indexBuffer);
605 				render_->DrawIndexed(glprim[prim], result.drawNumTrans, GL_UNSIGNED_SHORT, (void *)(intptr_t)indexBufferOffset);
606 			} else {
607 				vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, result.drawNumTrans * sizeof(TransformedVertex), &vertexBuffer);
608 				render_->BindVertexBuffer(softwareInputLayout_, vertexBuffer, vertexBufferOffset);
609 				render_->Draw(glprim[prim], 0, result.drawNumTrans);
610 			}
611 		} else if (result.action == SW_CLEAR) {
612 			u32 clearColor = result.color;
613 			float clearDepth = result.depth;
614 
615 			bool colorMask = gstate.isClearModeColorMask();
616 			bool alphaMask = gstate.isClearModeAlphaMask();
617 			bool depthMask = gstate.isClearModeDepthMask();
618 			if (depthMask) {
619 				framebufferManager_->SetDepthUpdated();
620 			}
621 
622 			GLbitfield target = 0;
623 			// Without this, we will clear RGB when clearing stencil, which breaks games.
624 			uint8_t rgbaMask = (colorMask ? 7 : 0) | (alphaMask ? 8 : 0);
625 			if (colorMask || alphaMask) target |= GL_COLOR_BUFFER_BIT;
626 			if (alphaMask) target |= GL_STENCIL_BUFFER_BIT;
627 			if (depthMask) target |= GL_DEPTH_BUFFER_BIT;
628 
629 			render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask, vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH);
630 			framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
631 
632 			if ((gstate_c.featureFlags & GPU_USE_CLEAR_RAM_HACK) && colorMask && (alphaMask || gstate.FrameBufFormat() == GE_FORMAT_565)) {
633 				int scissorX1 = gstate.getScissorX1();
634 				int scissorY1 = gstate.getScissorY1();
635 				int scissorX2 = gstate.getScissorX2() + 1;
636 				int scissorY2 = gstate.getScissorY2() + 1;
637 				framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor);
638 			}
639 			gstate_c.Dirty(DIRTY_BLEND_STATE);  // Make sure the color mask gets re-applied.
640 		}
641 	}
642 
643 	gpuStats.numDrawCalls += numDrawCalls;
644 	gpuStats.numVertsSubmitted += vertexCountInDrawCalls_;
645 
646 	indexGen.Reset();
647 	decodedVerts_ = 0;
648 	numDrawCalls = 0;
649 	vertexCountInDrawCalls_ = 0;
650 	decodeCounter_ = 0;
651 	dcid_ = 0;
652 	prevPrim_ = GE_PRIM_INVALID;
653 	gstate_c.vertexFullAlpha = true;
654 	framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
655 
656 	// Now seems as good a time as any to reset the min/max coords, which we may examine later.
657 	gstate_c.vertBounds.minU = 512;
658 	gstate_c.vertBounds.minV = 512;
659 	gstate_c.vertBounds.maxU = 0;
660 	gstate_c.vertBounds.maxV = 0;
661 
662 	GPUDebug::NotifyDraw();
663 }
664 
IsCodePtrVertexDecoder(const u8 * ptr) const665 bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const {
666 	return decJitCache_->IsInSpace(ptr);
667 }
668 
SupportsHWTessellation() const669 bool DrawEngineGLES::SupportsHWTessellation() const {
670 	bool hasTexelFetch = gl_extensions.GLES3 || (!gl_extensions.IsGLES && gl_extensions.VersionGEThan(3, 3, 0)) || gl_extensions.EXT_gpu_shader4;
671 	return hasTexelFetch && gstate_c.SupportsAll(GPU_SUPPORTS_VERTEX_TEXTURE_FETCH | GPU_SUPPORTS_TEXTURE_FLOAT | GPU_SUPPORTS_INSTANCE_RENDERING);
672 }
673 
UpdateUseHWTessellation(bool enable)674 bool DrawEngineGLES::UpdateUseHWTessellation(bool enable) {
675 	return enable && SupportsHWTessellation();
676 }
677 
SendDataToShader(const SimpleVertex * const * points,int size_u,int size_v,u32 vertType,const Spline::Weight2D & weights)678 void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) {
679 	bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
680 	bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0;
681 
682 	int size = size_u * size_v;
683 	float *pos = new float[size * 4];
684 	float *tex = hasTexCoord ? new float[size * 4] : nullptr;
685 	float *col = hasColor ? new float[size * 4] : nullptr;
686 	int stride = 4;
687 
688 	CopyControlPoints(pos, tex, col, stride, stride, stride, points, size, vertType);
689 	// Removed the 1D texture support, it's unlikely to be relevant for performance.
690 	// Control Points
691 	if (prevSizeU < size_u || prevSizeV < size_v) {
692 		prevSizeU = size_u;
693 		prevSizeV = size_v;
694 		if (!data_tex[0])
695 			data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D, size_u * 3, size_v, 1);
696 		renderManager_->TextureImage(data_tex[0], 0, size_u * 3, size_v, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
697 		renderManager_->FinalizeTexture(data_tex[0], 0, false);
698 	}
699 	renderManager_->BindTexture(TEX_SLOT_SPLINE_POINTS, data_tex[0]);
700 	// Position
701 	renderManager_->TextureSubImage(data_tex[0], 0, 0, 0, size_u, size_v, Draw::DataFormat::R32G32B32A32_FLOAT, (u8 *)pos, GLRAllocType::NEW);
702 	// Texcoord
703 	if (hasTexCoord)
704 		renderManager_->TextureSubImage(data_tex[0], 0, size_u, 0, size_u, size_v, Draw::DataFormat::R32G32B32A32_FLOAT, (u8 *)tex, GLRAllocType::NEW);
705 	// Color
706 	if (hasColor)
707 		renderManager_->TextureSubImage(data_tex[0], 0, size_u * 2, 0, size_u, size_v, Draw::DataFormat::R32G32B32A32_FLOAT, (u8 *)col, GLRAllocType::NEW);
708 
709 	// Weight U
710 	if (prevSizeWU < weights.size_u) {
711 		prevSizeWU = weights.size_u;
712 		if (!data_tex[1])
713 			data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_u * 2, 1, 1);
714 		renderManager_->TextureImage(data_tex[1], 0, weights.size_u * 2, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
715 		renderManager_->FinalizeTexture(data_tex[1], 0, false);
716 	}
717 	renderManager_->BindTexture(TEX_SLOT_SPLINE_WEIGHTS_U, data_tex[1]);
718 	renderManager_->TextureSubImage(data_tex[1], 0, 0, 0, weights.size_u * 2, 1, Draw::DataFormat::R32G32B32A32_FLOAT, (u8 *)weights.u, GLRAllocType::NONE);
719 
720 	// Weight V
721 	if (prevSizeWV < weights.size_v) {
722 		prevSizeWV = weights.size_v;
723 		if (!data_tex[2])
724 			data_tex[2] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_v * 2, 1, 1);
725 		renderManager_->TextureImage(data_tex[2], 0, weights.size_v * 2, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
726 		renderManager_->FinalizeTexture(data_tex[2], 0, false);
727 	}
728 	renderManager_->BindTexture(TEX_SLOT_SPLINE_WEIGHTS_V, data_tex[2]);
729 	renderManager_->TextureSubImage(data_tex[2], 0, 0, 0, weights.size_v * 2, 1, Draw::DataFormat::R32G32B32A32_FLOAT, (u8 *)weights.v, GLRAllocType::NONE);
730 }
731 
EndFrame()732 void TessellationDataTransferGLES::EndFrame() {
733 	for (int i = 0; i < 3; i++) {
734 		if (data_tex[i]) {
735 			renderManager_->DeleteTexture(data_tex[i]);
736 			data_tex[i] = nullptr;
737 		}
738 	}
739 	prevSizeU = prevSizeV = prevSizeWU = prevSizeWV = 0;
740 }
741