mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-30 04:54:18 +01:00
implement vertex descriptors & draw
This commit is contained in:
parent
e5395277a7
commit
cb525b22ff
@ -549,6 +549,7 @@ if(ENABLE_METAL)
|
|||||||
HW/Latte/Renderer/Metal/RendererShaderMtl.h
|
HW/Latte/Renderer/Metal/RendererShaderMtl.h
|
||||||
HW/Latte/Renderer/Metal/CachedFBOMtl.cpp
|
HW/Latte/Renderer/Metal/CachedFBOMtl.cpp
|
||||||
HW/Latte/Renderer/Metal/CachedFBOMtl.h
|
HW/Latte/Renderer/Metal/CachedFBOMtl.h
|
||||||
|
HW/Latte/Renderer/Metal/MetalMemoryManager.cpp
|
||||||
HW/Latte/Renderer/Metal/MetalMemoryManager.h
|
HW/Latte/Renderer/Metal/MetalMemoryManager.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -3818,18 +3818,21 @@ void LatteDecompiler_emitMSLShader(LatteDecompilerShaderContext* shaderContext,
|
|||||||
LatteDecompiler::emitHeader(shaderContext);
|
LatteDecompiler::emitHeader(shaderContext);
|
||||||
// helper functions
|
// helper functions
|
||||||
LatteDecompiler_emitHelperFunctions(shaderContext, src);
|
LatteDecompiler_emitHelperFunctions(shaderContext, src);
|
||||||
const char* outputTypeName;
|
const char* functionType = "";
|
||||||
|
const char* outputTypeName = "";
|
||||||
switch (shader->shaderType)
|
switch (shader->shaderType)
|
||||||
{
|
{
|
||||||
case LatteConst::ShaderType::Vertex:
|
case LatteConst::ShaderType::Vertex:
|
||||||
|
functionType = "vertex";
|
||||||
outputTypeName = "VertexOut";
|
outputTypeName = "VertexOut";
|
||||||
break;
|
break;
|
||||||
case LatteConst::ShaderType::Pixel:
|
case LatteConst::ShaderType::Pixel:
|
||||||
|
functionType = "fragment";
|
||||||
outputTypeName = "FragmentOut";
|
outputTypeName = "FragmentOut";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// start of main
|
// start of main
|
||||||
src->addFmt("{} main0(", outputTypeName);
|
src->addFmt("{} {} main0(", functionType, outputTypeName);
|
||||||
LatteDecompiler::emitInputs(shaderContext);
|
LatteDecompiler::emitInputs(shaderContext);
|
||||||
src->add(") {" _CRLF);
|
src->add(") {" _CRLF);
|
||||||
src->addFmt("{} out;" _CRLF, outputTypeName);
|
src->addFmt("{} out;" _CRLF, outputTypeName);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||||
#include "Common/precompiled.h"
|
#include "Common/precompiled.h"
|
||||||
#include "Metal/MTLPixelFormat.hpp"
|
#include "Metal/MTLPixelFormat.hpp"
|
||||||
|
#include "Metal/MTLVertexDescriptor.hpp"
|
||||||
|
|
||||||
// TODO: separate color and depth formats
|
// TODO: separate color and depth formats
|
||||||
std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_FORMAT_TABLE = {
|
std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_FORMAT_TABLE = {
|
||||||
@ -106,3 +107,90 @@ size_t GetMtlTextureBytesPerImage(Latte::E_GX2SURFFMT format, uint32 height, siz
|
|||||||
|
|
||||||
return CeilDivide(height, formatInfo.blockTexelSize.y) * bytesPerRow;
|
return CeilDivide(height, formatInfo.blockTexelSize.y) * bytesPerRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MTL::PrimitiveType GetMtlPrimitiveType(LattePrimitiveMode mode)
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case LattePrimitiveMode::POINTS:
|
||||||
|
return MTL::PrimitiveTypePoint;
|
||||||
|
case LattePrimitiveMode::LINES:
|
||||||
|
return MTL::PrimitiveTypeLine;
|
||||||
|
case LattePrimitiveMode::TRIANGLES:
|
||||||
|
return MTL::PrimitiveTypeTriangle;
|
||||||
|
case LattePrimitiveMode::TRIANGLE_STRIP:
|
||||||
|
return MTL::PrimitiveTypeTriangleStrip;
|
||||||
|
default:
|
||||||
|
printf("unimplemented primitive type %u\n", (uint32)mode);
|
||||||
|
cemu_assert_debug(false);
|
||||||
|
return MTL::PrimitiveTypeTriangle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MTL::VertexFormat GetMtlVertexFormat(uint8 format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case FMT_32_32_32_32_FLOAT:
|
||||||
|
return MTL::VertexFormatUInt4;
|
||||||
|
case FMT_32_32_32_FLOAT:
|
||||||
|
return MTL::VertexFormatUInt3;
|
||||||
|
case FMT_32_32_FLOAT:
|
||||||
|
return MTL::VertexFormatUInt2;
|
||||||
|
case FMT_32_FLOAT:
|
||||||
|
return MTL::VertexFormatUInt;
|
||||||
|
case FMT_8_8_8_8:
|
||||||
|
return MTL::VertexFormatUChar4;
|
||||||
|
case FMT_8_8_8:
|
||||||
|
return MTL::VertexFormatUChar3;
|
||||||
|
case FMT_8_8:
|
||||||
|
return MTL::VertexFormatUChar2;
|
||||||
|
case FMT_8:
|
||||||
|
return MTL::VertexFormatUChar;
|
||||||
|
case FMT_32_32_32_32:
|
||||||
|
return MTL::VertexFormatUInt4;
|
||||||
|
case FMT_32_32_32:
|
||||||
|
return MTL::VertexFormatUInt3;
|
||||||
|
case FMT_32_32:
|
||||||
|
return MTL::VertexFormatUInt2;
|
||||||
|
case FMT_32:
|
||||||
|
return MTL::VertexFormatUInt;
|
||||||
|
case FMT_16_16_16_16:
|
||||||
|
return MTL::VertexFormatUShort4; // verified to match OpenGL
|
||||||
|
case FMT_16_16_16:
|
||||||
|
return MTL::VertexFormatUShort3;
|
||||||
|
case FMT_16_16:
|
||||||
|
return MTL::VertexFormatUShort2;
|
||||||
|
case FMT_16:
|
||||||
|
return MTL::VertexFormatUShort;
|
||||||
|
case FMT_16_16_16_16_FLOAT:
|
||||||
|
return MTL::VertexFormatUShort4; // verified to match OpenGL
|
||||||
|
case FMT_16_16_16_FLOAT:
|
||||||
|
return MTL::VertexFormatUShort3;
|
||||||
|
case FMT_16_16_FLOAT:
|
||||||
|
return MTL::VertexFormatUShort2;
|
||||||
|
case FMT_16_FLOAT:
|
||||||
|
return MTL::VertexFormatUShort;
|
||||||
|
case FMT_2_10_10_10:
|
||||||
|
return MTL::VertexFormatUInt; // verified to match OpenGL
|
||||||
|
default:
|
||||||
|
printf("unsupported vertex format: %u\n", (uint32)format);
|
||||||
|
assert_dbg();
|
||||||
|
return MTL::VertexFormatInvalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MTL::IndexType GetMtlIndexType(Renderer::INDEX_TYPE indexType)
|
||||||
|
{
|
||||||
|
switch (indexType)
|
||||||
|
{
|
||||||
|
case Renderer::INDEX_TYPE::U16:
|
||||||
|
return MTL::IndexTypeUInt16;
|
||||||
|
case Renderer::INDEX_TYPE::U32:
|
||||||
|
return MTL::IndexTypeUInt32;
|
||||||
|
default:
|
||||||
|
printf("unsupported index type: %u\n", (uint32)indexType);
|
||||||
|
assert_dbg();
|
||||||
|
return MTL::IndexTypeUInt32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
#include <Metal/Metal.hpp>
|
#include <Metal/Metal.hpp>
|
||||||
|
|
||||||
#include "Cafe/HW/Latte/ISA/LatteReg.h"
|
#include "Cafe/HW/Latte/ISA/LatteReg.h"
|
||||||
|
#include "Cafe/HW/Latte/Core/LatteConst.h"
|
||||||
|
//#include "Cafe/HW/Latte/Core/FetchShader.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
||||||
|
|
||||||
struct Uvec2 {
|
struct Uvec2 {
|
||||||
uint32 x;
|
uint32 x;
|
||||||
@ -20,3 +23,9 @@ const MtlPixelFormatInfo GetMtlPixelFormatInfo(Latte::E_GX2SURFFMT format);
|
|||||||
size_t GetMtlTextureBytesPerRow(Latte::E_GX2SURFFMT format, uint32 width);
|
size_t GetMtlTextureBytesPerRow(Latte::E_GX2SURFFMT format, uint32 width);
|
||||||
|
|
||||||
size_t GetMtlTextureBytesPerImage(Latte::E_GX2SURFFMT format, uint32 height, size_t bytesPerRow);
|
size_t GetMtlTextureBytesPerImage(Latte::E_GX2SURFFMT format, uint32 height, size_t bytesPerRow);
|
||||||
|
|
||||||
|
MTL::PrimitiveType GetMtlPrimitiveType(LattePrimitiveMode mode);
|
||||||
|
|
||||||
|
MTL::VertexFormat GetMtlVertexFormat(uint8 format);
|
||||||
|
|
||||||
|
MTL::IndexType GetMtlIndexType(Renderer::INDEX_TYPE indexType);
|
||||||
|
26
src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp
Normal file
26
src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
|
|
||||||
|
void* MetalMemoryManager::GetTextureUploadBuffer(size_t size)
|
||||||
|
{
|
||||||
|
if (m_textureUploadBuffer.size() < size)
|
||||||
|
{
|
||||||
|
m_textureUploadBuffer.resize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_textureUploadBuffer.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: optimize this
|
||||||
|
MetalBufferAllocation MetalMemoryManager::GetBufferAllocation(size_t size)
|
||||||
|
{
|
||||||
|
MTL::Buffer* buffer = m_mtlr->GetDevice()->newBuffer(size, MTL::ResourceStorageModeShared);
|
||||||
|
|
||||||
|
MetalBufferAllocation allocation;
|
||||||
|
allocation.bufferIndex = m_buffers.size();
|
||||||
|
allocation.bufferOffset = 0;
|
||||||
|
allocation.data = buffer->contents();
|
||||||
|
|
||||||
|
m_buffers.push_back(buffer);
|
||||||
|
|
||||||
|
return allocation;
|
||||||
|
}
|
@ -1,22 +1,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Metal/Metal.hpp>
|
||||||
|
|
||||||
#include "Cafe/HW/Latte/ISA/LatteReg.h"
|
#include "Cafe/HW/Latte/ISA/LatteReg.h"
|
||||||
|
|
||||||
|
struct MetalBufferAllocation
|
||||||
|
{
|
||||||
|
void* data;
|
||||||
|
uint32 bufferIndex;
|
||||||
|
size_t bufferOffset;
|
||||||
|
};
|
||||||
|
|
||||||
class MetalMemoryManager
|
class MetalMemoryManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MetalMemoryManager() = default;
|
MetalMemoryManager(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {}
|
||||||
|
|
||||||
void* GetTextureUploadBuffer(size_t size)
|
MTL::Buffer* GetBuffer(uint32 bufferIndex)
|
||||||
{
|
{
|
||||||
if (m_textureUploadBuffer.size() < size)
|
return m_buffers[bufferIndex];
|
||||||
{
|
|
||||||
m_textureUploadBuffer.resize(size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_textureUploadBuffer.data();
|
void* GetTextureUploadBuffer(size_t size);
|
||||||
}
|
|
||||||
|
MetalBufferAllocation GetBufferAllocation(size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class MetalRenderer* m_mtlr;
|
||||||
|
|
||||||
std::vector<uint8> m_textureUploadBuffer;
|
std::vector<uint8> m_textureUploadBuffer;
|
||||||
|
std::vector<MTL::Buffer*> m_buffers;
|
||||||
};
|
};
|
||||||
|
@ -5,8 +5,10 @@
|
|||||||
#include "Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.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 "Cafe/HW/Latte/Core/FetchShader.h"
|
||||||
|
#include "Cafe/HW/Latte/Core/LatteShader.h"
|
||||||
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
||||||
|
#include "Metal/MTLVertexDescriptor.hpp"
|
||||||
#include "gui/guiWrapper.h"
|
#include "gui/guiWrapper.h"
|
||||||
|
|
||||||
extern bool hasValidFramebufferAttached;
|
extern bool hasValidFramebufferAttached;
|
||||||
@ -15,10 +17,14 @@ MetalRenderer::MetalRenderer()
|
|||||||
{
|
{
|
||||||
m_device = MTL::CreateSystemDefaultDevice();
|
m_device = MTL::CreateSystemDefaultDevice();
|
||||||
m_commandQueue = m_device->newCommandQueue();
|
m_commandQueue = m_device->newCommandQueue();
|
||||||
|
|
||||||
|
m_memoryManager = new MetalMemoryManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalRenderer::~MetalRenderer()
|
MetalRenderer::~MetalRenderer()
|
||||||
{
|
{
|
||||||
|
delete m_memoryManager;
|
||||||
|
|
||||||
m_commandQueue->release();
|
m_commandQueue->release();
|
||||||
m_device->release();
|
m_device->release();
|
||||||
}
|
}
|
||||||
@ -155,7 +161,7 @@ void MetalRenderer::rendertarget_bindFramebufferObject(LatteCachedFBO* cfbo)
|
|||||||
|
|
||||||
void* MetalRenderer::texture_acquireTextureUploadBuffer(uint32 size)
|
void* MetalRenderer::texture_acquireTextureUploadBuffer(uint32 size)
|
||||||
{
|
{
|
||||||
return m_memoryManager.GetTextureUploadBuffer(size);
|
return m_memoryManager->GetTextureUploadBuffer(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::texture_releaseTextureUploadBuffer(uint8* mem)
|
void MetalRenderer::texture_releaseTextureUploadBuffer(uint8* mem)
|
||||||
@ -431,8 +437,7 @@ void MetalRenderer::draw_beginSequence()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// apply render target
|
// apply render target
|
||||||
// HACK: not implemented yet
|
LatteMRT::ApplyCurrentState();
|
||||||
//LatteMRT::ApplyCurrentState();
|
|
||||||
|
|
||||||
// viewport and scissor box
|
// viewport and scissor box
|
||||||
LatteRenderTarget_updateViewport();
|
LatteRenderTarget_updateViewport();
|
||||||
@ -453,6 +458,8 @@ void MetalRenderer::draw_beginSequence()
|
|||||||
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)
|
||||||
{
|
{
|
||||||
std::cout << "DRAW" << std::endl;
|
std::cout << "DRAW" << std::endl;
|
||||||
|
|
||||||
|
ensureCommandBuffer();
|
||||||
// TODO: uncomment
|
// TODO: uncomment
|
||||||
//if (m_state.skipDrawSequence)
|
//if (m_state.skipDrawSequence)
|
||||||
//{
|
//{
|
||||||
@ -461,8 +468,6 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
// Render pass
|
// Render pass
|
||||||
LatteMRT::ApplyCurrentState();
|
|
||||||
|
|
||||||
if (!m_state.activeFBO)
|
if (!m_state.activeFBO)
|
||||||
{
|
{
|
||||||
printf("no active FBO, skipping draw\n");
|
printf("no active FBO, skipping draw\n");
|
||||||
@ -470,17 +475,70 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto renderPassDescriptor = m_state.activeFBO->GetRenderPassDescriptor();
|
auto renderPassDescriptor = m_state.activeFBO->GetRenderPassDescriptor();
|
||||||
m_renderCommandEncoder = m_commandBuffer->renderCommandEncoder(renderPassDescriptor);
|
beginRenderPassIfNeeded(renderPassDescriptor);
|
||||||
|
|
||||||
// Shaders
|
// Shaders
|
||||||
/*
|
|
||||||
LatteDecompilerShader* vertexShader = LatteSHRC_GetActiveVertexShader();
|
LatteDecompilerShader* vertexShader = LatteSHRC_GetActiveVertexShader();
|
||||||
LatteDecompilerShader* pixelShader = LatteSHRC_GetActivePixelShader();
|
LatteDecompilerShader* pixelShader = LatteSHRC_GetActivePixelShader();
|
||||||
|
|
||||||
|
auto fetchShader = vertexShader->compatibleFetchShader;
|
||||||
|
|
||||||
|
// Vertex descriptor
|
||||||
|
MTL::VertexDescriptor* vertexDescriptor = MTL::VertexDescriptor::alloc()->init();
|
||||||
|
for (auto& bufferGroup : fetchShader->bufferGroups)
|
||||||
|
{
|
||||||
|
std::optional<LatteConst::VertexFetchType2> fetchType;
|
||||||
|
|
||||||
|
for (sint32 j = 0; j < bufferGroup.attribCount; ++j)
|
||||||
|
{
|
||||||
|
auto& attr = bufferGroup.attrib[j];
|
||||||
|
|
||||||
|
uint32 semanticId = vertexShader->resourceMapping.attributeMapping[attr.semanticId];
|
||||||
|
if (semanticId == (uint32)-1)
|
||||||
|
continue; // attribute not used?
|
||||||
|
|
||||||
|
auto attribute = vertexDescriptor->attributes()->object(semanticId);
|
||||||
|
attribute->setOffset(attr.offset);
|
||||||
|
// Bind from the end to not conflict with uniform buffers
|
||||||
|
attribute->setBufferIndex(GET_MTL_VERTEX_BUFFER_INDEX(attr.attributeBufferIndex));
|
||||||
|
attribute->setFormat(GetMtlVertexFormat(attr.format));
|
||||||
|
|
||||||
|
if (fetchType.has_value())
|
||||||
|
cemu_assert_debug(fetchType == attr.fetchType);
|
||||||
|
else
|
||||||
|
fetchType = attr.fetchType;
|
||||||
|
|
||||||
|
if (attr.fetchType == LatteConst::INSTANCE_DATA)
|
||||||
|
{
|
||||||
|
cemu_assert_debug(attr.aluDivisor == 1); // other divisor not yet supported
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 bufferIndex = bufferGroup.attributeBufferIndex;
|
||||||
|
uint32 bufferBaseRegisterIndex = mmSQ_VTX_ATTRIBUTE_BLOCK_START + bufferIndex * 7;
|
||||||
|
// TODO: is LatteGPUState.contextNew correct?
|
||||||
|
uint32 bufferStride = (LatteGPUState.contextNew.GetRawView()[bufferBaseRegisterIndex + 2] >> 11) & 0xFFFF;
|
||||||
|
printf("buffer %u has stride %u bytes\n", bufferIndex, bufferStride);
|
||||||
|
|
||||||
|
auto layout = vertexDescriptor->layouts()->object(GET_MTL_VERTEX_BUFFER_INDEX(bufferIndex));
|
||||||
|
layout->setStride(bufferStride);
|
||||||
|
if (!fetchType.has_value() || fetchType == LatteConst::VertexFetchType2::VERTEX_DATA)
|
||||||
|
layout->setStepFunction(MTL::VertexStepFunctionPerVertex);
|
||||||
|
else if (fetchType == LatteConst::VertexFetchType2::INSTANCE_DATA)
|
||||||
|
layout->setStepFunction(MTL::VertexStepFunctionPerInstance);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("unimplemented vertex fetch type %u\n", (uint32)fetchType.value());
|
||||||
|
cemu_assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Render pipeline state
|
// Render pipeline state
|
||||||
MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
|
MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
|
||||||
renderPipelineDescriptor->setVertexFunction(static_cast<RendererShaderMtl*>(vertexShader->shader)->GetFunction());
|
renderPipelineDescriptor->setVertexFunction(static_cast<RendererShaderMtl*>(vertexShader->shader)->GetFunction());
|
||||||
renderPipelineDescriptor->setFragmentFunction(static_cast<RendererShaderMtl*>(pixelShader->shader)->GetFunction());
|
renderPipelineDescriptor->setFragmentFunction(static_cast<RendererShaderMtl*>(pixelShader->shader)->GetFunction());
|
||||||
|
// TODO: don't always set the vertex descriptor
|
||||||
|
renderPipelineDescriptor->setVertexDescriptor(vertexDescriptor);
|
||||||
|
|
||||||
NS::Error* error = nullptr;
|
NS::Error* error = nullptr;
|
||||||
MTL::RenderPipelineState* renderPipelineState = m_device->newRenderPipelineState(renderPipelineDescriptor, &error);
|
MTL::RenderPipelineState* renderPipelineState = m_device->newRenderPipelineState(renderPipelineDescriptor, &error);
|
||||||
@ -489,12 +547,12 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
|
|||||||
printf("error creating render pipeline state: %s\n", error->localizedDescription()->utf8String());
|
printf("error creating render pipeline state: %s\n", error->localizedDescription()->utf8String());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
m_renderCommandEncoder->setRenderPipelineState(renderPipelineState);
|
||||||
|
|
||||||
// TODO: bind resources
|
// TODO: bind resources
|
||||||
|
|
||||||
const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(LatteGPUState.contextRegister[mmVGT_PRIMITIVE_TYPE]);
|
const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(LatteGPUState.contextRegister[mmVGT_PRIMITIVE_TYPE]);
|
||||||
// TODO: uncomment
|
auto mtlPrimitiveType = GetMtlPrimitiveType(primitiveMode);
|
||||||
//auto mtlPrimitiveType = GetMtlPrimitiveType(primitiveMode);
|
|
||||||
|
|
||||||
Renderer::INDEX_TYPE hostIndexType;
|
Renderer::INDEX_TYPE hostIndexType;
|
||||||
uint32 hostIndexCount;
|
uint32 hostIndexCount;
|
||||||
@ -503,21 +561,17 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
|
|||||||
uint32 indexBufferOffset = 0;
|
uint32 indexBufferOffset = 0;
|
||||||
uint32 indexBufferIndex = 0;
|
uint32 indexBufferIndex = 0;
|
||||||
LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMin, indexMax, hostIndexType, hostIndexCount, indexBufferOffset, indexBufferIndex);
|
LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMin, indexMax, hostIndexType, hostIndexCount, indexBufferOffset, indexBufferIndex);
|
||||||
*/
|
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
// TODO: uncomment
|
|
||||||
/*
|
|
||||||
if (hostIndexType != INDEX_TYPE::NONE)
|
if (hostIndexType != INDEX_TYPE::NONE)
|
||||||
{
|
{
|
||||||
auto mtlIndexType = GetMtlIndexType(hostIndexType);
|
auto mtlIndexType = GetMtlIndexType(hostIndexType);
|
||||||
// TODO: get index buffer
|
MTL::Buffer* indexBuffer = m_memoryManager->GetBuffer(indexBufferIndex);
|
||||||
m_renderCommandEncoder->drawIndexedPrimitives(mtlPrimitiveType, hostIndexCount, mtlIndexType, indexBuffer, 0, instanceCount, baseVertex, baseInstance);
|
m_renderCommandEncoder->drawIndexedPrimitives(mtlPrimitiveType, hostIndexCount, mtlIndexType, indexBuffer, 0, instanceCount, baseVertex, baseInstance);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
m_renderCommandEncoder->drawPrimitives(mtlPrimitiveType, baseVertex, count, instanceCount, baseInstance);
|
m_renderCommandEncoder->drawPrimitives(mtlPrimitiveType, baseVertex, count, instanceCount, baseInstance);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::draw_endSequence()
|
void MetalRenderer::draw_endSequence()
|
||||||
@ -527,9 +581,11 @@ void MetalRenderer::draw_endSequence()
|
|||||||
|
|
||||||
void* MetalRenderer::indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex)
|
void* MetalRenderer::indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex)
|
||||||
{
|
{
|
||||||
printf("MetalRenderer::indexData_reserveIndexMemory not implemented\n");
|
auto allocation = m_memoryManager->GetBufferAllocation(size);
|
||||||
|
offset = allocation.bufferOffset;
|
||||||
|
bufferIndex = allocation.bufferIndex;
|
||||||
|
|
||||||
return nullptr;
|
return allocation.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::indexData_uploadIndexMemory(uint32 offset, uint32 size)
|
void MetalRenderer::indexData_uploadIndexMemory(uint32 offset, uint32 size)
|
||||||
|
@ -7,8 +7,10 @@
|
|||||||
#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"
|
#include "Metal/MTLRenderCommandEncoder.hpp"
|
||||||
|
#include "Metal/MTLRenderPass.hpp"
|
||||||
|
|
||||||
#define MAX_MTL_BUFFERS 31
|
#define MAX_MTL_BUFFERS 31
|
||||||
|
#define GET_MTL_VERTEX_BUFFER_INDEX(index) (MAX_MTL_BUFFERS - index - 1)
|
||||||
|
|
||||||
struct MetalState
|
struct MetalState
|
||||||
{
|
{
|
||||||
@ -168,7 +170,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
CA::MetalLayer* m_metalLayer;
|
CA::MetalLayer* m_metalLayer;
|
||||||
|
|
||||||
MetalMemoryManager m_memoryManager;
|
MetalMemoryManager* m_memoryManager;
|
||||||
|
|
||||||
// Metal objects
|
// Metal objects
|
||||||
MTL::Device* m_device;
|
MTL::Device* m_device;
|
||||||
@ -186,7 +188,18 @@ private:
|
|||||||
{
|
{
|
||||||
if (!m_commandBuffer)
|
if (!m_commandBuffer)
|
||||||
{
|
{
|
||||||
|
// Debug
|
||||||
|
m_commandQueue->insertDebugCaptureBoundary();
|
||||||
|
|
||||||
m_commandBuffer = m_commandQueue->commandBuffer();
|
m_commandBuffer = m_commandQueue->commandBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void beginRenderPassIfNeeded(MTL::RenderPassDescriptor* renderPassDescriptor)
|
||||||
|
{
|
||||||
|
if (!m_renderCommandEncoder)
|
||||||
|
{
|
||||||
|
m_renderCommandEncoder = m_commandBuffer->renderCommandEncoder(renderPassDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
#include "Cemu/Logging/CemuLogging.h"
|
#include "Cemu/Logging/CemuLogging.h"
|
||||||
|
#include "Metal/MTLFunctionDescriptor.hpp"
|
||||||
|
|
||||||
RendererShaderMtl::RendererShaderMtl(MetalRenderer* mtlRenderer, ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& mslCode)
|
RendererShaderMtl::RendererShaderMtl(MetalRenderer* mtlRenderer, ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& mslCode)
|
||||||
: RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader)
|
: RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader)
|
||||||
@ -9,11 +10,20 @@ RendererShaderMtl::RendererShaderMtl(MetalRenderer* mtlRenderer, ShaderType type
|
|||||||
MTL::Library* library = mtlRenderer->GetDevice()->newLibrary(NS::String::string(mslCode.c_str(), NS::ASCIIStringEncoding), nullptr, &error);
|
MTL::Library* library = mtlRenderer->GetDevice()->newLibrary(NS::String::string(mslCode.c_str(), NS::ASCIIStringEncoding), nullptr, &error);
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
printf("Failed to create library (error: %s) -> source:\n%s", error->localizedDescription()->utf8String(), mslCode.c_str());
|
printf("Failed to create library (error: %s) -> source:\n%s\n", error->localizedDescription()->utf8String(), mslCode.c_str());
|
||||||
|
error->release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MTL::FunctionDescriptor* desc = MTL::FunctionDescriptor::alloc()->init();
|
||||||
|
desc->setName(NS::String::string("main0", NS::ASCIIStringEncoding));
|
||||||
|
error = nullptr;
|
||||||
|
m_function = library->newFunction(desc, &error);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
printf("Failed to create function (error: %s)\n", error->localizedDescription()->utf8String());
|
||||||
error->release();
|
error->release();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_function = library->newFunction(NS::String::string("main0", NS::ASCIIStringEncoding));
|
|
||||||
library->release();
|
library->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user