gpu: Implement basic texcopy

* Improves rendering in FE:A but the screens will still not show
  because it requires surface validation
This commit is contained in:
GPUCode 2023-08-06 14:25:32 +03:00
parent 297afd20d7
commit 82d9511993
15 changed files with 139 additions and 16 deletions

View file

@ -117,6 +117,10 @@ class GPU {
renderer->displayTransfer(inputAddr, outputAddr, inputSize, outputSize, flags);
}
void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) {
renderer->textureCopy(inputAddr, outputAddr, totalBytes, inputSize, outputSize, flags);
}
// Read a value of type T from physical address paddr
// This is necessary because vertex attribute fetching uses physical addresses
template <typename T>

View file

@ -7,6 +7,7 @@
#include <sstream>
#include <string>
#include <vector>
#include <memory>
#include "termcolor.hpp"
@ -30,6 +31,17 @@ using s32 = std::int32_t;
using s64 = std::int64_t;
namespace Helpers {
template <class... Args>
std::string format(const std::string& fmt, Args&&... args) {
const int size = std::snprintf(nullptr, 0, fmt.c_str(), args...) + 1;
if (size <= 0) {
return {};
}
const auto buf = std::make_unique<char[]>(size);
std::snprintf(buf.get(), size, fmt.c_str(), args ...);
return std::string(buf.get(), buf.get() + size - 1);
}
// Unconditional panic, unlike panicDev which does not panic on user builds
template <class... Args>
[[noreturn]] static void panic(const char* fmt, Args&&... args) {

View file

@ -49,6 +49,7 @@ class Renderer {
virtual void initGraphicsContext(SDL_Window* window) = 0; // Initialize graphics context
virtual void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) = 0; // Clear a GPU buffer in VRAM
virtual void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) = 0; // Perform display transfer
virtual void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) = 0;
virtual void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) = 0; // Draw the given vertices
virtual void screenshot(const std::string& name) = 0;

View file

@ -77,9 +77,10 @@ class RendererGL final : public Renderer {
void initGraphicsContext(SDL_Window* window) override; // Initialize graphics context
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) override; // Clear a GPU buffer in VRAM
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) override; // Perform display transfer
void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) override;
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) override; // Draw the given vertices
ColourBuffer getColourBuffer(u32 addr, PICA::ColorFmt format, u32 width, u32 height);
std::optional<ColourBuffer> getColourBuffer(u32 addr, PICA::ColorFmt format, u32 width, u32 height, bool createIfnotFound = true);
// Take a screenshot of the screen and store it in a file
void screenshot(const std::string& name) override;

View file

@ -76,6 +76,16 @@ public:
size++;
// Find an existing surface we completely invalidate and overwrite it with the new surface
for (auto& e : buffer) {
if (e.valid && e.range.lower() >= surface.range.lower() && e.range.upper() <= surface.range.upper()) {
e.free();
e = surface;
e.allocate();
return e;
}
}
// Find an invalid entry in the cache and overwrite it with the new surface
for (auto& e : buffer) {
if (!e.valid) {

View file

@ -65,7 +65,8 @@ struct ColourBuffer {
texture.setMagFilter(OpenGL::Linear);
glBindTexture(GL_TEXTURE_2D, prevTexture);
//Helpers::panic("Creating FBO: %d, %d\n", size.x(), size.y());
const auto name = Helpers::format("Surface %dx%d %s from 0x%08X", size.x(), size.y(), PICA::textureFormatToString(format), location);
OpenGL::setObjectLabel(GL_TEXTURE, texture.handle(), name.c_str());
fbo.createWithDrawTexture(texture);
fbo.bind(OpenGL::DrawAndReadFramebuffer);

View file

@ -12,6 +12,7 @@ class RendererNull final : public Renderer {
void initGraphicsContext(SDL_Window* window) override;
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) override;
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) override;
void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) override;
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) override;
void screenshot(const std::string& name) override;
};

View file

@ -12,6 +12,7 @@ class RendererSw final : public Renderer {
void initGraphicsContext(SDL_Window* window) override;
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) override;
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) override;
void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) override;
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) override;
void screenshot(const std::string& name) override;
};
};

View file

@ -52,6 +52,7 @@ class RendererVK final : public Renderer {
void initGraphicsContext(SDL_Window* window) override;
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) override;
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) override;
void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) override;
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) override;
void screenshot(const std::string& name) override;
};
};