mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-02 05:54:18 +01:00
implement render passes
This commit is contained in:
parent
4c78c6afbb
commit
e5395277a7
@ -547,6 +547,8 @@ if(ENABLE_METAL)
|
|||||||
HW/Latte/Renderer/Metal/LatteTextureViewMtl.h
|
HW/Latte/Renderer/Metal/LatteTextureViewMtl.h
|
||||||
HW/Latte/Renderer/Metal/RendererShaderMtl.cpp
|
HW/Latte/Renderer/Metal/RendererShaderMtl.cpp
|
||||||
HW/Latte/Renderer/Metal/RendererShaderMtl.h
|
HW/Latte/Renderer/Metal/RendererShaderMtl.h
|
||||||
|
HW/Latte/Renderer/Metal/CachedFBOMtl.cpp
|
||||||
|
HW/Latte/Renderer/Metal/CachedFBOMtl.h
|
||||||
HW/Latte/Renderer/Metal/MetalMemoryManager.h
|
HW/Latte/Renderer/Metal/MetalMemoryManager.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
37
src/Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.cpp
Normal file
37
src/Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.cpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h"
|
||||||
|
#include "Metal/MTLRenderPass.hpp"
|
||||||
|
|
||||||
|
void CachedFBOMtl::CreateRenderPass()
|
||||||
|
{
|
||||||
|
m_renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
auto& buffer = colorBuffer[i];
|
||||||
|
auto textureView = (LatteTextureViewMtl*)buffer.texture;
|
||||||
|
if (!textureView)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto colorAttachment = m_renderPassDescriptor->colorAttachments()->object(i);
|
||||||
|
colorAttachment->setTexture(textureView->GetTexture());
|
||||||
|
colorAttachment->setLoadAction(MTL::LoadActionLoad);
|
||||||
|
colorAttachment->setStoreAction(MTL::StoreActionStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup depth attachment
|
||||||
|
if (depthBuffer.texture)
|
||||||
|
{
|
||||||
|
auto textureView = static_cast<LatteTextureViewMtl*>(depthBuffer.texture);
|
||||||
|
auto depthAttachment = m_renderPassDescriptor->depthAttachment();
|
||||||
|
depthAttachment->setTexture(textureView->GetTexture());
|
||||||
|
depthAttachment->setLoadAction(MTL::LoadActionLoad);
|
||||||
|
depthAttachment->setStoreAction(MTL::StoreActionStore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedFBOMtl::~CachedFBOMtl()
|
||||||
|
{
|
||||||
|
m_renderPassDescriptor->release();
|
||||||
|
}
|
27
src/Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.h
Normal file
27
src/Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Metal/Metal.hpp>
|
||||||
|
|
||||||
|
#include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h"
|
||||||
|
#include "Cafe/HW/Latte/Core/LatteCachedFBO.h"
|
||||||
|
|
||||||
|
class CachedFBOMtl : public LatteCachedFBO
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CachedFBOMtl(uint64 key) : LatteCachedFBO(key)
|
||||||
|
{
|
||||||
|
CreateRenderPass();
|
||||||
|
}
|
||||||
|
|
||||||
|
~CachedFBOMtl();
|
||||||
|
|
||||||
|
MTL::RenderPassDescriptor* GetRenderPassDescriptor()
|
||||||
|
{
|
||||||
|
return m_renderPassDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MTL::RenderPassDescriptor* m_renderPassDescriptor = nullptr;
|
||||||
|
|
||||||
|
void CreateRenderPass();
|
||||||
|
};
|
@ -2,9 +2,11 @@
|
|||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalLayer.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalLayer.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||||
|
|
||||||
#include "HW/Latte/Core/LatteShader.h"
|
#include "HW/Latte/Core/LatteShader.h"
|
||||||
|
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
||||||
#include "gui/guiWrapper.h"
|
#include "gui/guiWrapper.h"
|
||||||
|
|
||||||
extern bool hasValidFramebufferAttached;
|
extern bool hasValidFramebufferAttached;
|
||||||
@ -68,6 +70,12 @@ void MetalRenderer::DrawEmptyFrame(bool mainWindow)
|
|||||||
|
|
||||||
void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC)
|
void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC)
|
||||||
{
|
{
|
||||||
|
if (m_renderCommandEncoder)
|
||||||
|
{
|
||||||
|
m_renderCommandEncoder->endEncoding();
|
||||||
|
m_renderCommandEncoder->release();
|
||||||
|
m_renderCommandEncoder = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
CA::MetalDrawable* drawable = m_metalLayer->nextDrawable();
|
CA::MetalDrawable* drawable = m_metalLayer->nextDrawable();
|
||||||
if (drawable)
|
if (drawable)
|
||||||
@ -131,19 +139,18 @@ void MetalRenderer::renderTarget_setScissor(sint32 scissorX, sint32 scissorY, si
|
|||||||
|
|
||||||
LatteCachedFBO* MetalRenderer::rendertarget_createCachedFBO(uint64 key)
|
LatteCachedFBO* MetalRenderer::rendertarget_createCachedFBO(uint64 key)
|
||||||
{
|
{
|
||||||
printf("MetalRenderer::rendertarget_createCachedFBO not implemented\n");
|
return new CachedFBOMtl(key);
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::rendertarget_deleteCachedFBO(LatteCachedFBO* fbo)
|
void MetalRenderer::rendertarget_deleteCachedFBO(LatteCachedFBO* cfbo)
|
||||||
{
|
{
|
||||||
printf("MetalRenderer::rendertarget_deleteCachedFBO not implemented\n");
|
if (cfbo == (LatteCachedFBO*)m_state.activeFBO)
|
||||||
|
m_state.activeFBO = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::rendertarget_bindFramebufferObject(LatteCachedFBO* cfbo)
|
void MetalRenderer::rendertarget_bindFramebufferObject(LatteCachedFBO* cfbo)
|
||||||
{
|
{
|
||||||
printf("MetalRenderer::rendertarget_bindFramebufferObject not implemented\n");
|
m_state.activeFBO = (CachedFBOMtl*)cfbo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* MetalRenderer::texture_acquireTextureUploadBuffer(uint32 size)
|
void* MetalRenderer::texture_acquireTextureUploadBuffer(uint32 size)
|
||||||
@ -292,7 +299,6 @@ void MetalRenderer::texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIn
|
|||||||
|
|
||||||
void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize)
|
void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize)
|
||||||
{
|
{
|
||||||
std::cout << "TEXTURE LOAD SLICE" << std::endl;
|
|
||||||
auto mtlTexture = (LatteTextureMtl*)hostTexture;
|
auto mtlTexture = (LatteTextureMtl*)hostTexture;
|
||||||
|
|
||||||
size_t bytesPerRow = GetMtlTextureBytesPerRow(mtlTexture->GetFormat(), width);
|
size_t bytesPerRow = GetMtlTextureBytesPerRow(mtlTexture->GetFormat(), width);
|
||||||
@ -389,14 +395,14 @@ void MetalRenderer::streamout_rendererFinishDrawcall()
|
|||||||
|
|
||||||
void MetalRenderer::draw_beginSequence()
|
void MetalRenderer::draw_beginSequence()
|
||||||
{
|
{
|
||||||
skipDraws = false;
|
m_state.skipDrawSequence = false;
|
||||||
|
|
||||||
// update shader state
|
// update shader state
|
||||||
LatteSHRC_UpdateActiveShaders();
|
LatteSHRC_UpdateActiveShaders();
|
||||||
if (LatteGPUState.activeShaderHasError)
|
if (LatteGPUState.activeShaderHasError)
|
||||||
{
|
{
|
||||||
cemuLog_logDebugOnce(LogType::Force, "Skipping drawcalls due to shader error");
|
cemuLog_logDebugOnce(LogType::Force, "Skipping drawcalls due to shader error");
|
||||||
skipDraws = true;
|
m_state.skipDrawSequence = true;
|
||||||
cemu_assert_debug(false);
|
cemu_assert_debug(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -409,14 +415,14 @@ void MetalRenderer::draw_beginSequence()
|
|||||||
if (!LatteMRT::UpdateCurrentFBO())
|
if (!LatteMRT::UpdateCurrentFBO())
|
||||||
{
|
{
|
||||||
debug_printf("Rendertarget invalid\n");
|
debug_printf("Rendertarget invalid\n");
|
||||||
skipDraws = true;
|
m_state.skipDrawSequence = true;
|
||||||
return; // no render target
|
return; // no render target
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasValidFramebufferAttached)
|
if (!hasValidFramebufferAttached)
|
||||||
{
|
{
|
||||||
debug_printf("Drawcall with no color buffer or depth buffer attached\n");
|
debug_printf("Drawcall with no color buffer or depth buffer attached\n");
|
||||||
skipDraws = true;
|
m_state.skipDrawSequence = true;
|
||||||
return; // no render target
|
return; // no render target
|
||||||
}
|
}
|
||||||
LatteTexture_updateTextures();
|
LatteTexture_updateTextures();
|
||||||
@ -441,12 +447,77 @@ void MetalRenderer::draw_beginSequence()
|
|||||||
rasterizerEnable = true;
|
rasterizerEnable = true;
|
||||||
|
|
||||||
if (!rasterizerEnable == false)
|
if (!rasterizerEnable == false)
|
||||||
skipDraws = true;
|
m_state.skipDrawSequence = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count, MPTR indexDataMPTR, Latte::LATTE_VGT_DMA_INDEX_TYPE::E_INDEX_TYPE indexType, bool isFirst)
|
void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count, MPTR indexDataMPTR, Latte::LATTE_VGT_DMA_INDEX_TYPE::E_INDEX_TYPE indexType, bool isFirst)
|
||||||
{
|
{
|
||||||
printf("MetalRenderer::draw_execute not implemented\n");
|
std::cout << "DRAW" << std::endl;
|
||||||
|
// TODO: uncomment
|
||||||
|
//if (m_state.skipDrawSequence)
|
||||||
|
//{
|
||||||
|
// printf("skipping draw\n");
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Render pass
|
||||||
|
LatteMRT::ApplyCurrentState();
|
||||||
|
|
||||||
|
if (!m_state.activeFBO)
|
||||||
|
{
|
||||||
|
printf("no active FBO, skipping draw\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto renderPassDescriptor = m_state.activeFBO->GetRenderPassDescriptor();
|
||||||
|
m_renderCommandEncoder = m_commandBuffer->renderCommandEncoder(renderPassDescriptor);
|
||||||
|
|
||||||
|
// Shaders
|
||||||
|
/*
|
||||||
|
LatteDecompilerShader* vertexShader = LatteSHRC_GetActiveVertexShader();
|
||||||
|
LatteDecompilerShader* pixelShader = LatteSHRC_GetActivePixelShader();
|
||||||
|
|
||||||
|
// Render pipeline state
|
||||||
|
MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
|
||||||
|
renderPipelineDescriptor->setVertexFunction(static_cast<RendererShaderMtl*>(vertexShader->shader)->GetFunction());
|
||||||
|
renderPipelineDescriptor->setFragmentFunction(static_cast<RendererShaderMtl*>(pixelShader->shader)->GetFunction());
|
||||||
|
|
||||||
|
NS::Error* error = nullptr;
|
||||||
|
MTL::RenderPipelineState* renderPipelineState = m_device->newRenderPipelineState(renderPipelineDescriptor, &error);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
printf("error creating render pipeline state: %s\n", error->localizedDescription()->utf8String());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: bind resources
|
||||||
|
|
||||||
|
const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(LatteGPUState.contextRegister[mmVGT_PRIMITIVE_TYPE]);
|
||||||
|
// TODO: uncomment
|
||||||
|
//auto mtlPrimitiveType = GetMtlPrimitiveType(primitiveMode);
|
||||||
|
|
||||||
|
Renderer::INDEX_TYPE hostIndexType;
|
||||||
|
uint32 hostIndexCount;
|
||||||
|
uint32 indexMin = 0;
|
||||||
|
uint32 indexMax = 0;
|
||||||
|
uint32 indexBufferOffset = 0;
|
||||||
|
uint32 indexBufferIndex = 0;
|
||||||
|
LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMin, indexMax, hostIndexType, hostIndexCount, indexBufferOffset, indexBufferIndex);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
// TODO: uncomment
|
||||||
|
/*
|
||||||
|
if (hostIndexType != INDEX_TYPE::NONE)
|
||||||
|
{
|
||||||
|
auto mtlIndexType = GetMtlIndexType(hostIndexType);
|
||||||
|
// TODO: get index buffer
|
||||||
|
m_renderCommandEncoder->drawIndexedPrimitives(mtlPrimitiveType, hostIndexCount, mtlIndexType, indexBuffer, 0, instanceCount, baseVertex, baseInstance);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_renderCommandEncoder->drawPrimitives(mtlPrimitiveType, baseVertex, count, instanceCount, baseInstance);
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::draw_endSequence()
|
void MetalRenderer::draw_endSequence()
|
||||||
|
@ -6,6 +6,17 @@
|
|||||||
|
|
||||||
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h"
|
||||||
|
#include "Metal/MTLRenderCommandEncoder.hpp"
|
||||||
|
|
||||||
|
#define MAX_MTL_BUFFERS 31
|
||||||
|
|
||||||
|
struct MetalState
|
||||||
|
{
|
||||||
|
bool skipDrawSequence = false;
|
||||||
|
class CachedFBOMtl* activeFBO = nullptr;
|
||||||
|
//MTL::Buffer* vertexBuffers[MAX_MTL_BUFFERS] = {nullptr};
|
||||||
|
//MTL::Buffer* indexBuffer = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
class MetalRenderer : public Renderer
|
class MetalRenderer : public Renderer
|
||||||
{
|
{
|
||||||
@ -163,10 +174,12 @@ private:
|
|||||||
MTL::Device* m_device;
|
MTL::Device* m_device;
|
||||||
MTL::CommandQueue* m_commandQueue;
|
MTL::CommandQueue* m_commandQueue;
|
||||||
|
|
||||||
|
// Active objects
|
||||||
MTL::CommandBuffer* m_commandBuffer = nullptr;
|
MTL::CommandBuffer* m_commandBuffer = nullptr;
|
||||||
|
MTL::RenderCommandEncoder* m_renderCommandEncoder = nullptr;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
bool skipDraws = false;
|
MetalState m_state;
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
void ensureCommandBuffer()
|
void ensureCommandBuffer()
|
||||||
|
Loading…
Reference in New Issue
Block a user