1 #include <cstdio>
2 #include <vector>
3 #include <string>
4 #include <algorithm>
5 #include <map>
6 
7 #include "ppsspp_config.h"
8 
9 #include "Common/Data/Convert/ColorConv.h"
10 #include "Common/Data/Convert/SmallDataConvert.h"
11 #include "Common/Math/math_util.h"
12 #include "Common/Math/lin/matrix4x4.h"
13 #include "Common/GPU/thin3d.h"
14 #include "Common/GPU/Shader.h"
15 #include "Common/GPU/OpenGL/DataFormatGL.h"
16 #include "Common/GPU/OpenGL/GLCommon.h"
17 #include "Common/GPU/OpenGL/GLDebugLog.h"
18 #include "Common/GPU/OpenGL/GLFeatures.h"
19 
20 #include "Common/GPU/OpenGL/GLRenderManager.h"
21 
22 // #define DEBUG_READ_PIXELS 1
23 
24 namespace Draw {
25 
26 static const unsigned short compToGL[] = {
27 	GL_NEVER,
28 	GL_LESS,
29 	GL_EQUAL,
30 	GL_LEQUAL,
31 	GL_GREATER,
32 	GL_NOTEQUAL,
33 	GL_GEQUAL,
34 	GL_ALWAYS
35 };
36 
37 static const unsigned short blendEqToGL[] = {
38 	GL_FUNC_ADD,
39 	GL_FUNC_SUBTRACT,
40 	GL_FUNC_REVERSE_SUBTRACT,
41 	GL_MIN,
42 	GL_MAX,
43 };
44 
45 static const unsigned short blendFactorToGL[] = {
46 	GL_ZERO,
47 	GL_ONE,
48 	GL_SRC_COLOR,
49 	GL_ONE_MINUS_SRC_COLOR,
50 	GL_DST_COLOR,
51 	GL_ONE_MINUS_DST_COLOR,
52 	GL_SRC_ALPHA,
53 	GL_ONE_MINUS_SRC_ALPHA,
54 	GL_DST_ALPHA,
55 	GL_ONE_MINUS_DST_ALPHA,
56 	GL_CONSTANT_COLOR,
57 	GL_ONE_MINUS_CONSTANT_COLOR,
58 	GL_CONSTANT_ALPHA,
59 	GL_ONE_MINUS_CONSTANT_ALPHA,
60 #if !defined(USING_GLES2)   // TODO: Remove when we have better headers
61 	GL_SRC1_COLOR,
62 	GL_ONE_MINUS_SRC1_COLOR,
63 	GL_SRC1_ALPHA,
64 	GL_ONE_MINUS_SRC1_ALPHA,
65 #elif !PPSSPP_PLATFORM(IOS)
66 	GL_SRC1_COLOR_EXT,
67 	GL_ONE_MINUS_SRC1_COLOR_EXT,
68 	GL_SRC1_ALPHA_EXT,
69 	GL_ONE_MINUS_SRC1_ALPHA_EXT,
70 #else
71 	GL_INVALID_ENUM,
72 	GL_INVALID_ENUM,
73 	GL_INVALID_ENUM,
74 	GL_INVALID_ENUM,
75 #endif
76 };
77 
78 static const unsigned short texWrapToGL[] = {
79 	GL_REPEAT,
80 	GL_MIRRORED_REPEAT,
81 	GL_CLAMP_TO_EDGE,
82 #if !defined(USING_GLES2)
83 	GL_CLAMP_TO_BORDER,
84 #else
85 	GL_CLAMP_TO_EDGE,
86 #endif
87 };
88 
89 static const unsigned short texFilterToGL[] = {
90 	GL_NEAREST,
91 	GL_LINEAR,
92 };
93 
94 static const unsigned short texMipFilterToGL[2][2] = {
95 	// Min nearest:
96 	{ GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR },
97 	// Min linear:
98 	{ GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR },
99 };
100 
101 #ifndef USING_GLES2
102 static const unsigned short logicOpToGL[] = {
103 	GL_CLEAR,
104 	GL_SET,
105 	GL_COPY,
106 	GL_COPY_INVERTED,
107 	GL_NOOP,
108 	GL_INVERT,
109 	GL_AND,
110 	GL_NAND,
111 	GL_OR,
112 	GL_NOR,
113 	GL_XOR,
114 	GL_EQUIV,
115 	GL_AND_REVERSE,
116 	GL_AND_INVERTED,
117 	GL_OR_REVERSE,
118 	GL_OR_INVERTED,
119 };
120 #endif
121 
122 static const GLuint stencilOpToGL[8] = {
123 	GL_KEEP,
124 	GL_ZERO,
125 	GL_REPLACE,
126 	GL_INCR,
127 	GL_DECR,
128 	GL_INVERT,
129 	GL_INCR_WRAP,
130 	GL_DECR_WRAP,
131 };
132 
133 static const unsigned short primToGL[] = {
134 	GL_POINTS,
135 	GL_LINES,
136 	GL_LINE_STRIP,
137 	GL_TRIANGLES,
138 	GL_TRIANGLE_STRIP,
139 	GL_TRIANGLE_FAN,
140 };
141 
142 class OpenGLBuffer;
143 
144 class OpenGLBlendState : public BlendState {
145 public:
146 	bool enabled;
147 	GLuint eqCol, eqAlpha;
148 	GLuint srcCol, srcAlpha, dstCol, dstAlpha;
149 	int colorMask;
150 	// uint32_t fixedColor;
151 
Apply(GLRenderManager * render)152 	void Apply(GLRenderManager *render) {
153 		render->SetBlendAndMask(colorMask, enabled, srcCol, dstCol, srcAlpha, dstAlpha, eqCol, eqAlpha);
154 	}
155 };
156 
157 class OpenGLSamplerState : public SamplerState {
158 public:
159 	GLint wrapU;
160 	GLint wrapV;
161 	GLint wrapW;
162 	GLint magFilt;
163 	GLint minFilt;
164 	GLint mipMinFilt;
165 };
166 
167 class OpenGLDepthStencilState : public DepthStencilState {
168 public:
169 	bool depthTestEnabled;
170 	bool depthWriteEnabled;
171 	GLuint depthComp;
172 	// TODO: Two-sided. Although in practice, do we care?
173 	bool stencilEnabled;
174 	GLuint stencilFail;
175 	GLuint stencilZFail;
176 	GLuint stencilPass;
177 	GLuint stencilCompareOp;
178 	uint8_t stencilCompareMask;
179 	uint8_t stencilWriteMask;
180 
Apply(GLRenderManager * render,uint8_t stencilRef)181 	void Apply(GLRenderManager *render, uint8_t stencilRef) {
182 		render->SetDepth(depthTestEnabled, depthWriteEnabled, depthComp);
183 		render->SetStencilFunc(stencilEnabled, stencilCompareOp, stencilRef, stencilCompareMask);
184 		render->SetStencilOp(stencilWriteMask, stencilFail, stencilZFail, stencilPass);
185 	}
186 };
187 
188 class OpenGLRasterState : public RasterState {
189 public:
Apply(GLRenderManager * render)190 	void Apply(GLRenderManager *render) {
191 		render->SetRaster(cullEnable, frontFace, cullMode, GL_FALSE, GL_FALSE);
192 	}
193 
194 	GLboolean cullEnable;
195 	GLenum cullMode;
196 	GLenum frontFace;
197 };
198 
ShaderStageToOpenGL(ShaderStage stage)199 GLuint ShaderStageToOpenGL(ShaderStage stage) {
200 	switch (stage) {
201 	case ShaderStage::Vertex: return GL_VERTEX_SHADER;
202 #ifndef USING_GLES2
203 	case ShaderStage::Compute: return GL_COMPUTE_SHADER;
204 	case ShaderStage::Geometry: return GL_GEOMETRY_SHADER;
205 #endif
206 	case ShaderStage::Fragment:
207 	default:
208 		return GL_FRAGMENT_SHADER;
209 	}
210 }
211 
212 class OpenGLShaderModule : public ShaderModule {
213 public:
OpenGLShaderModule(GLRenderManager * render,ShaderStage stage,const std::string & tag)214 	OpenGLShaderModule(GLRenderManager *render, ShaderStage stage, const std::string &tag) : render_(render), stage_(stage), tag_(tag) {
215 		DEBUG_LOG(G3D, "Shader module created (%p)", this);
216 		glstage_ = ShaderStageToOpenGL(stage);
217 	}
218 
~OpenGLShaderModule()219 	~OpenGLShaderModule() {
220 		if (shader_)
221 			render_->DeleteShader(shader_);
222 	}
223 
224 	bool Compile(GLRenderManager *render, ShaderLanguage language, const uint8_t *data, size_t dataSize);
GetShader() const225 	GLRShader *GetShader() const {
226 		return shader_;
227 	}
GetSource() const228 	const std::string &GetSource() const { return source_; }
229 
GetLanguage()230 	ShaderLanguage GetLanguage() {
231 		return language_;
232 	}
GetStage() const233 	ShaderStage GetStage() const override {
234 		return stage_;
235 	}
236 
237 private:
238 	GLRenderManager *render_;
239 	ShaderStage stage_;
240 	ShaderLanguage language_ = GLSL_1xx;
241 	GLRShader *shader_ = nullptr;
242 	GLuint glstage_ = 0;
243 	std::string source_;  // So we can recompile in case of context loss.
244 	std::string tag_;
245 };
246 
Compile(GLRenderManager * render,ShaderLanguage language,const uint8_t * data,size_t dataSize)247 bool OpenGLShaderModule::Compile(GLRenderManager *render, ShaderLanguage language, const uint8_t *data, size_t dataSize) {
248 	source_ = std::string((const char *)data);
249 	// Add the prelude on automatically.
250 	if (glstage_ == GL_FRAGMENT_SHADER || glstage_ == GL_VERTEX_SHADER) {
251 		if (source_.find("#version") == source_.npos) {
252 			source_ = ApplyGLSLPrelude(source_, glstage_);
253 		}
254 	}
255 
256 	shader_ = render->CreateShader(glstage_, source_, tag_);
257 	return true;
258 }
259 
260 class OpenGLInputLayout : public InputLayout {
261 public:
OpenGLInputLayout(GLRenderManager * render)262 	OpenGLInputLayout(GLRenderManager *render) : render_(render) {}
263 	~OpenGLInputLayout();
264 
265 	void Compile(const InputLayoutDesc &desc);
RequiresBuffer()266 	bool RequiresBuffer() {
267 		return false;
268 	}
269 
270 	GLRInputLayout *inputLayout_ = nullptr;
271 	int stride = 0;
272 private:
273 	GLRenderManager *render_;
274 };
275 
276 class OpenGLPipeline : public Pipeline {
277 public:
OpenGLPipeline(GLRenderManager * render)278 	OpenGLPipeline(GLRenderManager *render) : render_(render) {
279 	}
~OpenGLPipeline()280 	~OpenGLPipeline() {
281 		for (auto &iter : shaders) {
282 			iter->Release();
283 		}
284 		if (program_) render_->DeleteProgram(program_);
285 	}
286 
287 	bool LinkShaders();
288 
RequiresBuffer()289 	bool RequiresBuffer() override {
290 		return inputLayout && inputLayout->RequiresBuffer();
291 	}
292 
293 	GLuint prim = 0;
294 	std::vector<OpenGLShaderModule *> shaders;
295 	AutoRef<OpenGLInputLayout> inputLayout;
296 	AutoRef<OpenGLDepthStencilState> depthStencil;
297 	AutoRef<OpenGLBlendState> blend;
298 	AutoRef<OpenGLRasterState> raster;
299 
300 	// TODO: Optimize by getting the locations first and putting in a custom struct
301 	UniformBufferDesc dynamicUniforms;
302 	GLint samplerLocs_[MAX_TEXTURE_SLOTS]{};
303 	std::vector<GLint> dynamicUniformLocs_;
304 	GLRProgram *program_ = nullptr;
305 
306 private:
307 	GLRenderManager *render_;
308 };
309 
310 class OpenGLFramebuffer;
311 class OpenGLTexture;
312 
313 class OpenGLContext : public DrawContext {
314 public:
315 	OpenGLContext();
316 	virtual ~OpenGLContext();
317 
SetTargetSize(int w,int h)318 	void SetTargetSize(int w, int h) override {
319 		DrawContext::SetTargetSize(w, h);
320 		renderManager_.Resize(w, h);
321 	}
322 
GetDeviceCaps() const323 	const DeviceCaps &GetDeviceCaps() const override {
324 		return caps_;
325 	}
GetSupportedShaderLanguages() const326 	uint32_t GetSupportedShaderLanguages() const override {
327 		if (gl_extensions.GLES3) {
328 			return (uint32_t)(ShaderLanguage::GLSL_3xx | ShaderLanguage::GLSL_1xx);
329 		} else {
330 			return (uint32_t)ShaderLanguage::GLSL_1xx;
331 		}
332 	}
333 
334 	uint32_t GetDataFormatSupport(DataFormat fmt) const override;
335 
SetErrorCallback(ErrorCallbackFn callback,void * userdata)336 	void SetErrorCallback(ErrorCallbackFn callback, void *userdata) override {
337 		renderManager_.SetErrorCallback(callback, userdata);
338 	}
339 
340 	DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) override;
341 	BlendState *CreateBlendState(const BlendStateDesc &desc) override;
342 	SamplerState *CreateSamplerState(const SamplerStateDesc &desc) override;
343 	RasterState *CreateRasterState(const RasterStateDesc &desc) override;
344 	Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc) override;
345 	InputLayout *CreateInputLayout(const InputLayoutDesc &desc) override;
346 	ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const std::string &tag) override;
347 
348 	Texture *CreateTexture(const TextureDesc &desc) override;
349 	Buffer *CreateBuffer(size_t size, uint32_t usageFlags) override;
350 	Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) override;
351 
352 	void BeginFrame() override;
353 	void EndFrame() override;
354 
355 	void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override;
356 
357 	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;
358 	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;
359 	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;
360 
361 	// These functions should be self explanatory.
362 	void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override;
GetCurrentRenderTarget()363 	Framebuffer *GetCurrentRenderTarget() override {
364 		return curRenderTarget_;
365 	}
366 	void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override;
367 
368 	void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
369 
BindSamplerStates(int start,int count,SamplerState ** states)370 	void BindSamplerStates(int start, int count, SamplerState **states) override {
371 		_assert_(start + count <= MAX_TEXTURE_SLOTS);
372 		for (int i = 0; i < count; i++) {
373 			int index = i + start;
374 			boundSamplers_[index] = static_cast<OpenGLSamplerState *>(states[i]);
375 		}
376 	}
377 
SetScissorRect(int left,int top,int width,int height)378 	void SetScissorRect(int left, int top, int width, int height) override {
379 		renderManager_.SetScissor({ left, top, width, height });
380 	}
381 
SetViewports(int count,Viewport * viewports)382 	void SetViewports(int count, Viewport *viewports) override {
383 		// Same structure, different name.
384 		renderManager_.SetViewport((GLRViewport &)*viewports);
385 	}
386 
SetBlendFactor(float color[4])387 	void SetBlendFactor(float color[4]) override {
388 		renderManager_.SetBlendFactor(color);
389 	}
390 
SetStencilRef(uint8_t ref)391 	void SetStencilRef(uint8_t ref) override {
392 		stencilRef_ = ref;
393 		renderManager_.SetStencilFunc(
394 			curPipeline_->depthStencil->stencilEnabled,
395 			curPipeline_->depthStencil->stencilCompareOp,
396 			ref,
397 			curPipeline_->depthStencil->stencilCompareMask);
398 	}
399 
400 	void BindTextures(int start, int count, Texture **textures) override;
401 	void BindPipeline(Pipeline *pipeline) override;
BindVertexBuffers(int start,int count,Buffer ** buffers,const int * offsets)402 	void BindVertexBuffers(int start, int count, Buffer **buffers, const int *offsets) override {
403 		_assert_(start + count <= ARRAY_SIZE(curVBuffers_));
404 		for (int i = 0; i < count; i++) {
405 			curVBuffers_[i + start] = (OpenGLBuffer *)buffers[i];
406 			curVBufferOffsets_[i + start] = offsets ? offsets[i] : 0;
407 		}
408 	}
BindIndexBuffer(Buffer * indexBuffer,int offset)409 	void BindIndexBuffer(Buffer *indexBuffer, int offset) override {
410 		curIBuffer_ = (OpenGLBuffer  *)indexBuffer;
411 		curIBufferOffset_ = offset;
412 	}
413 
414 	void UpdateDynamicUniformBuffer(const void *ub, size_t size) override;
415 
416 	// TODO: Add more sophisticated draws.
417 	void Draw(int vertexCount, int offset) override;
418 	void DrawIndexed(int vertexCount, int offset) override;
419 	void DrawUP(const void *vdata, int vertexCount) override;
420 
421 	void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
422 
GetInfoString(InfoField info) const423 	std::string GetInfoString(InfoField info) const override {
424 		// TODO: Make these actually query the right information
425 		switch (info) {
426 			case APINAME:
427 				if (gl_extensions.IsGLES) {
428 					return "OpenGL ES";
429 				} else {
430 					return "OpenGL";
431 				}
432 			case VENDORSTRING: return renderManager_.GetGLString(GL_VENDOR);
433 			case VENDOR:
434 				switch (caps_.vendor) {
435 				case GPUVendor::VENDOR_AMD: return "VENDOR_AMD";
436 				case GPUVendor::VENDOR_IMGTEC: return "VENDOR_POWERVR";
437 				case GPUVendor::VENDOR_NVIDIA: return "VENDOR_NVIDIA";
438 				case GPUVendor::VENDOR_INTEL: return "VENDOR_INTEL";
439 				case GPUVendor::VENDOR_QUALCOMM: return "VENDOR_ADRENO";
440 				case GPUVendor::VENDOR_ARM: return "VENDOR_ARM";
441 				case GPUVendor::VENDOR_BROADCOM: return "VENDOR_BROADCOM";
442 				case GPUVendor::VENDOR_VIVANTE: return "VENDOR_VIVANTE";
443 				case GPUVendor::VENDOR_APPLE: return "VENDOR_APPLE";
444 				case GPUVendor::VENDOR_UNKNOWN:
445 				default:
446 					return "VENDOR_UNKNOWN";
447 				}
448 				break;
449 			case DRIVER: return renderManager_.GetGLString(GL_RENDERER);
450 			case SHADELANGVERSION: return renderManager_.GetGLString(GL_SHADING_LANGUAGE_VERSION);
451 			case APIVERSION: return renderManager_.GetGLString(GL_VERSION);
452 			default: return "?";
453 		}
454 	}
455 
GetNativeObject(NativeObject obj)456 	uint64_t GetNativeObject(NativeObject obj) override {
457 		switch (obj) {
458 		case NativeObject::RENDER_MANAGER:
459 			return (uint64_t)(uintptr_t)&renderManager_;
460 		default:
461 			return 0;
462 		}
463 	}
464 
HandleEvent(Event ev,int width,int height,void * param1,void * param2)465 	void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override {}
466 
GetCurrentStepId() const467 	int GetCurrentStepId() const override {
468 		return renderManager_.GetCurrentStepId();
469 	}
470 
471 	void InvalidateCachedState() override;
472 
473 private:
474 	void ApplySamplers();
475 
476 	GLRenderManager renderManager_;
477 
478 	DeviceCaps caps_{};
479 
480 	// Bound state
481 	AutoRef<OpenGLSamplerState> boundSamplers_[MAX_TEXTURE_SLOTS];
482 	// Point to GLRTexture directly because they can point to the textures
483 	// in framebuffers too (which also can be bound).
484 	const GLRTexture *boundTextures_[MAX_TEXTURE_SLOTS]{};
485 
486 	AutoRef<OpenGLPipeline> curPipeline_;
487 	AutoRef<OpenGLBuffer> curVBuffers_[4]{};
488 	int curVBufferOffsets_[4]{};
489 	AutoRef<OpenGLBuffer> curIBuffer_;
490 	int curIBufferOffset_ = 0;
491 	AutoRef<Framebuffer> curRenderTarget_;
492 
493 	uint8_t stencilRef_ = 0;
494 
495 	// Frames in flight is not such a strict concept as with Vulkan until we start using glBufferStorage and fences.
496 	// But might as well have the structure ready, and can't hurt to rotate buffers.
497 	struct FrameData {
498 		GLPushBuffer *push;
499 	};
500 	FrameData frameData_[GLRenderManager::MAX_INFLIGHT_FRAMES]{};
501 };
502 
MakeIntelSimpleVer(int v1,int v2,int v3)503 static constexpr int MakeIntelSimpleVer(int v1, int v2, int v3) {
504 	return (v1 << 16) | (v2 << 8) | v3;
505 }
506 
HasIntelDualSrcBug(int versions[4])507 static bool HasIntelDualSrcBug(int versions[4]) {
508 	// Intel uses a confusing set of at least 3 version numbering schemes.  This is the one given to OpenGL.
509 	switch (MakeIntelSimpleVer(versions[0], versions[1], versions[2])) {
510 	case MakeIntelSimpleVer(9, 17, 10):
511 	case MakeIntelSimpleVer(9, 18, 10):
512 		return false;
513 	case MakeIntelSimpleVer(10, 18, 10):
514 		return versions[3] < 4061;
515 	case MakeIntelSimpleVer(10, 18, 14):
516 		return versions[3] < 4080;
517 	default:
518 		// Older than above didn't support dual src anyway, newer should have the fix.
519 		return false;
520 	}
521 }
522 
OpenGLContext()523 OpenGLContext::OpenGLContext() {
524 	// TODO: Detect more caps
525 	if (gl_extensions.IsGLES) {
526 		if (gl_extensions.OES_packed_depth_stencil || gl_extensions.OES_depth24) {
527 			caps_.preferredDepthBufferFormat = DataFormat::D24_S8;
528 		} else {
529 			caps_.preferredDepthBufferFormat = DataFormat::D16;
530 		}
531 	} else {
532 		caps_.preferredDepthBufferFormat = DataFormat::D24_S8;
533 	}
534 	caps_.framebufferBlitSupported = gl_extensions.NV_framebuffer_blit || gl_extensions.ARB_framebuffer_object;
535 	caps_.framebufferDepthBlitSupported = caps_.framebufferBlitSupported;
536 	caps_.depthClampSupported = gl_extensions.ARB_depth_clamp;
537 
538 	// Interesting potential hack for emulating GL_DEPTH_CLAMP (use a separate varying, force depth in fragment shader):
539 	// This will induce a performance penalty on many architectures though so a blanket enable of this
540 	// is probably not a good idea.
541 	// https://stackoverflow.com/questions/5960757/how-to-emulate-gl-depth-clamp-nv
542 
543 	switch (gl_extensions.gpuVendor) {
544 	case GPU_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break;
545 	case GPU_VENDOR_NVIDIA: caps_.vendor = GPUVendor::VENDOR_NVIDIA; break;
546 	case GPU_VENDOR_ARM: caps_.vendor = GPUVendor::VENDOR_ARM; break;
547 	case GPU_VENDOR_QUALCOMM: caps_.vendor = GPUVendor::VENDOR_QUALCOMM; break;
548 	case GPU_VENDOR_BROADCOM: caps_.vendor = GPUVendor::VENDOR_BROADCOM; break;
549 	case GPU_VENDOR_INTEL: caps_.vendor = GPUVendor::VENDOR_INTEL; break;
550 	case GPU_VENDOR_IMGTEC: caps_.vendor = GPUVendor::VENDOR_IMGTEC; break;
551 	case GPU_VENDOR_VIVANTE: caps_.vendor = GPUVendor::VENDOR_VIVANTE; break;
552 	case GPU_VENDOR_APPLE: caps_.vendor = GPUVendor::VENDOR_APPLE; break;
553 	case GPU_VENDOR_UNKNOWN:
554 	default:
555 		caps_.vendor = GPUVendor::VENDOR_UNKNOWN;
556 		break;
557 	}
558 	for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) {
559 		frameData_[i].push = renderManager_.CreatePushBuffer(i, GL_ARRAY_BUFFER, 64 * 1024);
560 	}
561 
562 	if (!gl_extensions.VersionGEThan(3, 0, 0)) {
563 		// Don't use this extension on sub 3.0 OpenGL versions as it does not seem reliable.
564 		bugs_.Infest(Bugs::DUAL_SOURCE_BLENDING_BROKEN);
565 	} else if (caps_.vendor == GPUVendor::VENDOR_INTEL) {
566 		// Note: this is for Intel drivers with GL3+.
567 		// Also on Intel, see https://github.com/hrydgard/ppsspp/issues/10117
568 		// TODO: Remove entirely sometime reasonably far in driver years after 2015.
569 		const std::string ver = GetInfoString(Draw::InfoField::APIVERSION);
570 		int versions[4]{};
571 		if (sscanf(ver.c_str(), "Build %d.%d.%d.%d", &versions[0], &versions[1], &versions[2], &versions[3]) == 4) {
572 			if (HasIntelDualSrcBug(versions)) {
573 				bugs_.Infest(Bugs::DUAL_SOURCE_BLENDING_BROKEN);
574 			}
575 		}
576 	}
577 
578 	// Try to detect old Tegra chips by checking for sub 3.0 GL versions. Like Vivante and Broadcom,
579 	// those can't handle NaN values in conditionals.
580 	if (caps_.vendor == GPUVendor::VENDOR_VIVANTE ||
581 		caps_.vendor == GPUVendor::VENDOR_BROADCOM ||
582 		(caps_.vendor == GPUVendor::VENDOR_NVIDIA && !gl_extensions.VersionGEThan(3, 0, 0))) {
583 		bugs_.Infest(Bugs::BROKEN_NAN_IN_CONDITIONAL);
584 	}
585 
586 	// TODO: Make this check more lenient. Disabled for all right now
587 	// because it murders performance on Mali.
588 	if (caps_.vendor != GPUVendor::VENDOR_NVIDIA) {
589 		bugs_.Infest(Bugs::ANY_MAP_BUFFER_RANGE_SLOW);
590 	}
591 
592 	if (caps_.vendor == GPUVendor::VENDOR_IMGTEC) {
593 		// See https://github.com/hrydgard/ppsspp/commit/8974cd675e538f4445955e3eac572a9347d84232
594 		// TODO: Should this workaround be removed for newer devices/drivers?
595 		bugs_.Infest(Bugs::PVR_GENMIPMAP_HEIGHT_GREATER);
596 	}
597 
598 #if PPSSPP_PLATFORM(IOS)
599 	// For some reason, this bug does not appear on M1.
600 	if (caps_.vendor == GPUVendor::VENDOR_APPLE) {
601 		bugs_.Infest(Bugs::BROKEN_FLAT_IN_SHADER);
602 	}
603 #endif
604 
605 	shaderLanguageDesc_.Init(GLSL_1xx);
606 
607 	shaderLanguageDesc_.glslVersionNumber = gl_extensions.GLSLVersion();
608 
609 	snprintf(shaderLanguageDesc_.driverInfo, sizeof(shaderLanguageDesc_.driverInfo),
610 		"%s - GLSL %d", gl_extensions.model, gl_extensions.GLSLVersion());
611 	// Detect shader language features.
612 	if (gl_extensions.IsGLES) {
613 		shaderLanguageDesc_.gles = true;
614 		if (gl_extensions.GLES3) {
615 			shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_3xx;
616 			shaderLanguageDesc_.fragColor0 = "fragColor0";
617 			shaderLanguageDesc_.texture = "texture";
618 			shaderLanguageDesc_.glslES30 = true;
619 			shaderLanguageDesc_.bitwiseOps = true;
620 			shaderLanguageDesc_.texelFetch = "texelFetch";
621 			shaderLanguageDesc_.varying_vs = "out";
622 			shaderLanguageDesc_.varying_fs = "in";
623 			shaderLanguageDesc_.attribute = "in";
624 		} else {
625 			shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx;
626 			if (gl_extensions.EXT_gpu_shader4) {
627 				shaderLanguageDesc_.bitwiseOps = true;
628 				shaderLanguageDesc_.texelFetch = "texelFetch2D";
629 			}
630 			if (gl_extensions.EXT_blend_func_extended) {
631 				// Oldy moldy GLES, so use the fixed output name.
632 				shaderLanguageDesc_.fragColor1 = "gl_SecondaryFragColorEXT";
633 			}
634 		}
635 	} else {
636 		// I don't know why we were checking for IsCoreContext here before.
637 		if (gl_extensions.VersionGEThan(3, 3, 0)) {
638 			shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_3xx;
639 			shaderLanguageDesc_.fragColor0 = "fragColor0";
640 			shaderLanguageDesc_.texture = "texture";
641 			shaderLanguageDesc_.glslES30 = true;
642 			shaderLanguageDesc_.bitwiseOps = true;
643 			shaderLanguageDesc_.texelFetch = "texelFetch";
644 			shaderLanguageDesc_.varying_vs = "out";
645 			shaderLanguageDesc_.varying_fs = "in";
646 			shaderLanguageDesc_.attribute = "in";
647 		} else if (gl_extensions.VersionGEThan(3, 0, 0)) {
648 			shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx;
649 			shaderLanguageDesc_.fragColor0 = "fragColor0";
650 			shaderLanguageDesc_.texture = "texture";
651 			shaderLanguageDesc_.bitwiseOps = true;
652 			shaderLanguageDesc_.texelFetch = "texelFetch";
653 			shaderLanguageDesc_.varying_vs = "out";
654 			shaderLanguageDesc_.varying_fs = "in";
655 			shaderLanguageDesc_.attribute = "in";
656 		} else {
657 			// This too...
658 			shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx;
659 			if (gl_extensions.EXT_gpu_shader4) {
660 				shaderLanguageDesc_.bitwiseOps = true;
661 				shaderLanguageDesc_.texelFetch = "texelFetch2D";
662 			}
663 		}
664 	}
665 
666 	if (gl_extensions.IsGLES) {
667 		caps_.framebufferFetchSupported = (gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch);
668 		if (gl_extensions.EXT_shader_framebuffer_fetch) {
669 			shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require";
670 			shaderLanguageDesc_.lastFragData = gl_extensions.GLES3 ? "fragColor0" : "gl_LastFragData[0]";
671 		} else if (gl_extensions.ARM_shader_framebuffer_fetch) {
672 			shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_ARM_shader_framebuffer_fetch : require";
673 			shaderLanguageDesc_.lastFragData = "gl_LastFragColorARM";
674 		}
675 	}
676 }
677 
~OpenGLContext()678 OpenGLContext::~OpenGLContext() {
679 	DestroyPresets();
680 	for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) {
681 		renderManager_.DeletePushBuffer(frameData_[i].push);
682 	}
683 }
684 
BeginFrame()685 void OpenGLContext::BeginFrame() {
686 	renderManager_.BeginFrame();
687 	FrameData &frameData = frameData_[renderManager_.GetCurFrame()];
688 	renderManager_.BeginPushBuffer(frameData.push);
689 }
690 
EndFrame()691 void OpenGLContext::EndFrame() {
692 	FrameData &frameData = frameData_[renderManager_.GetCurFrame()];
693 	renderManager_.EndPushBuffer(frameData.push);  // upload the data!
694 	renderManager_.Finish();
695 
696 	InvalidateCachedState();
697 }
698 
InvalidateCachedState()699 void OpenGLContext::InvalidateCachedState() {
700 	// Unbind stuff.
701 	for (auto &texture : boundTextures_) {
702 		texture = nullptr;
703 	}
704 	for (auto &sampler : boundSamplers_) {
705 		sampler = nullptr;
706 	}
707 	curPipeline_ = nullptr;
708 }
709 
CreateInputLayout(const InputLayoutDesc & desc)710 InputLayout *OpenGLContext::CreateInputLayout(const InputLayoutDesc &desc) {
711 	OpenGLInputLayout *fmt = new OpenGLInputLayout(&renderManager_);
712 	fmt->Compile(desc);
713 	return fmt;
714 }
715 
TypeToTarget(TextureType type)716 GLuint TypeToTarget(TextureType type) {
717 	switch (type) {
718 #ifndef USING_GLES2
719 	case TextureType::LINEAR1D: return GL_TEXTURE_1D;
720 #endif
721 	case TextureType::LINEAR2D: return GL_TEXTURE_2D;
722 	case TextureType::LINEAR3D: return GL_TEXTURE_3D;
723 	case TextureType::CUBE: return GL_TEXTURE_CUBE_MAP;
724 #ifndef USING_GLES2
725 	case TextureType::ARRAY1D: return GL_TEXTURE_1D_ARRAY;
726 #endif
727 	case TextureType::ARRAY2D: return GL_TEXTURE_2D_ARRAY;
728 	default:
729 		ERROR_LOG(G3D,  "Bad texture type %d", (int)type);
730 		return GL_NONE;
731 	}
732 }
733 
734 class OpenGLTexture : public Texture {
735 public:
736 	OpenGLTexture(GLRenderManager *render, const TextureDesc &desc);
737 	~OpenGLTexture();
738 
HasMips() const739 	bool HasMips() const {
740 		return mipLevels_ > 1 || generatedMips_;
741 	}
742 
GetType() const743 	TextureType GetType() const { return type_; }
Bind(int stage)744 	void Bind(int stage) {
745 		render_->BindTexture(stage, tex_);
746 	}
NumMipmaps() const747 	int NumMipmaps() const {
748 		return mipLevels_;
749 	}
GetTex() const750 	const GLRTexture *GetTex() const {
751 		return tex_;
752 	}
753 
754 private:
755 	void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback callback);
756 
757 	GLRenderManager *render_;
758 	GLRTexture *tex_;
759 
760 	DataFormat format_;
761 	TextureType type_;
762 	int mipLevels_;
763 	bool generatedMips_;
764 };
765 
OpenGLTexture(GLRenderManager * render,const TextureDesc & desc)766 OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : render_(render) {
767 	generatedMips_ = false;
768 	width_ = desc.width;
769 	height_ = desc.height;
770 	depth_ = desc.depth;
771 	format_ = desc.format;
772 	type_ = desc.type;
773 	GLenum target = TypeToTarget(desc.type);
774 	tex_ = render->CreateTexture(target, desc.width, desc.height, desc.mipLevels);
775 
776 	mipLevels_ = desc.mipLevels;
777 	if (desc.initData.empty())
778 		return;
779 
780 	int level = 0;
781 	for (auto data : desc.initData) {
782 		SetImageData(0, 0, 0, width_, height_, depth_, level, 0, data, desc.initDataCallback);
783 		width_ = (width_ + 1) / 2;
784 		height_ = (height_ + 1) / 2;
785 		depth_ = (depth_ + 1) / 2;
786 		level++;
787 	}
788 	mipLevels_ = desc.generateMips ? desc.mipLevels : level;
789 
790 	bool genMips = false;
791 	if ((int)desc.initData.size() < desc.mipLevels && desc.generateMips) {
792 		// Assumes the texture is bound for editing
793 		genMips = true;
794 		generatedMips_ = true;
795 	}
796 	render->FinalizeTexture(tex_, mipLevels_, genMips);
797 }
798 
~OpenGLTexture()799 OpenGLTexture::~OpenGLTexture() {
800 	if (tex_) {
801 		render_->DeleteTexture(tex_);
802 		tex_ = 0;
803 		generatedMips_ = false;
804 	}
805 }
806 
807 class OpenGLFramebuffer : public Framebuffer {
808 public:
OpenGLFramebuffer(GLRenderManager * render,GLRFramebuffer * framebuffer)809 	OpenGLFramebuffer(GLRenderManager *render, GLRFramebuffer *framebuffer) : render_(render), framebuffer_(framebuffer) {
810 		width_ = framebuffer->width;
811 		height_ = framebuffer->height;
812 	}
~OpenGLFramebuffer()813 	~OpenGLFramebuffer() {
814 		render_->DeleteFramebuffer(framebuffer_);
815 	}
816 
817 	GLRenderManager *render_;
818 	GLRFramebuffer *framebuffer_ = nullptr;
819 };
820 
SetImageData(int x,int y,int z,int width,int height,int depth,int level,int stride,const uint8_t * data,TextureCallback callback)821 void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback callback) {
822 	if ((width != width_ || height != height_ || depth != depth_) && level == 0) {
823 		// When switching to texStorage we need to handle this correctly.
824 		width_ = width;
825 		height_ = height;
826 		depth_ = depth;
827 	}
828 
829 	if (stride == 0)
830 		stride = width;
831 
832 	size_t alignment = DataFormatSizeInBytes(format_);
833 	// Make a copy of data with stride eliminated.
834 	uint8_t *texData = new uint8_t[(size_t)(width * height * depth * alignment)];
835 
836 	bool texDataPopulated = false;
837 	if (callback) {
838 		texDataPopulated = callback(texData, data, width, height, depth, width * (int)alignment, height * width * (int)alignment);
839 	}
840 	if (texDataPopulated) {
841 		if (format_ == DataFormat::A1R5G5B5_UNORM_PACK16) {
842 			format_ = DataFormat::R5G5B5A1_UNORM_PACK16;
843 			ConvertBGRA5551ToABGR1555((u16 *)texData, (const u16 *)texData, width * height * depth);
844 		}
845 	} else {
846 		// Emulate support for DataFormat::A1R5G5B5_UNORM_PACK16.
847 		if (format_ == DataFormat::A1R5G5B5_UNORM_PACK16) {
848 			format_ = DataFormat::R5G5B5A1_UNORM_PACK16;
849 			for (int y = 0; y < height; y++) {
850 				ConvertBGRA5551ToABGR1555((u16 *)(texData + y * width * alignment), (const u16 *)(data + y * stride * alignment), width);
851 			}
852 		} else {
853 			for (int y = 0; y < height; y++) {
854 				memcpy(texData + y * width * alignment, data + y * stride * alignment, width * alignment);
855 			}
856 		}
857 	}
858 
859 	render_->TextureImage(tex_, level, width, height, format_, texData);
860 }
861 
862 #ifdef DEBUG_READ_PIXELS
863 // TODO: Make more generic.
LogReadPixelsError(GLenum error)864 static void LogReadPixelsError(GLenum error) {
865 	switch (error) {
866 	case GL_NO_ERROR:
867 		break;
868 	case GL_INVALID_ENUM:
869 		ERROR_LOG(G3D, "glReadPixels: GL_INVALID_ENUM");
870 		break;
871 	case GL_INVALID_VALUE:
872 		ERROR_LOG(G3D, "glReadPixels: GL_INVALID_VALUE");
873 		break;
874 	case GL_INVALID_OPERATION:
875 		ERROR_LOG(G3D, "glReadPixels: GL_INVALID_OPERATION");
876 		break;
877 	case GL_INVALID_FRAMEBUFFER_OPERATION:
878 		ERROR_LOG(G3D, "glReadPixels: GL_INVALID_FRAMEBUFFER_OPERATION");
879 		break;
880 	case GL_OUT_OF_MEMORY:
881 		ERROR_LOG(G3D, "glReadPixels: GL_OUT_OF_MEMORY");
882 		break;
883 #ifndef USING_GLES2
884 	case GL_STACK_UNDERFLOW:
885 		ERROR_LOG(G3D, "glReadPixels: GL_STACK_UNDERFLOW");
886 		break;
887 	case GL_STACK_OVERFLOW:
888 		ERROR_LOG(G3D, "glReadPixels: GL_STACK_OVERFLOW");
889 		break;
890 #endif
891 	default:
892 		ERROR_LOG(G3D, "glReadPixels: %08x", error);
893 		break;
894 	}
895 }
896 #endif
897 
CopyFramebufferToMemorySync(Framebuffer * src,int channelBits,int x,int y,int w,int h,Draw::DataFormat dataFormat,void * pixels,int pixelStride,const char * tag)898 bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat dataFormat, void *pixels, int pixelStride, const char *tag) {
899 	if (gl_extensions.IsGLES && (channelBits & FB_COLOR_BIT) == 0) {
900 		// Can't readback depth or stencil on GLES.
901 		return false;
902 	}
903 	OpenGLFramebuffer *fb = (OpenGLFramebuffer *)src;
904 	GLuint aspect = 0;
905 	if (channelBits & FB_COLOR_BIT)
906 		aspect |= GL_COLOR_BUFFER_BIT;
907 	if (channelBits & FB_DEPTH_BIT)
908 		aspect |= GL_DEPTH_BUFFER_BIT;
909 	if (channelBits & FB_STENCIL_BIT)
910 		aspect |= GL_STENCIL_BUFFER_BIT;
911 	renderManager_.CopyFramebufferToMemorySync(fb ? fb->framebuffer_ : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride, tag);
912 	return true;
913 }
914 
915 
CreateTexture(const TextureDesc & desc)916 Texture *OpenGLContext::CreateTexture(const TextureDesc &desc) {
917 	return new OpenGLTexture(&renderManager_, desc);
918 }
919 
CreateDepthStencilState(const DepthStencilStateDesc & desc)920 DepthStencilState *OpenGLContext::CreateDepthStencilState(const DepthStencilStateDesc &desc) {
921 	OpenGLDepthStencilState *ds = new OpenGLDepthStencilState();
922 	ds->depthTestEnabled = desc.depthTestEnabled;
923 	ds->depthWriteEnabled = desc.depthWriteEnabled;
924 	ds->depthComp = compToGL[(int)desc.depthCompare];
925 	ds->stencilEnabled = desc.stencilEnabled;
926 	ds->stencilCompareOp = compToGL[(int)desc.front.compareOp];
927 	ds->stencilPass = stencilOpToGL[(int)desc.front.passOp];
928 	ds->stencilFail = stencilOpToGL[(int)desc.front.failOp];
929 	ds->stencilZFail = stencilOpToGL[(int)desc.front.depthFailOp];
930 	ds->stencilWriteMask = desc.front.writeMask;
931 	ds->stencilCompareMask = desc.front.compareMask;
932 	return ds;
933 }
934 
CreateBlendState(const BlendStateDesc & desc)935 BlendState *OpenGLContext::CreateBlendState(const BlendStateDesc &desc) {
936 	OpenGLBlendState *bs = new OpenGLBlendState();
937 	bs->enabled = desc.enabled;
938 	bs->eqCol = blendEqToGL[(int)desc.eqCol];
939 	bs->srcCol = blendFactorToGL[(int)desc.srcCol];
940 	bs->dstCol = blendFactorToGL[(int)desc.dstCol];
941 	bs->eqAlpha = blendEqToGL[(int)desc.eqAlpha];
942 	bs->srcAlpha = blendFactorToGL[(int)desc.srcAlpha];
943 	bs->dstAlpha = blendFactorToGL[(int)desc.dstAlpha];
944 	bs->colorMask = desc.colorMask;
945 	return bs;
946 }
947 
CreateSamplerState(const SamplerStateDesc & desc)948 SamplerState *OpenGLContext::CreateSamplerState(const SamplerStateDesc &desc) {
949 	OpenGLSamplerState *samps = new OpenGLSamplerState();
950 	samps->wrapU = texWrapToGL[(int)desc.wrapU];
951 	samps->wrapV = texWrapToGL[(int)desc.wrapV];
952 	samps->wrapW = texWrapToGL[(int)desc.wrapW];
953 	samps->magFilt = texFilterToGL[(int)desc.magFilter];
954 	samps->minFilt = texFilterToGL[(int)desc.minFilter];
955 	samps->mipMinFilt = texMipFilterToGL[(int)desc.minFilter][(int)desc.mipFilter];
956 	return samps;
957 }
958 
CreateRasterState(const RasterStateDesc & desc)959 RasterState *OpenGLContext::CreateRasterState(const RasterStateDesc &desc) {
960 	OpenGLRasterState *rs = new OpenGLRasterState();
961 	if (desc.cull == CullMode::NONE) {
962 		rs->cullEnable = GL_FALSE;
963 		return rs;
964 	}
965 	rs->cullEnable = GL_TRUE;
966 	switch (desc.frontFace) {
967 	case Facing::CW:
968 		rs->frontFace = GL_CW;
969 		break;
970 	case Facing::CCW:
971 		rs->frontFace = GL_CCW;
972 		break;
973 	}
974 	switch (desc.cull) {
975 	case CullMode::FRONT:
976 		rs->cullMode = GL_FRONT;
977 		break;
978 	case CullMode::BACK:
979 		rs->cullMode = GL_BACK;
980 		break;
981 	case CullMode::FRONT_AND_BACK:
982 		rs->cullMode = GL_FRONT_AND_BACK;
983 		break;
984 	case CullMode::NONE:
985 		// Unsupported
986 		break;
987 	}
988 	return rs;
989 }
990 
991 class OpenGLBuffer : public Buffer {
992 public:
OpenGLBuffer(GLRenderManager * render,size_t size,uint32_t flags)993 	OpenGLBuffer(GLRenderManager *render, size_t size, uint32_t flags) : render_(render) {
994 		target_ = (flags & BufferUsageFlag::INDEXDATA) ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
995 		usage_ = 0;
996 		if (flags & BufferUsageFlag::DYNAMIC)
997 			usage_ = GL_STREAM_DRAW;
998 		else
999 			usage_ = GL_STATIC_DRAW;
1000 		buffer_ = render->CreateBuffer(target_, size, usage_);
1001 		totalSize_ = size;
1002 	}
~OpenGLBuffer()1003 	~OpenGLBuffer() override {
1004 		render_->DeleteBuffer(buffer_);
1005 	}
1006 
1007 	GLRenderManager *render_;
1008 	GLRBuffer *buffer_;
1009 	GLuint target_;
1010 	GLuint usage_;
1011 
1012 	size_t totalSize_;
1013 };
1014 
CreateBuffer(size_t size,uint32_t usageFlags)1015 Buffer *OpenGLContext::CreateBuffer(size_t size, uint32_t usageFlags) {
1016 	return new OpenGLBuffer(&renderManager_, size, usageFlags);
1017 }
1018 
UpdateBuffer(Buffer * buffer,const uint8_t * data,size_t offset,size_t size,UpdateBufferFlags flags)1019 void OpenGLContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) {
1020 	OpenGLBuffer *buf = (OpenGLBuffer *)buffer;
1021 
1022 	if (size + offset > buf->totalSize_) {
1023 		Crash();
1024 	}
1025 
1026 	uint8_t *dataCopy = new uint8_t[size];
1027 	memcpy(dataCopy, data, size);
1028 	// if (flags & UPDATE_DISCARD) we could try to orphan the buffer using glBufferData.
1029 	// But we're much better off using separate buffers per FrameData...
1030 	renderManager_.BufferSubdata(buf->buffer_, offset, size, dataCopy);
1031 }
1032 
CreateGraphicsPipeline(const PipelineDesc & desc)1033 Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
1034 	if (!desc.shaders.size()) {
1035 		ERROR_LOG(G3D,  "Pipeline requires at least one shader");
1036 		return nullptr;
1037 	}
1038 	if ((uint32_t)desc.prim >= (uint32_t)Primitive::PRIMITIVE_TYPE_COUNT) {
1039 		ERROR_LOG(G3D, "Invalid primitive type");
1040 		return nullptr;
1041 	}
1042 	if (!desc.depthStencil || !desc.blend || !desc.raster) {
1043 		ERROR_LOG(G3D,  "Incomplete prim desciption");
1044 		return nullptr;
1045 	}
1046 
1047 	OpenGLPipeline *pipeline = new OpenGLPipeline(&renderManager_);
1048 	for (auto iter : desc.shaders) {
1049 		if (iter) {
1050 			iter->AddRef();
1051 			pipeline->shaders.push_back(static_cast<OpenGLShaderModule *>(iter));
1052 		} else {
1053 			ERROR_LOG(G3D,  "ERROR: Tried to create graphics pipeline with a null shader module");
1054 			delete pipeline;
1055 			return nullptr;
1056 		}
1057 	}
1058 	if (desc.uniformDesc) {
1059 		pipeline->dynamicUniforms = *desc.uniformDesc;
1060 		pipeline->dynamicUniformLocs_.resize(desc.uniformDesc->uniforms.size());
1061 	}
1062 	if (pipeline->LinkShaders()) {
1063 		// Build the rest of the virtual pipeline object.
1064 		pipeline->prim = primToGL[(int)desc.prim];
1065 		pipeline->depthStencil = (OpenGLDepthStencilState *)desc.depthStencil;
1066 		pipeline->blend = (OpenGLBlendState *)desc.blend;
1067 		pipeline->raster = (OpenGLRasterState *)desc.raster;
1068 		pipeline->inputLayout = (OpenGLInputLayout *)desc.inputLayout;
1069 		return pipeline;
1070 	} else {
1071 		ERROR_LOG(G3D,  "Failed to create pipeline - shaders failed to link");
1072 		delete pipeline;
1073 		return nullptr;
1074 	}
1075 }
1076 
BindTextures(int start,int count,Texture ** textures)1077 void OpenGLContext::BindTextures(int start, int count, Texture **textures) {
1078 	_assert_(start + count <= MAX_TEXTURE_SLOTS);
1079 	for (int i = start; i < start + count; i++) {
1080 		OpenGLTexture *glTex = static_cast<OpenGLTexture *>(textures[i - start]);
1081 		if (!glTex) {
1082 			boundTextures_[i] = nullptr;
1083 			renderManager_.BindTexture(i, nullptr);
1084 			continue;
1085 		}
1086 		glTex->Bind(i);
1087 		boundTextures_[i] = glTex->GetTex();
1088 	}
1089 }
1090 
ApplySamplers()1091 void OpenGLContext::ApplySamplers() {
1092 	for (int i = 0; i < MAX_TEXTURE_SLOTS; i++) {
1093 		const OpenGLSamplerState *samp = boundSamplers_[i];
1094 		const GLRTexture *tex = boundTextures_[i];
1095 		if (tex) {
1096 			_assert_(samp);
1097 		} else {
1098 			continue;
1099 		}
1100 		GLenum wrapS;
1101 		GLenum wrapT;
1102 		if (tex->canWrap) {
1103 			wrapS = samp->wrapU;
1104 			wrapT = samp->wrapV;
1105 		} else {
1106 			wrapS = GL_CLAMP_TO_EDGE;
1107 			wrapT = GL_CLAMP_TO_EDGE;
1108 		}
1109 		GLenum magFilt = samp->magFilt;
1110 		GLenum minFilt = tex->numMips > 1 ? samp->mipMinFilt : samp->minFilt;
1111 		renderManager_.SetTextureSampler(i, wrapS, wrapT, magFilt, minFilt, 0.0f);
1112 		renderManager_.SetTextureLod(i, 0.0, (float)(tex->numMips - 1), 0.0);
1113 	}
1114 }
1115 
CreateShaderModule(ShaderStage stage,ShaderLanguage language,const uint8_t * data,size_t dataSize,const std::string & tag)1116 ShaderModule *OpenGLContext::CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const std::string &tag) {
1117 	OpenGLShaderModule *shader = new OpenGLShaderModule(&renderManager_, stage, tag);
1118 	if (shader->Compile(&renderManager_, language, data, dataSize)) {
1119 		return shader;
1120 	} else {
1121 		shader->Release();
1122 		return nullptr;
1123 	}
1124 }
1125 
LinkShaders()1126 bool OpenGLPipeline::LinkShaders() {
1127 	std::vector<GLRShader *> linkShaders;
1128 	for (auto shaderModule : shaders) {
1129 		if (shaderModule) {
1130 			GLRShader *shader = shaderModule->GetShader();
1131 			if (shader) {
1132 				linkShaders.push_back(shader);
1133 			} else {
1134 				ERROR_LOG(G3D,  "LinkShaders: Bad shader module");
1135 				return false;
1136 			}
1137 		} else {
1138 			ERROR_LOG(G3D,  "LinkShaders: Bad shader in module");
1139 			return false;
1140 		}
1141 	}
1142 
1143 	std::vector<GLRProgram::Semantic> semantics;
1144 	// Bind all the common vertex data points. Mismatching ones will be ignored.
1145 	semantics.push_back({ SEM_POSITION, "Position" });
1146 	semantics.push_back({ SEM_COLOR0, "Color0" });
1147 	semantics.push_back({ SEM_TEXCOORD0, "TexCoord0" });
1148 	semantics.push_back({ SEM_NORMAL, "Normal" });
1149 	semantics.push_back({ SEM_TANGENT, "Tangent" });
1150 	semantics.push_back({ SEM_BINORMAL, "Binormal" });
1151 	// For postshaders.
1152 	semantics.push_back({ SEM_POSITION, "a_position" });
1153 	semantics.push_back({ SEM_TEXCOORD0, "a_texcoord0" });
1154 	std::vector<GLRProgram::UniformLocQuery> queries;
1155 	queries.push_back({ &samplerLocs_[0], "sampler0" });
1156 	queries.push_back({ &samplerLocs_[1], "sampler1" });
1157 	queries.push_back({ &samplerLocs_[2], "sampler2" });
1158 	_assert_(queries.size() >= MAX_TEXTURE_SLOTS);
1159 	for (size_t i = 0; i < dynamicUniforms.uniforms.size(); ++i) {
1160 		queries.push_back({ &dynamicUniformLocs_[i], dynamicUniforms.uniforms[i].name });
1161 	}
1162 	std::vector<GLRProgram::Initializer> initialize;
1163 	for (int i = 0; i < MAX_TEXTURE_SLOTS; ++i)
1164 		initialize.push_back({ &samplerLocs_[i], 0, i });
1165 	program_ = render_->CreateProgram(linkShaders, semantics, queries, initialize, false);
1166 	return true;
1167 }
1168 
BindPipeline(Pipeline * pipeline)1169 void OpenGLContext::BindPipeline(Pipeline *pipeline) {
1170 	curPipeline_ = (OpenGLPipeline *)pipeline;
1171 	if (!curPipeline_) {
1172 		return;
1173 	}
1174 	curPipeline_->blend->Apply(&renderManager_);
1175 	curPipeline_->depthStencil->Apply(&renderManager_, stencilRef_);
1176 	curPipeline_->raster->Apply(&renderManager_);
1177 	renderManager_.BindProgram(curPipeline_->program_);
1178 }
1179 
UpdateDynamicUniformBuffer(const void * ub,size_t size)1180 void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
1181 	if (curPipeline_->dynamicUniforms.uniformBufferSize != size) {
1182 		Crash();
1183 	}
1184 
1185 	for (size_t i = 0; i < curPipeline_->dynamicUniforms.uniforms.size(); ++i) {
1186 		const auto &uniform = curPipeline_->dynamicUniforms.uniforms[i];
1187 		const GLint &loc = curPipeline_->dynamicUniformLocs_[i];
1188 		const float *data = (const float *)((uint8_t *)ub + uniform.offset);
1189 		switch (uniform.type) {
1190 		case UniformType::FLOAT1:
1191 		case UniformType::FLOAT2:
1192 		case UniformType::FLOAT3:
1193 		case UniformType::FLOAT4:
1194 			renderManager_.SetUniformF(&loc, 1 + (int)uniform.type - (int)UniformType::FLOAT1, data);
1195 			break;
1196 		case UniformType::MATRIX4X4:
1197 			renderManager_.SetUniformM4x4(&loc, data);
1198 			break;
1199 		}
1200 	}
1201 }
1202 
Draw(int vertexCount,int offset)1203 void OpenGLContext::Draw(int vertexCount, int offset) {
1204 	_dbg_assert_msg_(curVBuffers_[0] != nullptr, "Can't call Draw without a vertex buffer");
1205 	ApplySamplers();
1206 	if (curPipeline_->inputLayout) {
1207 		renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
1208 	}
1209 	renderManager_.Draw(curPipeline_->prim, offset, vertexCount);
1210 }
1211 
DrawIndexed(int vertexCount,int offset)1212 void OpenGLContext::DrawIndexed(int vertexCount, int offset) {
1213 	_dbg_assert_msg_(curVBuffers_[0] != nullptr, "Can't call DrawIndexed without a vertex buffer");
1214 	_dbg_assert_msg_(curIBuffer_ != nullptr, "Can't call DrawIndexed without an index buffer");
1215 	ApplySamplers();
1216 	if (curPipeline_->inputLayout) {
1217 		renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
1218 	}
1219 	renderManager_.BindIndexBuffer(curIBuffer_->buffer_);
1220 	renderManager_.DrawIndexed(curPipeline_->prim, vertexCount, GL_UNSIGNED_SHORT, (void *)((intptr_t)curIBufferOffset_ + offset * sizeof(uint32_t)));
1221 }
1222 
DrawUP(const void * vdata,int vertexCount)1223 void OpenGLContext::DrawUP(const void *vdata, int vertexCount) {
1224 	_assert_(curPipeline_->inputLayout != nullptr);
1225 	int stride = curPipeline_->inputLayout->stride;
1226 	size_t dataSize = stride * vertexCount;
1227 
1228 	FrameData &frameData = frameData_[renderManager_.GetCurFrame()];
1229 
1230 	GLRBuffer *buf;
1231 	size_t offset = frameData.push->Push(vdata, dataSize, &buf);
1232 
1233 	ApplySamplers();
1234 	if (curPipeline_->inputLayout) {
1235 		renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, buf, offset);
1236 	}
1237 	renderManager_.Draw(curPipeline_->prim, 0, vertexCount);
1238 }
1239 
Clear(int mask,uint32_t colorval,float depthVal,int stencilVal)1240 void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) {
1241 	float col[4];
1242 	Uint8x4ToFloat4(col, colorval);
1243 	GLuint glMask = 0;
1244 	if (mask & FBChannel::FB_COLOR_BIT) {
1245 		glMask |= GL_COLOR_BUFFER_BIT;
1246 	}
1247 	if (mask & FBChannel::FB_DEPTH_BIT) {
1248 		glMask |= GL_DEPTH_BUFFER_BIT;
1249 	}
1250 	if (mask & FBChannel::FB_STENCIL_BIT) {
1251 		glMask |= GL_STENCIL_BUFFER_BIT;
1252 	}
1253 	renderManager_.Clear(colorval, depthVal, stencilVal, glMask, 0xF, 0, 0, targetWidth_, targetHeight_);
1254 }
1255 
T3DCreateGLContext()1256 DrawContext *T3DCreateGLContext() {
1257 	return new OpenGLContext();
1258 }
1259 
~OpenGLInputLayout()1260 OpenGLInputLayout::~OpenGLInputLayout() {
1261 	render_->DeleteInputLayout(inputLayout_);
1262 }
1263 
Compile(const InputLayoutDesc & desc)1264 void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) {
1265 	// TODO: This is only accurate if there's only one stream. But whatever, for now we
1266 	// never use multiple streams anyway.
1267 	stride = desc.bindings.empty() ? 0 : (GLsizei)desc.bindings[0].stride;
1268 
1269 	std::vector<GLRInputLayout::Entry> entries;
1270 	for (auto &attr : desc.attributes) {
1271 		GLRInputLayout::Entry entry;
1272 		entry.location = attr.location;
1273 		entry.stride = (GLsizei)desc.bindings[attr.binding].stride;
1274 		entry.offset = attr.offset;
1275 		switch (attr.format) {
1276 		case DataFormat::R32G32_FLOAT:
1277 			entry.count = 2;
1278 			entry.type = GL_FLOAT;
1279 			entry.normalized = GL_FALSE;
1280 			break;
1281 		case DataFormat::R32G32B32_FLOAT:
1282 			entry.count = 3;
1283 			entry.type = GL_FLOAT;
1284 			entry.normalized = GL_FALSE;
1285 			break;
1286 		case DataFormat::R32G32B32A32_FLOAT:
1287 			entry.count = 4;
1288 			entry.type = GL_FLOAT;
1289 			entry.normalized = GL_FALSE;
1290 			break;
1291 		case DataFormat::R8G8B8A8_UNORM:
1292 			entry.count = 4;
1293 			entry.type = GL_UNSIGNED_BYTE;
1294 			entry.normalized = GL_TRUE;
1295 			break;
1296 		case DataFormat::UNDEFINED:
1297 		default:
1298 			ERROR_LOG(G3D,  "Thin3DGLVertexFormat: Invalid or unknown component type applied.");
1299 			break;
1300 		}
1301 
1302 		entries.push_back(entry);
1303 	}
1304 	if (!entries.empty()) {
1305 		inputLayout_ = render_->CreateInputLayout(entries);
1306 	} else {
1307 		inputLayout_ = nullptr;
1308 	}
1309 }
1310 
CreateFramebuffer(const FramebufferDesc & desc)1311 Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) {
1312 	CheckGLExtensions();
1313 
1314 	GLRFramebuffer *framebuffer = renderManager_.CreateFramebuffer(desc.width, desc.height, desc.z_stencil);
1315 	OpenGLFramebuffer *fbo = new OpenGLFramebuffer(&renderManager_, framebuffer);
1316 	return fbo;
1317 }
1318 
BindFramebufferAsRenderTarget(Framebuffer * fbo,const RenderPassInfo & rp,const char * tag)1319 void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) {
1320 	OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
1321 	GLRRenderPassAction color = (GLRRenderPassAction)rp.color;
1322 	GLRRenderPassAction depth = (GLRRenderPassAction)rp.depth;
1323 	GLRRenderPassAction stencil = (GLRRenderPassAction)rp.stencil;
1324 
1325 	renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer_ : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil, tag);
1326 	curRenderTarget_ = fb;
1327 }
1328 
CopyFramebufferImage(Framebuffer * fbsrc,int srcLevel,int srcX,int srcY,int srcZ,Framebuffer * fbdst,int dstLevel,int dstX,int dstY,int dstZ,int width,int height,int depth,int channelBits,const char * tag)1329 void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) {
1330 	OpenGLFramebuffer *src = (OpenGLFramebuffer *)fbsrc;
1331 	OpenGLFramebuffer *dst = (OpenGLFramebuffer *)fbdst;
1332 
1333 	int aspect = 0;
1334 	if (channelBits & FB_COLOR_BIT) {
1335 		aspect |= GL_COLOR_BUFFER_BIT;
1336 	} else if (channelBits & (FB_STENCIL_BIT | FB_DEPTH_BIT)) {
1337 		if (channelBits & FB_DEPTH_BIT)
1338 			aspect |= GL_DEPTH_BUFFER_BIT;
1339 		if (channelBits & FB_STENCIL_BIT)
1340 			aspect |= GL_STENCIL_BUFFER_BIT;
1341 	}
1342 	renderManager_.CopyFramebuffer(src->framebuffer_, GLRect2D{ srcX, srcY, width, height }, dst->framebuffer_, GLOffset2D{ dstX, dstY }, aspect, tag);
1343 }
1344 
BlitFramebuffer(Framebuffer * fbsrc,int srcX1,int srcY1,int srcX2,int srcY2,Framebuffer * fbdst,int dstX1,int dstY1,int dstX2,int dstY2,int channels,FBBlitFilter linearFilter,const char * tag)1345 bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *fbdst, int dstX1, int dstY1, int dstX2, int dstY2, int channels, FBBlitFilter linearFilter, const char *tag) {
1346 	OpenGLFramebuffer *src = (OpenGLFramebuffer *)fbsrc;
1347 	OpenGLFramebuffer *dst = (OpenGLFramebuffer *)fbdst;
1348 	GLuint aspect = 0;
1349 	if (channels & FB_COLOR_BIT)
1350 		aspect |= GL_COLOR_BUFFER_BIT;
1351 	if (channels & FB_DEPTH_BIT)
1352 		aspect |= GL_DEPTH_BUFFER_BIT;
1353 	if (channels & FB_STENCIL_BIT)
1354 		aspect |= GL_STENCIL_BUFFER_BIT;
1355 
1356 	renderManager_.BlitFramebuffer(src->framebuffer_, GLRect2D{ srcX1, srcY1, srcX2 - srcX1, srcY2 - srcY1 }, dst->framebuffer_, GLRect2D{ dstX1, dstY1, dstX2 - dstX1, dstY2 - dstY1 }, aspect, linearFilter == FB_BLIT_LINEAR, tag);
1357 	return true;
1358 }
1359 
BindFramebufferAsTexture(Framebuffer * fbo,int binding,FBChannel channelBit,int color)1360 void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int color) {
1361 	OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
1362 	_assert_(binding < MAX_TEXTURE_SLOTS);
1363 
1364 	GLuint aspect = 0;
1365 	if (channelBit & FB_COLOR_BIT) {
1366 		aspect |= GL_COLOR_BUFFER_BIT;
1367 		boundTextures_[binding] = &fb->framebuffer_->color_texture;
1368 	}
1369 	if (channelBit & FB_DEPTH_BIT) {
1370 		aspect |= GL_DEPTH_BUFFER_BIT;
1371 		boundTextures_[binding] = &fb->framebuffer_->z_stencil_texture;
1372 	}
1373 	if (channelBit & FB_STENCIL_BIT) {
1374 		aspect |= GL_STENCIL_BUFFER_BIT;
1375 		boundTextures_[binding] = &fb->framebuffer_->z_stencil_texture;
1376 	}
1377 	renderManager_.BindFramebufferAsTexture(fb->framebuffer_, binding, aspect, color);
1378 }
1379 
GetFramebufferDimensions(Framebuffer * fbo,int * w,int * h)1380 void OpenGLContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
1381 	OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
1382 	if (fb) {
1383 		*w = fb->Width();
1384 		*h = fb->Height();
1385 	} else {
1386 		*w = targetWidth_;
1387 		*h = targetHeight_;
1388 	}
1389 }
1390 
GetDataFormatSupport(DataFormat fmt) const1391 uint32_t OpenGLContext::GetDataFormatSupport(DataFormat fmt) const {
1392 	switch (fmt) {
1393 	case DataFormat::R4G4B4A4_UNORM_PACK16:
1394 	case DataFormat::R5G6B5_UNORM_PACK16:
1395 	case DataFormat::R5G5B5A1_UNORM_PACK16:
1396 		return FMT_RENDERTARGET | FMT_TEXTURE | FMT_AUTOGEN_MIPS;  // native support
1397 
1398 	case DataFormat::R8G8B8A8_UNORM:
1399 		return FMT_RENDERTARGET | FMT_TEXTURE | FMT_INPUTLAYOUT | FMT_AUTOGEN_MIPS;
1400 
1401 	case DataFormat::A1R5G5B5_UNORM_PACK16:
1402 		return FMT_TEXTURE;  // we will emulate this! Very fast to convert from R5G5B5A1_UNORM_PACK16 during upload.
1403 
1404 	case DataFormat::R32_FLOAT:
1405 	case DataFormat::R32G32_FLOAT:
1406 	case DataFormat::R32G32B32_FLOAT:
1407 	case DataFormat::R32G32B32A32_FLOAT:
1408 		return FMT_INPUTLAYOUT;
1409 
1410 	case DataFormat::R8_UNORM:
1411 		return 0;
1412 	case DataFormat::BC1_RGBA_UNORM_BLOCK:
1413 	case DataFormat::BC2_UNORM_BLOCK:
1414 	case DataFormat::BC3_UNORM_BLOCK:
1415 		return FMT_TEXTURE;
1416 	default:
1417 		return 0;
1418 	}
1419 }
1420 
1421 }  // namespace Draw
1422