Geometry pipeline v2

Co-Authored-By: Sky <skylersaleh@gmail.com>
This commit is contained in:
wheremyfoodat 2023-02-26 20:41:33 +02:00
parent 1019f65824
commit e80679fe77
9 changed files with 114 additions and 48 deletions

View file

@ -72,6 +72,10 @@ void GPU::drawArrays() {
log("PICA::DrawElements(vertex count = %d, index buffer config = %08X)\n", vertexCount, indexBufferConfig);
}
// Total number of input attributes to shader. Differs between GS and VS. Currently stubbed to the VS one, as we don't have geometry shaders.
const u32 inputAttrCount = (regs[PICAInternalRegs::VertexShaderInputBufferCfg] & 0xf) + 1;
const u64 inputAttrCfg = getVertexShaderInputConfig();
for (u32 i = 0; i < vertexCount; i++) {
u32 vertexIndex; // Index of the vertex in the VBO
@ -89,72 +93,112 @@ void GPU::drawArrays() {
}
}
int attrCount = 0; // Number of attributes we've passed to the shader
for (int attrCount = 0; attrCount < totalAttribCount; attrCount++) {
int attrCount = 0;
int buffer = 0; // Vertex buffer index for non-fixed attributes
while (attrCount < totalAttribCount) {
// Check if attribute is fixed or not
if (fixedAttribMask & (1 << attrCount)) { // Fixed attribute
vec4f& fixedAttr = shaderUnit.vs.fixedAttributes[attrCount]; // TODO: Is this how it works?
vec4f& inputAttr = shaderUnit.vs.attributes[attrCount];
vec4f& inputAttr = currentAttributes[attrCount];
std::memcpy(&inputAttr, &fixedAttr, sizeof(vec4f)); // Copy fixed attr to input attr
attrCount++;
} else { // Non-fixed attribute
auto& attr = attributeInfo[attrCount]; // Get information for this attribute
auto& attr = attributeInfo[buffer]; // Get information for this attribute
u64 attrCfg = attr.getConfigFull(); // Get config1 | (config2 << 32)
uint index = (attrCfg >> (attrCount * 4)) & 0xf; // Get index of attribute in vertexCfg
if (index >= 12) Helpers::panic("[PICA] Vertex attribute used as padding");
u32 attribInfo = (vertexCfg >> (index * 4)) & 0xf;
u32 attribType = attribInfo & 0x3; // Type of attribute(sbyte/ubyte/short/float)
u32 componentCount = (attribInfo >> 2) + 1; // Total number of components
// Address to fetch the attribute from
u32 attrAddress = vertexBase + attr.offset + (vertexIndex * attr.size);
vec4f& attribute = shaderUnit.vs.attributes[attrCount];
uint component; // Current component
switch (attribType) {
case 2: { // Short
s16* ptr = getPointerPhys<s16>(attrAddress);
for (component = 0; component < componentCount; component++) {
float val = static_cast<float>(*ptr++);
attribute[component] = f24::fromFloat32(val);
for (int j = 0; j < attr.componentCount; j++) {
uint index = (attrCfg >> (j * 4)) & 0xf; // Get index of attribute in vertexCfg
if (index >= 12) Helpers::panic("[PICA] Vertex attribute used as padding");
u32 attribInfo = (vertexCfg >> (index * 4)) & 0xf;
u32 attribType = attribInfo & 0x3; // Type of attribute(sbyte/ubyte/short/float)
u32 size = (attribInfo >> 2) + 1; // Total number of components
//printf("vertex_attribute_strides[%d] = %d\n", attrCount, attr.size);
vec4f& attribute = currentAttributes[attrCount];
uint component; // Current component
switch (attribType) {
case 0: { // Signed byte
s8* ptr = getPointerPhys<s8>(attrAddress);
for (component = 0; component < size; component++) {
float val = static_cast<float>(*ptr++);
attribute[component] = f24::fromFloat32(val);
}
attrAddress += size * sizeof(s8);
break;
}
break;
case 1: { // Unsigned byte
u8* ptr = getPointerPhys<u8>(attrAddress);
for (component = 0; component < size; component++) {
float val = static_cast<float>(*ptr++);
attribute[component] = f24::fromFloat32(val);
}
attrAddress += size * sizeof(u8);
break;
}
case 2: { // Short
s16* ptr = getPointerPhys<s16>(attrAddress);
for (component = 0; component < size; component++) {
float val = static_cast<float>(*ptr++);
attribute[component] = f24::fromFloat32(val);
}
attrAddress += size * sizeof(s16);
break;
}
case 3: { // Float
float* ptr = getPointerPhys<float>(attrAddress);
for (component = 0; component < size; component++) {
float val = *ptr++;
attribute[component] = f24::fromFloat32(val);
}
attrAddress += size * sizeof(float);
break;
}
default: Helpers::panic("[PICA] Unimplemented attribute type %d", attribType);
}
case 3: { // Float
float* ptr = getPointerPhys<float>(attrAddress);
for (component = 0; component < componentCount; component++) {
float val = *ptr++;
attribute[component] = f24::fromFloat32(val);
}
break;
// Fill the remaining attribute lanes with default parameters (1.0 for alpha/w, 0.0) for everything else
// Corgi does this although I'm not sure if it's actually needed for anything.
// TODO: Find out
while (component < 4) {
attribute[component] = (component == 3) ? f24::fromFloat32(1.0) : f24::fromFloat32(0.0);
component++;
}
default: Helpers::panic("[PICA] Unimplemented attribute type %d", attribType);
}
// Fill the remaining attribute lanes with default parameters (1.0 for alpha/w, 0.0) for everything else
// Corgi does this although I'm not sure if it's actually needed for anything.
// TODO: Find out
while (component < 4) {
attribute[component] = (component == 3) ? f24::fromFloat32(1.0) : f24::fromFloat32(0.0);
component++;
attrCount++;
}
buffer++;
}
}
// Before running the shader, the PICA maps the fetched attributes from the attribute registers to the shader input registers
// Based on the SH_ATTRIBUTES_PERMUTATION registers.
// Ie it might attribute #0 to v2, #1 to v7, etc
for (int j = 0; j < totalAttribCount; j++) {
const u32 mapping = (inputAttrCfg >> (j * 4)) & 0xf;
std::memcpy(&shaderUnit.vs.inputs[mapping], &currentAttributes[j], sizeof(vec4f));
}
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));
std::memcpy(&vertices[i].UVs, &shaderUnit.vs.outputs[2], 2 * sizeof(f24));
//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());
//printf("U: %f, V: %f\n", vertices[i].UVs.u(), vertices[i].UVs.v());
}
// The fourth type is meant to be "Geometry primitive". TODO: Find out what that is
static constexpr std::array<OpenGL::Primitives, 4> primTypes = {
OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::LineStrip
OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::Triangle
};
const auto shape = primTypes[primType];
renderer.drawVertices(shape, vertices, vertexCount);

View file

@ -94,7 +94,7 @@ u8 PICAShader::getIndexedSource(u32 source, u32 index) {
PICAShader::vec4f PICAShader::getSource(u32 source) {
if (source < 0x10)
return attributes[source];
return inputs[source];
else if (source < 0x20)
return tempRegisters[source - 0x10];
else if (source <= 0x7f)
@ -237,7 +237,6 @@ void PICAShader::mova(u32 instruction) {
const u32 operandDescriptor = operandDescriptors[instruction & 0x7f];
const u32 src = (instruction >> 12) & 0x7f;
const u32 idx = (instruction >> 19) & 3;
const u32 dest = (instruction >> 21) & 0x1f;
if (idx) Helpers::panic("[PICA] MOVA: idx != 0");
vec4f srcVector = getSourceSwizzled<1>(src, operandDescriptor);

View file

@ -18,7 +18,7 @@ void PICAShader::reset() {
f32UniformTransfer = false;
const vec4f zero = vec4f({ f24::zero(), f24::zero(), f24::zero(), f24::zero() });
attributes.fill(zero);
inputs.fill(zero);
floatUniforms.fill(zero);
outputs.fill(zero);
tempRegisters.fill(zero);