CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Common/GPU/OpenGL/GLQueueRunner.h
Views: 1401
#pragma once12#include <cstdint>3#include <vector>4#include <set>5#include <unordered_map>67#include "Common/GPU/OpenGL/GLCommon.h"8#include "Common/GPU/OpenGL/GLFrameData.h"9#include "Common/GPU/DataFormat.h"10#include "Common/GPU/Shader.h"11#include "Common/GPU/thin3d.h"12#include "Common/Data/Collections/TinySet.h"13#include "Common/Data/Collections/FastVec.h"1415struct GLRViewport {16float x, y, w, h, minZ, maxZ;17};1819struct GLRect2D {20int x, y, w, h;21};2223struct GLOffset2D {24int x, y;25};2627enum class GLRAllocType : uint8_t {28NONE,29NEW,30ALIGNED,31};3233class GLRShader;34class GLRTexture;35class GLRBuffer;36class GLRFramebuffer;37class GLRProgram;38class GLRInputLayout;3940enum class GLRRenderCommand : uint8_t {41DEPTH,42STENCIL,43BLEND,44BLENDCOLOR,45LOGICOP,46UNIFORM4I,47UNIFORM4UI,48UNIFORM4F,49UNIFORMMATRIX,50UNIFORMSTEREOMATRIX,51TEXTURESAMPLER,52TEXTURELOD,53VIEWPORT,54SCISSOR,55RASTER,56CLEAR,57INVALIDATE,58BINDPROGRAM,59BINDTEXTURE,60BIND_FB_TEXTURE,61BIND_VERTEX_BUFFER,62GENMIPS,63DRAW,64TEXTURE_SUBIMAGE,65};6667// TODO: Bloated since the biggest struct decides the size. Will need something more efficient (separate structs with shared68// type field, smashed right after each other?)69// Also, all GLenums are really only 16 bits.70struct GLRRenderData {71GLRRenderData(GLRRenderCommand _cmd) : cmd(_cmd) {}72GLRRenderCommand cmd;73union {74struct {75GLboolean enabled;76GLenum srcColor;77GLenum dstColor;78GLenum srcAlpha;79GLenum dstAlpha;80GLenum funcColor;81GLenum funcAlpha;82int mask;83} blend;84struct {85float color[4];86} blendColor;87struct {88GLboolean enabled;89GLenum logicOp;90} logic;91struct {92GLboolean enabled;93GLboolean write;94GLenum func;95} depth;96struct {97GLenum func;98GLenum sFail;99GLenum zFail;100GLenum pass;101GLboolean enabled;102uint8_t ref;103uint8_t compareMask;104uint8_t writeMask;105} stencil;106struct {107GLRInputLayout *inputLayout;108GLRBuffer *vertexBuffer;109GLRBuffer *indexBuffer;110uint32_t vertexOffset;111uint32_t indexOffset;112GLenum mode; // primitive113GLint first;114GLint count;115GLint indexType;116GLint instances;117} draw;118struct {119const char *name; // if null, use loc120const GLint *loc; // NOTE: This is a pointer so we can immediately use things that are "queried" during program creation.121GLint count;122float v[4];123} uniform4;124struct {125const char *name; // if null, use loc126const GLint *loc;127float m[16];128} uniformMatrix4;129struct {130const char *name; // if null, use loc131const GLint *loc;132float *mData; // new'd, 32 entries133} uniformStereoMatrix4;134struct {135uint32_t clearColor;136float clearZ;137uint8_t clearStencil;138uint8_t colorMask; // Like blend, but for the clear.139GLuint clearMask; // GL_COLOR_BUFFER_BIT etc140int16_t scissorX;141int16_t scissorY;142int16_t scissorW;143int16_t scissorH;144} clear; // also used for invalidate145struct {146int slot;147GLRTexture *texture;148} texture;149struct {150GLRTexture *texture;151Draw::DataFormat format;152uint8_t slot;153uint8_t level;154uint16_t width;155uint16_t height;156uint16_t x;157uint16_t y;158GLRAllocType allocType;159uint8_t *data; // owned, delete[]-d160} texture_subimage;161struct {162GLRFramebuffer* framebuffer;163int slot;164int aspect;165} bind_fb_texture;166struct {167GLRBuffer *buffer;168GLuint target;169} bind_buffer;170struct {171GLRProgram *program;172} program;173struct {174int slot;175GLenum wrapS;176GLenum wrapT;177GLenum magFilter;178GLenum minFilter; // also includes mip. GL...179float anisotropy;180} textureSampler;181struct {182int slot;183float minLod;184float maxLod;185float lodBias;186} textureLod;187struct {188GLRViewport vp;189} viewport;190struct {191GLRect2D rc;192} scissor;193struct {194GLenum frontFace;195GLenum cullFace;196GLboolean cullEnable;197GLboolean ditherEnable;198GLboolean depthClampEnable;199} raster;200};201};202203// Unlike in Vulkan, we can't create stuff on the main thread, but need to204// defer this too. A big benefit will be that we'll be able to do all creation205// at the start of the frame.206enum class GLRInitStepType : uint8_t {207CREATE_TEXTURE,208CREATE_SHADER,209CREATE_PROGRAM,210CREATE_BUFFER,211CREATE_INPUT_LAYOUT,212CREATE_FRAMEBUFFER,213214TEXTURE_IMAGE,215TEXTURE_FINALIZE,216BUFFER_SUBDATA,217};218219struct GLRInitStep {220GLRInitStep(GLRInitStepType _type) : stepType(_type) {}221GLRInitStepType stepType;222union {223struct {224GLRTexture *texture;225} create_texture;226struct {227GLRShader *shader;228// This char arrays needs to be allocated with new[].229char *code;230GLuint stage;231} create_shader;232struct {233GLRProgram *program;234GLRShader *shaders[3];235int num_shaders;236bool support_dual_source;237} create_program;238struct {239GLRBuffer *buffer;240int size;241GLuint usage;242} create_buffer;243struct {244GLRInputLayout *inputLayout;245} create_input_layout;246struct {247GLRFramebuffer *framebuffer;248} create_framebuffer;249struct {250GLRBuffer *buffer;251int offset;252int size;253uint8_t *data; // owned, delete[]-d254bool deleteData;255} buffer_subdata;256struct {257GLRTexture *texture;258Draw::DataFormat format;259int level;260uint16_t width;261uint16_t height;262uint16_t depth;263GLRAllocType allocType;264bool linearFilter;265uint8_t *data; // owned, delete[]-d266} texture_image;267struct {268GLRTexture *texture;269int loadedLevels;270bool genMips;271} texture_finalize;272};273};274275enum class GLRStepType : uint8_t {276RENDER,277COPY,278BLIT,279READBACK,280READBACK_IMAGE,281RENDER_SKIP,282};283284enum class GLRRenderPassAction {285DONT_CARE,286CLEAR,287KEEP,288};289290class GLRFramebuffer;291292enum GLRAspect {293GLR_ASPECT_COLOR = 1,294GLR_ASPECT_DEPTH = 2,295GLR_ASPECT_STENCIL = 3,296};297const char *GLRAspectToString(GLRAspect aspect);298299struct GLRStep {300GLRStep(GLRStepType _type) : stepType(_type), tag() {}301GLRStepType stepType;302FastVec<GLRRenderData> commands;303TinySet<const GLRFramebuffer *, 8> dependencies;304const char *tag;305union {306struct {307GLRFramebuffer *framebuffer;308GLRRenderPassAction color;309GLRRenderPassAction depth;310GLRRenderPassAction stencil;311} render;312struct {313GLRFramebuffer *src;314GLRFramebuffer *dst;315GLRect2D srcRect;316GLOffset2D dstPos;317int aspectMask;318} copy;319struct {320GLRFramebuffer *src;321GLRFramebuffer *dst;322GLRect2D srcRect;323GLRect2D dstRect;324int aspectMask;325GLboolean filter;326} blit;327struct {328GLRFramebuffer* src;329GLRect2D srcRect;330int aspectMask;331Draw::DataFormat dstFormat;332} readback;333struct {334GLRTexture *texture;335GLRect2D srcRect;336int mipLevel;337} readback_image;338};339};340341class GLQueueRunner {342public:343GLQueueRunner() {}344345void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {346errorCallback_ = callback;347errorCallbackUserData_ = userdata;348}349350void SetDeviceCaps(const Draw::DeviceCaps &caps) {351caps_ = caps;352}353354void RunInitSteps(const FastVec<GLRInitStep> &steps, bool skipGLCalls);355356void RunSteps(const std::vector<GLRStep *> &steps, GLFrameData &frameData, bool skipGLCalls, bool keepSteps, bool useVR);357358void CreateDeviceObjects();359void DestroyDeviceObjects();360361void CopyFromReadbackBuffer(GLRFramebuffer *framebuffer, int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels);362363void Resize(int width, int height) {364targetWidth_ = width;365targetHeight_ = height;366}367368bool SawOutOfMemory() {369return sawOutOfMemory_;370}371372std::string GetGLString(int name) const {373auto it = glStrings_.find(name);374return it != glStrings_.end() ? it->second : "";375}376377private:378void InitCreateFramebuffer(const GLRInitStep &step);379380void PerformBindFramebufferAsRenderTarget(const GLRStep &pass);381void PerformRenderPass(const GLRStep &pass, bool first, bool last, GLQueueProfileContext &profile);382void PerformCopy(const GLRStep &pass);383void PerformBlit(const GLRStep &pass);384void PerformReadback(const GLRStep &pass);385void PerformReadbackImage(const GLRStep &pass);386387void fbo_ext_create(const GLRInitStep &step);388void fbo_bind_fb_target(bool read, GLuint name);389GLenum fbo_get_fb_target(bool read, GLuint **cached);390void fbo_unbind();391392std::string StepToString(const GLRStep &step) const;393394GLRFramebuffer *curFB_ = nullptr;395396GLuint globalVAO_ = 0;397398Draw::DeviceCaps caps_{}; // For sanity checks.399400int curFBWidth_ = 0;401int curFBHeight_ = 0;402int targetWidth_ = 0;403int targetHeight_ = 0;404405// Readback buffer. Currently we only support synchronous readback, so we only really need one.406// We size it generously.407uint8_t *readbackBuffer_ = nullptr;408int readbackBufferSize_ = 0;409uint32_t readbackAspectMask_ = 0;410411float maxAnisotropyLevel_ = 0.0f;412413// Framebuffer state?414GLuint currentDrawHandle_ = 0;415GLuint currentReadHandle_ = 0;416417std::unordered_map<int, std::string> glStrings_;418419bool sawOutOfMemory_ = false;420bool useDebugGroups_ = false;421422ErrorCallbackFn errorCallback_ = nullptr;423void *errorCallbackUserData_ = nullptr;424};425426const char *RenderCommandToString(GLRRenderCommand cmd);427428429