add: render target caches

This commit is contained in:
Samuliak 2024-07-02 16:06:20 +02:00
parent 67e3a1d8eb
commit 53c9611ac2
4 changed files with 85 additions and 1 deletions

View file

@ -0,0 +1,77 @@
#pragma once
#include <array>
#include <string>
#include <Metal/Metal.hpp>
#include "PICA/regs.hpp"
#include "boost/icl/interval.hpp"
#include "helpers.hpp"
#include "math_util.hpp"
#include "opengl.hpp"
template <typename T>
using Interval = boost::icl::right_open_interval<T>;
namespace Metal {
struct RenderTarget {
MTL::Device* device;
u32 location;
PICA::TextureFmt format;
OpenGL::uvec2 size;
bool valid;
// Range of VRAM taken up by buffer
Interval<u32> range;
MTL::Texture* texture = nullptr;
RenderTarget() : valid(false) {}
RenderTarget(MTL::Device* dev, u32 loc, PICA::TextureFmt format, u32 x, u32 y, bool valid = true)
: device(dev), location(loc), format(format), size({x, y}), valid(valid) {
u64 endLoc = (u64)loc + sizeInBytes();
// Check if start and end are valid here
range = Interval<u32>(loc, (u32)endLoc);
}
Math::Rect<u32> getSubRect(u32 inputAddress, u32 width, u32 height) {
const u32 startOffset = (inputAddress - location) / sizePerPixel(format);
const u32 x0 = (startOffset % (size.x() * 8)) / 8;
const u32 y0 = (startOffset / (size.x() * 8)) * 8;
return Math::Rect<u32>{x0, y0, x0 + width, y0 + height};
}
// For 2 textures to "match" we only care about their locations, formats, and dimensions to match
// For other things, such as filtering mode, etc, we can just switch the attributes of the cached texture
bool matches(Texture& other) {
return location == other.location && format == other.format &&
size.x() == other.size.x() && size.y() == other.size.y();
}
void allocate() {
MTL::TextureDescriptor* descriptor = MTL::TextureDescriptor::alloc()->init();
descriptor->setTextureType(MTL::TextureType2D);
descriptor->setPixelFormat(MTL::PixelFormatRGBA8Unorm);
descriptor->setWidth(size.u());
descriptor->setHeight(size.v());
descriptor->setUsage(MTL::TextureUsageRenderTarget | MTL::TextureUsageShaderRead);
descriptor->setStorageMode(MTL::StorageModePrivate);
texture = device->newTexture(descriptor);
}
void free() {
valid = false;
if (texture) {
texture->release();
}
}
u64 sizeInBytes() {
return (size_t)size.x() * (size_t)size.y() * PICA::sizePerPixel(format);
}
};
} // namespace Metal

View file

@ -3,6 +3,7 @@
#include "renderer.hpp" #include "renderer.hpp"
#include "texture.hpp" #include "texture.hpp"
#include "render_target.hpp"
// HACK: use the OpenGL cache // HACK: use the OpenGL cache
#include "../renderer_gl/surface_cache.hpp" #include "../renderer_gl/surface_cache.hpp"
@ -34,6 +35,8 @@ class RendererMTL final : public Renderer {
MTL::CommandQueue* commandQueue; MTL::CommandQueue* commandQueue;
// Caches // Caches
SurfaceCache<Metal::Texture, 16, true> colorRenderTargetCache;
SurfaceCache<Metal::Texture, 16, true> depthStencilRenderTargetCache;
SurfaceCache<Metal::Texture, 256, true> textureCache; SurfaceCache<Metal::Texture, 256, true> textureCache;
// HACK // HACK

View file

@ -18,6 +18,8 @@ RendererMTL::RendererMTL(GPU& gpu, const std::array<u32, regNum>& internalRegs,
RendererMTL::~RendererMTL() {} RendererMTL::~RendererMTL() {}
void RendererMTL::reset() { void RendererMTL::reset() {
colorRenderTargetCache.reset();
depthStencilRenderTargetCache.reset();
textureCache.reset(); textureCache.reset();
// TODO: implement // TODO: implement
@ -233,6 +235,8 @@ void RendererMTL::screenshot(const std::string& name) {
} }
void RendererMTL::deinitGraphicsContext() { void RendererMTL::deinitGraphicsContext() {
colorRenderTargetCache.reset();
depthStencilRenderTargetCache.reset();
textureCache.reset(); textureCache.reset();
// TODO: implement // TODO: implement

View file

@ -12,7 +12,7 @@ void Texture::allocate() {
descriptor->setPixelFormat(MTL::PixelFormatRGBA8Unorm); descriptor->setPixelFormat(MTL::PixelFormatRGBA8Unorm);
descriptor->setWidth(size.u()); descriptor->setWidth(size.u());
descriptor->setHeight(size.v()); descriptor->setHeight(size.v());
descriptor->setUsage(MTL::TextureUsageShaderRead | MTL::TextureUsageShaderWrite); descriptor->setUsage(MTL::TextureUsageShaderRead);
descriptor->setStorageMode(MTL::StorageModeShared); // TODO: use private + staging buffers? descriptor->setStorageMode(MTL::StorageModeShared); // TODO: use private + staging buffers?
texture = device->newTexture(descriptor); texture = device->newTexture(descriptor);