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