gl_resource_manager.cpp
1 // Copyright 2022 Citra Emulator Project 2 // Licensed under GPLv2 or any later version 3 // Refer to the license.txt file included. 4 5 #include "common/microprofile.h" 6 #include "video_core/renderer_opengl/gl_resource_manager.h" 7 #include "video_core/renderer_opengl/gl_shader_util.h" 8 #include "video_core/renderer_opengl/gl_state.h" 9 10 MICROPROFILE_DEFINE(OpenGL_ResourceCreation, "OpenGL", "Resource Creation", MP_RGB(128, 128, 192)); 11 MICROPROFILE_DEFINE(OpenGL_ResourceDeletion, "OpenGL", "Resource Deletion", MP_RGB(128, 128, 192)); 12 13 namespace OpenGL { 14 15 void OGLRenderbuffer::Create() { 16 if (handle != 0) { 17 return; 18 } 19 20 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 21 glGenRenderbuffers(1, &handle); 22 } 23 24 void OGLRenderbuffer::Release() { 25 if (handle == 0) { 26 return; 27 } 28 29 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); 30 glDeleteRenderbuffers(1, &handle); 31 OpenGLState::GetCurState().ResetRenderbuffer(handle).Apply(); 32 handle = 0; 33 } 34 35 void OGLTexture::Create() { 36 if (handle != 0) { 37 return; 38 } 39 40 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 41 glGenTextures(1, &handle); 42 } 43 44 void OGLTexture::Release() { 45 if (handle == 0) { 46 return; 47 } 48 49 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); 50 glDeleteTextures(1, &handle); 51 OpenGLState::GetCurState().ResetTexture(handle).Apply(); 52 handle = 0; 53 } 54 55 void OGLTexture::Allocate(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, 56 GLsizei height, GLsizei depth) { 57 GLuint old_tex = OpenGLState::GetCurState().texture_units[0].texture_2d; 58 glActiveTexture(GL_TEXTURE0); 59 glBindTexture(target, handle); 60 61 switch (target) { 62 case GL_TEXTURE_1D: 63 case GL_TEXTURE: 64 glTexStorage1D(target, levels, internalformat, width); 65 break; 66 case GL_TEXTURE_2D: 67 case GL_TEXTURE_1D_ARRAY: 68 case GL_TEXTURE_RECTANGLE: 69 case GL_TEXTURE_CUBE_MAP: 70 glTexStorage2D(target, levels, internalformat, width, height); 71 break; 72 case GL_TEXTURE_3D: 73 case GL_TEXTURE_2D_ARRAY: 74 case GL_TEXTURE_CUBE_MAP_ARRAY: 75 glTexStorage3D(target, levels, internalformat, width, height, depth); 76 break; 77 } 78 79 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 80 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 81 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 82 83 glBindTexture(GL_TEXTURE_2D, old_tex); 84 } 85 86 void OGLSampler::Create() { 87 if (handle != 0) { 88 return; 89 } 90 91 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 92 glGenSamplers(1, &handle); 93 } 94 95 void OGLSampler::Release() { 96 if (handle == 0) { 97 return; 98 } 99 100 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); 101 glDeleteSamplers(1, &handle); 102 OpenGLState::GetCurState().ResetSampler(handle).Apply(); 103 handle = 0; 104 } 105 106 void OGLShader::Create(std::string_view source, GLenum type) { 107 if (handle != 0) 108 return; 109 if (source.empty()) 110 return; 111 112 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 113 handle = LoadShader(source, type); 114 } 115 116 void OGLShader::Release() { 117 if (handle == 0) 118 return; 119 120 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); 121 glDeleteShader(handle); 122 handle = 0; 123 } 124 125 void OGLProgram::Create(bool separable_program, std::span<const GLuint> shaders) { 126 if (handle != 0) 127 return; 128 129 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 130 handle = LoadProgram(separable_program, shaders); 131 } 132 133 void OGLProgram::Create(std::string_view vert_shader, std::string_view frag_shader) { 134 OGLShader vert, frag; 135 vert.Create(vert_shader, GL_VERTEX_SHADER); 136 frag.Create(frag_shader, GL_FRAGMENT_SHADER); 137 138 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 139 const std::array shaders{vert.handle, frag.handle}; 140 Create(false, shaders); 141 } 142 143 void OGLProgram::Release() { 144 if (handle == 0) 145 return; 146 147 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); 148 glDeleteProgram(handle); 149 OpenGLState::GetCurState().ResetProgram(handle).Apply(); 150 handle = 0; 151 } 152 153 void OGLPipeline::Create() { 154 if (handle != 0) 155 return; 156 157 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 158 glGenProgramPipelines(1, &handle); 159 } 160 161 void OGLPipeline::Release() { 162 if (handle == 0) 163 return; 164 165 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); 166 glDeleteProgramPipelines(1, &handle); 167 OpenGLState::GetCurState().ResetPipeline(handle).Apply(); 168 handle = 0; 169 } 170 171 void OGLBuffer::Create() { 172 if (handle != 0) 173 return; 174 175 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 176 glGenBuffers(1, &handle); 177 } 178 179 void OGLBuffer::Release() { 180 if (handle == 0) 181 return; 182 183 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); 184 glDeleteBuffers(1, &handle); 185 OpenGLState::GetCurState().ResetBuffer(handle).Apply(); 186 handle = 0; 187 } 188 189 void OGLVertexArray::Create() { 190 if (handle != 0) 191 return; 192 193 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 194 glGenVertexArrays(1, &handle); 195 } 196 197 void OGLVertexArray::Release() { 198 if (handle == 0) 199 return; 200 201 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); 202 glDeleteVertexArrays(1, &handle); 203 OpenGLState::GetCurState().ResetVertexArray(handle).Apply(); 204 handle = 0; 205 } 206 207 void OGLFramebuffer::Create() { 208 if (handle != 0) 209 return; 210 211 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 212 glGenFramebuffers(1, &handle); 213 } 214 215 void OGLFramebuffer::Release() { 216 if (handle == 0) 217 return; 218 219 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); 220 glDeleteFramebuffers(1, &handle); 221 OpenGLState::GetCurState().ResetFramebuffer(handle).Apply(); 222 handle = 0; 223 } 224 225 } // namespace OpenGL