mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #11676 from unknownbrackets/gles-depth
WIP - GLES: Download depth values via shader
This commit is contained in:
commit
683a4e0fb2
12 changed files with 321 additions and 87 deletions
|
@ -1221,6 +1221,7 @@ endif()
|
|||
set(GPU_GLES
|
||||
GPU/GLES/DepalettizeShaderGLES.cpp
|
||||
GPU/GLES/DepalettizeShaderGLES.h
|
||||
GPU/GLES/DepthBufferGLES.cpp
|
||||
GPU/GLES/GPU_GLES.cpp
|
||||
GPU/GLES/GPU_GLES.h
|
||||
GPU/GLES/FragmentShaderGeneratorGLES.cpp
|
||||
|
|
198
GPU/GLES/DepthBufferGLES.cpp
Normal file
198
GPU/GLES/DepthBufferGLES.cpp
Normal file
|
@ -0,0 +1,198 @@
|
|||
// Copyright (c) 2012- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <algorithm>
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "GPU/Common/GPUStateUtils.h"
|
||||
#include "GPU/GLES/DrawEngineGLES.h"
|
||||
#include "GPU/GLES/FramebufferManagerGLES.h"
|
||||
#include "GPU/GLES/ShaderManagerGLES.h"
|
||||
#include "GPU/GLES/TextureCacheGLES.h"
|
||||
|
||||
static const char *depth_dl_fs = R"(
|
||||
#ifdef GL_ES
|
||||
#if GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#endif
|
||||
#if __VERSION__ >= 130
|
||||
#define varying in
|
||||
#define texture2D texture
|
||||
#define gl_FragColor fragColor0
|
||||
out vec4 fragColor0;
|
||||
#endif
|
||||
varying vec2 v_texcoord0;
|
||||
uniform vec2 u_depthFactor;
|
||||
uniform vec4 u_depthShift;
|
||||
uniform vec4 u_depthTo8;
|
||||
uniform sampler2D tex;
|
||||
void main() {
|
||||
float depth = texture2D(tex, v_texcoord0).r;
|
||||
// At this point, clamped maps [0, 1] to [0, 65535].
|
||||
float clamped = clamp((depth + u_depthFactor.x) * u_depthFactor.y, 0.0, 1.0);
|
||||
|
||||
vec4 enc = u_depthShift * clamped;
|
||||
enc = floor(mod(enc, 256.0)) * u_depthTo8;
|
||||
enc = enc * u_depthTo8;
|
||||
// Let's ignore the bits outside 16 bit precision.
|
||||
gl_FragColor = enc.yzww;
|
||||
}
|
||||
)";
|
||||
|
||||
static const char *depth_vs = R"(
|
||||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
#endif
|
||||
#if __VERSION__ >= 130
|
||||
#define attribute in
|
||||
#define varying out
|
||||
#endif
|
||||
attribute vec4 a_position;
|
||||
attribute vec2 a_texcoord0;
|
||||
varying vec2 v_texcoord0;
|
||||
void main() {
|
||||
v_texcoord0 = a_texcoord0;
|
||||
gl_Position = a_position;
|
||||
}
|
||||
)";
|
||||
|
||||
void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
|
||||
if (!vfb->fbo) {
|
||||
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// Pixel size always 4 here because we always request float
|
||||
const u32 bufSize = vfb->z_stride * (h - y) * 4;
|
||||
const u32 z_address = vfb->z_address;
|
||||
const int packWidth = std::min(vfb->z_stride, std::min(x + w, (int)vfb->width));
|
||||
|
||||
if (!convBuf_ || convBufSize_ < bufSize) {
|
||||
delete[] convBuf_;
|
||||
convBuf_ = new u8[bufSize];
|
||||
convBufSize_ = bufSize;
|
||||
}
|
||||
|
||||
DEBUG_LOG(FRAMEBUF, "Reading depthbuffer to mem at %08x for vfb=%08x", z_address, vfb->fb_address);
|
||||
|
||||
// TODO: On desktop, we can just directly download, but for now testing.
|
||||
const bool useColorPath = true; // gl_extensions.IsGLES;
|
||||
bool format16Bit = false;
|
||||
|
||||
if (useColorPath) {
|
||||
if (!depthDownloadProgram_) {
|
||||
std::string errorString;
|
||||
static std::string vs_code, fs_code;
|
||||
vs_code = ApplyGLSLPrelude(depth_vs, GL_VERTEX_SHADER);
|
||||
fs_code = ApplyGLSLPrelude(depth_dl_fs, GL_FRAGMENT_SHADER);
|
||||
std::vector<GLRShader *> shaders;
|
||||
shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vs_code, "depth_dl"));
|
||||
shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code, "depth_dl"));
|
||||
std::vector<GLRProgram::Semantic> semantics;
|
||||
semantics.push_back({ 0, "a_position" });
|
||||
semantics.push_back({ 1, "a_texcoord0" });
|
||||
std::vector<GLRProgram::UniformLocQuery> queries;
|
||||
queries.push_back({ &u_depthDownloadTex, "tex" });
|
||||
queries.push_back({ &u_depthDownloadFactor, "u_depthFactor" });
|
||||
queries.push_back({ &u_depthDownloadShift, "u_depthShift" });
|
||||
queries.push_back({ &u_depthDownloadTo8, "u_depthTo8" });
|
||||
std::vector<GLRProgram::Initializer> inits;
|
||||
inits.push_back({ &u_depthDownloadTex, 0, TEX_SLOT_PSP_TEXTURE });
|
||||
depthDownloadProgram_ = render_->CreateProgram(shaders, semantics, queries, inits, false);
|
||||
for (auto iter : shaders) {
|
||||
render_->DeleteShader(iter);
|
||||
}
|
||||
if (!depthDownloadProgram_) {
|
||||
ERROR_LOG_REPORT(G3D, "Failed to compile depthDownloadProgram! This shouldn't happen.\n%s", errorString.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
shaderManagerGL_->DirtyLastShader();
|
||||
auto *blitFBO = GetTempFBO(TempFBO::COPY, vfb->renderWidth, vfb->renderHeight, Draw::FBO_8888);
|
||||
draw_->BindFramebufferAsRenderTarget(blitFBO, { Draw::RPAction::CLEAR, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE });
|
||||
render_->SetViewport({ 0, 0, (float)vfb->renderWidth, (float)vfb->renderHeight, 0.0f, 1.0f });
|
||||
textureCacheGL_->ForgetLastTexture();
|
||||
|
||||
// We must bind the program after starting the render pass, and set the color mask after clearing.
|
||||
render_->SetScissor({ 0, 0, vfb->renderWidth, vfb->renderHeight });
|
||||
render_->SetDepth(false, false, GL_ALWAYS);
|
||||
render_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE);
|
||||
render_->BindProgram(depthDownloadProgram_);
|
||||
|
||||
if (!gstate_c.Supports(GPU_SUPPORTS_ACCURATE_DEPTH)) {
|
||||
float factors[] = { 0.0f, 1.0f };
|
||||
render_->SetUniformF(&u_depthDownloadFactor, 2, factors);
|
||||
} else {
|
||||
const float factor = DepthSliceFactor();
|
||||
float factors[] = { -0.5f * (factor - 1.0f) * (1.0f / factor), factor };
|
||||
render_->SetUniformF(&u_depthDownloadFactor, 2, factors);
|
||||
}
|
||||
float shifts[] = { 16777215.0f, 16777215.0f / 256.0f, 16777215.0f / 65536.0f, 16777215.0f / 16777216.0f };
|
||||
render_->SetUniformF(&u_depthDownloadShift, 4, shifts);
|
||||
float to8[] = { 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f };
|
||||
render_->SetUniformF(&u_depthDownloadTo8, 4, to8);
|
||||
|
||||
draw_->BindFramebufferAsTexture(vfb->fbo, TEX_SLOT_PSP_TEXTURE, Draw::FB_DEPTH_BIT, 0);
|
||||
float u1 = 1.0f;
|
||||
float v1 = 1.0f;
|
||||
DrawActiveTexture(x, y, w, h, vfb->renderWidth, vfb->renderHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST);
|
||||
|
||||
draw_->CopyFramebufferToMemorySync(blitFBO, Draw::FB_COLOR_BIT, 0, y, packWidth, h, Draw::DataFormat::R8G8B8A8_UNORM, convBuf_, vfb->z_stride);
|
||||
// TODO: Use 4444 so we can copy lines directly?
|
||||
format16Bit = true;
|
||||
} else {
|
||||
draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, y, packWidth, h, Draw::DataFormat::D32F, convBuf_, vfb->z_stride);
|
||||
format16Bit = false;
|
||||
}
|
||||
|
||||
int dstByteOffset = y * vfb->z_stride * sizeof(u16);
|
||||
u16 *depth = (u16 *)Memory::GetPointer(z_address + dstByteOffset);
|
||||
u32_le *packed32 = (u32_le *)convBuf_;
|
||||
GLfloat *packedf = (GLfloat *)convBuf_;
|
||||
|
||||
int totalPixels = h == 1 ? packWidth : vfb->z_stride * h;
|
||||
if (format16Bit) {
|
||||
for (int yp = 0; yp < h; ++yp) {
|
||||
int row_offset = vfb->z_stride * yp;
|
||||
for (int xp = 0; xp < packWidth; ++xp) {
|
||||
const int i = row_offset + xp;
|
||||
depth[i] = packed32[i] & 0xFFFF;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int yp = 0; yp < h; ++yp) {
|
||||
int row_offset = vfb->z_stride * yp;
|
||||
for (int xp = 0; xp < packWidth; ++xp) {
|
||||
const int i = row_offset + xp;
|
||||
float scaled = FromScaledDepth(packedf[i]);
|
||||
if (scaled <= 0.0f) {
|
||||
depth[i] = 0;
|
||||
} else if (scaled >= 65535.0f) {
|
||||
depth[i] = 65535;
|
||||
} else {
|
||||
depth[i] = (int)scaled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
|
||||
}
|
|
@ -326,6 +326,10 @@ void FramebufferManagerGLES::DestroyDeviceObjects() {
|
|||
render_->DeleteProgram(stencilUploadProgram_);
|
||||
stencilUploadProgram_ = nullptr;
|
||||
}
|
||||
if (depthDownloadProgram_) {
|
||||
render_->DeleteProgram(depthDownloadProgram_);
|
||||
depthDownloadProgram_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
FramebufferManagerGLES::~FramebufferManagerGLES() {
|
||||
|
@ -652,48 +656,6 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
|
|||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE);
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
|
||||
if (!vfb->fbo) {
|
||||
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// Pixel size always 4 here because we always request float
|
||||
const u32 bufSize = vfb->z_stride * (h - y) * 4;
|
||||
const u32 z_address = (0x04000000) | vfb->z_address;
|
||||
const int packWidth = std::min(vfb->z_stride, std::min(x + w, (int)vfb->width));
|
||||
|
||||
if (!convBuf_ || convBufSize_ < bufSize) {
|
||||
delete [] convBuf_;
|
||||
convBuf_ = new u8[bufSize];
|
||||
convBufSize_ = bufSize;
|
||||
}
|
||||
|
||||
DEBUG_LOG(FRAMEBUF, "Reading depthbuffer to mem at %08x for vfb=%08x", z_address, vfb->fb_address);
|
||||
|
||||
draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, y, packWidth, h, Draw::DataFormat::D32F, convBuf_, vfb->z_stride);
|
||||
|
||||
int dstByteOffset = y * vfb->z_stride * sizeof(u16);
|
||||
u16 *depth = (u16 *)Memory::GetPointer(z_address + dstByteOffset);
|
||||
GLfloat *packed = (GLfloat *)convBuf_;
|
||||
|
||||
int totalPixels = h == 1 ? packWidth : vfb->z_stride * h;
|
||||
for (int yp = 0; yp < h; ++yp) {
|
||||
int row_offset = vfb->z_stride * yp;
|
||||
for (int xp = 0; xp < packWidth; ++xp) {
|
||||
const int i = row_offset + xp;
|
||||
float scaled = FromScaledDepth(packed[i]);
|
||||
if (scaled <= 0.0f) {
|
||||
depth[i] = 0;
|
||||
} else if (scaled >= 65535.0f) {
|
||||
depth[i] = 65535;
|
||||
} else {
|
||||
depth[i] = (int)scaled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::EndFrame() {
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,12 @@ private:
|
|||
int u_stencilUploadTex = -1;
|
||||
int u_stencilValue = -1;
|
||||
int u_postShaderTex = -1;
|
||||
|
||||
GLRProgram *depthDownloadProgram_ = nullptr;
|
||||
int u_depthDownloadTex = -1;
|
||||
int u_depthDownloadFactor = -1;
|
||||
int u_depthDownloadShift = -1;
|
||||
int u_depthDownloadTo8 = -1;
|
||||
|
||||
// Cached uniform locs
|
||||
int u_draw2d_tex = -1;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "Core/ConfigValues.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "GPU/Common/StencilCommon.h"
|
||||
#include "GPU/GLES/DrawEngineGLES.h"
|
||||
#include "GPU/GLES/FramebufferManagerGLES.h"
|
||||
#include "GPU/GLES/ShaderManagerGLES.h"
|
||||
#include "GPU/GLES/TextureCacheGLES.h"
|
||||
|
@ -143,7 +144,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
|
|||
queries.push_back({ &u_stencilUploadTex, "tex" });
|
||||
queries.push_back({ &u_stencilValue, "u_stencilValue" });
|
||||
std::vector<GLRProgram::Initializer> inits;
|
||||
inits.push_back({ &u_stencilUploadTex, 0, 0 });
|
||||
inits.push_back({ &u_stencilUploadTex, 0, TEX_SLOT_PSP_TEXTURE });
|
||||
stencilUploadProgram_ = render_->CreateProgram(shaders, semantics, queries, inits, false);
|
||||
for (auto iter : shaders) {
|
||||
render_->DeleteShader(iter);
|
||||
|
|
|
@ -339,6 +339,7 @@
|
|||
<ClCompile Include="Directx9\VertexShaderGeneratorDX9.cpp" />
|
||||
<ClCompile Include="GeDisasm.cpp" />
|
||||
<ClCompile Include="GLES\DepalettizeShaderGLES.cpp" />
|
||||
<ClCompile Include="GLES\DepthBufferGLES.cpp" />
|
||||
<ClCompile Include="GLES\FragmentShaderGeneratorGLES.cpp" />
|
||||
<ClCompile Include="GLES\FragmentTestCacheGLES.cpp" />
|
||||
<ClCompile Include="GLES\FramebufferManagerGLES.cpp" />
|
||||
|
|
|
@ -548,5 +548,8 @@
|
|||
<ClCompile Include="Debugger\Debugger.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GLES\DepthBufferGLES.cpp">
|
||||
<Filter>GLES</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -247,6 +247,7 @@ EXEC_AND_LIB_FILES := \
|
|||
$(SRC)/GPU/Debugger/Stepping.cpp \
|
||||
$(SRC)/GPU/GLES/FramebufferManagerGLES.cpp \
|
||||
$(SRC)/GPU/GLES/DepalettizeShaderGLES.cpp \
|
||||
$(SRC)/GPU/GLES/DepthBufferGLES.cpp.arm \
|
||||
$(SRC)/GPU/GLES/GPU_GLES.cpp.arm \
|
||||
$(SRC)/GPU/GLES/StencilBufferGLES.cpp.arm \
|
||||
$(SRC)/GPU/GLES/TextureCacheGLES.cpp.arm \
|
||||
|
|
|
@ -249,6 +249,7 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool ski
|
|||
switch (init.type) {
|
||||
case 0:
|
||||
glUniform1i(uniform, init.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -388,31 +389,69 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) {
|
|||
#endif
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
|
||||
auto initFBOTexture = [&](GLRTexture &tex, GLint internalFormat, GLenum format, GLenum type, bool linear) {
|
||||
glGenTextures(1, &tex.texture);
|
||||
tex.target = GL_TEXTURE_2D;
|
||||
tex.maxLod = 0.0f;
|
||||
|
||||
// Create the surfaces.
|
||||
glBindTexture(GL_TEXTURE_2D, tex.texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, fbo->width, fbo->height, 0, format, type, nullptr);
|
||||
|
||||
tex.wrapS = GL_CLAMP_TO_EDGE;
|
||||
tex.wrapT = GL_CLAMP_TO_EDGE;
|
||||
tex.magFilter = linear ? GL_LINEAR : GL_NEAREST;
|
||||
tex.minFilter = linear ? GL_LINEAR : GL_NEAREST;
|
||||
tex.canWrap = isPowerOf2(fbo->width) && isPowerOf2(fbo->height);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tex.wrapS);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tex.wrapT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tex.magFilter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, tex.minFilter);
|
||||
if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
}
|
||||
};
|
||||
|
||||
// Color texture is same everywhere
|
||||
glGenFramebuffers(1, &fbo->handle);
|
||||
glGenTextures(1, &fbo->color_texture.texture);
|
||||
fbo->color_texture.target = GL_TEXTURE_2D;
|
||||
fbo->color_texture.maxLod = 0.0f;
|
||||
initFBOTexture(fbo->color_texture, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true);
|
||||
|
||||
// Create the surfaces.
|
||||
glBindTexture(GL_TEXTURE_2D, fbo->color_texture.texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
retry_depth:
|
||||
if (!fbo->z_stencil_) {
|
||||
ILOG("Creating %i x %i FBO using no depth", fbo->width, fbo->height);
|
||||
|
||||
fbo->color_texture.wrapS = GL_CLAMP_TO_EDGE;
|
||||
fbo->color_texture.wrapT = GL_CLAMP_TO_EDGE;
|
||||
fbo->color_texture.magFilter = GL_LINEAR;
|
||||
fbo->color_texture.minFilter = GL_LINEAR;
|
||||
fbo->color_texture.canWrap = isPowerOf2(fbo->width) && isPowerOf2(fbo->height);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, fbo->color_texture.wrapS);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, fbo->color_texture.wrapT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, fbo->color_texture.magFilter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, fbo->color_texture.minFilter);
|
||||
if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
}
|
||||
fbo->z_stencil_buffer = 0;
|
||||
fbo->stencil_buffer = 0;
|
||||
fbo->z_buffer = 0;
|
||||
|
||||
if (gl_extensions.IsGLES) {
|
||||
if (gl_extensions.OES_packed_depth_stencil) {
|
||||
// Bind it all together
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
|
||||
} else if (gl_extensions.IsGLES) {
|
||||
if (gl_extensions.OES_packed_depth_stencil && (gl_extensions.OES_depth_texture || gl_extensions.GLES3)) {
|
||||
ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8 texture", fbo->width, fbo->height);
|
||||
fbo->z_stencil_buffer = 0;
|
||||
fbo->stencil_buffer = 0;
|
||||
fbo->z_buffer = 0;
|
||||
|
||||
if (gl_extensions.GLES3) {
|
||||
initFBOTexture(fbo->z_stencil_texture, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false);
|
||||
} else {
|
||||
initFBOTexture(fbo->z_stencil_texture, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false);
|
||||
}
|
||||
|
||||
// Bind it all together
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
|
||||
if (gl_extensions.GLES3) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
|
||||
} else {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
|
||||
}
|
||||
} else if (gl_extensions.OES_packed_depth_stencil) {
|
||||
ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", fbo->width, fbo->height);
|
||||
// Standard method
|
||||
fbo->stencil_buffer = 0;
|
||||
|
@ -448,6 +487,18 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) {
|
|||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer);
|
||||
}
|
||||
} else if (gl_extensions.VersionGEThan(3, 0)) {
|
||||
ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8 texture", fbo->width, fbo->height);
|
||||
fbo->z_stencil_buffer = 0;
|
||||
fbo->stencil_buffer = 0;
|
||||
fbo->z_buffer = 0;
|
||||
|
||||
initFBOTexture(fbo->z_stencil_texture, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false);
|
||||
|
||||
// Bind it all together
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture.texture, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, fbo->z_stencil_texture.texture, 0);
|
||||
} else {
|
||||
fbo->stencil_buffer = 0;
|
||||
fbo->z_buffer = 0;
|
||||
|
@ -464,6 +515,13 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) {
|
|||
}
|
||||
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE && !fbo->z_buffer) {
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
// Uh oh, maybe we need a z/stencil. Platforms sometimes, right?
|
||||
fbo->z_stencil_ = true;
|
||||
goto retry_depth;
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case GL_FRAMEBUFFER_COMPLETE:
|
||||
// ILOG("Framebuffer verified complete.");
|
||||
|
@ -472,7 +530,7 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) {
|
|||
ELOG("GL_FRAMEBUFFER_UNSUPPORTED");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
||||
ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ");
|
||||
ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
|
||||
break;
|
||||
default:
|
||||
FLOG("Other framebuffer error: %i", status);
|
||||
|
@ -894,10 +952,14 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
|
|||
}
|
||||
if (c.bind_fb_texture.aspect == GL_COLOR_BUFFER_BIT) {
|
||||
if (curTex[slot] != &c.bind_fb_texture.framebuffer->color_texture)
|
||||
glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->color_texture.texture);
|
||||
glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->color_texture.texture);
|
||||
curTex[slot] = &c.bind_fb_texture.framebuffer->color_texture;
|
||||
} else if (c.bind_fb_texture.aspect == GL_DEPTH_BUFFER_BIT) {
|
||||
if (curTex[slot] != &c.bind_fb_texture.framebuffer->z_stencil_texture)
|
||||
glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->z_stencil_texture.texture);
|
||||
curTex[slot] = &c.bind_fb_texture.framebuffer->z_stencil_texture;
|
||||
} else {
|
||||
// TODO: Depth texturing?
|
||||
// TODO: Stencil texturing?
|
||||
curTex[slot] = nullptr;
|
||||
}
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
|
@ -1458,36 +1520,30 @@ GLRFramebuffer::~GLRFramebuffer() {
|
|||
return;
|
||||
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
|
||||
if (handle) {
|
||||
if (handle) {
|
||||
if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, handle);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO);
|
||||
glDeleteFramebuffers(1, &handle);
|
||||
}
|
||||
if (z_stencil_buffer)
|
||||
glDeleteRenderbuffers(1, &z_stencil_buffer);
|
||||
if (z_buffer)
|
||||
glDeleteRenderbuffers(1, &z_buffer);
|
||||
if (stencil_buffer)
|
||||
glDeleteRenderbuffers(1, &stencil_buffer);
|
||||
} else if (gl_extensions.EXT_framebuffer_object) {
|
||||
#ifndef USING_GLES2
|
||||
if (handle) {
|
||||
} else if (gl_extensions.EXT_framebuffer_object) {
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, handle);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_defaultFBO);
|
||||
glDeleteFramebuffersEXT(1, &handle);
|
||||
}
|
||||
if (z_stencil_buffer)
|
||||
glDeleteRenderbuffers(1, &z_stencil_buffer);
|
||||
if (z_buffer)
|
||||
glDeleteRenderbuffers(1, &z_buffer);
|
||||
if (stencil_buffer)
|
||||
glDeleteRenderbuffers(1, &stencil_buffer);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// These can only be set when supported.
|
||||
if (z_stencil_buffer)
|
||||
glDeleteRenderbuffers(1, &z_stencil_buffer);
|
||||
if (z_buffer)
|
||||
glDeleteRenderbuffers(1, &z_buffer);
|
||||
if (stencil_buffer)
|
||||
glDeleteRenderbuffers(1, &stencil_buffer);
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
}
|
||||
|
|
|
@ -61,10 +61,12 @@ void GLDeleter::Perform(GLRenderManager *renderManager, bool skipGLCalls) {
|
|||
inputLayouts.clear();
|
||||
for (auto framebuffer : framebuffers) {
|
||||
if (skipGLCalls) {
|
||||
framebuffer->handle = 0;
|
||||
framebuffer->color_texture.texture = 0;
|
||||
framebuffer->z_stencil_buffer = 0;
|
||||
framebuffer->z_stencil_texture.texture = 0;
|
||||
framebuffer->z_buffer = 0;
|
||||
framebuffer->stencil_buffer = 0;
|
||||
framebuffer->z_stencil_buffer = 0;
|
||||
framebuffer->handle = 0;
|
||||
}
|
||||
delete framebuffer;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,9 @@ public:
|
|||
|
||||
GLuint handle = 0;
|
||||
GLRTexture color_texture;
|
||||
GLuint z_stencil_buffer = 0; // Either this is set, or the two below.
|
||||
// Either z_stencil_texture, z_stencil_buffer, or (z_buffer and stencil_buffer) are set.
|
||||
GLuint z_stencil_buffer = 0;
|
||||
GLRTexture z_stencil_texture;
|
||||
GLuint z_buffer = 0;
|
||||
GLuint stencil_buffer = 0;
|
||||
|
||||
|
|
|
@ -188,6 +188,7 @@ SOURCES_CXX += \
|
|||
$(GPUDIR)/Software/Lighting.cpp \
|
||||
$(GPUDIR)/Software/Rasterizer.cpp \
|
||||
$(GPUDIR)/GLES/DepalettizeShaderGLES.cpp \
|
||||
$(GPUDIR)/GLES/DepthBufferGLES.cpp \
|
||||
$(GPUDIR)/GLES/VertexShaderGeneratorGLES.cpp \
|
||||
$(GPUDIR)/GLES/DrawEngineGLES.cpp \
|
||||
$(GPUDIR)/GLES/GPU_GLES.cpp \
|
||||
|
|
Loading…
Add table
Reference in a new issue