Merge pull request #33 from Wunkolo/span-vertex

Use `std::span` to pass vertex data
This commit is contained in:
wheremyfoodat 2023-06-17 01:38:40 +03:00 committed by GitHub
commit dafa919e1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 62 additions and 32 deletions

View file

@ -1,6 +1,6 @@
BasedOnStyle: Google BasedOnStyle: Google
IndentWidth: 4 IndentWidth: 4
ColumnLimit: 120 ColumnLimit: 150
AccessModifierOffset: -2 AccessModifierOffset: -2
TabWidth: 4 TabWidth: 4
NamespaceIndentation: All NamespaceIndentation: All

View file

@ -30,6 +30,19 @@
#include "gl3w.h" #include "gl3w.h"
// Check if we have C++20. If yes, we can add C++20 std::span support
#ifdef _MSVC_LANG // MSVC does not properly define __cplusplus without a compiler flag...
#if _MSVC_LANG >= 202002L
#define OPENGL_HAVE_CPP20
#endif
#elif __cplusplus >= 202002L
#define OPENGL_HAVE_CPP20
#endif // MSVC_LANG
#ifdef OPENGL_HAVE_CPP20
#include <span>
#endif
// Uncomment the following define if you want GL objects to automatically free themselves when their lifetime ends // Uncomment the following define if you want GL objects to automatically free themselves when their lifetime ends
// #define OPENGL_DESTRUCTORS // #define OPENGL_DESTRUCTORS
@ -389,17 +402,30 @@ namespace OpenGL {
void free() { glDeleteBuffers(1, &m_handle); } void free() { glDeleteBuffers(1, &m_handle); }
// Reallocates the buffer on every call. Prefer the sub version if possible. // Reallocates the buffer on every call. Prefer the sub version if possible.
template <typename VertType> template <typename VertType>
void bufferVerts(VertType* vertices, int vertCount, GLenum usage = GL_DYNAMIC_DRAW) { void bufferVerts(VertType* vertices, int vertCount, GLenum usage = GL_DYNAMIC_DRAW) {
glBufferData(GL_ARRAY_BUFFER, sizeof(VertType) * vertCount, vertices, usage); glBufferData(GL_ARRAY_BUFFER, sizeof(VertType) * vertCount, vertices, usage);
} }
// Only use if you used createFixedSize // Only use if you used createFixedSize
template <typename VertType> template <typename VertType>
void bufferVertsSub(VertType* vertices, int vertCount, GLintptr offset = 0) { void bufferVertsSub(VertType* vertices, int vertCount, GLintptr offset = 0) {
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(VertType) * vertCount, vertices); glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(VertType) * vertCount, vertices);
} }
};
// If C++20 is available, add overloads that take std::span instead of raw pointers
#ifdef OPENGL_HAVE_CPP20
template <typename VertType>
void bufferVerts(std::span<const VertType> vertices, GLenum usage = GL_DYNAMIC_DRAW) {
glBufferData(GL_ARRAY_BUFFER, sizeof(VertType) * vertices.size(), vertices.data(), usage);
}
template <typename VertType>
void bufferVertsSub(std::span<const VertType> vertices, GLintptr offset = 0) {
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(VertType) * vertices.size(), vertices.data());
}
#endif
};
enum DepthFunc { enum DepthFunc {
Never = GL_NEVER, // Depth test never passes Never = GL_NEVER, // Depth test never passes

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <array> #include <array>
#include <span>
#include "helpers.hpp" #include "helpers.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "opengl.hpp" #include "opengl.hpp"
@ -24,7 +26,7 @@ class Renderer {
OpenGL::VertexBuffer vbo; OpenGL::VertexBuffer vbo;
GLint alphaControlLoc = -1; GLint alphaControlLoc = -1;
GLint texUnitConfigLoc = -1; GLint texUnitConfigLoc = -1;
// Depth configuration uniform locations // Depth configuration uniform locations
GLint depthOffsetLoc = -1; GLint depthOffsetLoc = -1;
GLint depthScaleLoc = -1; GLint depthScaleLoc = -1;
@ -41,11 +43,11 @@ class Renderer {
SurfaceCache<ColourBuffer, 10> colourBufferCache; SurfaceCache<ColourBuffer, 10> colourBufferCache;
SurfaceCache<Texture, 256> textureCache; SurfaceCache<Texture, 256> textureCache;
OpenGL::uvec2 fbSize; // The size of the framebuffer (ie both the colour and depth buffer)' OpenGL::uvec2 fbSize; // The size of the framebuffer (ie both the colour and depth buffer)'
u32 colourBufferLoc; // Location in 3DS VRAM for the colour buffer
ColourBuffer::Formats colourBufferFormat; // Format of the colours stored in the colour buffer
u32 colourBufferLoc; // Location in 3DS VRAM for the colour buffer
ColourBuffer::Formats colourBufferFormat; // Format of the colours stored in the colour buffer
// Same for the depth/stencil buffer // Same for the depth/stencil buffer
u32 depthBufferLoc; u32 depthBufferLoc;
DepthBuffer::Formats depthBufferFormat; DepthBuffer::Formats depthBufferFormat;
@ -54,7 +56,7 @@ class Renderer {
OpenGL::VertexArray dummyVAO; OpenGL::VertexArray dummyVAO;
OpenGL::VertexBuffer dummyVBO; OpenGL::VertexBuffer dummyVBO;
static constexpr u32 regNum = 0x300; // Number of internal PICA registers static constexpr u32 regNum = 0x300; // Number of internal PICA registers
const std::array<u32, regNum>& regs; const std::array<u32, regNum>& regs;
OpenGL::Framebuffer getColourFBO(); OpenGL::Framebuffer getColourFBO();
@ -64,16 +66,16 @@ class Renderer {
void setupBlending(); void setupBlending();
void bindDepthBuffer(); void bindDepthBuffer();
public: public:
Renderer(GPU& gpu, const std::array<u32, regNum>& internalRegs) : gpu(gpu), regs(internalRegs) {} Renderer(GPU& gpu, const std::array<u32, regNum>& internalRegs) : gpu(gpu), regs(internalRegs) {}
void reset(); void reset();
void display(); // Display the 3DS screen contents to the window void display(); // Display the 3DS screen contents to the window
void initGraphicsContext(); // Initialize graphics context void initGraphicsContext(); // Initialize graphics context
void getGraphicsContext(); // Set up graphics context for rendering void getGraphicsContext(); // Set up graphics context for rendering
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control); // Clear a GPU buffer in VRAM void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control); // Clear a GPU buffer in VRAM
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags); // Perform display transfer void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags); // Perform display transfer
void drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 count); // Draw the given vertices void drawVertices(OpenGL::Primitives primType, std::span<const Vertex> vertices); // Draw the given vertices
void setFBSize(u32 width, u32 height) { void setFBSize(u32 width, u32 height) {
fbSize.x() = width; fbSize.x() = width;

View file

@ -1,7 +1,10 @@
#include "PICA/gpu.hpp" #include "PICA/gpu.hpp"
#include <array>
#include <cstdio>
#include "PICA/float_types.hpp" #include "PICA/float_types.hpp"
#include "PICA/regs.hpp" #include "PICA/regs.hpp"
#include <cstdio>
using namespace Floats; using namespace Floats;
@ -41,7 +44,7 @@ void GPU::drawArrays(bool indexed) {
drawArrays<false>(); drawArrays<false>();
} }
Vertex* vertices = new Vertex[Renderer::vertexBufferSize]; static std::array<Vertex, Renderer::vertexBufferSize> vertices;
template <bool indexed> template <bool indexed>
void GPU::drawArrays() { void GPU::drawArrays() {
@ -205,7 +208,7 @@ void GPU::drawArrays() {
OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::Triangle OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::Triangle
}; };
const auto shape = primTypes[primType]; const auto shape = primTypes[primType];
renderer.drawVertices(shape, vertices, vertexCount); renderer.drawVertices(shape, std::span(vertices).first(vertexCount));
} }
Vertex GPU::getImmediateModeVertex() { Vertex GPU::getImmediateModeVertex() {

View file

@ -157,7 +157,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
// If we've reached 3 verts, issue a draw call // If we've reached 3 verts, issue a draw call
// Handle rendering depending on the primitive type // Handle rendering depending on the primitive type
if (immediateModeVertIndex == 3) { if (immediateModeVertIndex == 3) {
renderer.drawVertices(OpenGL::Triangle, &immediateModeVertices[0], 3); renderer.drawVertices(OpenGL::Triangle, immediateModeVertices);
switch (primType) { switch (primType) {
// Triangle or geometry primitive. Draw a triangle and discard all vertices // Triangle or geometry primitive. Draw a triangle and discard all vertices

View file

@ -213,7 +213,6 @@ void Renderer::initGraphicsContext() {
void Renderer::getGraphicsContext() { void Renderer::getGraphicsContext() {
OpenGL::disableScissor(); OpenGL::disableScissor();
OpenGL::setViewport(400, 240);
vbo.bind(); vbo.bind();
vao.bind(); vao.bind();
@ -265,7 +264,7 @@ void Renderer::setupBlending() {
} }
} }
void Renderer::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 count) { void Renderer::drawVertices(OpenGL::Primitives primType, std::span<const Vertex> vertices) {
// Adjust alpha test if necessary // Adjust alpha test if necessary
const u32 alphaControl = regs[PICAInternalRegs::AlphaTestConfig]; const u32 alphaControl = regs[PICAInternalRegs::AlphaTestConfig];
if (alphaControl != oldAlphaControl) { if (alphaControl != oldAlphaControl) {
@ -352,8 +351,8 @@ void Renderer::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 c
} }
} }
vbo.bufferVertsSub(vertices, count); vbo.bufferVertsSub(vertices);
OpenGL::draw(primType, count); OpenGL::draw(primType, vertices.size());
} }
constexpr u32 topScreenBuffer = 0x1f000000; constexpr u32 topScreenBuffer = 0x1f000000;