support depth render targets

This commit is contained in:
Samuliak 2024-07-03 07:40:32 +02:00
parent 1df81c373c
commit 1ba54b44fb
4 changed files with 52 additions and 10 deletions

View file

@ -0,0 +1,30 @@
#pragma once
#include <Metal/Metal.hpp>
#include "PICA/regs.hpp"
// HACK: both functions return a hardcoded format for now, since render pipeline needs to know the format at creation time
namespace PICA {
inline MTL::PixelFormat toMTLPixelFormatColor(ColorFmt format) {
return MTL::PixelFormatRGBA8Unorm;
//switch (format) {
//case ColorFmt::RGBA8: return MTL::PixelFormatRGBA8Unorm;
//case ColorFmt::RGB8: return MTL::PixelFormatRGBA8Unorm; // TODO: return the correct format
//case ColorFmt::RGBA5551: return MTL::PixelFormatBGR5A1Unorm;
//case ColorFmt::RGB565: return MTL::PixelFormatB5G6R5Unorm; // TODO: check if this is correct
//case ColorFmt::RGBA4: return MTL::PixelFormatABGR4Unorm; // TODO: check if this is correct
//}
}
inline MTL::PixelFormat toMTLPixelFormatDepth(DepthFmt format) {
return MTL::PixelFormatDepth24Unorm_Stencil8;
//switch (format) {
//case DepthFmt::Depth16: return MTL::PixelFormatDepth16Unorm;
//case DepthFmt::Unknown1: return MTL::PixelFormatInvalid;
//case DepthFmt::Depth24: return MTL::PixelFormatDepth32Float; // TODO: is this okay?
//case DepthFmt::Depth24Stencil8: return MTL::PixelFormatDepth24Unorm_Stencil8;
//}
}
} // namespace PICA

View file

@ -2,22 +2,23 @@
#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"
#include "pica_to_mtl.hpp"
template <typename T>
using Interval = boost::icl::right_open_interval<T>;
namespace Metal {
template <typename Format_t>
struct RenderTarget {
MTL::Device* device;
u32 location;
PICA::ColorFmt format;
Format_t format;
OpenGL::uvec2 size;
bool valid;
@ -28,9 +29,8 @@ struct RenderTarget {
RenderTarget() : valid(false) {}
RenderTarget(MTL::Device* dev, u32 loc, PICA::ColorFmt format, u32 x, u32 y, bool valid = true)
RenderTarget(MTL::Device* dev, u32 loc, Format_t 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);
@ -51,9 +51,18 @@ struct RenderTarget {
}
void allocate() {
MTL::PixelFormat pixelFormat = MTL::PixelFormatInvalid;
if (std::is_same<Format_t, PICA::ColorFmt>::value) {
pixelFormat = PICA::toMTLPixelFormatColor((PICA::ColorFmt)format);
} else if (std::is_same<Format_t, PICA::DepthFmt>::value) {
pixelFormat = PICA::toMTLPixelFormatDepth((PICA::DepthFmt)format);
} else {
panic("Invalid format type");
}
MTL::TextureDescriptor* descriptor = MTL::TextureDescriptor::alloc()->init();
descriptor->setTextureType(MTL::TextureType2D);
descriptor->setPixelFormat(MTL::PixelFormatRGBA8Unorm);
descriptor->setPixelFormat(pixelFormat);
descriptor->setWidth(size.u());
descriptor->setHeight(size.v());
descriptor->setUsage(MTL::TextureUsageRenderTarget | MTL::TextureUsageShaderRead);
@ -74,4 +83,7 @@ struct RenderTarget {
}
};
typedef RenderTarget<PICA::ColorFmt> ColorRenderTarget;
typedef RenderTarget<PICA::DepthFmt> DepthStencilRenderTarget;
} // namespace Metal

View file

@ -35,8 +35,8 @@ class RendererMTL final : public Renderer {
MTL::CommandQueue* commandQueue;
// Caches
SurfaceCache<Metal::RenderTarget, 16, true> colorRenderTargetCache;
SurfaceCache<Metal::RenderTarget, 16, true> depthStencilRenderTargetCache;
SurfaceCache<Metal::ColorRenderTarget, 16, true> colorRenderTargetCache;
SurfaceCache<Metal::DepthStencilRenderTarget, 16, true> depthStencilRenderTargetCache;
SurfaceCache<Metal::Texture, 256, true> textureCache;
// Helpers
@ -56,7 +56,7 @@ class RendererMTL final : public Renderer {
}
}
std::optional<Metal::RenderTarget> getColorRenderTarget(u32 addr, PICA::ColorFmt format, u32 width, u32 height, bool createIfnotFound = true);
std::optional<Metal::ColorRenderTarget> getColorRenderTarget(u32 addr, PICA::ColorFmt format, u32 width, u32 height, bool createIfnotFound = true);
MTL::Texture* getTexture(Metal::Texture& tex);
void setupTextureEnvState(MTL::RenderCommandEncoder* encoder);
void bindTexturesToSlots(MTL::RenderCommandEncoder* encoder);

View file

@ -359,7 +359,7 @@ void RendererMTL::deinitGraphicsContext() {
Helpers::warn("RendererMTL::deinitGraphicsContext not implemented");
}
std::optional<Metal::RenderTarget> RendererMTL::getColorRenderTarget(u32 addr, PICA::ColorFmt format, u32 width, u32 height, bool createIfnotFound) {
std::optional<Metal::ColorRenderTarget> RendererMTL::getColorRenderTarget(u32 addr, PICA::ColorFmt format, u32 width, u32 height, bool createIfnotFound) {
// Try to find an already existing buffer that contains the provided address
// This is a more relaxed check compared to getColourFBO as display transfer/texcopy may refer to
// subrect of a surface and in case of texcopy we don't know the format of the surface.
@ -373,7 +373,7 @@ std::optional<Metal::RenderTarget> RendererMTL::getColorRenderTarget(u32 addr, P
}
// Otherwise create and cache a new buffer.
Metal::RenderTarget sampleBuffer(device, addr, format, width, height);
Metal::ColorRenderTarget sampleBuffer(device, addr, format, width, height);
return colorRenderTargetCache.add(sampleBuffer);
}