/ src / video_core / renderer_opengl / gl_resource_manager.cpp
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