added forgotten file
This commit is contained in:
656
engine/ml_video.cpp
Normal file
656
engine/ml_video.cpp
Normal 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()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user