added forgotten file

This commit is contained in:
2025-07-07 19:40:18 +03:00
parent 83bc9b7f16
commit f5b26be510

656
engine/ml_video.cpp Normal file
View File

@@ -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<ITexture*> 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<MTL::Texture*> g_destroyImageBuffer;
CUtlVector<MTL::Buffer*> 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<MLShader_t> m_shaders;
MTL::RenderPipelineState *m_pipeline;
CUtlVector<ShaderInput_t> 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<BufferBarrier_t> buffers, CUtlVector<ImageBarrier_t> 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<RenderingColorAttachment_t> 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<Shader_t> shaders,
CUtlVector<ShaderInput_t> inputs,
uint32_t nConstantsSize,
uint32_t nVertexSize,
CUtlVector<VertexAttribute_t> vertexFormat,
CUtlVector<EImageFormat> outputFormats,
bool bDepth
)
{
CMlGraphicsPipeline *pPipeline = new CMlGraphicsPipeline;
CUtlVector<MLShader_t> 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<uint8_t> 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<stbi_uc> 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<uint8_t> 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()
{
}