Support depth clamping in OpenGL where available.

Should make support for depth texturing quite easy.

Unfortunately, this extension does not exist on OpenGL ES. There we'll
have to use ugly tricks with gl_FragDepth if we want this.
This commit is contained in:
Henrik Rydgård committed 2021-07-09 21:09:44 +02:00
1 parent 5bd9e93196
commit df6abe83a3
9 files changed
+44 -6

No files matched your search

+12
View File
@@ -793,6 +793,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
bool blendEnabled = false;
bool cullEnabled = false;
bool ditherEnabled = false;
bool depthClampEnabled = false;
#ifndef USING_GLES2
int logicOp = -1;
bool logicEnabled = false;
@@ -1283,6 +1284,15 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
glDisable(GL_DITHER);
ditherEnabled = false;
}
if (c.raster.depthClampEnable) {
if (!depthClampEnabled) {
glEnable(GL_DEPTH_CLAMP);
depthClampEnabled = true;
}
} else if (!c.raster.depthClampEnable && depthClampEnabled) {
glDisable(GL_DEPTH_CLAMP);
depthClampEnabled = false;
}
CHECK_GL_ERROR_IF_DEBUG();
break;
default:
@@ -1321,6 +1331,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
glDisable(GL_BLEND);
if (cullEnabled)
glDisable(GL_CULL_FACE);
if (depthClampEnabled)
glDisable(GL_DEPTH_CLAMP);
#ifndef USING_GLES2
if (!gl_extensions.IsGLES && logicEnabled) {
glDisable(GL_COLOR_LOGIC_OP);
+1
View File
@@ -196,6 +196,7 @@ struct GLRRenderData {
GLenum frontFace;
GLenum cullFace;
GLboolean ditherEnable;
GLboolean depthClampEnable;
} raster;
};
};
+2 -1
View File
@@ -813,13 +813,14 @@ public:
curRenderStep_->commands.push_back(data);
}
void SetRaster(GLboolean cullEnable, GLenum frontFace, GLenum cullFace, GLboolean ditherEnable) {
void SetRaster(GLboolean cullEnable, GLenum frontFace, GLenum cullFace, GLboolean ditherEnable, GLboolean depthClamp) {
_dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
GLRRenderData data{ GLRRenderCommand::RASTER };
data.raster.cullEnable = cullEnable;
data.raster.frontFace = frontFace;
data.raster.cullFace = cullFace;
data.raster.ditherEnable = ditherEnable;
data.raster.depthClampEnable = depthClamp;
curRenderStep_->commands.push_back(data);
}
+5 -1
View File
@@ -188,7 +188,7 @@ public:
class OpenGLRasterState : public RasterState {
public:
void Apply(GLRenderManager *render) {
render->SetRaster(cullEnable, frontFace, cullMode, false);
render->SetRaster(cullEnable, frontFace, cullMode, GL_FALSE, GL_FALSE);
}
GLboolean cullEnable;
@@ -533,6 +533,10 @@ OpenGLContext::OpenGLContext() {
}
caps_.framebufferBlitSupported = gl_extensions.NV_framebuffer_blit || gl_extensions.ARB_framebuffer_object;
caps_.framebufferDepthBlitSupported = caps_.framebufferBlitSupported;
caps_.depthClampSupported = gl_extensions.ARB_depth_clamp;
// Interesting potential hack for emulating GL_DEPTH_CLAMP (use a separate varying, force depth in fragment shader):
// https://stackoverflow.com/questions/5960757/how-to-emulate-gl-depth-clamp-nv
switch (gl_extensions.gpuVendor) {
case GPU_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break;
+1 -1
View File
@@ -133,7 +133,7 @@ void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int
// 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_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE, GL_FALSE);
render_->BindProgram(depthDownloadProgram_);
if (!gstate_c.Supports(GPU_SUPPORTS_ACCURATE_DEPTH)) {
+1 -1
View File
@@ -203,7 +203,7 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float
// We always want a plain state here, well, except for when it's used by the stencil stuff...
render_->SetDepth(false, false, GL_ALWAYS);
render_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE);
render_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE, GL_FALSE);
if (!(flags & DRAWTEX_KEEP_STENCIL_ALPHA)) {
render_->SetNoBlendAndMask(0xF);
render_->SetStencilDisabled();
+3
View File
@@ -221,6 +221,9 @@ void GPU_GLES::CheckGPUFeatures() {
if (gl_extensions.ARB_texture_float || gl_extensions.OES_texture_float)
features |= GPU_SUPPORTS_TEXTURE_FLOAT;
if (draw_->GetDeviceCaps().depthClampSupported)
features |= GPU_SUPPORTS_DEPTH_CLAMP;
// If we already have a 16-bit depth buffer, we don't need to round.
bool prefer24 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D24_S8;
if (prefer24) {
+18 -1
View File
@@ -230,7 +230,24 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
GLenum cullMode = cullingMode[gstate.getCullMode() ^ !useBufferedRendering];
cullEnable = !gstate.isModeClear() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled();
renderManager->SetRaster(cullEnable, GL_CCW, cullMode, dither);
bool depthClampEnable = false;
if (gstate.isModeClear() || gstate.isModeThrough()) {
// TODO: Might happen in clear mode if not through...
depthClampEnable = false;
} else {
// Set cull
if (gstate.getDepthRangeMin() == 0 || gstate.getDepthRangeMax() == 65535) {
// TODO: Still has a bug where we clamp to depth range if one is not the full range.
// But the alternate is not clamping in either direction...
depthClampEnable = gstate.isDepthClampEnabled() && gstate_c.Supports(GPU_SUPPORTS_DEPTH_CLAMP);
} else {
// We just want to clip in this case, the clamp would be clipped anyway.
depthClampEnable = false;
}
}
renderManager->SetRaster(cullEnable, GL_CCW, cullMode, dither, depthClampEnable);
}
if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE)) {
+1 -1
View File
@@ -191,7 +191,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, StencilUplo
render_->SetDepth(false, false, GL_ALWAYS);
render_->Clear(0, 0, 0, GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 0x8, 0, 0, 0, 0);
render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF);
render_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE);
render_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE, GL_FALSE);
render_->BindProgram(stencilUploadProgram_);
render_->SetNoBlendAndMask(0x8);