Skip to content

Commit

Permalink
GL: Add fallback for when driver doesn't provide glDrawRangeElementsB…
Browse files Browse the repository at this point in the history
…aseVertex
  • Loading branch information
wheremyfoodat committed Oct 23, 2024
1 parent 8c80099 commit 7b1afc8
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 6 deletions.
21 changes: 21 additions & 0 deletions include/PICA/pica_simd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,4 +250,25 @@ namespace PICA::IndexBuffer {
return analyzePortable<useShortIndices>(indexBuffer, vertexCount);
#endif
}

// In some really unfortunate scenarios (eg Android Studio emulator), we don't have access to glDrawRangeElementsBaseVertex
// So we need to subtract the base vertex index from every index in the index buffer ourselves
// This is not really common, so we do it without SIMD for the moment, just to be able to run on Android Studio
template <bool useShortIndices>
void subtractBaseIndex(u8* indexBuffer, u32 vertexCount, u16 baseIndex) {
// Calculate the minimum and maximum indices used in the index buffer, so we'll only upload them
if constexpr (useShortIndices) {
u16* indexBuffer16 = reinterpret_cast<u16*>(indexBuffer);

for (u32 i = 0; i < vertexCount; i++) {
indexBuffer16[i] -= baseIndex;
}
} else {
u8 baseIndex8 = u8(baseIndex);

for (u32 i = 0; i < vertexCount; i++) {
indexBuffer[i] -= baseIndex8;
}
}
}
} // namespace PICA::IndexBuffer
2 changes: 2 additions & 0 deletions include/renderer_gl/gl_driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ namespace OpenGL {
struct Driver {
bool supportsExtFbFetch = false;
bool supportsArmFbFetch = false;
// Does this driver support glDraw(Range)ElementsBaseVertex?
bool supportsDrawElementsBaseVertex = false;

bool supportFbFetch() const { return supportsExtFbFetch || supportsArmFbFetch; }
};
Expand Down
30 changes: 24 additions & 6 deletions src/core/renderer_gl/renderer_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "PICA/float_types.hpp"
#include "PICA/gpu.hpp"
#include "PICA/pica_frag_uniforms.hpp"
#include "PICA/pica_simd.hpp"
#include "PICA/regs.hpp"
#include "PICA/shader_decompiler.hpp"
#include "config.hpp"
Expand Down Expand Up @@ -192,8 +193,9 @@ void RendererGL::initGraphicsContextInternal() {
reset();

// Populate our driver info structure
driverInfo.supportsExtFbFetch = GLAD_GL_EXT_shader_framebuffer_fetch != 0;
driverInfo.supportsArmFbFetch = GLAD_GL_ARM_shader_framebuffer_fetch != 0;
driverInfo.supportsExtFbFetch = (GLAD_GL_EXT_shader_framebuffer_fetch != 0);
driverInfo.supportsArmFbFetch = (GLAD_GL_ARM_shader_framebuffer_fetch != 0);
driverInfo.supportsDrawElementsBaseVertex = (glDrawRangeElementsBaseVertex != nullptr);

// Initialize the default vertex shader used with shadergen
std::string defaultShadergenVSSource = fragShaderGen.getDefaultVertexShader();
Expand Down Expand Up @@ -519,10 +521,20 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span<const Vertex> v
if (performIndexedRender) {
// When doing indexed rendering, use glDrawRangeElementsBaseVertex to issue the indexed draw
hwIndexBuffer->Bind();
glDrawRangeElementsBaseVertex(
primitiveTopology, minimumIndex, maximumIndex, GLsizei(vertices.size()), usingShortIndices ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE,
hwIndexBufferOffset, -GLint(minimumIndex)
);

if (glDrawRangeElementsBaseVertex != nullptr) [[likely]] {
glDrawRangeElementsBaseVertex(
primitiveTopology, minimumIndex, maximumIndex, GLsizei(vertices.size()), usingShortIndices ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE,
hwIndexBufferOffset, -GLint(minimumIndex)
);
} else {
// If glDrawRangeElementsBaseVertex is not available then prepareForDraw will have subtracted the base vertex from the index buffer
// for us, so just use glDrawRangeElements
glDrawRangeElements(
primitiveTopology, 0, maximumIndex - minimumIndex, GLsizei(vertices.size()),
usingShortIndices ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE, hwIndexBufferOffset
);
}
} else {
// When doing non-indexed rendering, just use glDrawArrays
OpenGL::draw(primitiveTopology, GLsizei(vertices.size()));
Expand Down Expand Up @@ -1170,6 +1182,12 @@ void RendererGL::accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAccele
hwIndexBufferOffset = reinterpret_cast<void*>(usize(indexBufferRes.buffer_offset));

std::memcpy(indexBufferRes.pointer, accel->indexBuffer, indexBufferSize);
// If we don't have glDrawRangeElementsBaseVertex, we must subtract the base index value from our index buffer manually
if (!driverInfo.supportsDrawElementsBaseVertex) [[unlikely]] {
usingShortIndices ? PICA::IndexBuffer::subtractBaseIndex<true>((u8*)indexBufferRes.pointer, vertexCount, accel->minimumIndex)
: PICA::IndexBuffer::subtractBaseIndex<false>((u8*)indexBufferRes.pointer, vertexCount, accel->minimumIndex);
}

hwIndexBuffer->Unmap(indexBufferSize);
}

Expand Down

0 comments on commit 7b1afc8

Please sign in to comment.