diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index 8989d8fe..968dae44 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -2,7 +2,10 @@ namespace PICAInternalRegs { enum : u32 { - // Geometry pipeline regs + // Framebuffer registers + DepthAndColorMask = 0x107, + + // Geometry pipeline registers VertexAttribLoc = 0x200, AttribFormatLow = 0x201, AttribFormatHigh = 0x202, diff --git a/include/logger.hpp b/include/logger.hpp index cb264da5..7bcde212 100644 --- a/include/logger.hpp +++ b/include/logger.hpp @@ -21,7 +21,7 @@ namespace Log { static Logger kernelLogger; static Logger debugStringLogger; // Enables output for the outputDebugString SVC static Logger svcLogger; - static Logger gpuLogger; + static Logger gpuLogger; // Service loggers static Logger aptLogger; diff --git a/src/core/PICA/gpu.cpp b/src/core/PICA/gpu.cpp index 0acc168b..6e46282a 100644 --- a/src/core/PICA/gpu.cpp +++ b/src/core/PICA/gpu.cpp @@ -130,6 +130,8 @@ void GPU::drawArrays() { shaderUnit.vs.run(); std::memcpy(&vertices[i].position, &shaderUnit.vs.outputs[0], sizeof(vec4f)); std::memcpy(&vertices[i].colour, &shaderUnit.vs.outputs[1], sizeof(vec4f)); + + printf("(x, y, z) = (%f, %f, %f)\n", (double)vertices[i].position.x(), (double)vertices[i].position.y(), (double)vertices[i].position.z()); } drawVertices(OpenGL::Triangle, vertices, vertexCount); diff --git a/src/core/PICA/renderer_opengl.cpp b/src/core/PICA/renderer_opengl.cpp index 33f7ed4f..db50f21c 100644 --- a/src/core/PICA/renderer_opengl.cpp +++ b/src/core/PICA/renderer_opengl.cpp @@ -1,4 +1,5 @@ #include "PICA/gpu.hpp" +#include "PICA/regs.hpp" #include "opengl.hpp" // This is all hacked up to display our first triangle @@ -75,7 +76,16 @@ void GPU::initGraphicsContext() { glBindTexture(GL_TEXTURE_2D, 0); fbo.createWithDrawTexture(fboTexture); - fbo.bind(OpenGL::DrawFramebuffer); + fbo.bind(OpenGL::DrawAndReadFramebuffer); + + GLuint rbo; + glGenRenderbuffers(1, &rbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 400, 240); // use a single renderbuffer object for both a depth AND stencil buffer. + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // now actually attach it + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + Helpers::panic("Incomplete framebuffer"); + //glBindRenderbuffer(GL_RENDERBUFFER, 0); OpenGL::setViewport(400, 240); OpenGL::setClearColor(0.0, 0.0, 0.0, 1.0); @@ -106,7 +116,6 @@ void GPU::initGraphicsContext() { } void GPU::getGraphicsContext() { - OpenGL::disableDepth(); OpenGL::disableScissor(); OpenGL::setViewport(400, 240); fbo.bind(OpenGL::DrawAndReadFramebuffer); @@ -117,6 +126,34 @@ void GPU::getGraphicsContext() { } void GPU::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 count) { + // Adjust depth buffer + const u32 depthControl = regs[PICAInternalRegs::DepthAndColorMask]; + bool depthEnable = depthControl & 1; + bool depthWriteEnable = (depthControl >> 12) & 1; + int depthFunc = (depthControl >> 4) & 7; + int colourMask = (depthControl >> 8) & 0xf; + + static constexpr std::array depthModes = { + GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL + }; + + printf("Depth enable: %d, func: %d, writeEnable: %d\n", depthEnable, depthFunc, depthWriteEnable); + + if (depthEnable) { + OpenGL::enableDepth(); + glDepthFunc(depthModes[depthFunc]); + glDepthMask(depthWriteEnable ? GL_TRUE : GL_FALSE); + } else { + if (depthWriteEnable) { + OpenGL::enableDepth(); + glDepthFunc(GL_ALWAYS); + } else { + OpenGL::disableDepth(); + } + } + + if (colourMask != 0xf) Helpers::panic("[PICA] Colour mask = %X != 0xf", colourMask); + vbo.bufferVertsSub(vertices, count); OpenGL::draw(primType, count); } @@ -126,15 +163,16 @@ constexpr u32 bottomScreenBuffer = 0x1f300000; // Quick hack to display top screen for now void GPU::display() { + OpenGL::disableDepth(); OpenGL::disableScissor(); OpenGL::bindScreenFramebuffer(); fboTexture.bind(); displayProgram.use(); - dummyVBO.bind(); dummyVAO.bind(); - OpenGL::setViewport(0, 240, 400, 240); - + OpenGL::setClearColor(0.0, 0.0, 0.0, 1.0); // Clear screen colour + OpenGL::clearColor(); + OpenGL::setViewport(0, 240, 400, 240); // Actually draw our 3DS screen OpenGL::draw(OpenGL::TriangleStrip, 4); } diff --git a/src/core/PICA/shader_interpreter.cpp b/src/core/PICA/shader_interpreter.cpp index cf299547..b23ef192 100644 --- a/src/core/PICA/shader_interpreter.cpp +++ b/src/core/PICA/shader_interpreter.cpp @@ -111,8 +111,8 @@ PICAShader::vec4f& PICAShader::getDest(u32 dest) { bool PICAShader::isCondTrue(u32 instruction) { u32 condition = (instruction >> 22) & 3; - bool refX = ((instruction >> 24) & 1) != 0; - bool refY = ((instruction >> 25) & 1) != 0; + bool refY = ((instruction >> 24) & 1) != 0; + bool refX = ((instruction >> 25) & 1) != 0; switch (condition) { case 0: // Either cmp register matches @@ -142,7 +142,7 @@ void PICAShader::add(u32 instruction) { u32 componentMask = operandDescriptor & 0xf; for (int i = 0; i < 4; i++) { if (componentMask & (1 << i)) { - destVector[3 - i] = srcVec1[3 - i] + srcVec2[3 - 1]; + destVector[3 - i] = srcVec1[3 - i] + srcVec2[3 - i]; } } } @@ -163,7 +163,7 @@ void PICAShader::mul(u32 instruction) { u32 componentMask = operandDescriptor & 0xf; for (int i = 0; i < 4; i++) { if (componentMask & (1 << i)) { - destVector[3 - i] = srcVec1[3 - i] * srcVec2[3 - 1]; + destVector[3 - i] = srcVec1[3 - i] * srcVec2[3 - i]; } } } @@ -278,7 +278,7 @@ void PICAShader::rsq(u32 instruction) { vec4f srcVec1 = getSourceSwizzled<1>(src1, operandDescriptor); vec4f& destVector = getDest(dest); - f24 res = f24::fromFloat32(1.0f / std::sqrt(srcVec1[0].toFloat32())); + f24 res = f24::fromFloat32(1.0f / std::sqrtf(srcVec1[0].toFloat32())); u32 componentMask = operandDescriptor & 0xf; for (int i = 0; i < 4; i++) { @@ -316,8 +316,8 @@ void PICAShader::cmp(u32 instruction) { const u32 src1 = (instruction >> 12) & 0x7f; const u32 src2 = (instruction >> 7) & 0x1f; // src2 coming first because PICA moment const u32 idx = (instruction >> 19) & 3; - const u32 cmpX = (instruction >> 21) & 7; - const u32 cmpY = (instruction >> 24) & 7; + const u32 cmpY = (instruction >> 21) & 7; + const u32 cmpX = (instruction >> 24) & 7; const u32 cmpOperations[2] = { cmpX, cmpY }; if (idx) Helpers::panic("[PICA] CMP: idx != 0"); @@ -375,7 +375,6 @@ void PICAShader::ifc(u32 instruction) { } void PICAShader::callu(u32 instruction) { - const u32 dest = (instruction >> 10) & 0xfff; const u32 bit = (instruction >> 22) & 0xf; // Bit of the bool uniform to check if (boolUniform & (1 << bit)) { @@ -383,6 +382,7 @@ void PICAShader::callu(u32 instruction) { Helpers::panic("[PICA] Overflowed CALL stack"); const u32 num = instruction & 0xff; + const u32 dest = (instruction >> 10) & 0xfff; auto& block = callInfo[callIndex++]; block.endingPC = dest + num; diff --git a/src/emulator.cpp b/src/emulator.cpp index e4e3b758..de04d310 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -23,15 +23,9 @@ void Emulator::render() { void Emulator::run() { while (window.isOpen()) { - // Clear window to black - OpenGL::bindScreenFramebuffer(); - OpenGL::disableScissor(); - OpenGL::setClearColor(0.0, 0.0, 0.0, 1.0); - OpenGL::clearColor(); - gpu.getGraphicsContext(); // Give the GPU a rendering context runFrame(); // Run 1 frame of instructions - gpu.display(); + gpu.display(); // Display graphics // Send VBlank interrupts kernel.sendGPUInterrupt(GPUInterrupt::VBlank0);