diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp index 22b8a069..1d0ad0a8 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp @@ -186,7 +186,7 @@ MTL::VertexFormat GetMtlVertexFormat(uint8 format) case FMT_2_10_10_10: return MTL::VertexFormatUInt; // verified to match OpenGL default: - printf("unsupported vertex format: %u\n", (uint32)format); + printf("unsupported vertex format %u\n", (uint32)format); assert_dbg(); return MTL::VertexFormatInvalid; } @@ -201,7 +201,7 @@ MTL::IndexType GetMtlIndexType(Renderer::INDEX_TYPE indexType) case Renderer::INDEX_TYPE::U32: return MTL::IndexTypeUInt32; default: - printf("unsupported index type: %u\n", (uint32)indexType); + printf("unsupported index type %u\n", (uint32)indexType); assert_dbg(); return MTL::IndexTypeUInt32; } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp index d09ab116..6e609e4f 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp @@ -3,9 +3,11 @@ const size_t BUFFER_ALLOCATION_SIZE = 8 * 1024 * 1024; +// TODO: uncomment everything MetalBufferAllocation MetalBufferAllocator::GetBufferAllocation(size_t size) { // First, try to find a free range + /* for (uint32 i = 0; i < m_freeBufferRanges.size(); i++) { auto& range = m_freeBufferRanges[i]; @@ -27,9 +29,10 @@ MetalBufferAllocation MetalBufferAllocator::GetBufferAllocation(size_t size) return allocation; } } + */ // If no free range was found, allocate a new buffer - MTL::Buffer* buffer = m_mtlr->GetDevice()->newBuffer(std::max(size, BUFFER_ALLOCATION_SIZE), MTL::ResourceStorageModeShared); + MTL::Buffer* buffer = m_mtlr->GetDevice()->newBuffer(/*std::max(*/size/*, BUFFER_ALLOCATION_SIZE)*/, MTL::ResourceStorageModeShared); MetalBufferAllocation allocation; allocation.bufferIndex = m_buffers.size(); @@ -39,6 +42,7 @@ MetalBufferAllocation MetalBufferAllocator::GetBufferAllocation(size_t size) m_buffers.push_back(buffer); // If the buffer is larger than the requested size, add the remaining space to the free buffer ranges + /* if (size < BUFFER_ALLOCATION_SIZE) { MetalBufferRange range; @@ -48,6 +52,7 @@ MetalBufferAllocation MetalBufferAllocator::GetBufferAllocation(size_t size) m_freeBufferRanges.push_back(range); } + */ return allocation; } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 23213009..9874f771 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -11,6 +11,7 @@ #include "Cafe/HW/Latte/Core/FetchShader.h" #include "Cafe/HW/Latte/Core/LatteShader.h" #include "Cafe/HW/Latte/Core/LatteIndices.h" +#include "Cemu/Logging/CemuDebugLogging.h" #include "Foundation/NSTypes.hpp" #include "Metal/MTLRenderCommandEncoder.hpp" #include "gui/guiWrapper.h" @@ -171,7 +172,8 @@ void MetalRenderer::Flush(bool waitIdle) void MetalRenderer::NotifyLatteCommandProcessorIdle() { - printf("MetalRenderer::NotifyLatteCommandProcessorIdle not implemented\n"); + // TODO: should we? + CommitCommandBuffer(); } void MetalRenderer::AppendOverlayDebugInfo() @@ -181,12 +183,20 @@ void MetalRenderer::AppendOverlayDebugInfo() void MetalRenderer::renderTarget_setViewport(float x, float y, float width, float height, float nearZ, float farZ, bool halfZ) { - printf("MetalRenderer::renderTarget_setViewport not implemented\n"); + m_state.viewport = MTL::Viewport{x, y + height, width, -height, nearZ, farZ}; + if (m_encoderType == MetalEncoderType::Render) + { + static_cast(m_commandEncoder)->setViewport(m_state.viewport); + } } void MetalRenderer::renderTarget_setScissor(sint32 scissorX, sint32 scissorY, sint32 scissorWidth, sint32 scissorHeight) { - printf("MetalRenderer::renderTarget_setScissor not implemented\n"); + m_state.scissor = MTL::ScissorRect{NS::UInteger(scissorX), NS::UInteger(scissorY), NS::UInteger(scissorWidth), NS::UInteger(scissorHeight)}; + if (m_encoderType == MetalEncoderType::Render) + { + static_cast(m_commandEncoder)->setScissorRect(m_state.scissor); + } } LatteCachedFBO* MetalRenderer::rendertarget_createCachedFBO(uint64 key) @@ -456,7 +466,7 @@ void MetalRenderer::draw_beginSequence() LatteSHRC_UpdateActiveShaders(); if (LatteGPUState.activeShaderHasError) { - debug_printf("Skipping drawcalls due to shader error\n"); + printf("Skipping drawcalls due to shader error\n"); m_state.skipDrawSequence = true; cemu_assert_debug(false); return; @@ -469,14 +479,14 @@ void MetalRenderer::draw_beginSequence() LatteGPUState.repeatTextureInitialization = false; if (!LatteMRT::UpdateCurrentFBO()) { - debug_printf("Rendertarget invalid\n"); + printf("Rendertarget invalid\n"); m_state.skipDrawSequence = true; return; // no render target } if (!hasValidFramebufferAttached) { - debug_printf("Drawcall with no color buffer or depth buffer attached\n"); + printf("Drawcall with no color buffer or depth buffer attached\n"); m_state.skipDrawSequence = true; return; // no render target } @@ -540,6 +550,11 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 LatteSHRC_UpdateActiveShaders(); LatteDecompilerShader* vertexShader = LatteSHRC_GetActiveVertexShader(); LatteDecompilerShader* pixelShader = LatteSHRC_GetActivePixelShader(); + if (!vertexShader) + { + printf("no vertex function, skipping draw\n"); + return; + } auto fetchShader = vertexShader->compatibleFetchShader; @@ -648,8 +663,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 if (vertexBufferRange.needsRebind) { renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), vertexBufferRange.offset, GET_MTL_VERTEX_BUFFER_INDEX(i)); - // TODO: uncomment - //vertexBufferRange.needsRebind = false; + vertexBufferRange.needsRebind = false; } } @@ -671,7 +685,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 void MetalRenderer::draw_endSequence() { - printf("MetalRenderer::draw_endSequence not implemented\n"); + // TODO: do something? } void* MetalRenderer::indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex) @@ -878,3 +892,56 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE } } } + +void MetalRenderer::RebindRenderState(MTL::RenderCommandEncoder* renderCommandEncoder) +{ + // Viewport + if (m_state.viewport.width != 0.0) + { + printf("setting previous viewport X: %f Y: %f width: %f height %f\n", m_state.viewport.originX, m_state.viewport.originY, m_state.viewport.width, m_state.viewport.height); + renderCommandEncoder->setViewport(m_state.viewport); + } + else + { + // Find the framebuffer dimensions + uint32 framebufferWidth = 0, framebufferHeight = 0; + if (m_state.activeFBO->hasDepthBuffer()) + { + framebufferHeight = m_state.activeFBO->depthBuffer.texture->baseTexture->width; + framebufferHeight = m_state.activeFBO->depthBuffer.texture->baseTexture->height; + } + else + { + for (uint8 i = 0; i < 8; i++) + { + auto texture = m_state.activeFBO->colorBuffer[i].texture; + if (texture) + { + framebufferWidth = texture->baseTexture->width; + framebufferHeight = texture->baseTexture->height; + } + } + } + + MTL::Viewport viewport{0, (double)framebufferHeight, (double)framebufferWidth, -(double)framebufferHeight, 0.0, 1.0}; + printf("setting default viewport X: %f Y: %f width: %f height %f\n", viewport.originX, viewport.originY, viewport.width, viewport.height); + renderCommandEncoder->setViewport(viewport); + } + + // Scissor + if (m_state.scissor.width != 0) + { + renderCommandEncoder->setScissorRect(m_state.scissor); + } + + // Vertex buffers + for (uint8 i = 0; i < MAX_MTL_BUFFERS; i++) + { + auto& vertexBufferRange = m_state.vertexBuffers[i]; + if (vertexBufferRange.offset != -1) + { + renderCommandEncoder->setVertexBuffer(m_memoryManager->GetBufferCache(), vertexBufferRange.offset, GET_MTL_VERTEX_BUFFER_INDEX(i)); + vertexBufferRange.needsRebind = false; + } + } +} diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h index 45e9e703..2816be19 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h @@ -32,6 +32,8 @@ struct MetalState class LatteTextureViewMtl* textures[MAX_MTL_TEXTURES] = {nullptr}; MTL::Texture* colorRenderTargets[8] = {nullptr}; MTL::Texture* depthRenderTarget = nullptr; + MTL::Viewport viewport = {0, 0, 0, 0, 0, 0}; + MTL::ScissorRect scissor = {0, 0, 0, 0}; }; enum class MetalEncoderType @@ -272,6 +274,9 @@ private: m_commandEncoder = renderCommandEncoder; m_encoderType = MetalEncoderType::Render; + // Rebind all the render state + RebindRenderState(renderCommandEncoder); + return renderCommandEncoder; } @@ -342,4 +347,6 @@ private: } void BindStageResources(MTL::RenderCommandEncoder* renderCommandEncoder, LatteDecompilerShader* shader); + + void RebindRenderState(MTL::RenderCommandEncoder* renderCommandEncoder); };