1 #include "ppsspp_config.h"
2 #include <algorithm>
3
4 #include "Common/GPU/OpenGL/GLCommon.h"
5 #include "Common/GPU/OpenGL/GLDebugLog.h"
6 #include "Common/GPU/OpenGL/GLFeatures.h"
7 #include "Common/GPU/OpenGL/DataFormatGL.h"
8 #include "Common/Math/math_util.h"
9
10 #include "Common/Log.h"
11 #include "Common/MemoryUtil.h"
12 #include "Common/StringUtils.h"
13 #include "Common/Data/Convert/SmallDataConvert.h"
14
15 #include "Core/Reporting.h"
16 #include "GLQueueRunner.h"
17 #include "GLRenderManager.h"
18 #include "DataFormatGL.h"
19
20 static constexpr int TEXCACHE_NAME_CACHE_SIZE = 16;
21
22 #if PPSSPP_PLATFORM(IOS)
23 extern void bindDefaultFBO();
24 #endif
25
26 // Workaround for Retroarch. Simply declare
27 // extern GLuint g_defaultFBO;
28 // and set is as appropriate. Can adjust the variables in ext/native/base/display.h as
29 // appropriate.
30 GLuint g_defaultFBO = 0;
31
CreateDeviceObjects()32 void GLQueueRunner::CreateDeviceObjects() {
33 CHECK_GL_ERROR_IF_DEBUG();
34 if (gl_extensions.EXT_texture_filter_anisotropic) {
35 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel_);
36 } else {
37 maxAnisotropyLevel_ = 0.0f;
38 }
39
40 if (gl_extensions.ARB_vertex_array_object) {
41 glGenVertexArrays(1, &globalVAO_);
42 }
43
44 // An eternal optimist.
45 sawOutOfMemory_ = false;
46
47 // Populate some strings from the GL thread so they can be queried from thin3d.
48 // TODO: Merge with GLFeatures.cpp/h
49 auto populate = [&](int name) {
50 const GLubyte *value = glGetString(name);
51 if (!value)
52 glStrings_[name] = "?";
53 else
54 glStrings_[name] = (const char *)value;
55 };
56 populate(GL_VENDOR);
57 populate(GL_RENDERER);
58 populate(GL_VERSION);
59 populate(GL_SHADING_LANGUAGE_VERSION);
60 CHECK_GL_ERROR_IF_DEBUG();
61
62 useDebugGroups_ = !gl_extensions.IsGLES && gl_extensions.VersionGEThan(4, 3);
63 }
64
DestroyDeviceObjects()65 void GLQueueRunner::DestroyDeviceObjects() {
66 CHECK_GL_ERROR_IF_DEBUG();
67 if (!nameCache_.empty()) {
68 glDeleteTextures((GLsizei)nameCache_.size(), &nameCache_[0]);
69 nameCache_.clear();
70 }
71 if (gl_extensions.ARB_vertex_array_object) {
72 glDeleteVertexArrays(1, &globalVAO_);
73 }
74 delete[] readbackBuffer_;
75 readbackBuffer_ = nullptr;
76 readbackBufferSize_ = 0;
77 delete[] tempBuffer_;
78 tempBuffer_ = nullptr;
79 tempBufferSize_ = 0;
80 CHECK_GL_ERROR_IF_DEBUG();
81 }
82
83 template <typename Getiv, typename GetLog>
GetInfoLog(GLuint name,Getiv getiv,GetLog getLog)84 static std::string GetInfoLog(GLuint name, Getiv getiv, GetLog getLog) {
85 GLint bufLength = 0;
86 getiv(name, GL_INFO_LOG_LENGTH, &bufLength);
87 if (bufLength <= 0)
88 bufLength = 2048;
89
90 std::string infoLog;
91 infoLog.resize(bufLength);
92 GLsizei len = 0;
93 getLog(name, (GLsizei)infoLog.size(), &len, &infoLog[0]);
94 if (len <= 0)
95 return "(unknown reason)";
96
97 infoLog.resize(len);
98 return infoLog;
99 }
100
RunInitSteps(const std::vector<GLRInitStep> & steps,bool skipGLCalls)101 void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool skipGLCalls) {
102 if (skipGLCalls) {
103 // Some bookkeeping still needs to be done.
104 for (size_t i = 0; i < steps.size(); i++) {
105 const GLRInitStep &step = steps[i];
106 switch (step.stepType) {
107 case GLRInitStepType::BUFFER_SUBDATA:
108 {
109 if (step.buffer_subdata.deleteData)
110 delete[] step.buffer_subdata.data;
111 break;
112 }
113 case GLRInitStepType::TEXTURE_IMAGE:
114 {
115 if (step.texture_image.allocType == GLRAllocType::ALIGNED) {
116 FreeAlignedMemory(step.texture_image.data);
117 } else if (step.texture_image.allocType == GLRAllocType::NEW) {
118 delete[] step.texture_image.data;
119 }
120 break;
121 }
122 case GLRInitStepType::CREATE_PROGRAM:
123 {
124 WARN_LOG(G3D, "CREATE_PROGRAM found with skipGLCalls, not good");
125 break;
126 }
127 case GLRInitStepType::CREATE_SHADER:
128 {
129 WARN_LOG(G3D, "CREATE_SHADER found with skipGLCalls, not good");
130 break;
131 }
132 default:
133 break;
134 }
135 }
136 return;
137 }
138
139 #if !defined(USING_GLES2)
140 if (useDebugGroups_)
141 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "InitSteps");
142 #endif
143
144 CHECK_GL_ERROR_IF_DEBUG();
145 glActiveTexture(GL_TEXTURE0);
146 GLuint boundTexture = (GLuint)-1;
147 bool allocatedTextures = false;
148
149 for (size_t i = 0; i < steps.size(); i++) {
150 const GLRInitStep &step = steps[i];
151 switch (step.stepType) {
152 case GLRInitStepType::CREATE_TEXTURE:
153 {
154 GLRTexture *tex = step.create_texture.texture;
155 glGenTextures(1, &tex->texture);
156 glBindTexture(tex->target, tex->texture);
157 boundTexture = tex->texture;
158 CHECK_GL_ERROR_IF_DEBUG();
159 break;
160 }
161 case GLRInitStepType::CREATE_BUFFER:
162 {
163 GLRBuffer *buffer = step.create_buffer.buffer;
164 glGenBuffers(1, &buffer->buffer_);
165 glBindBuffer(buffer->target_, buffer->buffer_);
166 glBufferData(buffer->target_, step.create_buffer.size, nullptr, step.create_buffer.usage);
167 CHECK_GL_ERROR_IF_DEBUG();
168 break;
169 }
170 case GLRInitStepType::BUFFER_SUBDATA:
171 {
172 GLRBuffer *buffer = step.buffer_subdata.buffer;
173 glBindBuffer(buffer->target_, buffer->buffer_);
174 glBufferSubData(buffer->target_, step.buffer_subdata.offset, step.buffer_subdata.size, step.buffer_subdata.data);
175 if (step.buffer_subdata.deleteData)
176 delete[] step.buffer_subdata.data;
177 CHECK_GL_ERROR_IF_DEBUG();
178 break;
179 }
180 case GLRInitStepType::CREATE_PROGRAM:
181 {
182 CHECK_GL_ERROR_IF_DEBUG();
183 GLRProgram *program = step.create_program.program;
184 program->program = glCreateProgram();
185 _assert_msg_(step.create_program.num_shaders > 0, "Can't create a program with zero shaders");
186 bool anyFailed = false;
187 for (int j = 0; j < step.create_program.num_shaders; j++) {
188 _dbg_assert_msg_(step.create_program.shaders[j]->shader, "Can't create a program with a null shader");
189 anyFailed = anyFailed || step.create_program.shaders[j]->failed;
190 glAttachShader(program->program, step.create_program.shaders[j]->shader);
191 }
192
193 for (auto iter : program->semantics_) {
194 glBindAttribLocation(program->program, iter.location, iter.attrib);
195 }
196
197 #if !defined(USING_GLES2)
198 if (step.create_program.support_dual_source) {
199 // Dual source alpha
200 glBindFragDataLocationIndexed(program->program, 0, 0, "fragColor0");
201 glBindFragDataLocationIndexed(program->program, 0, 1, "fragColor1");
202 } else if (gl_extensions.VersionGEThan(3, 0, 0)) {
203 glBindFragDataLocation(program->program, 0, "fragColor0");
204 }
205 #elif !PPSSPP_PLATFORM(IOS)
206 if (gl_extensions.GLES3 && step.create_program.support_dual_source) {
207 glBindFragDataLocationIndexedEXT(program->program, 0, 0, "fragColor0");
208 glBindFragDataLocationIndexedEXT(program->program, 0, 1, "fragColor1");
209 }
210 #endif
211 glLinkProgram(program->program);
212
213 GLint linkStatus = GL_FALSE;
214 glGetProgramiv(program->program, GL_LINK_STATUS, &linkStatus);
215 if (linkStatus != GL_TRUE) {
216 std::string infoLog = GetInfoLog(program->program, glGetProgramiv, glGetProgramInfoLog);
217
218 // TODO: Could be other than vs/fs. Also, we're assuming order here...
219 GLRShader *vs = step.create_program.shaders[0];
220 GLRShader *fs = step.create_program.num_shaders > 1 ? step.create_program.shaders[1] : nullptr;
221 std::string vsDesc = vs->desc + (vs->failed ? " (failed)" : "");
222 std::string fsDesc = fs ? (fs->desc + (fs->failed ? " (failed)" : "")) : "(none)";
223 const char *vsCode = vs->code.c_str();
224 const char *fsCode = fs ? fs->code.c_str() : "(none)";
225 if (!anyFailed)
226 Reporting::ReportMessage("Error in shader program link: info: %s\nfs: %s\n%s\nvs: %s\n%s", infoLog.c_str(), fsDesc.c_str(), fsCode, vsDesc.c_str(), vsCode);
227
228 ERROR_LOG(G3D, "Could not link program:\n %s", infoLog.c_str());
229 ERROR_LOG(G3D, "VS desc:\n%s", vsDesc.c_str());
230 ERROR_LOG(G3D, "FS desc:\n%s", fsDesc.c_str());
231 ERROR_LOG(G3D, "VS:\n%s\n", vsCode);
232 ERROR_LOG(G3D, "FS:\n%s\n", fsCode);
233
234 #ifdef _WIN32
235 OutputDebugStringUTF8(infoLog.c_str());
236 if (vsCode)
237 OutputDebugStringUTF8(LineNumberString(vsCode).c_str());
238 if (fsCode)
239 OutputDebugStringUTF8(LineNumberString(fsCode).c_str());
240 #endif
241 CHECK_GL_ERROR_IF_DEBUG();
242 break;
243 }
244
245 glUseProgram(program->program);
246
247 // Query all the uniforms.
248 for (size_t j = 0; j < program->queries_.size(); j++) {
249 auto &x = program->queries_[j];
250 _dbg_assert_(x.name);
251 *x.dest = glGetUniformLocation(program->program, x.name);
252 }
253
254 // Run initializers.
255 for (size_t j = 0; j < program->initialize_.size(); j++) {
256 auto &init = program->initialize_[j];
257 GLint uniform = *init.uniform;
258 if (uniform != -1) {
259 switch (init.type) {
260 case 0:
261 glUniform1i(uniform, init.value);
262 break;
263 }
264 }
265 }
266 CHECK_GL_ERROR_IF_DEBUG();
267 break;
268 }
269 case GLRInitStepType::CREATE_SHADER:
270 {
271 CHECK_GL_ERROR_IF_DEBUG();
272 GLuint shader = glCreateShader(step.create_shader.stage);
273 step.create_shader.shader->shader = shader;
274 const char *code = step.create_shader.code;
275 glShaderSource(shader, 1, &code, nullptr);
276 glCompileShader(shader);
277 GLint success = 0;
278 glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
279 std::string infoLog = GetInfoLog(shader, glGetShaderiv, glGetShaderInfoLog);
280 if (!success) {
281 std::string errorString = StringFromFormat(
282 "Error in shader compilation for: %s\n"
283 "Info log: %s\n"
284 "Shader source:\n%s\n//END\n\n",
285 step.create_shader.shader->desc.c_str(),
286 infoLog.c_str(),
287 LineNumberString(code).c_str());
288 std::vector<std::string> lines;
289 SplitString(errorString, '\n', lines);
290 for (auto &line : lines) {
291 ERROR_LOG(G3D, "%s", line.c_str());
292 }
293 if (errorCallback_) {
294 std::string desc = StringFromFormat("Shader compilation failed: %s", step.create_shader.stage == GL_VERTEX_SHADER ? "vertex" : "fragment");
295 errorCallback_(desc.c_str(), errorString.c_str(), errorCallbackUserData_);
296 }
297 Reporting::ReportMessage("Error in shader compilation: info: %s\n%s\n%s", infoLog.c_str(), step.create_shader.shader->desc.c_str(), (const char *)code);
298 #ifdef SHADERLOG
299 OutputDebugStringUTF8(infoLog.c_str());
300 #endif
301 step.create_shader.shader->failed = true;
302 step.create_shader.shader->error = infoLog; // Hm, we never use this.
303 }
304 // Before we throw away the code, attach it to the shader for debugging.
305 step.create_shader.shader->code = code;
306 delete[] step.create_shader.code;
307 step.create_shader.shader->valid = true;
308 CHECK_GL_ERROR_IF_DEBUG();
309 break;
310 }
311 case GLRInitStepType::CREATE_INPUT_LAYOUT:
312 {
313 // GLRInputLayout *layout = step.create_input_layout.inputLayout;
314 // Nothing to do unless we want to create vertexbuffer objects (GL 4.5)
315 break;
316 }
317 case GLRInitStepType::CREATE_FRAMEBUFFER:
318 {
319 CHECK_GL_ERROR_IF_DEBUG();
320 boundTexture = (GLuint)-1;
321 InitCreateFramebuffer(step);
322 allocatedTextures = true;
323 CHECK_GL_ERROR_IF_DEBUG();
324 break;
325 }
326 case GLRInitStepType::TEXTURE_IMAGE:
327 {
328 GLRTexture *tex = step.texture_image.texture;
329 CHECK_GL_ERROR_IF_DEBUG();
330 if (boundTexture != tex->texture) {
331 glBindTexture(tex->target, tex->texture);
332 boundTexture = tex->texture;
333 }
334 if (!step.texture_image.data && step.texture_image.allocType != GLRAllocType::NONE)
335 Crash();
336 // For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage.
337
338 GLenum internalFormat, format, type;
339 int alignment;
340 Thin3DFormatToFormatAndType(step.texture_image.format, internalFormat, format, type, alignment);
341 glTexImage2D(tex->target, step.texture_image.level, internalFormat, step.texture_image.width, step.texture_image.height, 0, format, type, step.texture_image.data);
342 allocatedTextures = true;
343 if (step.texture_image.allocType == GLRAllocType::ALIGNED) {
344 FreeAlignedMemory(step.texture_image.data);
345 } else if (step.texture_image.allocType == GLRAllocType::NEW) {
346 delete[] step.texture_image.data;
347 }
348 CHECK_GL_ERROR_IF_DEBUG();
349 tex->wrapS = GL_CLAMP_TO_EDGE;
350 tex->wrapT = GL_CLAMP_TO_EDGE;
351 tex->magFilter = step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST;
352 tex->minFilter = step.texture_image.linearFilter ? GL_LINEAR : GL_NEAREST;
353 glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, tex->wrapS);
354 glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, tex->wrapT);
355 glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, tex->magFilter);
356 glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, tex->minFilter);
357 CHECK_GL_ERROR_IF_DEBUG();
358 break;
359 }
360 case GLRInitStepType::TEXTURE_FINALIZE:
361 {
362 CHECK_GL_ERROR_IF_DEBUG();
363 GLRTexture *tex = step.texture_finalize.texture;
364 if (boundTexture != tex->texture) {
365 glBindTexture(tex->target, tex->texture);
366 boundTexture = tex->texture;
367 }
368 if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
369 glTexParameteri(tex->target, GL_TEXTURE_MAX_LEVEL, step.texture_finalize.maxLevel);
370 }
371 tex->maxLod = (float)step.texture_finalize.maxLevel;
372 if (step.texture_finalize.genMips) {
373 glGenerateMipmap(tex->target);
374 }
375 CHECK_GL_ERROR_IF_DEBUG();
376 break;
377 }
378 default:
379 CHECK_GL_ERROR_IF_DEBUG();
380 Crash();
381 break;
382 }
383 }
384 CHECK_GL_ERROR_IF_DEBUG();
385
386 // TODO: Use GL_KHR_no_error or a debug callback, where supported?
387 if (false && allocatedTextures) {
388 // Users may use replacements or scaling, with high render resolutions, and run out of VRAM.
389 // This detects that, rather than looking like PPSSPP is broken.
390 // Calling glGetError() isn't great, but at the end of init, only after creating textures, shouldn't be too bad...
391 GLenum err = glGetError();
392 if (err == GL_OUT_OF_MEMORY) {
393 WARN_LOG_REPORT(G3D, "GL ran out of GPU memory; switching to low memory mode");
394 sawOutOfMemory_ = true;
395 } else if (err != GL_NO_ERROR) {
396 // We checked the err anyway, might as well log if there is one.
397 std::string errorString = GLEnumToString(err);
398 WARN_LOG(G3D, "Got an error after init: %08x (%s)", err, errorString.c_str());
399 if (errorCallback_) {
400 errorCallback_("GL frame init error", errorString.c_str(), errorCallbackUserData_);
401 }
402 }
403 }
404
405 glBindBuffer(GL_ARRAY_BUFFER, 0);
406 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
407
408 #if !defined(USING_GLES2)
409 if (useDebugGroups_)
410 glPopDebugGroup();
411 #endif
412 }
413
InitCreateFramebuffer(const GLRInitStep & step)414 void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) {
415 GLRFramebuffer *fbo = step.create_framebuffer.framebuffer;
416
417 #ifndef USING_GLES2
418 if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) {
419 fbo_ext_create(step);
420 } else if (!gl_extensions.ARB_framebuffer_object && !gl_extensions.IsGLES) {
421 return;
422 }
423 // If GLES2, we have basic FBO support and can just proceed.
424 #endif
425 CHECK_GL_ERROR_IF_DEBUG();
426
427 auto initFBOTexture = [&](GLRTexture &tex, GLint internalFormat, GLenum format, GLenum type, bool linear) {
428 glGenTextures(1, &tex.texture);
429 tex.target = GL_TEXTURE_2D;
430 tex.maxLod = 0.0f;
431
432 // Create the surfaces.
433 glBindTexture(GL_TEXTURE_2D, tex.texture);
434 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, fbo->width, fbo->height, 0, format, type, nullptr);
435
436 tex.wrapS = GL_CLAMP_TO_EDGE;
437 tex.wrapT = GL_CLAMP_TO_EDGE;
438 tex.magFilter = linear ? GL_LINEAR : GL_NEAREST;
439 tex.minFilter = linear ? GL_LINEAR : GL_NEAREST;
440
441 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tex.wrapS);
442 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tex.wrapT);
443 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tex.magFilter);
444 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, tex.minFilter);
445 if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
446 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
447 }
448 };
449
450 // Color texture is same everywhere
451 glGenFramebuffers(1, &fbo->handle);
452 initFBOTexture(fbo->color_texture, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true);
453
454 retry_depth:
455 if (!fbo->z_stencil_) {
456 INFO_LOG(G3D, "Creating %d x %d FBO using no depth", fbo->width, fbo->height);
457
458 fbo->z_stencil_buffer = 0;
459 fbo->stencil_buffer = 0;
460 fbo->z_buffer = 0;
461
462 // Bind it all together
463 glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
464 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
465 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
466 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
467 } else if (gl_extensions.IsGLES) {
468 if (gl_extensions.OES_packed_depth_stencil && (gl_extensions.OES_depth_texture || gl_extensions.GLES3)) {
469 INFO_LOG(G3D, "Creating %d x %d FBO using DEPTH24_STENCIL8 texture", fbo->width, fbo->height);
470 fbo->z_stencil_buffer = 0;
471 fbo->stencil_buffer = 0;
472 fbo->z_buffer = 0;
473
474 if (gl_extensions.GLES3) {
475 initFBOTexture(fbo->z_stencil_texture, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false);
476 } else {
477 initFBOTexture(fbo->z_stencil_texture, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false);
478 }
479
480 // Bind it all together
481 glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
482 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
483 if (gl_extensions.GLES3) {
484 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
485 } else {
486 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
487 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
488 }
489 } else if (gl_extensions.OES_packed_depth_stencil) {
490 INFO_LOG(G3D, "Creating %d x %d FBO using DEPTH24_STENCIL8", fbo->width, fbo->height);
491 // Standard method
492 fbo->stencil_buffer = 0;
493 fbo->z_buffer = 0;
494 // 24-bit Z, 8-bit stencil combined
495 glGenRenderbuffers(1, &fbo->z_stencil_buffer);
496 glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer);
497 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, fbo->width, fbo->height);
498
499 // Bind it all together
500 glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
501 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
502 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
503 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
504 } else {
505 INFO_LOG(G3D, "Creating %d x %d FBO using separate stencil", fbo->width, fbo->height);
506 // TEGRA
507 fbo->z_stencil_buffer = 0;
508 // 16/24-bit Z, separate 8-bit stencil
509 glGenRenderbuffers(1, &fbo->z_buffer);
510 glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer);
511 // Don't forget to make sure fbo_standard_z_depth() matches.
512 glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, fbo->width, fbo->height);
513
514 // 8-bit stencil buffer
515 glGenRenderbuffers(1, &fbo->stencil_buffer);
516 glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer);
517 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, fbo->width, fbo->height);
518
519 // Bind it all together
520 glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
521 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
522 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer);
523 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer);
524 }
525 } else if (gl_extensions.VersionGEThan(3, 0)) {
526 INFO_LOG(G3D, "Creating %d x %d FBO using DEPTH24_STENCIL8 texture", fbo->width, fbo->height);
527 fbo->z_stencil_buffer = 0;
528 fbo->stencil_buffer = 0;
529 fbo->z_buffer = 0;
530
531 initFBOTexture(fbo->z_stencil_texture, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false);
532
533 // Bind it all together
534 glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
535 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
536 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
537 } else {
538 fbo->stencil_buffer = 0;
539 fbo->z_buffer = 0;
540 // 24-bit Z, 8-bit stencil
541 glGenRenderbuffers(1, &fbo->z_stencil_buffer);
542 glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer);
543 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, fbo->width, fbo->height);
544
545 // Bind it all together
546 glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
547 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
548 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
549 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
550 }
551
552 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
553 if (status != GL_FRAMEBUFFER_COMPLETE && !fbo->z_buffer) {
554 CHECK_GL_ERROR_IF_DEBUG();
555 // Uh oh, maybe we need a z/stencil. Platforms sometimes, right?
556 fbo->z_stencil_ = true;
557 goto retry_depth;
558 }
559
560 switch (status) {
561 case GL_FRAMEBUFFER_COMPLETE:
562 // INFO_LOG(G3D, "Framebuffer verified complete.");
563 break;
564 case GL_FRAMEBUFFER_UNSUPPORTED:
565 ERROR_LOG(G3D, "GL_FRAMEBUFFER_UNSUPPORTED");
566 break;
567 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
568 ERROR_LOG(G3D, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
569 break;
570 default:
571 _assert_msg_(false, "Other framebuffer error: %d", status);
572 break;
573 }
574
575 // Unbind state we don't need
576 glBindRenderbuffer(GL_RENDERBUFFER, 0);
577 glBindTexture(GL_TEXTURE_2D, 0);
578 CHECK_GL_ERROR_IF_DEBUG();
579
580 currentDrawHandle_ = fbo->handle;
581 currentReadHandle_ = fbo->handle;
582 }
583
RunSteps(const std::vector<GLRStep * > & steps,bool skipGLCalls)584 void GLQueueRunner::RunSteps(const std::vector<GLRStep *> &steps, bool skipGLCalls) {
585 if (skipGLCalls) {
586 // Dry run
587 for (size_t i = 0; i < steps.size(); i++) {
588 const GLRStep &step = *steps[i];
589 switch (step.stepType) {
590 case GLRStepType::RENDER:
591 for (const auto &c : step.commands) {
592 switch (c.cmd) {
593 case GLRRenderCommand::TEXTURE_SUBIMAGE:
594 if (c.texture_subimage.data) {
595 if (c.texture_subimage.allocType == GLRAllocType::ALIGNED) {
596 FreeAlignedMemory(c.texture_subimage.data);
597 } else if (c.texture_subimage.allocType == GLRAllocType::NEW) {
598 delete[] c.texture_subimage.data;
599 }
600 }
601 break;
602 default:
603 break;
604 }
605 }
606 break;
607 default:
608 break;
609 }
610 delete steps[i];
611 }
612 return;
613 }
614
615 size_t totalRenderCount = 0;
616 for (auto &step : steps) {
617 if (step->stepType == GLRStepType::RENDER) {
618 // Skip empty render steps.
619 if (step->commands.empty()) {
620 step->stepType = GLRStepType::RENDER_SKIP;
621 continue;
622 }
623 totalRenderCount++;
624 }
625 }
626
627 auto ignoresContents = [](GLRRenderPassAction act) {
628 return act == GLRRenderPassAction::CLEAR || act == GLRRenderPassAction::DONT_CARE;
629 };
630 int invalidateAllMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
631
632 /*
633 for (int j = 0; j < (int)steps.size() - 1; ++j) {
634 GLRStep &primaryStep = *steps[j];
635 if (primaryStep.stepType == GLRStepType::RENDER) {
636 const GLRFramebuffer *fb = primaryStep.render.framebuffer;
637
638 // Let's see if we can invalidate it...
639 int invalidateMask = 0;
640 for (int i = j + 1; i < (int)steps.size(); ++i) {
641 const GLRStep &secondaryStep = *steps[i];
642 if (secondaryStep.stepType == GLRStepType::RENDER && secondaryStep.render.framebuffer == fb) {
643 if (ignoresContents(secondaryStep.render.color))
644 invalidateMask |= GL_COLOR_BUFFER_BIT;
645 if (ignoresContents(secondaryStep.render.depth))
646 invalidateMask |= GL_DEPTH_BUFFER_BIT;
647 if (ignoresContents(secondaryStep.render.stencil))
648 invalidateMask |= GL_STENCIL_BUFFER_BIT;
649
650 if (invalidateMask == invalidateAllMask)
651 break;
652 } else if (secondaryStep.dependencies.contains(fb)) {
653 // Can't do it, this step may depend on fb's data.
654 break;
655 }
656 }
657
658 if (invalidateMask) {
659 GLRRenderData data{ GLRRenderCommand::INVALIDATE };
660 data.clear.clearMask = invalidateMask;
661 primaryStep.commands.push_back(data);
662 }
663 }
664 }*/
665
666 CHECK_GL_ERROR_IF_DEBUG();
667 size_t renderCount = 0;
668 for (size_t i = 0; i < steps.size(); i++) {
669 const GLRStep &step = *steps[i];
670
671 #if !defined(USING_GLES2)
672 if (useDebugGroups_)
673 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, (GLuint)i + 10000, -1, step.tag);
674 #endif
675
676 switch (step.stepType) {
677 case GLRStepType::RENDER:
678 renderCount++;
679 PerformRenderPass(step, renderCount == 1, renderCount == totalRenderCount);
680 break;
681 case GLRStepType::COPY:
682 PerformCopy(step);
683 break;
684 case GLRStepType::BLIT:
685 PerformBlit(step);
686 break;
687 case GLRStepType::READBACK:
688 PerformReadback(step);
689 break;
690 case GLRStepType::READBACK_IMAGE:
691 PerformReadbackImage(step);
692 break;
693 case GLRStepType::RENDER_SKIP:
694 break;
695 default:
696 Crash();
697 break;
698 }
699
700 #if !defined(USING_GLES2)
701 if (useDebugGroups_)
702 glPopDebugGroup();
703 #endif
704
705 delete steps[i];
706 }
707 CHECK_GL_ERROR_IF_DEBUG();
708 }
709
LogSteps(const std::vector<GLRStep * > & steps)710 void GLQueueRunner::LogSteps(const std::vector<GLRStep *> &steps) {
711
712 }
713
714
PerformBlit(const GLRStep & step)715 void GLQueueRunner::PerformBlit(const GLRStep &step) {
716 CHECK_GL_ERROR_IF_DEBUG();
717 // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing
718 // in ES 2.0 that actually separate them anyway of course, so doesn't matter.
719 fbo_bind_fb_target(false, step.blit.dst->handle);
720 fbo_bind_fb_target(true, step.blit.src->handle);
721
722 int srcX1 = step.blit.srcRect.x;
723 int srcY1 = step.blit.srcRect.y;
724 int srcX2 = step.blit.srcRect.x + step.blit.srcRect.w;
725 int srcY2 = step.blit.srcRect.y + step.blit.srcRect.h;
726 int dstX1 = step.blit.dstRect.x;
727 int dstY1 = step.blit.dstRect.y;
728 int dstX2 = step.blit.dstRect.x + step.blit.dstRect.w;
729 int dstY2 = step.blit.dstRect.y + step.blit.dstRect.h;
730
731 if (gl_extensions.GLES3 || gl_extensions.ARB_framebuffer_object) {
732 glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, step.blit.aspectMask, step.blit.filter ? GL_LINEAR : GL_NEAREST);
733 CHECK_GL_ERROR_IF_DEBUG();
734 #if defined(USING_GLES2) && defined(__ANDROID__) // We only support this extension on Android, it's not even available on PC.
735 } else if (gl_extensions.NV_framebuffer_blit) {
736 glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, step.blit.aspectMask, step.blit.filter ? GL_LINEAR : GL_NEAREST);
737 CHECK_GL_ERROR_IF_DEBUG();
738 #endif // defined(USING_GLES2) && defined(__ANDROID__)
739 } else {
740 ERROR_LOG(G3D, "GLQueueRunner: Tried to blit without the capability");
741 }
742 }
743
PerformRenderPass(const GLRStep & step,bool first,bool last)744 void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last) {
745 CHECK_GL_ERROR_IF_DEBUG();
746
747 PerformBindFramebufferAsRenderTarget(step);
748
749 if (first) {
750 glDisable(GL_DEPTH_TEST);
751 glDisable(GL_STENCIL_TEST);
752 glDisable(GL_BLEND);
753 glDisable(GL_CULL_FACE);
754 glDisable(GL_DITHER);
755 glEnable(GL_SCISSOR_TEST);
756 #ifndef USING_GLES2
757 if (!gl_extensions.IsGLES) {
758 glDisable(GL_COLOR_LOGIC_OP);
759 }
760 #endif
761 }
762
763 /*
764 #ifndef USING_GLES2
765 if (g_Config.iInternalResolution == 0) {
766 glLineWidth(std::max(1, (int)(renderWidth_ / 480)));
767 glPointSize(std::max(1.0f, (float)(renderWidth_ / 480.f)));
768 } else {
769 glLineWidth(g_Config.iInternalResolution);
770 glPointSize((float)g_Config.iInternalResolution);
771 }
772 #endif
773 */
774
775 if (first && gl_extensions.ARB_vertex_array_object) {
776 glBindVertexArray(globalVAO_);
777 }
778
779 GLRProgram *curProgram = nullptr;
780 int activeSlot = 0;
781 if (first)
782 glActiveTexture(GL_TEXTURE0 + activeSlot);
783
784 // State filtering tracking.
785 int attrMask = 0;
786 int colorMask = -1;
787 int depthMask = -1;
788 int depthFunc = -1;
789 GLuint curArrayBuffer = (GLuint)0;
790 GLuint curElemArrayBuffer = (GLuint)0;
791 bool depthEnabled = false;
792 bool stencilEnabled = false;
793 bool blendEnabled = false;
794 bool cullEnabled = false;
795 bool ditherEnabled = false;
796 bool depthClampEnabled = false;
797 #ifndef USING_GLES2
798 int logicOp = -1;
799 bool logicEnabled = false;
800 #endif
801 GLuint blendEqColor = (GLuint)-1;
802 GLuint blendEqAlpha = (GLuint)-1;
803
804 GLRTexture *curTex[MAX_GL_TEXTURE_SLOTS]{};
805
806 CHECK_GL_ERROR_IF_DEBUG();
807 auto &commands = step.commands;
808 for (const auto &c : commands) {
809 switch (c.cmd) {
810 case GLRRenderCommand::DEPTH:
811 if (c.depth.enabled) {
812 if (!depthEnabled) {
813 glEnable(GL_DEPTH_TEST);
814 depthEnabled = true;
815 }
816 if (c.depth.write != depthMask) {
817 glDepthMask(c.depth.write);
818 depthMask = c.depth.write;
819 }
820 if (c.depth.func != depthFunc) {
821 glDepthFunc(c.depth.func);
822 depthFunc = c.depth.func;
823 }
824 } else if (!c.depth.enabled && depthEnabled) {
825 glDisable(GL_DEPTH_TEST);
826 depthEnabled = false;
827 }
828 break;
829 case GLRRenderCommand::STENCILFUNC:
830 if (c.stencilFunc.enabled) {
831 if (!stencilEnabled) {
832 glEnable(GL_STENCIL_TEST);
833 stencilEnabled = true;
834 }
835 glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask);
836 } else if (stencilEnabled) {
837 glDisable(GL_STENCIL_TEST);
838 stencilEnabled = false;
839 }
840 CHECK_GL_ERROR_IF_DEBUG();
841 break;
842 case GLRRenderCommand::STENCILOP:
843 glStencilOp(c.stencilOp.sFail, c.stencilOp.zFail, c.stencilOp.pass);
844 glStencilMask(c.stencilOp.writeMask);
845 break;
846 case GLRRenderCommand::BLEND:
847 if (c.blend.enabled) {
848 if (!blendEnabled) {
849 glEnable(GL_BLEND);
850 blendEnabled = true;
851 }
852 if (blendEqColor != c.blend.funcColor || blendEqAlpha != c.blend.funcAlpha) {
853 glBlendEquationSeparate(c.blend.funcColor, c.blend.funcAlpha);
854 blendEqColor = c.blend.funcColor;
855 blendEqAlpha = c.blend.funcAlpha;
856 }
857 glBlendFuncSeparate(c.blend.srcColor, c.blend.dstColor, c.blend.srcAlpha, c.blend.dstAlpha);
858 } else if (!c.blend.enabled && blendEnabled) {
859 glDisable(GL_BLEND);
860 blendEnabled = false;
861 }
862 if (c.blend.mask != colorMask) {
863 glColorMask(c.blend.mask & 1, (c.blend.mask >> 1) & 1, (c.blend.mask >> 2) & 1, (c.blend.mask >> 3) & 1);
864 colorMask = c.blend.mask;
865 }
866 CHECK_GL_ERROR_IF_DEBUG();
867 break;
868 case GLRRenderCommand::LOGICOP:
869 #ifndef USING_GLES2
870 if (c.logic.enabled) {
871 if (!logicEnabled) {
872 glEnable(GL_COLOR_LOGIC_OP);
873 logicEnabled = true;
874 }
875 if (logicOp != c.logic.logicOp) {
876 glLogicOp(c.logic.logicOp);
877 }
878 } else if (!c.logic.enabled && logicEnabled) {
879 glDisable(GL_COLOR_LOGIC_OP);
880 logicEnabled = false;
881 }
882 #endif
883 CHECK_GL_ERROR_IF_DEBUG();
884 break;
885 case GLRRenderCommand::CLEAR:
886 // Scissor test is on, and should be on after leaving this case. If we disable it,
887 // we re-enable it at the end.
888 if (c.clear.scissorW == 0) {
889 glDisable(GL_SCISSOR_TEST);
890 } else {
891 glScissor(c.clear.scissorX, c.clear.scissorY, c.clear.scissorW, c.clear.scissorH);
892 }
893 if (c.clear.colorMask != colorMask) {
894 glColorMask(c.clear.colorMask & 1, (c.clear.colorMask >> 1) & 1, (c.clear.colorMask >> 2) & 1, (c.clear.colorMask >> 3) & 1);
895 }
896 if (c.clear.clearMask & GL_COLOR_BUFFER_BIT) {
897 float color[4];
898 Uint8x4ToFloat4(color, c.clear.clearColor);
899 glClearColor(color[0], color[1], color[2], color[3]);
900 }
901 if (c.clear.clearMask & GL_DEPTH_BUFFER_BIT) {
902 #if defined(USING_GLES2)
903 glClearDepthf(c.clear.clearZ);
904 #else
905 if (gl_extensions.IsGLES) {
906 glClearDepthf(c.clear.clearZ);
907 } else {
908 glClearDepth(c.clear.clearZ);
909 }
910 #endif
911 }
912 if (c.clear.clearMask & GL_STENCIL_BUFFER_BIT) {
913 glClearStencil(c.clear.clearStencil);
914 }
915 glClear(c.clear.clearMask);
916 // Restore the color mask if it was different.
917 if (c.clear.colorMask != colorMask) {
918 glColorMask(colorMask & 1, (colorMask >> 1) & 1, (colorMask >> 2) & 1, (colorMask >> 3) & 1);
919 }
920 if (c.clear.scissorW == 0) {
921 glEnable(GL_SCISSOR_TEST);
922 }
923 CHECK_GL_ERROR_IF_DEBUG();
924 break;
925 case GLRRenderCommand::INVALIDATE:
926 {
927 GLenum attachments[3];
928 int count = 0;
929 bool isFBO = step.render.framebuffer != nullptr;
930 bool hasDepth = isFBO ? step.render.framebuffer->z_stencil_ : false;
931 if (c.clear.clearMask & GL_COLOR_BUFFER_BIT)
932 attachments[count++] = isFBO ? GL_COLOR_ATTACHMENT0 : GL_COLOR;
933 if (hasDepth && (c.clear.clearMask & GL_DEPTH_BUFFER_BIT))
934 attachments[count++] = isFBO ? GL_DEPTH_ATTACHMENT : GL_DEPTH;
935 if (hasDepth && (c.clear.clearMask & GL_STENCIL_BUFFER_BIT))
936 attachments[count++] = isFBO ? GL_STENCIL_ATTACHMENT : GL_STENCIL;
937 if (glInvalidateFramebuffer != nullptr && count != 0)
938 glInvalidateFramebuffer(GL_FRAMEBUFFER, count, attachments);
939 CHECK_GL_ERROR_IF_DEBUG();
940 break;
941 }
942 case GLRRenderCommand::BLENDCOLOR:
943 glBlendColor(c.blendColor.color[0], c.blendColor.color[1], c.blendColor.color[2], c.blendColor.color[3]);
944 break;
945 case GLRRenderCommand::VIEWPORT:
946 {
947 float y = c.viewport.vp.y;
948 if (!curFB_)
949 y = curFBHeight_ - y - c.viewport.vp.h;
950
951 // TODO: Support FP viewports through glViewportArrays
952 glViewport((GLint)c.viewport.vp.x, (GLint)y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h);
953 #if !defined(USING_GLES2)
954 if (gl_extensions.IsGLES) {
955 glDepthRangef(c.viewport.vp.minZ, c.viewport.vp.maxZ);
956 } else {
957 glDepthRange(c.viewport.vp.minZ, c.viewport.vp.maxZ);
958 }
959 #else
960 glDepthRangef(c.viewport.vp.minZ, c.viewport.vp.maxZ);
961 #endif
962 CHECK_GL_ERROR_IF_DEBUG();
963 break;
964 }
965 case GLRRenderCommand::SCISSOR:
966 {
967 int y = c.scissor.rc.y;
968 if (!curFB_)
969 y = curFBHeight_ - y - c.scissor.rc.h;
970 glScissor(c.scissor.rc.x, y, c.scissor.rc.w, c.scissor.rc.h);
971 CHECK_GL_ERROR_IF_DEBUG();
972 break;
973 }
974 case GLRRenderCommand::UNIFORM4F:
975 {
976 int loc = c.uniform4.loc ? *c.uniform4.loc : -1;
977 if (c.uniform4.name) {
978 loc = curProgram->GetUniformLoc(c.uniform4.name);
979 }
980 if (loc >= 0) {
981 switch (c.uniform4.count) {
982 case 1:
983 glUniform1f(loc, c.uniform4.v[0]);
984 break;
985 case 2:
986 glUniform2fv(loc, 1, c.uniform4.v);
987 break;
988 case 3:
989 glUniform3fv(loc, 1, c.uniform4.v);
990 break;
991 case 4:
992 glUniform4fv(loc, 1, c.uniform4.v);
993 break;
994 }
995 }
996 CHECK_GL_ERROR_IF_DEBUG();
997 break;
998 }
999 case GLRRenderCommand::UNIFORM4UI:
1000 {
1001 _dbg_assert_(curProgram);
1002 int loc = c.uniform4.loc ? *c.uniform4.loc : -1;
1003 if (c.uniform4.name) {
1004 loc = curProgram->GetUniformLoc(c.uniform4.name);
1005 }
1006 if (loc >= 0) {
1007 switch (c.uniform4.count) {
1008 case 1:
1009 glUniform1uiv(loc, 1, (GLuint *)&c.uniform4.v[0]);
1010 break;
1011 case 2:
1012 glUniform2uiv(loc, 1, (GLuint *)c.uniform4.v);
1013 break;
1014 case 3:
1015 glUniform3uiv(loc, 1, (GLuint *)c.uniform4.v);
1016 break;
1017 case 4:
1018 glUniform4uiv(loc, 1, (GLuint *)c.uniform4.v);
1019 break;
1020 }
1021 }
1022 CHECK_GL_ERROR_IF_DEBUG();
1023 break;
1024 }
1025 case GLRRenderCommand::UNIFORM4I:
1026 {
1027 _dbg_assert_(curProgram);
1028 int loc = c.uniform4.loc ? *c.uniform4.loc : -1;
1029 if (c.uniform4.name) {
1030 loc = curProgram->GetUniformLoc(c.uniform4.name);
1031 }
1032 if (loc >= 0) {
1033 switch (c.uniform4.count) {
1034 case 1:
1035 glUniform1iv(loc, 1, (GLint *)&c.uniform4.v[0]);
1036 break;
1037 case 2:
1038 glUniform2iv(loc, 1, (GLint *)c.uniform4.v);
1039 break;
1040 case 3:
1041 glUniform3iv(loc, 1, (GLint *)c.uniform4.v);
1042 break;
1043 case 4:
1044 glUniform4iv(loc, 1, (GLint *)c.uniform4.v);
1045 break;
1046 }
1047 }
1048 CHECK_GL_ERROR_IF_DEBUG();
1049 break;
1050 }
1051 case GLRRenderCommand::UNIFORMMATRIX:
1052 {
1053 _dbg_assert_(curProgram);
1054 int loc = c.uniformMatrix4.loc ? *c.uniformMatrix4.loc : -1;
1055 if (c.uniformMatrix4.name) {
1056 loc = curProgram->GetUniformLoc(c.uniformMatrix4.name);
1057 }
1058 if (loc >= 0) {
1059 glUniformMatrix4fv(loc, 1, false, c.uniformMatrix4.m);
1060 }
1061 CHECK_GL_ERROR_IF_DEBUG();
1062 break;
1063 }
1064 case GLRRenderCommand::BINDTEXTURE:
1065 {
1066 GLint slot = c.texture.slot;
1067 if (slot != activeSlot) {
1068 glActiveTexture(GL_TEXTURE0 + slot);
1069 activeSlot = slot;
1070 }
1071 if (c.texture.texture) {
1072 if (curTex[slot] != c.texture.texture) {
1073 glBindTexture(c.texture.texture->target, c.texture.texture->texture);
1074 curTex[slot] = c.texture.texture;
1075 }
1076 } else {
1077 glBindTexture(GL_TEXTURE_2D, 0); // Which target? Well we only use this one anyway...
1078 curTex[slot] = nullptr;
1079 }
1080 CHECK_GL_ERROR_IF_DEBUG();
1081 break;
1082 }
1083 case GLRRenderCommand::BIND_FB_TEXTURE:
1084 {
1085 GLint slot = c.bind_fb_texture.slot;
1086 if (slot != activeSlot) {
1087 glActiveTexture(GL_TEXTURE0 + slot);
1088 activeSlot = slot;
1089 }
1090 if (c.bind_fb_texture.aspect == GL_COLOR_BUFFER_BIT) {
1091 if (curTex[slot] != &c.bind_fb_texture.framebuffer->color_texture)
1092 glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->color_texture.texture);
1093 curTex[slot] = &c.bind_fb_texture.framebuffer->color_texture;
1094 } else if (c.bind_fb_texture.aspect == GL_DEPTH_BUFFER_BIT) {
1095 if (curTex[slot] != &c.bind_fb_texture.framebuffer->z_stencil_texture)
1096 glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->z_stencil_texture.texture);
1097 curTex[slot] = &c.bind_fb_texture.framebuffer->z_stencil_texture;
1098 } else {
1099 // TODO: Stencil texturing?
1100 curTex[slot] = nullptr;
1101 }
1102 CHECK_GL_ERROR_IF_DEBUG();
1103 break;
1104 }
1105 case GLRRenderCommand::BINDPROGRAM:
1106 {
1107 if (curProgram != c.program.program) {
1108 glUseProgram(c.program.program->program);
1109 curProgram = c.program.program;
1110 }
1111 CHECK_GL_ERROR_IF_DEBUG();
1112 break;
1113 }
1114 case GLRRenderCommand::BIND_VERTEX_BUFFER:
1115 {
1116 // TODO: Add fast path for glBindVertexBuffer
1117 GLRInputLayout *layout = c.bindVertexBuffer.inputLayout;
1118 GLuint buf = c.bindVertexBuffer.buffer ? c.bindVertexBuffer.buffer->buffer_ : 0;
1119 _dbg_assert_(!c.bindVertexBuffer.buffer->Mapped());
1120 if (buf != curArrayBuffer) {
1121 glBindBuffer(GL_ARRAY_BUFFER, buf);
1122 curArrayBuffer = buf;
1123 }
1124 int enable = layout->semanticsMask_ & ~attrMask;
1125 int disable = (~layout->semanticsMask_) & attrMask;
1126 for (int i = 0; i < 7; i++) { // SEM_MAX
1127 if (enable & (1 << i)) {
1128 glEnableVertexAttribArray(i);
1129 }
1130 if (disable & (1 << i)) {
1131 glDisableVertexAttribArray(i);
1132 }
1133 }
1134 attrMask = layout->semanticsMask_;
1135 for (size_t i = 0; i < layout->entries.size(); i++) {
1136 auto &entry = layout->entries[i];
1137 glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.bindVertexBuffer.offset + entry.offset));
1138 }
1139 CHECK_GL_ERROR_IF_DEBUG();
1140 break;
1141 }
1142 case GLRRenderCommand::BIND_BUFFER:
1143 {
1144 if (c.bind_buffer.target == GL_ARRAY_BUFFER) {
1145 Crash();
1146 } else if (c.bind_buffer.target == GL_ELEMENT_ARRAY_BUFFER) {
1147 GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer_ : 0;
1148 _dbg_assert_(!c.bind_buffer.buffer->Mapped());
1149 if (buf != curElemArrayBuffer) {
1150 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
1151 curElemArrayBuffer = buf;
1152 }
1153 } else {
1154 GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer_ : 0;
1155 _dbg_assert_(!c.bind_buffer.buffer->Mapped());
1156 glBindBuffer(c.bind_buffer.target, buf);
1157 }
1158 CHECK_GL_ERROR_IF_DEBUG();
1159 break;
1160 }
1161 case GLRRenderCommand::GENMIPS:
1162 // TODO: Should we include the texture handle in the command?
1163 // Also, should this not be an init command?
1164 glGenerateMipmap(GL_TEXTURE_2D);
1165 break;
1166 case GLRRenderCommand::DRAW:
1167 glDrawArrays(c.draw.mode, c.draw.first, c.draw.count);
1168 break;
1169 case GLRRenderCommand::DRAW_INDEXED:
1170 if (c.drawIndexed.instances == 1) {
1171 glDrawElements(c.drawIndexed.mode, c.drawIndexed.count, c.drawIndexed.indexType, c.drawIndexed.indices);
1172 } else {
1173 glDrawElementsInstanced(c.drawIndexed.mode, c.drawIndexed.count, c.drawIndexed.indexType, c.drawIndexed.indices, c.drawIndexed.instances);
1174 }
1175 CHECK_GL_ERROR_IF_DEBUG();
1176 break;
1177 case GLRRenderCommand::TEXTURESAMPLER:
1178 {
1179 CHECK_GL_ERROR_IF_DEBUG();
1180 GLint slot = c.textureSampler.slot;
1181 if (slot != activeSlot) {
1182 glActiveTexture(GL_TEXTURE0 + slot);
1183 activeSlot = slot;
1184 }
1185 GLRTexture *tex = curTex[slot];
1186 if (!tex) {
1187 break;
1188 }
1189 CHECK_GL_ERROR_IF_DEBUG();
1190 if (tex->canWrap) {
1191 if (tex->wrapS != c.textureSampler.wrapS) {
1192 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS);
1193 tex->wrapS = c.textureSampler.wrapS;
1194 }
1195 if (tex->wrapT != c.textureSampler.wrapT) {
1196 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT);
1197 tex->wrapT = c.textureSampler.wrapT;
1198 }
1199 }
1200 CHECK_GL_ERROR_IF_DEBUG();
1201 if (tex->magFilter != c.textureSampler.magFilter) {
1202 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter);
1203 tex->magFilter = c.textureSampler.magFilter;
1204 }
1205 CHECK_GL_ERROR_IF_DEBUG();
1206 if (tex->minFilter != c.textureSampler.minFilter) {
1207 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter);
1208 tex->minFilter = c.textureSampler.minFilter;
1209 }
1210 CHECK_GL_ERROR_IF_DEBUG();
1211 if (tex->anisotropy != c.textureSampler.anisotropy) {
1212 if (c.textureSampler.anisotropy != 0.0f) {
1213 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy);
1214 }
1215 tex->anisotropy = c.textureSampler.anisotropy;
1216 }
1217 CHECK_GL_ERROR_IF_DEBUG();
1218 break;
1219 }
1220 case GLRRenderCommand::TEXTURELOD:
1221 {
1222 GLint slot = c.textureSampler.slot;
1223 if (slot != activeSlot) {
1224 glActiveTexture(GL_TEXTURE0 + slot);
1225 activeSlot = slot;
1226 }
1227 GLRTexture *tex = curTex[slot];
1228 if (!tex) {
1229 break;
1230 }
1231 #ifndef USING_GLES2
1232 if (tex->lodBias != c.textureLod.lodBias && !gl_extensions.IsGLES) {
1233 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias);
1234 tex->lodBias = c.textureLod.lodBias;
1235 }
1236 #endif
1237 if (tex->minLod != c.textureLod.minLod) {
1238 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, c.textureLod.minLod);
1239 tex->minLod = c.textureLod.minLod;
1240 }
1241 if (tex->maxLod != c.textureLod.maxLod) {
1242 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod);
1243 tex->maxLod = c.textureLod.maxLod;
1244 }
1245 break;
1246 }
1247 case GLRRenderCommand::TEXTURE_SUBIMAGE:
1248 {
1249 GLRTexture *tex = c.texture_subimage.texture;
1250 // TODO: Need bind?
1251 if (!c.texture_subimage.data)
1252 Crash();
1253 // For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage.
1254 GLuint internalFormat, format, type;
1255 int alignment;
1256 Thin3DFormatToFormatAndType(c.texture_subimage.format, internalFormat, format, type, alignment);
1257 glTexSubImage2D(tex->target, c.texture_subimage.level, c.texture_subimage.x, c.texture_subimage.y, c.texture_subimage.width, c.texture_subimage.height, format, type, c.texture_subimage.data);
1258 if (c.texture_subimage.allocType == GLRAllocType::ALIGNED) {
1259 FreeAlignedMemory(c.texture_subimage.data);
1260 } else if (c.texture_subimage.allocType == GLRAllocType::NEW) {
1261 delete[] c.texture_subimage.data;
1262 }
1263 CHECK_GL_ERROR_IF_DEBUG();
1264 break;
1265 }
1266 case GLRRenderCommand::RASTER:
1267 if (c.raster.cullEnable) {
1268 if (!cullEnabled) {
1269 glEnable(GL_CULL_FACE);
1270 cullEnabled = true;
1271 }
1272 glFrontFace(c.raster.frontFace);
1273 glCullFace(c.raster.cullFace);
1274 } else if (!c.raster.cullEnable && cullEnabled) {
1275 glDisable(GL_CULL_FACE);
1276 cullEnabled = false;
1277 }
1278 if (c.raster.ditherEnable) {
1279 if (!ditherEnabled) {
1280 glEnable(GL_DITHER);
1281 ditherEnabled = true;
1282 }
1283 } else if (!c.raster.ditherEnable && ditherEnabled) {
1284 glDisable(GL_DITHER);
1285 ditherEnabled = false;
1286 }
1287 #ifndef USING_GLES2
1288 if (c.raster.depthClampEnable) {
1289 if (!depthClampEnabled) {
1290 glEnable(GL_DEPTH_CLAMP);
1291 depthClampEnabled = true;
1292 }
1293 } else if (!c.raster.depthClampEnable && depthClampEnabled) {
1294 glDisable(GL_DEPTH_CLAMP);
1295 depthClampEnabled = false;
1296 }
1297 #endif
1298 CHECK_GL_ERROR_IF_DEBUG();
1299 break;
1300 default:
1301 Crash();
1302 break;
1303 }
1304 }
1305
1306 for (int i = 0; i < 7; i++) {
1307 if (attrMask & (1 << i)) {
1308 glDisableVertexAttribArray(i);
1309 }
1310 }
1311
1312 if (activeSlot != 0) {
1313 glActiveTexture(GL_TEXTURE0);
1314 activeSlot = 0; // doesn't matter, just nice.
1315 }
1316 CHECK_GL_ERROR_IF_DEBUG();
1317
1318 // Wipe out the current state.
1319 if (curArrayBuffer != 0)
1320 glBindBuffer(GL_ARRAY_BUFFER, 0);
1321 if (curElemArrayBuffer != 0)
1322 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1323 if (last && gl_extensions.ARB_vertex_array_object) {
1324 glBindVertexArray(0);
1325 }
1326 if (last)
1327 glDisable(GL_SCISSOR_TEST);
1328 if (depthEnabled)
1329 glDisable(GL_DEPTH_TEST);
1330 if (stencilEnabled)
1331 glDisable(GL_STENCIL_TEST);
1332 if (blendEnabled)
1333 glDisable(GL_BLEND);
1334 if (cullEnabled)
1335 glDisable(GL_CULL_FACE);
1336 #ifndef USING_GLES2
1337 if (depthClampEnabled)
1338 glDisable(GL_DEPTH_CLAMP);
1339 if (!gl_extensions.IsGLES && logicEnabled) {
1340 glDisable(GL_COLOR_LOGIC_OP);
1341 }
1342 #endif
1343 if ((colorMask & 15) != 15)
1344 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1345 CHECK_GL_ERROR_IF_DEBUG();
1346 }
1347
PerformCopy(const GLRStep & step)1348 void GLQueueRunner::PerformCopy(const GLRStep &step) {
1349 CHECK_GL_ERROR_IF_DEBUG();
1350 GLuint srcTex = 0;
1351 GLuint dstTex = 0;
1352 GLuint target = GL_TEXTURE_2D;
1353
1354 const GLRect2D &srcRect = step.copy.srcRect;
1355 const GLOffset2D &dstPos = step.copy.dstPos;
1356
1357 GLRFramebuffer *src = step.copy.src;
1358 GLRFramebuffer *dst = step.copy.dst;
1359
1360 int srcLevel = 0;
1361 int dstLevel = 0;
1362 int srcZ = 0;
1363 int dstZ = 0;
1364 int depth = 1;
1365
1366 switch (step.copy.aspectMask) {
1367 case GL_COLOR_BUFFER_BIT:
1368 srcTex = src->color_texture.texture;
1369 dstTex = dst->color_texture.texture;
1370 break;
1371 case GL_DEPTH_BUFFER_BIT:
1372 // TODO: Support depth copies.
1373 _assert_msg_(false, "Depth copies not yet supported - soon");
1374 target = GL_RENDERBUFFER;
1375 /*
1376 srcTex = src->depth.texture;
1377 dstTex = src->depth.texture;
1378 */
1379 break;
1380 }
1381
1382 _dbg_assert_(srcTex);
1383 _dbg_assert_(dstTex);
1384
1385 #if defined(USING_GLES2)
1386 #if !PPSSPP_PLATFORM(IOS)
1387 _assert_msg_(gl_extensions.OES_copy_image || gl_extensions.NV_copy_image || gl_extensions.EXT_copy_image, "Image copy extension expected");
1388 glCopyImageSubDataOES(
1389 srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ,
1390 dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ,
1391 srcRect.w, srcRect.h, depth);
1392 #endif
1393 #else
1394 _assert_msg_(gl_extensions.ARB_copy_image || gl_extensions.NV_copy_image, "Image copy extension expected");
1395 if (gl_extensions.ARB_copy_image) {
1396 glCopyImageSubData(
1397 srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ,
1398 dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ,
1399 srcRect.w, srcRect.h, depth);
1400 } else if (gl_extensions.NV_copy_image) {
1401 // Older, pre GL 4.x NVIDIA cards.
1402 glCopyImageSubDataNV(
1403 srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ,
1404 dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ,
1405 srcRect.w, srcRect.h, depth);
1406 }
1407 #endif
1408 CHECK_GL_ERROR_IF_DEBUG();
1409 }
1410
PerformReadback(const GLRStep & pass)1411 void GLQueueRunner::PerformReadback(const GLRStep &pass) {
1412 using namespace Draw;
1413 CHECK_GL_ERROR_IF_DEBUG();
1414
1415 GLRFramebuffer *fb = pass.readback.src;
1416
1417 fbo_bind_fb_target(true, fb ? fb->handle : 0);
1418
1419 // Reads from the "bound for read" framebuffer. Note that if there's no fb, it's not valid to call this.
1420 if (fb && (gl_extensions.GLES3 || !gl_extensions.IsGLES))
1421 glReadBuffer(GL_COLOR_ATTACHMENT0);
1422
1423 CHECK_GL_ERROR_IF_DEBUG();
1424
1425 // Always read back in 8888 format for the color aspect.
1426 GLuint internalFormat = GL_RGBA;
1427 GLuint format = GL_RGBA;
1428 GLuint type = GL_UNSIGNED_BYTE;
1429 int srcAlignment = 4;
1430 int dstAlignment = (int)DataFormatSizeInBytes(pass.readback.dstFormat);
1431
1432 #ifndef USING_GLES2
1433 if (pass.readback.aspectMask & GL_DEPTH_BUFFER_BIT) {
1434 internalFormat = GL_DEPTH_COMPONENT;
1435 format = GL_DEPTH_COMPONENT;
1436 type = GL_FLOAT;
1437 srcAlignment = 4;
1438 } else if (pass.readback.aspectMask & GL_STENCIL_BUFFER_BIT) {
1439 internalFormat = GL_STENCIL_INDEX;
1440 format = GL_STENCIL_INDEX;
1441 type = GL_UNSIGNED_BYTE;
1442 srcAlignment = 1;
1443 }
1444 #endif
1445
1446 int pixelStride = pass.readback.srcRect.w;
1447 // Apply the correct alignment.
1448 glPixelStorei(GL_PACK_ALIGNMENT, srcAlignment);
1449 if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
1450 // Some drivers seem to require we specify this. See #8254.
1451 glPixelStorei(GL_PACK_ROW_LENGTH, pixelStride);
1452 }
1453
1454 GLRect2D rect = pass.readback.srcRect;
1455
1456 bool convert = internalFormat == GL_RGBA && pass.readback.dstFormat != DataFormat::R8G8B8A8_UNORM;
1457
1458 int tempSize = srcAlignment * rect.w * rect.h;
1459 int readbackSize = dstAlignment * rect.w * rect.h;
1460 if (convert && tempSize > tempBufferSize_) {
1461 delete[] tempBuffer_;
1462 tempBuffer_ = new uint8_t[tempSize];
1463 tempBufferSize_ = tempSize;
1464 }
1465 if (readbackSize > readbackBufferSize_) {
1466 delete[] readbackBuffer_;
1467 readbackBuffer_ = new uint8_t[readbackSize];
1468 readbackBufferSize_ = readbackSize;
1469 }
1470
1471 glReadPixels(rect.x, rect.y, rect.w, rect.h, format, type, convert ? tempBuffer_ : readbackBuffer_);
1472 #ifdef DEBUG_READ_PIXELS
1473 LogReadPixelsError(glGetError());
1474 #endif
1475 if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
1476 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1477 }
1478 if (convert && tempBuffer_ && readbackBuffer_) {
1479 ConvertFromRGBA8888(readbackBuffer_, tempBuffer_, pixelStride, pixelStride, rect.w, rect.h, pass.readback.dstFormat);
1480 }
1481 CHECK_GL_ERROR_IF_DEBUG();
1482 }
1483
PerformReadbackImage(const GLRStep & pass)1484 void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) {
1485 #ifndef USING_GLES2
1486 GLRTexture *tex = pass.readback_image.texture;
1487 GLRect2D rect = pass.readback_image.srcRect;
1488
1489 if (gl_extensions.VersionGEThan(4, 5)) {
1490 int size = 4 * rect.w * rect.h;
1491 if (size > readbackBufferSize_) {
1492 delete[] readbackBuffer_;
1493 readbackBuffer_ = new uint8_t[size];
1494 readbackBufferSize_ = size;
1495 }
1496
1497 glPixelStorei(GL_PACK_ALIGNMENT, 4);
1498 glGetTextureSubImage(tex->texture, pass.readback_image.mipLevel, rect.x, rect.y, 0, rect.w, rect.h, 1, GL_RGBA, GL_UNSIGNED_BYTE, readbackBufferSize_, readbackBuffer_);
1499 } else {
1500 glBindTexture(GL_TEXTURE_2D, tex->texture);
1501
1502 CHECK_GL_ERROR_IF_DEBUG();
1503
1504 GLint w, h;
1505 // This is only used for debugging (currently), and GL doesn't support a subrectangle.
1506 glGetTexLevelParameteriv(GL_TEXTURE_2D, pass.readback_image.mipLevel, GL_TEXTURE_WIDTH, &w);
1507 glGetTexLevelParameteriv(GL_TEXTURE_2D, pass.readback_image.mipLevel, GL_TEXTURE_HEIGHT, &h);
1508
1509 int size = 4 * std::max((int)w, rect.x + rect.w) * std::max((int)h, rect.h);
1510 if (size > readbackBufferSize_) {
1511 delete[] readbackBuffer_;
1512 readbackBuffer_ = new uint8_t[size];
1513 readbackBufferSize_ = size;
1514 }
1515
1516 glPixelStorei(GL_PACK_ALIGNMENT, 4);
1517 glPixelStorei(GL_PACK_ROW_LENGTH, rect.x + rect.w);
1518 glGetTexImage(GL_TEXTURE_2D, pass.readback_image.mipLevel, GL_RGBA, GL_UNSIGNED_BYTE, readbackBuffer_);
1519 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1520
1521 if (rect.x != 0 || rect.y != 0) {
1522 int dstStride = 4 * rect.w;
1523 int srcStride = 4 * (rect.x + rect.w);
1524 int xoff = 4 * rect.x;
1525 int yoff = rect.y * srcStride;
1526 for (int y = 0; y < rect.h; ++y) {
1527 memmove(readbackBuffer_ + h * dstStride, readbackBuffer_ + yoff + h * srcStride + xoff, dstStride);
1528 }
1529 }
1530 }
1531 #endif
1532
1533 CHECK_GL_ERROR_IF_DEBUG();
1534 }
1535
PerformBindFramebufferAsRenderTarget(const GLRStep & pass)1536 void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) {
1537 if (pass.render.framebuffer) {
1538 curFBWidth_ = pass.render.framebuffer->width;
1539 curFBHeight_ = pass.render.framebuffer->height;
1540 } else {
1541 curFBWidth_ = targetWidth_;
1542 curFBHeight_ = targetHeight_;
1543 }
1544
1545 curFB_ = pass.render.framebuffer;
1546 if (curFB_) {
1547 // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing
1548 // in ES 2.0 that actually separate them anyway of course, so doesn't matter.
1549 fbo_bind_fb_target(false, curFB_->handle);
1550 } else {
1551 fbo_unbind();
1552 // Backbuffer is now bound.
1553 }
1554 CHECK_GL_ERROR_IF_DEBUG();
1555 }
1556
CopyReadbackBuffer(int width,int height,Draw::DataFormat srcFormat,Draw::DataFormat destFormat,int pixelStride,uint8_t * pixels)1557 void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) {
1558 // TODO: Maybe move data format conversion here, and always read back 8888. Drivers
1559 // don't usually provide very optimized conversion implementations, though some do.
1560 // Just need to be careful about dithering, which may break Danganronpa.
1561 int bpp = (int)Draw::DataFormatSizeInBytes(destFormat);
1562 if (!readbackBuffer_ || bpp <= 0 || !pixels) {
1563 // Something went wrong during the read and no readback buffer was allocated, probably.
1564 return;
1565 }
1566 for (int y = 0; y < height; y++) {
1567 memcpy(pixels + y * pixelStride * bpp, readbackBuffer_ + y * width * bpp, width * bpp);
1568 }
1569 }
1570
AllocTextureName()1571 GLuint GLQueueRunner::AllocTextureName() {
1572 if (nameCache_.empty()) {
1573 nameCache_.resize(TEXCACHE_NAME_CACHE_SIZE);
1574 glGenTextures(TEXCACHE_NAME_CACHE_SIZE, &nameCache_[0]);
1575 }
1576 u32 name = nameCache_.back();
1577 nameCache_.pop_back();
1578 CHECK_GL_ERROR_IF_DEBUG();
1579 return name;
1580 }
1581
1582 // On PC, we always use GL_DEPTH24_STENCIL8.
1583 // On Android, we try to use what's available.
1584
1585 #ifndef USING_GLES2
fbo_ext_create(const GLRInitStep & step)1586 void GLQueueRunner::fbo_ext_create(const GLRInitStep &step) {
1587 GLRFramebuffer *fbo = step.create_framebuffer.framebuffer;
1588
1589 CHECK_GL_ERROR_IF_DEBUG();
1590
1591 // Color texture is same everywhere
1592 glGenFramebuffersEXT(1, &fbo->handle);
1593 glGenTextures(1, &fbo->color_texture.texture);
1594
1595 // Create the surfaces.
1596 glBindTexture(GL_TEXTURE_2D, fbo->color_texture.texture);
1597 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1598
1599 fbo->color_texture.target = GL_TEXTURE_2D;
1600 fbo->color_texture.wrapS = GL_CLAMP_TO_EDGE;
1601 fbo->color_texture.wrapT = GL_CLAMP_TO_EDGE;
1602 fbo->color_texture.magFilter = GL_LINEAR;
1603 fbo->color_texture.minFilter = GL_LINEAR;
1604 fbo->color_texture.maxLod = 0.0f;
1605 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, fbo->color_texture.wrapS);
1606 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, fbo->color_texture.wrapT);
1607 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, fbo->color_texture.magFilter);
1608 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, fbo->color_texture.minFilter);
1609
1610 fbo->stencil_buffer = 0;
1611 fbo->z_buffer = 0;
1612 // 24-bit Z, 8-bit stencil
1613 glGenRenderbuffersEXT(1, &fbo->z_stencil_buffer);
1614 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer);
1615 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, fbo->width, fbo->height);
1616 // glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height);
1617
1618 // Bind it all together
1619 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle);
1620 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
1621 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer);
1622 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer);
1623
1624 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1625 switch (status) {
1626 case GL_FRAMEBUFFER_COMPLETE_EXT:
1627 // INFO_LOG(G3D, "Framebuffer verified complete.");
1628 break;
1629 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
1630 ERROR_LOG(G3D, "GL_FRAMEBUFFER_UNSUPPORTED");
1631 break;
1632 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
1633 ERROR_LOG(G3D, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ");
1634 break;
1635 default:
1636 _assert_msg_(false, "Other framebuffer error: %d", status);
1637 break;
1638 }
1639 // Unbind state we don't need
1640 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1641 glBindTexture(GL_TEXTURE_2D, 0);
1642
1643 CHECK_GL_ERROR_IF_DEBUG();
1644
1645 currentDrawHandle_ = fbo->handle;
1646 currentReadHandle_ = fbo->handle;
1647 }
1648 #endif
1649
fbo_get_fb_target(bool read,GLuint ** cached)1650 GLenum GLQueueRunner::fbo_get_fb_target(bool read, GLuint **cached) {
1651 bool supportsBlit = gl_extensions.ARB_framebuffer_object;
1652 if (gl_extensions.IsGLES) {
1653 supportsBlit = (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit);
1654 }
1655
1656 // Note: GL_FRAMEBUFFER_EXT and GL_FRAMEBUFFER have the same value, same with _NV.
1657 if (supportsBlit) {
1658 if (read) {
1659 *cached = ¤tReadHandle_;
1660 return GL_READ_FRAMEBUFFER;
1661 } else {
1662 *cached = ¤tDrawHandle_;
1663 return GL_DRAW_FRAMEBUFFER;
1664 }
1665 } else {
1666 *cached = ¤tDrawHandle_;
1667 return GL_FRAMEBUFFER;
1668 }
1669 }
1670
fbo_bind_fb_target(bool read,GLuint name)1671 void GLQueueRunner::fbo_bind_fb_target(bool read, GLuint name) {
1672 CHECK_GL_ERROR_IF_DEBUG();
1673 GLuint *cached;
1674 GLenum target = fbo_get_fb_target(read, &cached);
1675 if (*cached != name) {
1676 if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
1677 glBindFramebuffer(target, name);
1678 } else {
1679 #ifndef USING_GLES2
1680 glBindFramebufferEXT(target, name);
1681 #endif
1682 }
1683 *cached = name;
1684 }
1685 CHECK_GL_ERROR_IF_DEBUG();
1686 }
1687
fbo_unbind()1688 void GLQueueRunner::fbo_unbind() {
1689 CHECK_GL_ERROR_IF_DEBUG();
1690 #ifndef USING_GLES2
1691 if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
1692 glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO);
1693 } else if (gl_extensions.EXT_framebuffer_object) {
1694 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_defaultFBO);
1695 }
1696 #else
1697 glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO);
1698 #endif
1699
1700 #if PPSSPP_PLATFORM(IOS)
1701 bindDefaultFBO();
1702 #endif
1703
1704 currentDrawHandle_ = 0;
1705 currentReadHandle_ = 0;
1706 CHECK_GL_ERROR_IF_DEBUG();
1707 }
1708
~GLRFramebuffer()1709 GLRFramebuffer::~GLRFramebuffer() {
1710 if (handle == 0 && z_stencil_buffer == 0 && z_buffer == 0 && stencil_buffer == 0)
1711 return;
1712
1713 CHECK_GL_ERROR_IF_DEBUG();
1714 if (handle) {
1715 if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
1716 glBindFramebuffer(GL_FRAMEBUFFER, handle);
1717 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
1718 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
1719 glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO);
1720 glDeleteFramebuffers(1, &handle);
1721 #ifndef USING_GLES2
1722 } else if (gl_extensions.EXT_framebuffer_object) {
1723 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, handle);
1724 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
1725 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0);
1726 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_defaultFBO);
1727 glDeleteFramebuffersEXT(1, &handle);
1728 #endif
1729 }
1730 }
1731
1732 // These can only be set when supported.
1733 if (z_stencil_buffer)
1734 glDeleteRenderbuffers(1, &z_stencil_buffer);
1735 if (z_buffer)
1736 glDeleteRenderbuffers(1, &z_buffer);
1737 if (stencil_buffer)
1738 glDeleteRenderbuffers(1, &stencil_buffer);
1739 CHECK_GL_ERROR_IF_DEBUG();
1740 }
1741