From f5b26be510fc7211f43ec8cb688fa6f086329eba Mon Sep 17 00:00:00 2001 From: kotofyt Date: Mon, 7 Jul 2025 19:40:18 +0300 Subject: [PATCH] added forgotten file --- engine/ml_video.cpp | 656 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 656 insertions(+) create mode 100644 engine/ml_video.cpp diff --git a/engine/ml_video.cpp b/engine/ml_video.cpp new file mode 100644 index 0000000..8531472 --- /dev/null +++ b/engine/ml_video.cpp @@ -0,0 +1,656 @@ +#include "Metal/Metal.hpp" +#include "math3d.h" +#include "filesystem.h" +#include "rendering.h" +#include "tier0/lib.h" +#include "tier1/utlvector.h" +#include "tier0/platform.h" +#include "rendering.h" +#include "ml_video.h" + +#define STB_IMAGE_IMPLEMENTATION +#if defined(__APPLE__) && defined(__MACH__) +#include "TargetConditionals.h" +#if TARGET_OS_IPHONE +// iOS +#define STBI_NO_THREAD_LOCALS +#else +// macOS +#endif +#else +// Other platforms +#endif +#include "stb_image.h" + +mat4 g_cameraView; +IImage *g_meshDepth; +IImage *g_meshDepthMSAA; +IImage *g_meshColor; +IImage *g_meshColorMSAA; + +CUtlVector g_textures; + +IBuffer *g_cameraProperties; +struct CameraProjection { + mat4 viewprojection; +}; + +CameraProjection *g_cameraDataMap; + +static MTL::RenderPassDescriptor *s_pRenderPass; +static MTL::RenderCommandEncoder *s_pEncoder; +static uint32_t s_nNumAttachments; + +CUtlVector g_destroyImageBuffer; +CUtlVector g_destroyBuffersBuffer; + +MTL::PixelFormat IRenderer_FormatToMl( EImageFormat format ) +{ + switch (format) + { + case IMAGE_FORMAT_R8G8B8A8: return MTL::PixelFormatRGBA8Unorm; + case IMAGE_FORMAT_R16G16B16A16: return MTL::PixelFormatRGBA16Unorm; + case IMAGE_FORMAT_DEPTH: return MTL::PixelFormatDepth32Float; + default: return MTL::PixelFormatRGBA8Unorm; + } +}; + +MTL::VertexFormat IRenderer_VertexToMl( EVertexFormat format ) +{ + switch (format) + { + case VERTEX_FORMAT_X16: return MTL::VertexFormatHalf; + case VERTEX_FORMAT_X16Y16: return MTL::VertexFormatHalf2; + case VERTEX_FORMAT_X16Y16Z16: return MTL::VertexFormatHalf3; + case VERTEX_FORMAT_X16Y16Z16W16: return MTL::VertexFormatHalf4; + case VERTEX_FORMAT_X32: return MTL::VertexFormatFloat; + case VERTEX_FORMAT_X32Y32: return MTL::VertexFormatFloat2; + case VERTEX_FORMAT_X32Y32Z32: return MTL::VertexFormatFloat3; + case VERTEX_FORMAT_X32Y32Z32W32: return MTL::VertexFormatFloat4; + default: return MTL::VertexFormatFloat3; + } +}; + +MTL::LoadAction IRenderer_LoadOpMl( EAttachmentLoadMode mode ) +{ + switch (mode) + { + case ATTACHMENT_LOAD_MODE_DONT_CARE: return MTL::LoadActionDontCare; + case ATTACHMENT_LOAD_MODE_CLEAR: return MTL::LoadActionClear; + case ATTACHMENT_LOAD_MODE_LOAD: return MTL::LoadActionLoad; + default: return MTL::LoadActionDontCare; + } +} + +MTL::StoreAction IRenderer_StoreOpMl( EAttachmentStoreMode mode ) +{ + switch (mode) + { + case ATTACHMENT_STORE_MODE_DONT_CARE: return MTL::StoreActionStore; + case ATTACHMENT_STORE_MODE_STORE: return MTL::StoreActionStore; + default: return MTL::StoreActionDontCare; + } +} + +class CMlBuffer: public IBuffer +{ +public: + void *Map() override; + void Unmap() override; + MTL::Buffer *m_buffer; + uint32_t m_nSize; +}; + + +class CMlImage: public IImage +{ +public: + MTL::Texture *m_image; +}; + + + +void *CMlBuffer::Map() +{ + return m_buffer->contents(); +} + +void CMlBuffer::Unmap() +{ + +} +struct MLShader_t { + EShaderType shaderType; + MTL::Library *library; + MTL::Function *function; + NS::String *szMain; +}; +class CMlGraphicsPipeline: public IGraphicsPipeline +{ +public: + CUtlVector m_shaders; + MTL::RenderPipelineState *m_pipeline; + CUtlVector m_inputs; + uint32_t m_nVertexSize; +}; + +class CMlTexture: public ITexture +{ +public: + MTL::Texture *m_texture; +}; + +IStorageBuffer *IRenderer::CreateStorageBuffer( uint32_t uSize ) +{ + CMlBuffer *pBuffer = new CMlBuffer; + pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared); + pBuffer->m_nSize = uSize; + return pBuffer; +} + +IUniformBuffer *IRenderer::CreateUniformBuffer( uint32_t uSize ) +{ + CMlBuffer *pBuffer = new CMlBuffer; + pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared); + pBuffer->m_nSize = uSize; + return pBuffer; +} + + +IVertexBuffer *IRenderer::CreateVertexBuffer( uint32_t uSize ) +{ + CMlBuffer *pBuffer = new CMlBuffer; + pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared); + pBuffer->m_nSize = uSize; + return pBuffer; +} + +IIndexBuffer *IRenderer::CreateIndexBuffer( uint32_t uSize ) +{ + CMlBuffer *pBuffer = new CMlBuffer; + pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared); + pBuffer->m_nSize = uSize; + return pBuffer; +} + + +IImage *IRenderer::CreateImage( EImageFormat format, uint32_t usage, uint32_t nWidth, uint32_t nHeight, uint32_t nSamples ) +{ + CMlImage *pImage = new CMlImage; + + MTL::TextureDescriptor *pCreateInfo = MTL::TextureDescriptor::alloc()->init(); + pCreateInfo->setPixelFormat(IRenderer_FormatToMl(format)); + pCreateInfo->setWidth(nWidth); + pCreateInfo->setHeight(nHeight); + + MTL::TextureUsage mlusage = 0; + if (usage&IMAGE_USAGE_COLOR_ATTACHMENT) mlusage |= MTL::TextureUsageRenderTarget; + if (usage&IMAGE_USAGE_DEPTH_ATTACHMENT) mlusage |= MTL::TextureUsageRenderTarget; + mlusage |= MTL::TextureUsageShaderRead; + mlusage |= MTL::TextureUsageShaderWrite; + pCreateInfo->setUsage(mlusage); + + pImage->m_image = g_mlDevice->newTexture(pCreateInfo); + + pCreateInfo->release(); + + return pImage; +}; + +void IRenderer::DestroyBuffer( IBuffer *pBuffer ) +{ + if (!pBuffer) + return; + CMlBuffer *pMlBuffer = (CMlBuffer*)pBuffer; + g_destroyBuffersBuffer.AppendTail(pMlBuffer->m_buffer); + delete (pMlBuffer); +} + +void IRenderer::DestroyImage( IImage *pImage ) +{ + if (!pImage) + return; + CMlImage *pMlImage = (CMlImage*)pImage; + g_destroyImageBuffer.AppendTail(pMlImage->m_image); + delete (pMlImage); +} + +IPipeline *g_pCurrentPipeline; + + +void IRenderer::SetConstants( uint32_t nSize, void *pData ) +{ + + if (!g_pCurrentPipeline) + return; + uint32_t nRoundedSize = nSize/8*8; + void *pTemporaryBuffer = V_malloc(nRoundedSize); + V_memcpy(pTemporaryBuffer, pData, nSize); + if (g_pCurrentPipeline->type == PIPELINE_TYPE_RASTERIZATION) + { + CMlGraphicsPipeline *pMlPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline; + s_pEncoder->setVertexBytes(pTemporaryBuffer, nRoundedSize, 29); + s_pEncoder->setFragmentBytes(pTemporaryBuffer, nRoundedSize, 29); + } + V_free(pTemporaryBuffer); +} + +void IRenderer::Barrier( uint32_t stageIn, uint32_t stageOut, CUtlVector buffers, CUtlVector images ) +{ + +} + +void IRenderer::BindData( uint32_t binding, IBuffer *pBuffer, IImage* pImage) +{ + if (!g_pCurrentPipeline) + return; + if (g_pCurrentPipeline->type == PIPELINE_TYPE_RASTERIZATION) + { + CMlBuffer *pMlBuffer = (CMlBuffer*)pBuffer; + CMlGraphicsPipeline *pMlPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline; + for (auto &input: pMlPipeline->m_inputs) + { + if (input.binding != binding) + continue; + + switch (input.type) + { + case SHADER_INPUT_TYPE_STORAGE_BUFFER: + case SHADER_INPUT_TYPE_UNIFORM_BUFFER: + if (!pBuffer) + Plat_FatalErrorFunc("pBuffer is NULL\n"); + s_pEncoder->setVertexBuffer(pMlBuffer->m_buffer, 0, binding); + s_pEncoder->setFragmentBuffer(pMlBuffer->m_buffer, 0, binding); + break; + case SHADER_INPUT_TYPE_IMAGE: + break; + case SHADER_INPUT_TYPE_TLAS: + break; + case SHADER_INPUT_TYPE_TEXTURES: + break; + }; + } + }; +} + + +void IRenderer::BindPipeline( IPipeline *pPipeline ) +{ + if (!pPipeline) + return; + if (pPipeline->type == PIPELINE_TYPE_RASTERIZATION) + { + CMlGraphicsPipeline *pVkPipeline = (CMlGraphicsPipeline*)pPipeline; + + s_pEncoder->setRenderPipelineState(pVkPipeline->m_pipeline); + } + g_pCurrentPipeline = pPipeline; +} + +void IRenderer::PushBindings() +{ + if (!g_pCurrentPipeline) + return; + if (g_pCurrentPipeline->type == PIPELINE_TYPE_RASTERIZATION) + { + CMlGraphicsPipeline *pPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline; + + MTL::ArgumentEncoder *argumentEncoder = 0; + for (auto &shader: pPipeline->m_shaders) + { + if (shader.shaderType == SHADER_TYPE_FRAGMENT) + { + argumentEncoder = shader.function->newArgumentEncoder(21); + break; + }; + } + MTL::Buffer *argumentBuffer = g_mlDevice->newBuffer(argumentEncoder->encodedLength(), MTL::ResourceStorageModeShared); + argumentEncoder->setArgumentBuffer(argumentBuffer, 0); + for ( uint32_t i = 0; i < g_textures.GetSize(); i++ ) + { + CMlTexture *texture = (CMlTexture*)g_textures[i]; + argumentEncoder->setTexture(texture->m_texture, i); + s_pEncoder->useResource(texture->m_texture, MTL::ResourceUsageRead); + } + s_pEncoder->useResource(argumentBuffer, MTL::ResourceUsageRead); + s_pEncoder->setFragmentBuffer(argumentBuffer, 0, 21); + g_destroyBuffersBuffer.AppendTail(argumentBuffer); + argumentEncoder->release(); + } +} + +void IRenderer::Begin( uint32_t nWidth, uint32_t nHeight, CUtlVector attachments, RenderingDepthAttachment_t depth ) +{ + s_pRenderPass = MTL::RenderPassDescriptor::alloc()->init(); + uint32_t i = 0; + for (auto &attachment: attachments) + { + CMlImage *pImage = (CMlImage*)attachment.pOutput; + CMlImage *pTemporary = (CMlImage*)attachment.pTemporary; + auto mlattachment = s_pRenderPass->colorAttachments()->object(i); + mlattachment->setTexture(pImage->m_image); + mlattachment->setLoadAction(IRenderer_LoadOpMl(attachment.loadMode)); + mlattachment->setStoreAction(IRenderer_StoreOpMl(attachment.storeMode)); + mlattachment->setClearColor(MTL::ClearColor(attachment.clearColor[0],attachment.clearColor[1],attachment.clearColor[2],attachment.clearColor[3])); + i++; + }; + if (depth.pOutput) + { + CMlImage *pImage = (CMlImage*)depth.pOutput; + CMlImage *pTemporary = (CMlImage*)depth.pTemporary; + s_pRenderPass->depthAttachment()->setClearDepth(depth.clearValue); + s_pRenderPass->depthAttachment()->setTexture(pImage->m_image); + s_pRenderPass->depthAttachment()->setLoadAction(IRenderer_LoadOpMl(depth.loadMode)); + s_pRenderPass->depthAttachment()->setStoreAction(IRenderer_StoreOpMl(depth.storeMode)); + } + + s_pEncoder = g_mlCommandBuffer->renderCommandEncoder(s_pRenderPass); + s_pEncoder->setCullMode(MTL::CullModeFront); +} + +void IRenderer::ResetState() +{ + +} + +void IRenderer::SetDepthMode( EDepthMode mode ) +{ + +} + +void IRenderer::Draw( IVertexBuffer *pVertex, IIndexBuffer *pIndex ) +{ + CMlBuffer *pMlVertex = (CMlBuffer*)pVertex; + CMlBuffer *pMlIndex = (CMlBuffer*)pIndex; + if (pMlIndex) + { + + } else { + MTL::DepthStencilDescriptor* depthStencilDesc = MTL::DepthStencilDescriptor::alloc()->init(); + depthStencilDesc->setDepthCompareFunction(MTL::CompareFunctionLess); + depthStencilDesc->setDepthWriteEnabled(true); + auto depthStencilState = g_mlDevice->newDepthStencilState(depthStencilDesc); + s_pEncoder->setDepthStencilState(depthStencilState); + + + CMlGraphicsPipeline *pPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline; + s_pEncoder->setVertexBuffer(pMlVertex->m_buffer, 0, 30); + s_pEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(pMlVertex->m_nSize/pPipeline->m_nVertexSize)); + } +} + +void IRenderer::End() +{ + s_pEncoder->endEncoding(); +} + +IBuffer *IRenderer::GetCameraMatrix() +{ + return g_cameraProperties; +} + +IImage *IRenderer::GetOutputImage() +{ +} + +IGraphicsPipeline *IRenderer::CreateGraphicsPipeline( + CUtlVector shaders, + CUtlVector inputs, + uint32_t nConstantsSize, + uint32_t nVertexSize, + CUtlVector vertexFormat, + CUtlVector outputFormats, + bool bDepth +) +{ + CMlGraphicsPipeline *pPipeline = new CMlGraphicsPipeline; + + + CUtlVector mlshaders; + MTL::RenderPipelineDescriptor *pCreateInfo = MTL::RenderPipelineDescriptor::alloc()->init(); + MTL::VertexDescriptor *vertexDescriptor = MTL::VertexDescriptor::alloc()->init(); + uint32_t i = 0; + for ( auto &vertex: vertexFormat ) + { + vertexDescriptor->attributes()->object(i)->setFormat(IRenderer_VertexToMl(vertex.format)); + vertexDescriptor->attributes()->object(i)->setOffset(vertex.offset); + vertexDescriptor->attributes()->object(i)->setBufferIndex(30); + i++; + } + vertexDescriptor->layouts()->object(30)->setStride(nVertexSize); + vertexDescriptor->layouts()->object(30)->setStepRate(1); + vertexDescriptor->layouts()->object(30)->setStepFunction(MTL::VertexStepFunctionPerVertex); + + NS::Error *error = NULL; + for ( auto &shader: shaders ) + { + MLShader_t mlshader = {}; + FileHandle_t f = IFileSystem::Open(shader.szPath, IFILE_READ); + if (!f) + Plat_FatalErrorFunc("Failed to open shader %s\n", shader.szPath.GetString()); + CUtlBuffer buffer(IFileSystem::Size(f)+1); + IFileSystem::Read(f, buffer.GetMemory(), buffer.GetSize()); + buffer[IFileSystem::Size(f)] = 0; + IFileSystem::Close(f); + NS::String *szSourceCode = NS::String::string((const char*)buffer.GetMemory(), NS::StringEncoding::UTF8StringEncoding); + MTL::CompileOptions *options = NULL; + mlshader.library = g_mlDevice->newLibrary(szSourceCode, options, &error); + if (error) + Plat_FatalErrorFunc("%s\n",error->localizedDescription()->utf8String()); + mlshader.szMain = NS::String::string("_main", NS::StringEncoding::UTF8StringEncoding); + mlshader.function = mlshader.library->newFunction(mlshader.szMain); + + if (shader.type == SHADER_TYPE_FRAGMENT) + pCreateInfo->setFragmentFunction(mlshader.function); + if (shader.type == SHADER_TYPE_VERTEX) + pCreateInfo->setVertexFunction(mlshader.function); + mlshader.shaderType = shader.type; + mlshaders.AppendTail(mlshader); + } + for ( i = 0; i < outputFormats.GetSize(); i++ ) + { + pCreateInfo->colorAttachments()->object(i)->setPixelFormat(IRenderer_FormatToMl(outputFormats[i])); + }; + if (bDepth) + pCreateInfo->setDepthAttachmentPixelFormat(MTL::PixelFormatDepth32Float); + pCreateInfo->setVertexDescriptor(vertexDescriptor); + pPipeline->type = PIPELINE_TYPE_RASTERIZATION; + pPipeline->m_pipeline = g_mlDevice->newRenderPipelineState(pCreateInfo, &error); + pPipeline->m_nVertexSize = nVertexSize; + pPipeline->m_inputs = inputs; + pPipeline->m_shaders = mlshaders; + if (error) + Plat_FatalErrorFunc("%s\n",error->localizedDescription()->utf8String()); + return pPipeline; +}; + +uint32_t ITextureManager::GetTextureID(ITexture *pTexture) +{ + uint32_t i = 0; + for (auto &t: g_textures) + { + if (pTexture == t) + return i; + i++; + } + return 0; +} + +ITexture *ITextureManager::LoadTexture( void *pData, uint32_t X, uint32_t Y, uint32_t numChannels ) +{ + CMlTexture *pTexture = new CMlTexture; + + MTL::TextureDescriptor *pCreateInfo = MTL::TextureDescriptor::alloc()->init(); + pCreateInfo->setPixelFormat(MTL::PixelFormatRGBA8Unorm_sRGB); + pCreateInfo->setWidth(X); + pCreateInfo->setHeight(Y); + pCreateInfo->setUsage(MTL::TextureUsageShaderRead); + + pTexture->m_texture = g_mlDevice->newTexture(pCreateInfo); + + MTL::Region region = MTL::Region(0, 0, 0, X, Y, 1); + NS::UInteger bytesPerRow = 4 * X; + + pTexture->m_texture->replaceRegion(region, 0, pData, bytesPerRow); + + pCreateInfo->release(); + + g_textures.AppendTail(pTexture); + + return pTexture; +}; + +ITexture *ITextureManager::LoadTexture( const char *szName ) +{ + for (ITexture *texture: g_textures) + { + if (!texture->szName) + continue; + if (!V_strcmp(texture->szName, szName)) + return texture; + }; + FileHandle_t file = IFileSystem::Open(szName, IFILE_READ); + if (!file) + Plat_FatalErrorFunc("Failed to load %s\n", szName); + + CUtlBuffer buffer(IFileSystem::Size(file)); + IFileSystem::Read(file, buffer.GetMemory(), buffer.GetSize()); + int nImageX; + int nImageY; + int nImageChannels; + stbi_uc *pixels = stbi_load_from_memory((stbi_uc*)buffer.GetMemory(), buffer.GetSize(), &nImageX, &nImageY, &nImageChannels, STBI_rgb_alpha); + ITexture *pTexture = ITextureManager::LoadTexture(pixels, nImageX, nImageY, 4); + pTexture->szName = szName; + return pTexture; +}; + +void IMetal::Init() +{ + char invalidTexture[1024] = {}; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + int index = i * 16 + j; + if ((i + j) % 2 == 0) { + invalidTexture[index*4] = 255; + } + } + } + g_cameraProperties = IRenderer::CreateUniformBuffer(sizeof(CameraProjection)); + g_cameraDataMap = (CameraProjection*)g_cameraProperties->Map(); + ITextureManager::LoadTexture(invalidTexture, 16, 16, 4); + + g_meshDepth = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, 1280, 720, 1); + g_meshDepthMSAA = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, 1280, 720, 4); + g_meshColor = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, 1280, 720, 1); + g_meshColorMSAA = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, 1280, 720, 4); + glm_mat4_identity(g_cameraView); +} + +static MTL::RenderPipelineState* s_fullScreenDraw; +void IMetal::CreatePipelines() +{ + for (auto &step: g_StepPrepass) + step.pPipeline->Init(); + for (auto &step: g_StepMeshRendering) + step.pPipeline->Init(); + for (auto &step: g_StepShading) + step.pPipeline->Init(); + for (auto &step: g_StepPostProcessing) + step.pPipeline->Init(); + for (auto &step: g_StepUI) + step.pPipeline->Init(); + + NS::Error *error = 0; + FileHandle_t f = IFileSystem::Open("gfx/ml_quad.metal", IFILE_READ); + CUtlBuffer buffer(IFileSystem::Size(f)+1); + IFileSystem::Read(f, buffer.GetMemory(), buffer.GetSize()); + buffer[IFileSystem::Size(f)] = 0; + IFileSystem::Close(f); + NS::String *szSourceCode = NS::String::string((const char*)buffer.GetMemory(), NS::StringEncoding::UTF8StringEncoding); + MTL::CompileOptions *options = NULL; + MTL::Library *library = g_mlDevice->newLibrary(szSourceCode, options, &error); + MTL::Function *vertexFunc = library->newFunction(NS::String::string("vertex_main", NS::UTF8StringEncoding)); + MTL::Function *fragmentFunc = library->newFunction(NS::String::string("fragment_main", NS::UTF8StringEncoding)); + + MTL::RenderPipelineDescriptor *pipelineDesc = MTL::RenderPipelineDescriptor::alloc()->init(); + pipelineDesc->setVertexFunction(vertexFunc); + pipelineDesc->setFragmentFunction(fragmentFunc); + pipelineDesc->colorAttachments()->object(0)->setPixelFormat(MTL::PixelFormatBGRA8Unorm); + + s_fullScreenDraw = g_mlDevice->newRenderPipelineState(pipelineDesc, &error); +} + +void IMetal::Frame() +{ + mat4 perspective; + glm_mat4_inv(g_cameraView, g_cameraDataMap->viewprojection); + glm_perspective(glm_rad(90),(float)g_nWindowWidth/g_nWindowHeight, 0.01, 100, perspective); + glm_rotate(perspective, glm_rad(90), (vec4){1,0,0,0}); + glm_scale(perspective, (vec4){1,-1,1,1}); + glm_rotate(perspective, glm_rad(90), (vec4){0,0,1,0}); + glm_scale(perspective, (vec4){1,1,-1,1}); + glm_mat4_mul(perspective,g_cameraDataMap->viewprojection,g_cameraDataMap->viewprojection); + + if (g_bConfigNotify) + { + IRenderer::DestroyImage(g_meshDepth); + IRenderer::DestroyImage(g_meshDepthMSAA); + IRenderer::DestroyImage(g_meshColor); + IRenderer::DestroyImage(g_meshColorMSAA); + g_meshDepth = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 1); + g_meshDepthMSAA = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 4); + g_meshColor = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 1); + g_meshColorMSAA = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 4); + } + + for (auto &step: g_StepPrepass) + step.pPipeline->Frame(0); + IRenderer::Begin(g_nWindowWidth, g_nWindowHeight, + { + { + g_meshColor, + 0, + ATTACHMENT_LOAD_MODE_CLEAR, + ATTACHMENT_STORE_MODE_STORE, + } + }, + { + g_meshDepth, + 0, + ATTACHMENT_LOAD_MODE_CLEAR, + ATTACHMENT_STORE_MODE_STORE, + 1, + }); + for (auto &step: g_StepMeshRendering) + step.pPipeline->Frame(0); + IRenderer::End(); + + CMlImage *pInImage = (CMlImage*)g_meshColor; + MTL::RenderPassDescriptor *renderPassDesc = MTL::RenderPassDescriptor::renderPassDescriptor(); + renderPassDesc->colorAttachments()->object(0)->setTexture(g_mlDrawableTexture); + renderPassDesc->colorAttachments()->object(0)->setLoadAction(MTL::LoadActionClear); + renderPassDesc->colorAttachments()->object(0)->setStoreAction(MTL::StoreActionStore); + renderPassDesc->colorAttachments()->object(0)->setClearColor(MTL::ClearColor(0.1, 0.1, 0.1, 1.0)); + + MTL::RenderCommandEncoder *encoder = g_mlCommandBuffer->renderCommandEncoder(renderPassDesc); + + encoder->setRenderPipelineState(s_fullScreenDraw); + encoder->setFragmentTexture(pInImage->m_image, 0); + + encoder->drawPrimitives(MTL::PrimitiveTypeTriangleStrip, NS::UInteger(0), NS::UInteger(4)); + + encoder->endEncoding(); + + for (auto &step: g_StepShading) + step.pPipeline->Frame(0); + for (auto &step: g_StepPostProcessing) + step.pPipeline->Frame(0); + for (auto &step: g_StepUI) + step.pPipeline->Frame(0); +} + +void IMetal::Deinit() +{ + +} +