mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 06:35:40 +12:00
[PICA] Alpha test and some new registers
This commit is contained in:
parent
6adc56df4e
commit
8b85255f4c
6 changed files with 104 additions and 29 deletions
|
@ -78,6 +78,7 @@ class GPU {
|
|||
u32 fixedAttribCount = 0; // How many attribute components have we written? When we get to 4 the attr will actually get submitted
|
||||
std::array<u32, 3> fixedAttrBuff; // Buffer to hold fixed attributes in until they get submitted
|
||||
|
||||
// OpenGL renderer state
|
||||
OpenGL::Framebuffer fbo;
|
||||
OpenGL::Texture fboTexture;
|
||||
OpenGL::Program triangleProgram;
|
||||
|
@ -85,6 +86,8 @@ class GPU {
|
|||
|
||||
OpenGL::VertexArray vao;
|
||||
OpenGL::VertexBuffer vbo;
|
||||
GLint alphaControlLoc = -1;
|
||||
u32 oldAlphaControl = 0;
|
||||
|
||||
// Dummy VAO/VBO for blitting the final output
|
||||
OpenGL::VertexArray dummyVAO;
|
||||
|
|
|
@ -2,7 +2,17 @@
|
|||
|
||||
namespace PICAInternalRegs {
|
||||
enum : u32 {
|
||||
// Rasterizer registers
|
||||
ViewportWidth = 0x41,
|
||||
ViewportInvw = 0x42,
|
||||
ViewportHeight = 0x43,
|
||||
ViewportInvh = 0x44,
|
||||
|
||||
DepthScale = 0x4D,
|
||||
DepthOffset = 0x4E,
|
||||
|
||||
// Framebuffer registers
|
||||
AlphaTestConfig = 0x104,
|
||||
DepthAndColorMask = 0x107,
|
||||
|
||||
// Geometry pipeline registers
|
||||
|
|
|
@ -74,7 +74,7 @@ class PICAShader {
|
|||
|
||||
std::array<Loop, 4> loopInfo;
|
||||
std::array<ConditionalInfo, 8> conditionalInfo;
|
||||
std::array<CallInfo, 8> callInfo;
|
||||
std::array<CallInfo, 4> callInfo;
|
||||
|
||||
ShaderType type;
|
||||
|
||||
|
@ -157,7 +157,7 @@ public:
|
|||
std::array<vec4f, 96> floatUniforms;
|
||||
|
||||
std::array<vec4f, 16> fixedAttributes; // Fixed vertex attributes
|
||||
std::array<vec4f, 16> attributes; // Attributes past to the shader
|
||||
std::array<vec4f, 16> attributes; // Attributes passed to the shader
|
||||
std::array<vec4f, 16> outputs;
|
||||
|
||||
PICAShader(ShaderType type) : type(type) {}
|
||||
|
@ -177,6 +177,7 @@ public:
|
|||
}
|
||||
|
||||
void uploadWord(u32 word) {
|
||||
if (bufferIndex >= 511) Helpers::panic("o no");
|
||||
bufferedShader[bufferIndex++] = word;
|
||||
bufferIndex &= 0x1ff;
|
||||
}
|
||||
|
|
|
@ -131,7 +131,8 @@ void GPU::drawArrays() {
|
|||
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());
|
||||
//printf("(x, y, z, w) = (%f, %f, %f, %f)\n", (double)vertices[i].position.x(), (double)vertices[i].position.y(), (double)vertices[i].position.z(), (double)vertices[i].position.w());
|
||||
//printf("(r, g, b, a) = (%f, %f, %f, %f)\n", (double)vertices[i].colour.r(), (double)vertices[i].colour.g(), (double)vertices[i].colour.b(), (double)vertices[i].colour.a());
|
||||
}
|
||||
|
||||
drawVertices(OpenGL::Triangle, vertices, vertexCount);
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#include "PICA/float_types.hpp"
|
||||
#include "PICA/gpu.hpp"
|
||||
#include "PICA/regs.hpp"
|
||||
#include "opengl.hpp"
|
||||
|
||||
using namespace Floats;
|
||||
|
||||
// This is all hacked up to display our first triangle
|
||||
|
||||
const char* vertexShader = R"(
|
||||
|
@ -24,8 +27,46 @@ const char* fragmentShader = R"(
|
|||
in vec4 colour;
|
||||
out vec4 fragColour;
|
||||
|
||||
uniform uint u_alphaControl;
|
||||
|
||||
void main() {
|
||||
fragColour = colour;
|
||||
gl_FragDepth *= -1.0;
|
||||
|
||||
if ((u_alphaControl & 1u) != 0u) { // Check if alpha test is on
|
||||
uint func = (u_alphaControl >> 4u) & 7u;
|
||||
float reference = float((u_alphaControl >> 8u) & 0xffu) / 255.0;
|
||||
float alpha = fragColour.a;
|
||||
|
||||
switch (func) {
|
||||
case 0: discard; break; // Never pass alpha test
|
||||
case 1: break; // Always pass alpha test
|
||||
case 2: // Pass if equal
|
||||
if (alpha != reference)
|
||||
discard;
|
||||
break;
|
||||
case 3: // Pass if not equal
|
||||
if (alpha == reference)
|
||||
discard;
|
||||
break;
|
||||
case 4: // Pass if less than
|
||||
if (alpha >= reference)
|
||||
discard;
|
||||
break;
|
||||
case 5: // Pass if less than or equal
|
||||
if (alpha > reference)
|
||||
discard;
|
||||
break;
|
||||
case 6: // Pass if greater than
|
||||
if (alpha <= reference)
|
||||
discard;
|
||||
break;
|
||||
case 7: // Pass if greater than or equal
|
||||
if (alpha < reference)
|
||||
discard;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -94,6 +135,10 @@ void GPU::initGraphicsContext() {
|
|||
OpenGL::Shader vert(vertexShader, OpenGL::Vertex);
|
||||
OpenGL::Shader frag(fragmentShader, OpenGL::Fragment);
|
||||
triangleProgram.create({ vert, frag });
|
||||
triangleProgram.use();
|
||||
|
||||
alphaControlLoc = OpenGL::uniformLocation(triangleProgram, "u_alphaControl");
|
||||
glUniform1ui(alphaControlLoc, 0); // Default alpha control to 0
|
||||
|
||||
OpenGL::Shader vertDisplay(displayVertexShader, OpenGL::Vertex);
|
||||
OpenGL::Shader fragDisplay(displayFragmentShader, OpenGL::Fragment);
|
||||
|
@ -126,7 +171,13 @@ void GPU::getGraphicsContext() {
|
|||
}
|
||||
|
||||
void GPU::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 count) {
|
||||
// Adjust depth buffer
|
||||
// Adjust alpha test if necessary
|
||||
const u32 alphaControl = regs[PICAInternalRegs::AlphaTestConfig];
|
||||
if (alphaControl != oldAlphaControl) {
|
||||
oldAlphaControl = alphaControl;
|
||||
glUniform1ui(alphaControlLoc, alphaControl);
|
||||
}
|
||||
|
||||
const u32 depthControl = regs[PICAInternalRegs::DepthAndColorMask];
|
||||
bool depthEnable = depthControl & 1;
|
||||
bool depthWriteEnable = (depthControl >> 12) & 1;
|
||||
|
@ -137,8 +188,17 @@ void GPU::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 count)
|
|||
GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL
|
||||
};
|
||||
|
||||
f24 depthScale = f24::fromRaw(regs[PICAInternalRegs::DepthScale] & 0xffffff);
|
||||
f24 depthOffset = f24::fromRaw(regs[PICAInternalRegs::DepthOffset] & 0xffffff);
|
||||
printf("Depth enable: %d, func: %d, writeEnable: %d\n", depthEnable, depthFunc, depthWriteEnable);
|
||||
|
||||
if (depthScale.toFloat32() != -1.0 || depthOffset.toFloat32() != 0.0)
|
||||
Helpers::panic("TODO: Implement depth scale/offset. Remove the depth *= -1.0 from fragment shader");
|
||||
|
||||
// TODO: Actually use this
|
||||
float viewportWidth = f24::fromRaw(regs[PICAInternalRegs::ViewportWidth] & 0xffffff).toFloat32() * 2.0;
|
||||
float viewportHeight = f24::fromRaw(regs[PICAInternalRegs::ViewportHeight] & 0xffffff).toFloat32() * 2.0;
|
||||
|
||||
if (depthEnable) {
|
||||
OpenGL::enableDepth();
|
||||
glDepthFunc(depthModes[depthFunc]);
|
||||
|
@ -153,7 +213,6 @@ void GPU::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 count)
|
|||
}
|
||||
|
||||
if (colourMask != 0xf) Helpers::panic("[PICA] Colour mask = %X != 0xf", colourMask);
|
||||
|
||||
vbo.bufferVertsSub(vertices, count);
|
||||
OpenGL::draw(primType, count);
|
||||
}
|
||||
|
|
|
@ -101,9 +101,9 @@ PICAShader::vec4f PICAShader::getSource(u32 source) {
|
|||
}
|
||||
|
||||
PICAShader::vec4f& PICAShader::getDest(u32 dest) {
|
||||
if (dest <= 0x6) {
|
||||
if (dest < 0x10) {
|
||||
return outputs[dest];
|
||||
} else if (dest >= 0x10 && dest <= 0x1f) { // Temporary registers
|
||||
} else if (dest < 0x20) {
|
||||
return tempRegisters[dest - 0x10];
|
||||
}
|
||||
Helpers::panic("[PICA] Unimplemented dest: %X", dest);
|
||||
|
@ -298,15 +298,15 @@ void PICAShader::mad(u32 instruction) {
|
|||
|
||||
src2 = getIndexedSource(src2, idx);
|
||||
|
||||
auto src1Vec = getSourceSwizzled<1>(src1, operandDescriptor);
|
||||
auto src2Vec = getSourceSwizzled<2>(src2, operandDescriptor);
|
||||
auto src3Vec = getSourceSwizzled<3>(src3, operandDescriptor);
|
||||
auto srcVec1 = getSourceSwizzled<1>(src1, operandDescriptor);
|
||||
auto srcVec2 = getSourceSwizzled<2>(src2, operandDescriptor);
|
||||
auto srcVec3 = getSourceSwizzled<3>(src3, operandDescriptor);
|
||||
auto& destVector = getDest(dest);
|
||||
|
||||
u32 componentMask = operandDescriptor & 0xf;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (componentMask & (1 << i)) {
|
||||
destVector[3 - i] = src1Vec[3 - i] * src2Vec[3 - i] + src3Vec[3 - i];
|
||||
destVector[3 - i] = srcVec1[3 - i] * srcVec2[3 - i] + srcVec3[3 - i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,6 +374,25 @@ void PICAShader::ifc(u32 instruction) {
|
|||
}
|
||||
}
|
||||
|
||||
void PICAShader::ifu(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)) {
|
||||
if (ifIndex >= 8) [[unlikely]]
|
||||
Helpers::panic("[PICA] Overflowed IF stack");
|
||||
|
||||
const u32 num = instruction & 0xff;
|
||||
|
||||
auto& block = conditionalInfo[ifIndex++];
|
||||
block.endingPC = dest;
|
||||
block.newPC = dest + num;
|
||||
}
|
||||
else {
|
||||
pc = dest;
|
||||
}
|
||||
}
|
||||
|
||||
void PICAShader::callu(u32 instruction) {
|
||||
const u32 bit = (instruction >> 22) & 0xf; // Bit of the bool uniform to check
|
||||
|
||||
|
@ -392,24 +411,6 @@ void PICAShader::callu(u32 instruction) {
|
|||
}
|
||||
}
|
||||
|
||||
void PICAShader::ifu(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)) {
|
||||
if (ifIndex >= 8) [[unlikely]]
|
||||
Helpers::panic("[PICA] Overflowed IF stack");
|
||||
|
||||
const u32 num = instruction & 0xff;
|
||||
|
||||
auto& block = conditionalInfo[ifIndex++];
|
||||
block.endingPC = dest;
|
||||
block.newPC = dest + num;
|
||||
} else {
|
||||
pc = dest;
|
||||
}
|
||||
}
|
||||
|
||||
void PICAShader::loop(u32 instruction) {
|
||||
if (loopIndex >= 4) [[unlikely]]
|
||||
Helpers::panic("[PICA] Overflowed loop stack");
|
||||
|
|
Loading…
Add table
Reference in a new issue