Merge pull request #74 from tanmaysachan/tsachan/metal

WIP Metal backend
This commit is contained in:
David Chavez 2024-11-12 19:37:23 +01:00 committed by GitHub
commit 7d8867a3ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 830 additions and 121 deletions

View File

@ -847,12 +847,7 @@ namespace RT64 {
auto *metalInterface = dynamic_cast<RT64::MetalInterface *>(renderInterface);
metalInterface->assignDeviceToLayer(view);
// SDL_Window's handle can be used directly if needed
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(window, &wmInfo);
TestInitialize(renderInterface, { wmInfo.info.cocoa.window });
TestInitialize(renderInterface, { window });
TestResize();
bool running = true;

4
src/hle/rt64_application_window.cpp Normal file → Executable file
View File

@ -135,7 +135,7 @@ namespace RT64 {
windowHandle.display = wmInfo.info.x11.display;
windowHandle.window = wmInfo.info.x11.window;
# elif defined(__APPLE__)
windowHandle.window = wmInfo.info.cocoa.window;
windowHandle.window = sdlWindow;
# else
static_assert(false && "Unimplemented");
# endif
@ -380,4 +380,4 @@ namespace RT64 {
#else
static_assert(false && "Unimplemented");
#endif
};
};

114
src/metal/rt64_metal.h Normal file → Executable file
View File

@ -5,6 +5,7 @@
#pragma once
#include "rhi/rt64_render_interface.h"
#include <map>
#ifdef __OBJC__
#import <Metal/Metal.h>
@ -33,9 +34,35 @@ namespace RT64 {
struct MetalPool;
struct MetalPipelineLayout;
struct MetalTexture;
struct MetalSampler;
struct MetalRenderState {
#ifdef __OBJC__
id<MTLRenderPipelineState> renderPipelineState = nil;
id<MTLDepthStencilState> depthStencilState = nil;
MTLCullMode cullMode = MTLCullModeNone;
MTLDepthClipMode depthClipMode = MTLDepthClipModeClip;
MTLWinding winding = MTLWindingClockwise;
MTLSamplePosition *samplePositions = nullptr;
#endif
uint32_t sampleCount = 0;
};
struct MetalDescriptorSet : RenderDescriptorSet {
#ifdef __OBJC__
id<MTLBuffer> descriptorBuffer;
std::vector<id<MTLBuffer>> residentBuffers;
std::unordered_map<uint32_t, id<MTLTexture>> indicesToTextures;
std::vector<id<MTLSamplerState>> staticSamplers;
std::vector<MTLArgumentDescriptor *> argumentDescriptors;
#endif
MetalDevice *device = nullptr;
uint32_t bufferOffset = 0;
uint32_t entryCount = 0;
uint32_t descriptorTypeMaxIndex = 0;
std::vector<RenderDescriptorRangeType> descriptorTypes;
std::vector<uint32_t> samplerIndices;
MetalDescriptorSet(MetalDevice *device, const RenderDescriptorSetDesc &desc);
MetalDescriptorSet(MetalDevice *device, uint32_t entryCount);
@ -45,12 +72,38 @@ namespace RT64 {
void setAccelerationStructure(uint32_t descriptorIndex, const RenderAccelerationStructure *accelerationStructure) override;
};
struct MetalDescriptorSetLayout {
#ifdef __OBJC__
std::vector<id<MTLSamplerState>> staticSamplers;
NSMutableArray* argumentDescriptors = nil;
id<MTLArgumentEncoder> argumentEncoder = nil;
id<MTLBuffer> descriptorBuffer = nil;
#endif
MetalDevice *device = nullptr;
std::vector<RenderDescriptorRangeType> descriptorTypes;
std::vector<uint32_t> descriptorToRangeIndex;
std::vector<uint32_t> descriptorIndexBases;
std::vector<uint32_t> descriptorRangeBinding;
std::vector<uint32_t> samplerIndices;
uint32_t bufferOffset = 0;
uint32_t entryCount = 0;
uint32_t descriptorTypeMaxIndex = 0;
uint32_t initialIndexOffset = 0;
MetalDescriptorSetLayout(MetalDevice *device, const RenderDescriptorSetDesc &desc);
~MetalDescriptorSetLayout();
};
struct MetalSwapChain : RenderSwapChain {
#ifdef __OBJC__
id<CAMetalDrawable> drawable = nil;
#endif
CAMetalLayer *layer = nullptr;
MetalCommandQueue *commandQueue = nullptr;
RenderWindow renderWindow = {};
std::vector<MetalTexture> textures;
uint32_t textureCount = 0;
MetalTexture *proxyTexture;
RenderFormat format = RenderFormat::UNKNOWN;
uint32_t width = 0;
uint32_t height = 0;
@ -70,7 +123,6 @@ namespace RT64 {
bool isEmpty() const override;
uint32_t getRefreshRate() const override;
void getWindowSize(uint32_t &dstWidth, uint32_t &dstHeight) const;
void setTextures();
};
struct MetalFramebuffer : RenderFramebuffer {
@ -92,13 +144,46 @@ namespace RT64 {
id<MTLRenderCommandEncoder> renderEncoder = nil;
id<MTLComputeCommandEncoder> computeEncoder = nil;
id<MTLBlitCommandEncoder> blitEncoder = nil;
MTLCaptureManager *captureManager = nil;
MTLRenderPassDescriptor *renderDescriptor = nil;
MTLPrimitiveType currentPrimitiveType = MTLPrimitiveTypeTriangle;
MTLIndexType currentIndexType = MTLIndexTypeUInt32;
id<MTLBuffer> indexBuffer = nil;
uint32_t viewCount = 0;
std::vector<id<MTLBuffer>> vertexBuffers;
std::vector<uint32_t> vertexBufferOffsets;
std::vector<uint32_t> vertexBufferIndices;
std::vector<MTLViewport> viewportVector;
std::vector<MTLScissorRect> scissorVector;
id<MTLBuffer> graphicsPushConstantsBuffer = nil;
id<MTLBuffer> computePushConstantsBuffer = nil;
std::map<id<MTLTexture>, id<MTLTexture>> resolveTo;
struct DrawCall {
enum class Type {
Draw,
DrawIndexed
};
Type type;
MTLPrimitiveType primitiveType = MTLPrimitiveTypeTriangle;
uint32_t startVertexLocation = 0;
uint32_t vertexCountPerInstance = 0;
uint32_t instanceCount = 0;
uint32_t startInstanceLocation = 0;
uint32_t indexCountPerInstance = 0;
MTLIndexType indexType = MTLIndexTypeUInt32;
id<MTLBuffer> indexBuffer = nil;
int32_t baseVertexLocation = 0;
uint32_t startIndexLocation = 0;
};
std::vector<DrawCall> deferredDrawCalls;
#endif
MetalDevice *device = nullptr;
@ -108,15 +193,26 @@ namespace RT64 {
const MetalPipelineLayout *activeComputePipelineLayout = nullptr;
const MetalPipelineLayout *activeGraphicsPipelineLayout = nullptr;
const MetalGraphicsPipeline *activeGraphicsPipeline = nullptr;
const MetalRenderState *activeRenderState = nullptr;
std::unordered_map<uint32_t, MetalDescriptorSet *> indicesToRenderDescriptorSets;
std::unordered_map<uint32_t, MetalDescriptorSet *> indicesToComputeDescriptorSets;
std::unordered_map<uint32_t, RenderColor> attachmentsToClear;
float depthClearValue = -1.0f;
uint32_t colorAttachmentsCount = 0;
MetalCommandList(MetalCommandQueue *queue, RenderCommandListType type);
~MetalCommandList() override;
void begin() override;
void end() override;
void endEncoder();
void endEncoder(bool clearDescs);
void guaranteeRenderDescriptor();
void guaranteeRenderEncoder();
void guaranteeComputeEncoder();
void guaranteeBlitEncoder();
void clearDrawCalls();
void barriers(RenderBarrierStages stages, const RenderBufferBarrier *bufferBarriers, uint32_t bufferBarriersCount, const RenderTextureBarrier *textureBarriers, uint32_t textureBarriersCount) override;
void dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) override;
void traceRays(uint32_t width, uint32_t height, uint32_t depth, RenderBufferReference shaderBindingTable, const RenderShaderBindingGroupsInfo &shaderBindingGroupsInfo) override;
@ -147,7 +243,7 @@ namespace RT64 {
void resolveTextureRegion(const RenderTexture *dstTexture, uint32_t dstX, uint32_t dstY, const RenderTexture *srcTexture, const RenderRect *srcRect) override;
void buildBottomLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, const RenderBottomLevelASBuildInfo &buildInfo) override;
void buildTopLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, RenderBufferReference instancesBuffer, const RenderTopLevelASBuildInfo &buildInfo) override;
void setDescriptorSet(const MetalPipelineLayout *activePipelineLayout, RenderDescriptorSet *descriptorSet, uint32_t setIndex, bool setCompute);
void setDescriptorSet(RenderDescriptorSet *descriptorSet, uint32_t setIndex, bool setCompute);
};
struct MetalCommandFence : RenderCommandFence {
@ -207,6 +303,7 @@ namespace RT64 {
MetalDevice *device = nullptr;
MetalPool *pool = nullptr;
RenderTextureDesc desc;
MetalSwapChain *parentSwapChain = nullptr;
MetalTexture() = default;
MetalTexture(MetalDevice *device, MetalPool *pool, const RenderTextureDesc &desc);
@ -219,7 +316,6 @@ namespace RT64 {
#ifdef __OBJC__
id<MTLTexture> mtlTexture = nil;
#endif
MetalTexture *texture = nullptr;
MetalTextureView(MetalTexture *texture, const RenderTextureViewDesc &desc);
~MetalTextureView() override;
@ -302,15 +398,21 @@ namespace RT64 {
id<MTLRenderPipelineState> state = nil;
#endif
MetalRenderState *renderState;
MetalGraphicsPipeline(MetalDevice *device, const RenderGraphicsPipelineDesc &desc);
~MetalGraphicsPipeline() override;
RenderPipelineProgram getProgram(const std::string &name) const override;
};
struct MetalPipelineLayout : RenderPipelineLayout {
#ifdef __OBJC__
id<MTLBuffer> pushConstantsBuffer = nil;
#endif
MetalDevice *device = nullptr;
std::vector<RenderPushConstantRange> pushConstantRanges;
uint32_t setCount = 0;
std::vector<MetalDescriptorSetLayout *> setLayoutHandles;
MetalPipelineLayout(MetalDevice *device, const RenderPipelineLayoutDesc &desc);
~MetalPipelineLayout() override;
@ -377,4 +479,4 @@ namespace RT64 {
void assignDeviceToLayer(void* layer);
};
};
};

821
src/metal/rt64_metal.mm Normal file → Executable file

File diff suppressed because it is too large Load Diff

5
src/rhi/rt64_render_interface_types.h Normal file → Executable file
View File

@ -23,7 +23,8 @@
#undef ControlMask
#undef Success
#elif defined(__APPLE__)
typedef struct _NSWindow NSWindow;
//typedef struct _NSWindow NSWindow;
#include <SDL.h>
#endif
namespace RT64 {
@ -43,7 +44,7 @@ namespace RT64 {
};
#elif defined(__APPLE__)
struct RenderWindow {
NSWindow* window;
SDL_Window* window;
bool operator==(const struct RenderWindow& rhs) const {
return window == rhs.window;
}