void GLDriver::decafClearDepthStencil(const pm4::DecafClearDepthStencil &data) { auto db_depth_clear = getRegister<latte::DB_DEPTH_CLEAR>(latte::Register::DB_DEPTH_CLEAR); auto db_stencil_clear = getRegister<latte::DB_STENCIL_CLEAR>(latte::Register::DB_STENCIL_CLEAR); auto dbFormat = data.db_depth_info.FORMAT(); auto hasStencil = (dbFormat == latte::DEPTH_8_24 || dbFormat == latte::DEPTH_8_24_FLOAT || dbFormat == latte::DEPTH_X24_8_32_FLOAT); // Find our depthbuffer to clear auto db_depth_base = bit_cast<latte::DB_DEPTH_BASE>(data.bufferAddr); auto buffer = getDepthBuffer(db_depth_base, data.db_depth_size, data.db_depth_info); // Bind depth buffer if (hasStencil) { gl::glNamedFramebufferTexture(mDepthClearFrameBuffer, gl::GL_DEPTH_STENCIL_ATTACHMENT, buffer->object, 0); } else { gl::glNamedFramebufferTexture(mDepthClearFrameBuffer, gl::GL_STENCIL_ATTACHMENT, 0, 0); gl::glNamedFramebufferTexture(mDepthClearFrameBuffer, gl::GL_DEPTH_ATTACHMENT, buffer->object, 0); } // Check depth frame buffer is complete auto status = gl::glCheckNamedFramebufferStatus(mDepthClearFrameBuffer, gl::GL_DRAW_FRAMEBUFFER); if (status != gl::GL_FRAMEBUFFER_COMPLETE) { gLog->warn("Skipping clear with invalid depth buffer, status {}.", status); return; } // Clear depth buffer gl::glDisable(gl::GL_SCISSOR_TEST); if (hasStencil) { gl::glClearNamedFramebufferfi(mDepthClearFrameBuffer, gl::GL_DEPTH_STENCIL, 0, db_depth_clear.DEPTH_CLEAR, db_stencil_clear.CLEAR()); } else { gl::glClearNamedFramebufferfv(mDepthClearFrameBuffer, gl::GL_DEPTH, 0, &db_depth_clear.DEPTH_CLEAR); } gl::glEnable(gl::GL_SCISSOR_TEST); }
bool GLDriver::checkActiveDepthBuffer() { auto db_depth_base = getRegister<latte::DB_DEPTH_BASE>(latte::Register::DB_DEPTH_BASE); auto &active = mActiveDepthBuffer; if (!db_depth_base.BASE_256B) { if (active) { // Unbind depth buffer gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_DEPTH_ATTACHMENT, 0, 0); active = nullptr; } return true; } // Bind depth buffer auto db_depth_size = getRegister<latte::DB_DEPTH_SIZE>(latte::Register::DB_DEPTH_SIZE); auto db_depth_info = getRegister<latte::DB_DEPTH_INFO>(latte::Register::DB_DEPTH_INFO); active = getDepthBuffer(db_depth_base, db_depth_size, db_depth_info); gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_DEPTH_ATTACHMENT, active->object, 0); return true; }
bool GLDriver::checkActiveDepthBuffer() { auto db_depth_base = getRegister<latte::DB_DEPTH_BASE>(latte::Register::DB_DEPTH_BASE); auto db_depth_size = getRegister<latte::DB_DEPTH_SIZE>(latte::Register::DB_DEPTH_SIZE); auto db_depth_info = getRegister<latte::DB_DEPTH_INFO>(latte::Register::DB_DEPTH_INFO); auto db_depth_control = getRegister<latte::DB_DEPTH_CONTROL>(latte::Register::DB_DEPTH_CONTROL); auto format = db_depth_info.FORMAT(); auto z_enable = db_depth_control.Z_ENABLE(); auto stencil_enable = db_depth_control.STENCIL_ENABLE(); // We unbind the depth buffer whenever depth testing is disabled so a // size mismatch with color buffers doesn't clip render operations, but // we have to look up the surface regardless of whether depth testing // is enabled; if it's a combined depth/stencil format and stencil // testing is enabled, we still have to bind the buffer to the stencil // attachment. SurfaceBuffer *surface; if (db_depth_base.BASE_256B()) { surface = getDepthBuffer(db_depth_base, db_depth_size, db_depth_info, false); } else { surface = nullptr; } auto surfaceObject = surface ? surface->active->object : 0; if (format != latte::DB_FORMAT::DEPTH_8_24 && format != latte::DB_FORMAT::DEPTH_8_24_FLOAT && format != latte::DB_FORMAT::DEPTH_X8_24 && format != latte::DB_FORMAT::DEPTH_X8_24_FLOAT && format != latte::DB_FORMAT::DEPTH_X24_8_32_FLOAT) { // You cannot bind a stencil buffer if the framebuffer does not support it. stencil_enable = false; } if (surfaceObject != mDepthBufferCache.object || z_enable != mDepthBufferCache.depthBound || stencil_enable != mDepthBufferCache.stencilBound) { if (z_enable && stencil_enable) { gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_DEPTH_STENCIL_ATTACHMENT, surfaceObject, 0); } else if (!z_enable && !stencil_enable) { if (mDepthBufferCache.depthBound || mDepthBufferCache.stencilBound) { gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_DEPTH_STENCIL_ATTACHMENT, 0, 0); } } else if (z_enable) { decaf_check(!stencil_enable); if (mDepthBufferCache.stencilBound) { gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_STENCIL_ATTACHMENT, 0, 0); } gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_DEPTH_ATTACHMENT, surfaceObject, 0); } else { decaf_check(!z_enable && stencil_enable); if (mDepthBufferCache.depthBound) { gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_DEPTH_ATTACHMENT, 0, 0); } gl::glFramebufferTexture(gl::GL_FRAMEBUFFER, gl::GL_STENCIL_ATTACHMENT, surfaceObject, 0); } mFramebufferChanged = true; mDepthBufferCache.object = surfaceObject; mDepthBufferCache.depthBound = z_enable; mDepthBufferCache.stencilBound = stencil_enable; } return true; }