PICA: Start implementing GPU vertex fetch

This commit is contained in:
wheremyfoodat 2024-08-21 00:47:57 +03:00
parent 652b600884
commit e13ef42b65
9 changed files with 117 additions and 8 deletions

View file

@ -0,0 +1,71 @@
#include "PICA/draw_acceleration.hpp"
#include <limits>
#include "PICA/gpu.hpp"
#include "PICA/regs.hpp"
void GPU::getAcceleratedDrawInfo(PICA::DrawAcceleration& accel, bool indexed) {
accel.indexed = indexed;
const u32 vertexBase = ((regs[PICA::InternalRegs::VertexAttribLoc] >> 1) & 0xfffffff) * 16;
const u32 vertexCount = regs[PICA::InternalRegs::VertexCountReg]; // Total # of vertices to transfer
accel.vertexBuffer = getPointerPhys<u8>(vertexBase);
if (indexed) {
u32 indexBufferConfig = regs[PICA::InternalRegs::IndexBufferConfig];
u32 indexBufferPointer = vertexBase + (indexBufferConfig & 0xfffffff);
u8* indexBuffer = getPointerPhys<u8>(indexBufferPointer);
u16 minimumIndex = std::numeric_limits<u16>::max();
u16 maximumIndex = 0;
// Check whether the index buffer uses u16 indices or u8
bool shortIndex = Helpers::getBit<31>(indexBufferConfig); // Indicates whether vert indices are 16-bit or 8-bit
// Calculate the minimum and maximum indices used in the index buffer, so we'll only upload them
if (shortIndex) {
u16* indexBuffer16 = reinterpret_cast<u16*>(indexBuffer);
for (int i = 0; i < vertexCount; i++) {
u16 index = indexBuffer16[i];
minimumIndex = std::min(minimumIndex, index);
maximumIndex = std::max(maximumIndex, index);
}
} else {
for (int i = 0; i < vertexCount; i++) {
u16 index = u16(indexBuffer[i]);
minimumIndex = std::min(minimumIndex, index);
maximumIndex = std::max(maximumIndex, index);
}
}
accel.indexBuffer = indexBuffer;
accel.minimumIndex = minimumIndex;
accel.maximumIndex = maximumIndex;
} else {
accel.indexBuffer = nullptr;
accel.minimumIndex = regs[PICA::InternalRegs::VertexOffsetReg];
accel.maximumIndex = accel.minimumIndex + vertexCount - 1;
}
int buffer = 0;
accel.vertexDataSize = 0;
for (int attrCount = 0; attrCount < totalAttribCount; attrCount++) {
bool fixedAttribute = (fixedAttribMask & (1 << attrCount)) != 0;
if (!fixedAttribute) {
auto& attr = attributeInfo[buffer]; // Get information for this attribute
if (attr.componentCount != 0) {
// Size of the attribute in bytes multiplied by the total number of vertices
const u32 bytes = attr.size * vertexCount;
// Add it to the total vertex data size, aligned to 4 bytes.
accel.vertexDataSize += (bytes + 3) & ~3;
}
buffer++;
}
}
accel.canBeAccelerated = true;
}

View file

@ -123,7 +123,15 @@ void GPU::reset() {
// Call the correct version of drawArrays based on whether this is an indexed draw (first template parameter)
// And whether we are going to use the shader JIT (second template parameter)
void GPU::drawArrays(bool indexed) {
const bool hwShaders = renderer->prepareForDraw(shaderUnit, false);
PICA::DrawAcceleration accel;
if (config.accelerateShaders) {
// If we are potentially going to use hw shaders, gather necessary to do vertex fetch, index buffering, etc on the GPU
// This includes parsing which vertices to upload, getting pointers to the index buffer data & vertex data, and so on
getAcceleratedDrawInfo(accel, indexed);
}
const bool hwShaders = renderer->prepareForDraw(shaderUnit, &accel, false);
if (hwShaders) {
if (indexed) {

View file

@ -249,7 +249,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
// If we've reached 3 verts, issue a draw call
// Handle rendering depending on the primitive type
if (immediateModeVertIndex == 3) {
renderer->prepareForDraw(shaderUnit, true);
renderer->prepareForDraw(shaderUnit, nullptr, true);
renderer->drawVertices(PICA::PrimType::TriangleList, immediateModeVertices);
switch (primType) {

View file

@ -942,7 +942,7 @@ OpenGL::Program& RendererGL::getSpecializedShader() {
return program;
}
bool RendererGL::prepareForDraw(ShaderUnit& shaderUnit, bool isImmediateMode) {
bool RendererGL::prepareForDraw(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel, bool isImmediateMode) {
// First we figure out if we will be using an ubershader
bool usingUbershader = emulatorConfig->useUbershaders;
if (usingUbershader) {
@ -993,6 +993,8 @@ bool RendererGL::prepareForDraw(ShaderUnit& shaderUnit, bool isImmediateMode) {
glBufferSubData(GL_UNIFORM_BUFFER, 0, PICAShader::totalUniformSize(), shaderUnit.vs.getUniformPointer());
}
}
accelerateVertexUpload(shaderUnit, accel);
}
if (usingUbershader) {
@ -1110,4 +1112,8 @@ void RendererGL::initUbershader(OpenGL::Program& program) {
glUniform1i(OpenGL::uniformLocation(program, "u_tex1"), 1);
glUniform1i(OpenGL::uniformLocation(program, "u_tex2"), 2);
glUniform1i(OpenGL::uniformLocation(program, "u_tex_luts"), 3);
}
void RendererGL::accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel) {
}