diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index 583bfc71..8ed7d135 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -72,12 +72,19 @@ public: void setColourFormat(u32 format) { colourBufferFormat = static_cast(format); } void setDepthFormat(DepthBuffer::Formats format) { depthBufferFormat = format; } - void setDepthFormat(u32 format) { depthBufferFormat = static_cast(format); } + void setDepthFormat(u32 format) { + if (format == 2) { + Helpers::panic("[PICA] Undocumented depth-stencil mode!"); + } + + depthBufferFormat = static_cast(format); + } void setColourBufferLoc(u32 loc) { colourBufferLoc = loc; } void setDepthBufferLoc(u32 loc) { depthBufferLoc = loc; } void setupBlending(); + void bindDepthBuffer(); static constexpr u32 vertexBufferSize = 0x1500; }; \ No newline at end of file diff --git a/include/renderer_gl/surfaces.hpp b/include/renderer_gl/surfaces.hpp index 93ccd839..4a68dc4a 100644 --- a/include/renderer_gl/surfaces.hpp +++ b/include/renderer_gl/surfaces.hpp @@ -40,13 +40,13 @@ struct ColourBuffer { void allocate() { // Create texture for the FBO, setting up filters and the like - // Reading back the current texture is slow, but allocate calls should be and far between. + // Reading back the current texture is slow, but allocate calls should be few and far between. // If this becomes a bottleneck, we can fix it semi-easily auto prevTexture = OpenGL::getTex2D(); texture.create(size.x(), size.y(), GL_RGBA8); texture.bind(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + texture.setMinFilter(OpenGL::Linear); + texture.setMagFilter(OpenGL::Linear); glBindTexture(GL_TEXTURE_2D, prevTexture); //Helpers::panic("Creating FBO: %d, %d\n", size.x(), size.y()); @@ -115,14 +115,47 @@ struct DepthBuffer { DepthBuffer() : valid(false) {} DepthBuffer(u32 loc, Formats format, u32 x, u32 y, bool valid = true) : - location(loc), format(format), size({x, y}), valid(valid) {} + location(loc), format(format), size({x, y}), valid(valid) { + + u64 endLoc = (u64)loc + sizeInBytes(); + // Check if start and end are valid here + range = Interval(loc, (u32)endLoc); + } bool hasStencil() { return format == Formats::Depth24Stencil8; } void allocate() { - printf("Make this depth buffer allocate itself\n"); + // Create texture for the FBO, setting up filters and the like + // Reading back the current texture is slow, but allocate calls should be few and far between. + // If this becomes a bottleneck, we can fix it semi-easily + auto prevTexture = OpenGL::getTex2D(); + + // Internal formats for the texture based on format + static constexpr std::array internalFormats = { + GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT24, GL_DEPTH24_STENCIL8 + }; + + // Format of the texture + static constexpr std::array formats = { + GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL + }; + + static constexpr std::array types = { + GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_INT_24_8 + }; + + auto internalFormat = internalFormats[(int)format]; + auto fmt = formats[(int)format]; + auto type = types[(int)format]; + + texture.createDSTexture(size.x(), size.y(), internalFormat, fmt, nullptr, type); + texture.bind(); + texture.setMinFilter(OpenGL::Linear); + texture.setMagFilter(OpenGL::Linear); + + glBindTexture(GL_TEXTURE_2D, prevTexture); } void free() { diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index c9c82984..5a41b6bd 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -291,14 +291,18 @@ void Renderer::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 c float viewportHeight = f24::fromRaw(regs[PICAInternalRegs::ViewportHeight] & 0xffffff).toFloat32() * 2.0; OpenGL::setViewport(viewportWidth, viewportHeight); + // Note: The code below must execute after we've bound the colour buffer & its framebuffer + // Because it attaches a depth texture to the aforementioned colour buffer if (depthEnable) { OpenGL::enableDepth(); glDepthFunc(depthModes[depthFunc]); glDepthMask(depthWriteEnable ? GL_TRUE : GL_FALSE); + bindDepthBuffer(); } else { if (depthWriteEnable) { OpenGL::enableDepth(); glDepthFunc(GL_ALWAYS); + bindDepthBuffer(); } else { OpenGL::disableDepth(); } @@ -364,8 +368,24 @@ OpenGL::Framebuffer Renderer::getColourFBO() { } } +void Renderer::bindDepthBuffer() { + // Similar logic as the getColourFBO function + DepthBuffer sampleBuffer(depthBufferLoc, depthBufferFormat, fbSize.x(), fbSize.y()); + auto buffer = depthBufferCache.find(sampleBuffer); + GLuint tex; + + if (buffer.has_value()) { + tex = buffer.value().get().texture.m_handle; + } else { + tex = depthBufferCache.add(sampleBuffer).texture.m_handle; + } + + auto attachment = depthBufferFormat == DepthBuffer::Formats::Depth24Stencil8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; + glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0); +} + OpenGL::Texture Renderer::getTexture(Texture& tex) { - // Similar logic as the getColourFBO/getDepthBuffer functions + // Similar logic as the getColourFBO/bindDepthBuffer functions auto buffer = textureCache.find(tex); if (buffer.has_value()) {