opengl_device.h (10265B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0) 3 4 #pragma once 5 6 #include "gpu_device.h" 7 #include "gpu_framebuffer_manager.h" 8 #include "gpu_shader_cache.h" 9 #include "opengl_context.h" 10 #include "opengl_loader.h" 11 #include "opengl_pipeline.h" 12 #include "opengl_texture.h" 13 14 #include <cstdio> 15 #include <memory> 16 #include <string_view> 17 #include <tuple> 18 19 class OpenGLPipeline; 20 class OpenGLStreamBuffer; 21 class OpenGLTexture; 22 class OpenGLDownloadTexture; 23 24 class OpenGLDevice final : public GPUDevice 25 { 26 friend OpenGLTexture; 27 friend OpenGLDownloadTexture; 28 29 public: 30 OpenGLDevice(); 31 ~OpenGLDevice(); 32 33 ALWAYS_INLINE static OpenGLDevice& GetInstance() { return *static_cast<OpenGLDevice*>(g_gpu_device.get()); } 34 ALWAYS_INLINE static OpenGLStreamBuffer* GetTextureStreamBuffer() 35 { 36 return GetInstance().m_texture_stream_buffer.get(); 37 } 38 ALWAYS_INLINE static bool IsGLES() { return GetInstance().m_gl_context->IsGLES(); } 39 static void BindUpdateTextureUnit(); 40 static bool ShouldUsePBOsForDownloads(); 41 static void SetErrorObject(Error* errptr, std::string_view prefix, GLenum glerr); 42 43 RenderAPI GetRenderAPI() const override; 44 45 bool HasSurface() const override; 46 void DestroySurface() override; 47 48 bool UpdateWindow() override; 49 void ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale) override; 50 51 std::string GetDriverInfo() const override; 52 53 void ExecuteAndWaitForGPUIdle() override; 54 55 std::unique_ptr<GPUTexture> CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples, 56 GPUTexture::Type type, GPUTexture::Format format, 57 const void* data = nullptr, u32 data_stride = 0) override; 58 std::unique_ptr<GPUSampler> CreateSampler(const GPUSampler::Config& config) override; 59 std::unique_ptr<GPUTextureBuffer> CreateTextureBuffer(GPUTextureBuffer::Format format, u32 size_in_elements) override; 60 61 std::unique_ptr<GPUDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GPUTexture::Format format) override; 62 std::unique_ptr<GPUDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GPUTexture::Format format, 63 void* memory, size_t memory_size, 64 u32 memory_stride) override; 65 66 bool SupportsTextureFormat(GPUTexture::Format format) const override; 67 void CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src, 68 u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) override; 69 void ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src, 70 u32 src_x, u32 src_y, u32 width, u32 height) override; 71 void ClearRenderTarget(GPUTexture* t, u32 c) override; 72 void ClearDepth(GPUTexture* t, float d) override; 73 void InvalidateRenderTarget(GPUTexture* t) override; 74 75 std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShaderStage stage, std::span<const u8> data, 76 Error* error) override; 77 std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShaderStage stage, GPUShaderLanguage language, 78 std::string_view source, const char* entry_point, 79 DynamicHeapArray<u8>* out_binary, Error* error) override; 80 std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config, Error* error) override; 81 82 void PushDebugGroup(const char* name) override; 83 void PopDebugGroup() override; 84 void InsertDebugMessage(const char* msg) override; 85 86 void MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_ptr, u32* map_space, 87 u32* map_base_vertex) override; 88 void UnmapVertexBuffer(u32 vertex_size, u32 vertex_count) override; 89 void MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index) override; 90 void UnmapIndexBuffer(u32 used_index_count) override; 91 void PushUniformBuffer(const void* data, u32 data_size) override; 92 void* MapUniformBuffer(u32 size) override; 93 void UnmapUniformBuffer(u32 size) override; 94 void SetRenderTargets(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, 95 GPUPipeline::RenderPassFlag feedback_loop = GPUPipeline::NoRenderPassFlags) override; 96 void SetPipeline(GPUPipeline* pipeline) override; 97 void SetTextureSampler(u32 slot, GPUTexture* texture, GPUSampler* sampler) override; 98 void SetTextureBuffer(u32 slot, GPUTextureBuffer* buffer) override; 99 void SetViewport(const GSVector4i rc) override; 100 void SetScissor(const GSVector4i rc) override; 101 void Draw(u32 vertex_count, u32 base_vertex) override; 102 void DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex) override; 103 void DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type) override; 104 105 void SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle) override; 106 107 bool BeginPresent(bool skip_present, u32 clear_color) override; 108 void EndPresent(bool explicit_present) override; 109 void SubmitPresent() override; 110 111 bool SetGPUTimingEnabled(bool enabled) override; 112 float GetAndResetAccumulatedGPUTime() override; 113 114 void CommitClear(OpenGLTexture* tex); 115 void CommitRTClearInFB(OpenGLTexture* tex, u32 idx); 116 void CommitDSClearInFB(OpenGLTexture* tex); 117 118 GLuint LookupProgramCache(const OpenGLPipeline::ProgramCacheKey& key, const GPUPipeline::GraphicsConfig& plconfig, Error* error); 119 GLuint CompileProgram(const GPUPipeline::GraphicsConfig& plconfig, Error* error); 120 void PostLinkProgram(const GPUPipeline::GraphicsConfig& plconfig, GLuint program_id); 121 void UnrefProgram(const OpenGLPipeline::ProgramCacheKey& key); 122 123 OpenGLPipeline::VertexArrayCache::const_iterator LookupVAOCache(const OpenGLPipeline::VertexArrayCacheKey& key, Error* error); 124 GLuint CreateVAO(std::span<const GPUPipeline::VertexAttribute> attributes, u32 stride, Error* error); 125 void UnrefVAO(const OpenGLPipeline::VertexArrayCacheKey& key); 126 127 void SetActiveTexture(u32 slot); 128 void UnbindTexture(GLuint id); 129 void UnbindTexture(OpenGLTexture* tex); 130 void UnbindSSBO(GLuint id); 131 void UnbindSampler(GLuint id); 132 void UnbindPipeline(const OpenGLPipeline* pl); 133 134 protected: 135 bool CreateDevice(std::string_view adapter, bool threaded_presentation, 136 std::optional<bool> exclusive_fullscreen_control, FeatureMask disabled_features, 137 Error* error) override; 138 void DestroyDevice() override; 139 140 bool OpenPipelineCache(const std::string& filename) override; 141 bool GetPipelineCacheData(DynamicHeapArray<u8>* data) override; 142 143 private: 144 static constexpr u8 NUM_TIMESTAMP_QUERIES = 3; 145 146 static constexpr GLenum UPDATE_TEXTURE_UNIT = GL_TEXTURE8; 147 148 static constexpr u32 VERTEX_BUFFER_SIZE = 8 * 1024 * 1024; 149 static constexpr u32 INDEX_BUFFER_SIZE = 4 * 1024 * 1024; 150 static constexpr u32 UNIFORM_BUFFER_SIZE = 2 * 1024 * 1024; 151 static constexpr u32 TEXTURE_STREAM_BUFFER_SIZE = 16 * 1024 * 1024; 152 153 bool CheckFeatures(FeatureMask disabled_features); 154 bool CreateBuffers(); 155 void DestroyBuffers(); 156 157 void SetSwapInterval(); 158 void RenderBlankFrame(); 159 160 s32 IsRenderTargetBound(const GPUTexture* tex) const; 161 static GLuint CreateFramebuffer(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags); 162 static void DestroyFramebuffer(GLuint fbo); 163 164 void UpdateViewport(); 165 void UpdateScissor(); 166 167 void CreateTimestampQueries(); 168 void DestroyTimestampQueries(); 169 void PopTimestampQuery(); 170 void KickTimestampQuery(); 171 172 GLuint CreateProgramFromPipelineCache(const OpenGLPipeline::ProgramCacheItem& it, 173 const GPUPipeline::GraphicsConfig& plconfig); 174 void AddToPipelineCache(OpenGLPipeline::ProgramCacheItem* it); 175 bool DiscardPipelineCache(); 176 void ClosePipelineCache(); 177 178 void ApplyRasterizationState(GPUPipeline::RasterizationState rs); 179 void ApplyDepthState(GPUPipeline::DepthState ds); 180 void ApplyBlendState(GPUPipeline::BlendState bs); 181 182 void SetVertexBufferOffsets(u32 base_vertex); 183 184 std::unique_ptr<OpenGLContext> m_gl_context; 185 186 std::unique_ptr<OpenGLStreamBuffer> m_vertex_buffer; 187 std::unique_ptr<OpenGLStreamBuffer> m_index_buffer; 188 std::unique_ptr<OpenGLStreamBuffer> m_uniform_buffer; 189 std::unique_ptr<OpenGLStreamBuffer> m_texture_stream_buffer; 190 191 // TODO: pass in file instead of blob for pipeline cache 192 OpenGLPipeline::VertexArrayCache m_vao_cache; 193 OpenGLPipeline::ProgramCache m_program_cache; 194 GPUFramebufferManager<GLuint, CreateFramebuffer, DestroyFramebuffer> m_framebuffer_manager; 195 196 // VAO cache - fixed max as key 197 OpenGLPipeline::VertexArrayCache::const_iterator m_last_vao = m_vao_cache.cend(); 198 GPUPipeline::BlendState m_last_blend_state = {}; 199 GPUPipeline::RasterizationState m_last_rasterization_state = {}; 200 GPUPipeline::DepthState m_last_depth_state = {}; 201 GLuint m_uniform_buffer_alignment = 1; 202 GLuint m_last_program = 0; 203 u32 m_last_texture_unit = 0; 204 std::array<std::pair<GLuint, GLuint>, MAX_TEXTURE_SAMPLERS> m_last_samplers = {}; 205 GLuint m_last_ssbo = 0; 206 GSVector4i m_last_viewport = {}; 207 GSVector4i m_last_scissor = GSVector4i::cxpr(0, 0, 1, 1); 208 209 // Misc framebuffers 210 GLuint m_read_fbo = 0; 211 GLuint m_write_fbo = 0; 212 213 GLuint m_current_fbo = 0; 214 u32 m_num_current_render_targets = 0; 215 std::array<OpenGLTexture*, MAX_RENDER_TARGETS> m_current_render_targets = {}; 216 OpenGLTexture* m_current_depth_target = nullptr; 217 218 OpenGLPipeline* m_current_pipeline = nullptr; 219 220 std::array<GLuint, NUM_TIMESTAMP_QUERIES> m_timestamp_queries = {}; 221 float m_accumulated_gpu_time = 0.0f; 222 u8 m_read_timestamp_query = 0; 223 u8 m_write_timestamp_query = 0; 224 u8 m_waiting_timestamp_queries = 0; 225 bool m_timestamp_query_started = false; 226 227 std::FILE* m_pipeline_disk_cache_file = nullptr; 228 std::string m_pipeline_disk_cache_filename; 229 u32 m_pipeline_disk_cache_data_end = 0; 230 bool m_pipeline_disk_cache_changed = false; 231 232 bool m_disable_pbo = false; 233 bool m_disable_async_download = false; 234 };