1 #pragma once
2 
3 #include <cstdint>
4 #include <vector>
5 #include <unordered_map>
6 
7 #include "Common/GPU/OpenGL/GLCommon.h"
8 #include "Common/GPU/DataFormat.h"
9 #include "Common/GPU/Shader.h"
10 #include "Common/Data/Collections/TinySet.h"
11 
12 struct GLRViewport {
13 	float x, y, w, h, minZ, maxZ;
14 };
15 
16 struct GLRect2D {
17 	int x, y, w, h;
18 };
19 
20 struct GLOffset2D {
21 	int x, y;
22 };
23 
24 enum class GLRAllocType {
25 	NONE,
26 	NEW,
27 	ALIGNED,
28 };
29 
30 class GLRShader;
31 class GLRTexture;
32 class GLRBuffer;
33 class GLRFramebuffer;
34 class GLRProgram;
35 class GLRInputLayout;
36 
37 enum class GLRRenderCommand : uint8_t {
38 	DEPTH,
39 	STENCILFUNC,
40 	STENCILOP,
41 	BLEND,
42 	BLENDCOLOR,
43 	LOGICOP,
44 	UNIFORM4I,
45 	UNIFORM4UI,
46 	UNIFORM4F,
47 	UNIFORMMATRIX,
48 	TEXTURESAMPLER,
49 	TEXTURELOD,
50 	VIEWPORT,
51 	SCISSOR,
52 	RASTER,
53 	CLEAR,
54 	INVALIDATE,
55 	BINDPROGRAM,
56 	BINDTEXTURE,
57 	BIND_FB_TEXTURE,
58 	BIND_VERTEX_BUFFER,
59 	BIND_BUFFER,
60 	GENMIPS,
61 	DRAW,
62 	DRAW_INDEXED,
63 	PUSH_CONSTANTS,
64 	TEXTURE_SUBIMAGE,
65 };
66 
67 // TODO: Bloated since the biggest struct decides the size. Will need something more efficient (separate structs with shared
68 // type field, smashed right after each other?)
69 // Also, all GLenums are really only 16 bits.
70 struct GLRRenderData {
71 	GLRRenderCommand cmd;
72 	union {
73 		struct {
74 			GLboolean enabled;
75 			GLenum srcColor;
76 			GLenum dstColor;
77 			GLenum srcAlpha;
78 			GLenum dstAlpha;
79 			GLenum funcColor;
80 			GLenum funcAlpha;
81 			int mask;
82 		} blend;
83 		struct {
84 			float color[4];
85 		} blendColor;
86 		struct {
87 			GLboolean enabled;
88 			GLenum logicOp;
89 		} logic;
90 		struct {
91 			GLboolean enabled;
92 			GLboolean write;
93 			GLenum func;
94 		} depth;
95 		struct {
96 			GLboolean enabled;
97 			GLenum func;
98 			uint8_t ref;
99 			uint8_t compareMask;
100 		} stencilFunc;
101 		struct {
102 			GLenum sFail;
103 			GLenum zFail;
104 			GLenum pass;
105 			uint8_t writeMask;
106 		} stencilOp;  // also write mask
107 		struct {
108 			GLenum mode;  // primitive
109 			GLint buffer;
110 			GLint first;
111 			GLint count;
112 		} draw;
113 		struct {
114 			GLenum mode;  // primitive
115 			GLint count;
116 			GLint instances;
117 			GLint indexType;
118 			void *indices;
119 		} drawIndexed;
120 		struct {
121 			const char *name;  // if null, use loc
122 			const GLint *loc; // NOTE: This is a pointer so we can immediately use things that are "queried" during program creation.
123 			GLint count;
124 			float v[4];
125 		} uniform4;
126 		struct {
127 			const char *name;  // if null, use loc
128 			const GLint *loc;
129 			float m[16];
130 		} uniformMatrix4;
131 		struct {
132 			uint32_t clearColor;
133 			float clearZ;
134 			uint8_t clearStencil;
135 			uint8_t colorMask; // Like blend, but for the clear.
136 			GLuint clearMask;   // GL_COLOR_BUFFER_BIT etc
137 			int16_t scissorX;
138 			int16_t scissorY;
139 			int16_t scissorW;
140 			int16_t scissorH;
141 		} clear;  // also used for invalidate
142 		struct {
143 			int slot;
144 			GLRTexture *texture;
145 		} texture;
146 		struct {
147 			GLRTexture *texture;
148 			Draw::DataFormat format;
149 			int level;
150 			int x;
151 			int y;
152 			int width;
153 			int height;
154 			GLRAllocType allocType;
155 			uint8_t *data;  // owned, delete[]-d
156 		} texture_subimage;
157 		struct {
158 			int slot;
159 			GLRFramebuffer *framebuffer;
160 			int aspect;
161 		} bind_fb_texture;
162 		struct {
163 			GLRBuffer *buffer;
164 			GLuint target;
165 		} bind_buffer;
166 		struct {
167 			GLRProgram *program;
168 		} program;
169 		struct {
170 			GLRInputLayout *inputLayout;
171 			GLRBuffer *buffer;
172 			size_t offset;
173 		} bindVertexBuffer;
174 		struct {
175 			int slot;
176 			GLenum wrapS;
177 			GLenum wrapT;
178 			GLenum magFilter;
179 			GLenum minFilter;  // also includes mip. GL...
180 			float anisotropy;
181 		} textureSampler;
182 		struct {
183 			int slot;
184 			float minLod;
185 			float maxLod;
186 			float lodBias;
187 		} textureLod;
188 		struct {
189 			GLRViewport vp;
190 		} viewport;
191 		struct {
192 			GLRect2D rc;
193 		} scissor;
194 		struct {
195 			GLboolean cullEnable;
196 			GLenum frontFace;
197 			GLenum cullFace;
198 			GLboolean ditherEnable;
199 			GLboolean depthClampEnable;
200 		} raster;
201 	};
202 };
203 
204 // Unlike in Vulkan, we can't create stuff on the main thread, but need to
205 // defer this too. A big benefit will be that we'll be able to do all creation
206 // at the start of the frame.
207 enum class GLRInitStepType : uint8_t {
208 	CREATE_TEXTURE,
209 	CREATE_SHADER,
210 	CREATE_PROGRAM,
211 	CREATE_BUFFER,
212 	CREATE_INPUT_LAYOUT,
213 	CREATE_FRAMEBUFFER,
214 
215 	TEXTURE_IMAGE,
216 	TEXTURE_FINALIZE,
217 	BUFFER_SUBDATA,
218 };
219 
220 struct GLRInitStep {
GLRInitStepGLRInitStep221 	GLRInitStep(GLRInitStepType _type) : stepType(_type) {}
222 	GLRInitStepType stepType;
223 	union {
224 		struct {
225 			GLRTexture *texture;
226 			GLenum target;
227 		} create_texture;
228 		struct {
229 			GLRShader *shader;
230 			// This char arrays needs to be allocated with new[].
231 			char *code;
232 			GLuint stage;
233 		} create_shader;
234 		struct {
235 			GLRProgram *program;
236 			GLRShader *shaders[3];
237 			int num_shaders;
238 			bool support_dual_source;
239 		} create_program;
240 		struct {
241 			GLRBuffer *buffer;
242 			int size;
243 			GLuint usage;
244 		} create_buffer;
245 		struct {
246 			GLRInputLayout *inputLayout;
247 		} create_input_layout;
248 		struct {
249 			GLRFramebuffer *framebuffer;
250 		} create_framebuffer;
251 		struct {
252 			GLRBuffer *buffer;
253 			int offset;
254 			int size;
255 			uint8_t *data;  // owned, delete[]-d
256 			bool deleteData;
257 		} buffer_subdata;
258 		struct {
259 			GLRTexture *texture;
260 			Draw::DataFormat format;
261 			int level;
262 			int width;
263 			int height;
264 			GLRAllocType allocType;
265 			bool linearFilter;
266 			uint8_t *data;  // owned, delete[]-d
267 		} texture_image;
268 		struct {
269 			GLRTexture *texture;
270 			int maxLevel;
271 			bool genMips;
272 		} texture_finalize;
273 	};
274 };
275 
276 enum class GLRStepType : uint8_t {
277 	RENDER,
278 	COPY,
279 	BLIT,
280 	READBACK,
281 	READBACK_IMAGE,
282 	RENDER_SKIP,
283 };
284 
285 enum class GLRRenderPassAction {
286 	DONT_CARE,
287 	CLEAR,
288 	KEEP,
289 };
290 
291 class GLRFramebuffer;
292 
293 enum {
294 	GLR_ASPECT_COLOR = 1,
295 	GLR_ASPECT_DEPTH = 2,
296 	GLR_ASPECT_STENCIL = 3,
297 };
298 
299 struct GLRStep {
GLRStepGLRStep300 	GLRStep(GLRStepType _type) : stepType(_type) {}
301 	GLRStepType stepType;
302 	std::vector<GLRRenderData> commands;
303 	TinySet<const GLRFramebuffer *, 8> dependencies;
304 	const char *tag;
305 	union {
306 		struct {
307 			GLRFramebuffer *framebuffer;
308 			GLRRenderPassAction color;
309 			GLRRenderPassAction depth;
310 			GLRRenderPassAction stencil;
311 			// Note: not accurate.
312 			int numDraws;
313 		} render;
314 		struct {
315 			GLRFramebuffer *src;
316 			GLRFramebuffer *dst;
317 			GLRect2D srcRect;
318 			GLOffset2D dstPos;
319 			int aspectMask;
320 		} copy;
321 		struct {
322 			GLRFramebuffer *src;
323 			GLRFramebuffer *dst;
324 			GLRect2D srcRect;
325 			GLRect2D dstRect;
326 			int aspectMask;
327 			GLboolean filter;
328 		} blit;
329 		struct {
330 			int aspectMask;
331 			GLRFramebuffer *src;
332 			GLRect2D srcRect;
333 			Draw::DataFormat dstFormat;
334 		} readback;
335 		struct {
336 			GLRTexture *texture;
337 			GLRect2D srcRect;
338 			int mipLevel;
339 		} readback_image;
340 	};
341 };
342 
343 class GLQueueRunner {
344 public:
GLQueueRunner()345 	GLQueueRunner() {}
346 
SetErrorCallback(ErrorCallbackFn callback,void * userdata)347 	void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {
348 		errorCallback_ = callback;
349 		errorCallbackUserData_ = userdata;
350 	}
351 
352 	void RunInitSteps(const std::vector<GLRInitStep> &steps, bool skipGLCalls);
353 
354 	void RunSteps(const std::vector<GLRStep *> &steps, bool skipGLCalls);
355 	void LogSteps(const std::vector<GLRStep *> &steps);
356 
357 	void CreateDeviceObjects();
358 	void DestroyDeviceObjects();
359 
RPIndex(GLRRenderPassAction color,GLRRenderPassAction depth)360 	inline int RPIndex(GLRRenderPassAction color, GLRRenderPassAction depth) {
361 		return (int)depth * 3 + (int)color;
362 	}
363 
364 	void CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels);
365 
Resize(int width,int height)366 	void Resize(int width, int height) {
367 		targetWidth_ = width;
368 		targetHeight_ = height;
369 	}
370 
SawOutOfMemory()371 	bool SawOutOfMemory() {
372 		return sawOutOfMemory_;
373 	}
374 
GetGLString(int name)375 	std::string GetGLString(int name) const {
376 		auto it = glStrings_.find(name);
377 		return it != glStrings_.end() ? it->second : "";
378 	}
379 
380 private:
381 	void InitCreateFramebuffer(const GLRInitStep &step);
382 
383 	void PerformBindFramebufferAsRenderTarget(const GLRStep &pass);
384 	void PerformRenderPass(const GLRStep &pass, bool first, bool last);
385 	void PerformCopy(const GLRStep &pass);
386 	void PerformBlit(const GLRStep &pass);
387 	void PerformReadback(const GLRStep &pass);
388 	void PerformReadbackImage(const GLRStep &pass);
389 
390 	void LogRenderPass(const GLRStep &pass);
391 	void LogCopy(const GLRStep &pass);
392 	void LogBlit(const GLRStep &pass);
393 	void LogReadback(const GLRStep &pass);
394 	void LogReadbackImage(const GLRStep &pass);
395 
396 	void ResizeReadbackBuffer(size_t requiredSize);
397 
398 	void fbo_ext_create(const GLRInitStep &step);
399 	void fbo_bind_fb_target(bool read, GLuint name);
400 	GLenum fbo_get_fb_target(bool read, GLuint **cached);
401 	void fbo_unbind();
402 
403 	GLRFramebuffer *curFB_ = nullptr;
404 
405 	GLuint globalVAO_ = 0;
406 
407 	int curFBWidth_ = 0;
408 	int curFBHeight_ = 0;
409 	int targetWidth_ = 0;
410 	int targetHeight_ = 0;
411 
412 	// Readback buffer. Currently we only support synchronous readback, so we only really need one.
413 	// We size it generously.
414 	uint8_t *readbackBuffer_ = nullptr;
415 	int readbackBufferSize_ = 0;
416 	// Temp buffer for color conversion
417 	uint8_t *tempBuffer_ = nullptr;
418 	int tempBufferSize_ = 0;
419 
420 	float maxAnisotropyLevel_ = 0.0f;
421 
422 	// Framebuffer state?
423 	GLuint currentDrawHandle_ = 0;
424 	GLuint currentReadHandle_ = 0;
425 
426 	GLuint AllocTextureName();
427 
428 	// Texture name cache. Ripped straight from TextureCacheGLES.
429 	std::vector<GLuint> nameCache_;
430 	std::unordered_map<int, std::string> glStrings_;
431 
432 	bool sawOutOfMemory_ = false;
433 	bool useDebugGroups_ = false;
434 
435 	ErrorCallbackFn errorCallback_ = nullptr;
436 	void *errorCallbackUserData_ = nullptr;
437 };
438