diff --git a/.github/workflows/macosx.yml b/.github/workflows/macosx.yml index ac0c43c..6ebde1a 100644 --- a/.github/workflows/macosx.yml +++ b/.github/workflows/macosx.yml @@ -23,7 +23,7 @@ jobs: fail-fast: false matrix: prj: [ BlankApp, HelloTriangle, SpinningCube, ModelLoading ] - rhi: [ metal, opengl ] # TODO: Add vulkan + rhi: [ metal ] # TODO: Add vulkan steps: - name: Get current date as package key diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index d93327d..1806af9 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -47,17 +47,12 @@ jobs: - name: Update xmake repository run: xmake repo --update - - name: Retrieve dependencies hash - id: dep_hash - run: echo "hash=$(xmake l utils.ci.packageskey)" >> $GITHUB_ENV - shell: bash - - name: Restore cached xmake dependencies id: restore-depcache uses: actions/cache/restore@v4 with: path: ${{ env.XMAKE_GLOBALDIR }}/.xmake/packages - key: ${{ matrix.rhi }}-${{ matrix.prj }}-${{ env.hash }}-W${{ env.key }} + key: ${{ matrix.rhi }}-${{ matrix.prj }}-W${{ env.key }} - name: Check xmake packages directory exists shell: bash diff --git a/Core/Graphics/Buffer.h b/Core/Graphics/Buffer.h index 7b3fb4c..ec48072 100644 --- a/Core/Graphics/Buffer.h +++ b/Core/Graphics/Buffer.h @@ -2,6 +2,7 @@ #include #include +#include #if defined(CGL_RHI_DX11) #include diff --git a/Core/Graphics/RHI/Metal/METALIndexBuffer.h b/Core/Graphics/RHI/Metal/METALIndexBuffer.h index 532c582..33e4a36 100644 --- a/Core/Graphics/RHI/Metal/METALIndexBuffer.h +++ b/Core/Graphics/RHI/Metal/METALIndexBuffer.h @@ -2,14 +2,15 @@ #include "Foundation/NSTypes.hpp" #include "Metal/MTLBuffer.hpp" +#include "Metal/MTLStageInputOutputDescriptor.hpp" namespace CGL::Graphics { struct METALIndexBuffer { MTL::Buffer* Buffer; + MTL::IndexType Format; - NS::UInteger Offset; - NS::UInteger Index; + NS::UInteger IndicesCount; }; } diff --git a/Core/Graphics/RHI/Metal/METALPipelineHandler.cpp b/Core/Graphics/RHI/Metal/METALPipelineHandler.cpp index 81c7472..cf0d145 100644 --- a/Core/Graphics/RHI/Metal/METALPipelineHandler.cpp +++ b/Core/Graphics/RHI/Metal/METALPipelineHandler.cpp @@ -23,14 +23,27 @@ namespace CGL::Graphics { m_rpState = gpu_device->newRenderPipelineState(m_rpDescriptor, &ns_error); - if(!m_rpState) - { + if(!m_rpState) + { CGL_LOG(METALPipelineHandler, Error, ns_error->localizedDescription()->utf8String()); return; } CGL_LOG(METALPipelineHandler, Info, "RenderPipelineState Created"); + + MTL::DepthStencilDescriptor* depthStencilDescriptor = MTL::DepthStencilDescriptor::alloc()->init(); + + depthStencilDescriptor->setDepthWriteEnabled(true); + depthStencilDescriptor->setDepthCompareFunction(MTL::CompareFunction::CompareFunctionAlways); + + this->m_depthStencilState = gpu_device->newDepthStencilState(depthStencilDescriptor); + + CGL_LOG(METALPipelineHandler, Info, "DepthStencilState Created"); + m_rpDescriptor->release(); m_rpDescriptor = nullptr; + + depthStencilDescriptor->release(); + depthStencilDescriptor = nullptr; } } diff --git a/Core/Graphics/RHI/Metal/METALPipelineHandler.h b/Core/Graphics/RHI/Metal/METALPipelineHandler.h index cc43864..f5c43c9 100644 --- a/Core/Graphics/RHI/Metal/METALPipelineHandler.h +++ b/Core/Graphics/RHI/Metal/METALPipelineHandler.h @@ -3,7 +3,8 @@ #include "Metal/MTLDevice.hpp" #include "Metal/MTLRenderPipeline.hpp" -#include "Core/Logging/Log.h" +#include +#include namespace CGL::Graphics { @@ -17,10 +18,18 @@ namespace CGL::Graphics inline MTL::RenderPipelineDescriptor* GetRenderPipelineDescriptor() const { return m_rpDescriptor; } inline MTL::RenderPipelineState* GetRenderPipelineState() const { return m_rpState; } - void CreateRenderPipelineState(MTL::Device* gpu_device); + inline MTL::DepthStencilState* GetDepthStencilState() const { return m_depthStencilState; } + + inline void SetIndexBuffer(IndexBuffer* indexBuffer) { m_indexBuffer = indexBuffer; } + inline METALIndexBuffer* GetIndexBuffer() const { return m_indexBuffer; } + void CreateRenderPipelineState(MTL::Device* gpu_device); private: MTL::RenderPipelineDescriptor* m_rpDescriptor; MTL::RenderPipelineState* m_rpState; + + MTL::DepthStencilState* m_depthStencilState; + + METALIndexBuffer* m_indexBuffer; }; } diff --git a/Core/Graphics/RHI/Metal/METALRenderer.cpp b/Core/Graphics/RHI/Metal/METALRenderer.cpp index da0d10c..a573f7d 100644 --- a/Core/Graphics/RHI/Metal/METALRenderer.cpp +++ b/Core/Graphics/RHI/Metal/METALRenderer.cpp @@ -58,7 +58,14 @@ namespace CGL::Graphics void Renderer::SetRenderPipeline_METAL() { GetImpl()->GetRenderPipelineHandler()->CreateRenderPipelineState(GetImpl()->GetDevice()); - GetImpl()->GetRenderCommandEncoder()->setRenderPipelineState(GetImpl()->GetRenderPipelineHandler()->GetRenderPipelineState()); + + const auto& rCommandEncoder = GetImpl()->GetRenderCommandEncoder(); + + rCommandEncoder->setFrontFacingWinding(MTL::WindingClockwise); + rCommandEncoder->setCullMode(MTL::CullModeBack); + rCommandEncoder->setTriangleFillMode(MTL::TriangleFillMode::TriangleFillModeFill); + rCommandEncoder->setRenderPipelineState(GetImpl()->GetRenderPipelineHandler()->GetRenderPipelineState()); + rCommandEncoder->setDepthStencilState(GetImpl()->GetRenderPipelineHandler()->GetDepthStencilState()); } void Renderer::SetPrimitiveTopology_METAL(PrimitiveType topology) @@ -99,9 +106,19 @@ namespace CGL::Graphics void Renderer::SetIndexBuffer_METAL(const IndexBuffer& buffer) { - // TODO: implement index buffer + GetImpl()->GetRenderPipelineHandler()->SetIndexBuffer(&const_cast(buffer)); } + void Renderer::SetConstantBufferData_METAL(const MTL::Buffer* buffer, const void* data, size_t size) + { + memcpy(const_cast(buffer)->contents(), data, size); + } + + void Renderer::SetConstantBuffer_METAL([[maybe_unused]] ShaderType type, [[maybe_unused]] u32 startSlot, const MTL::Buffer* buffer) + { + GetImpl()->GetRenderCommandEncoder()->setVertexBuffer(buffer, 0, 1); + } + ShaderCompileResult Renderer::CompileVertexShader_METAL(const ShaderSource& source, VertexShader* outShader) { assert(GetImpl() && GetImpl()->GetDevice() && outShader); @@ -168,7 +185,20 @@ namespace CGL::Graphics IndexBuffer Renderer::CreateIndexBuffer_METAL(const BufferSource& source) { - // TODO: implement Index Buffer + assert(GetImpl() && GetImpl()->GetDevice()); + + const u32 sourceSZ = source.TypeSize * source.Count; + + return IndexBuffer { + .Buffer = GetImpl()->GetDevice()->newBuffer(source.Data, sourceSZ, MTL::ResourceStorageModeShared), + .Format = (source.TypeSize == sizeof(u16) ? MTL::IndexTypeUInt16 : MTL::IndexTypeUInt32), + .IndicesCount = source.Count + }; + } + + void Renderer::CreateConstantBuffer_METAL(const BufferSource& source, MTL::Buffer** outBuffer) + { + *outBuffer = GetImpl()->GetDevice()->newBuffer(source.TypeSize, MTL::ResourceStorageModeShared); } void Renderer::Draw_METAL(u32 vertexCount, u32 startVertex) @@ -178,8 +208,12 @@ namespace CGL::Graphics ); } - void Renderer::DrawIndexed_METAL(u32 indexCount, u32 startIndex, u32 baseVertex) + void Renderer::DrawIndexed_METAL(u32 indexCount, [[maybe_unused]] u32 startIndex, [[maybe_unused]] u32 baseVertex) { - // TODO: implement indexed drawcall + const METALIndexBuffer* IndexBuffer = GetImpl()->GetRenderPipelineHandler()->GetIndexBuffer(); + + GetImpl()->GetRenderCommandEncoder()->drawIndexedPrimitives( + GetImpl()->GetPrimitiveType(), indexCount, IndexBuffer->Format, IndexBuffer->Buffer, 0 + ); } } diff --git a/Core/Graphics/Renderer.h b/Core/Graphics/Renderer.h index 038a8d4..97a9695 100644 --- a/Core/Graphics/Renderer.h +++ b/Core/Graphics/Renderer.h @@ -121,6 +121,9 @@ namespace CGL::Graphics ShaderCompileResult CompilePixelShader_METAL(const ShaderSource& source, PixelShader* outShader); VertexBuffer CreateVertexBuffer_METAL(const BufferSource& source); IndexBuffer CreateIndexBuffer_METAL(const BufferSource& source); + void CreateConstantBuffer_METAL(const BufferSource& source, MTL::Buffer** outBuffer); + void SetConstantBufferData_METAL(const MTL::Buffer* buffer, const void* data, size_t size); + void SetConstantBuffer_METAL(ShaderType type, u32 startSlot, const MTL::Buffer* buffer); void Draw_METAL(u32 vertexCount, u32 startVertex = 0); void DrawIndexed_METAL(u32 indexCount, u32 startIndex = 0, u32 baseVertex = 0); METALRendererImpl* GetImpl() const; diff --git a/Core/Graphics/Renderer.inl b/Core/Graphics/Renderer.inl index e1c9d8f..320af92 100644 --- a/Core/Graphics/Renderer.inl +++ b/Core/Graphics/Renderer.inl @@ -2,32 +2,38 @@ namespace CGL::Graphics { - template + template void Renderer::CreateContantBuffer(const BufferSource& source, ConstantBuffer& outBuffer) { #if defined(CGL_RHI_DX11) CreateContantBuffer_D3D11(source, outBuffer.Buffer); #elif defined(CGL_RHI_OPENGL) CreateConstantBuffer_OPENGL(source, outBuffer.Buffer); +#elif defined(CGL_RHI_METAL) + CreateConstantBuffer_METAL(source, &outBuffer.Buffer); #endif } - template + template void Renderer::SetConstantBufferData(const ConstantBuffer& buffer, const T& data) { #if defined(CGL_RHI_DX11) SetConstantBufferData_D3D11(buffer.Buffer.Get(), static_cast(&data), sizeof(T)); #elif defined(CGL_RHI_OPENGL) - SetConstantBufferData_OPENGL(buffer.Buffer, static_cast(&data), sizeof(T)); -#endif + SetConstantBufferData_OPENGL(buffer.Buffer, static_cast(&data), sizeof(T)); +#elif defined(CGL_RHI_METAL) + SetConstantBufferData_METAL(buffer.Buffer, static_cast(&data), sizeof(T)); +#endif } - template + template void Renderer::SetConstantBuffer(ShaderType shaderType, u32 startSlot, const ConstantBuffer& buffer) { #if defined(CGL_RHI_DX11) SetContantBuffer_D3D11(shaderType, startSlot, buffer.Buffer); #elif defined(CGL_RHI_OPENGL) SetConstantBuffer_OPENGL(shaderType, startSlot, buffer.Buffer); -#endif +#elif defined(CGL_RHI_METAL) + SetConstantBuffer_METAL(shaderType, startSlot, buffer.Buffer); +#endif } -} \ No newline at end of file +} diff --git a/Samples/SpinningCube/Assets/Metal/SpinningCubePS.metal b/Samples/SpinningCube/Assets/Metal/SpinningCubePS.metal new file mode 100644 index 0000000..1db96a7 --- /dev/null +++ b/Samples/SpinningCube/Assets/Metal/SpinningCubePS.metal @@ -0,0 +1,12 @@ +#include +using namespace metal; + +struct VertexOut { + float4 position [[position]]; + float4 color; +}; + +fragment float4 SpinningCubePS(VertexOut in [[stage_in]]) +{ + return in.color; +} diff --git a/Samples/SpinningCube/Assets/Metal/SpinningCubeVS.metal b/Samples/SpinningCube/Assets/Metal/SpinningCubeVS.metal new file mode 100644 index 0000000..c481b6d --- /dev/null +++ b/Samples/SpinningCube/Assets/Metal/SpinningCubeVS.metal @@ -0,0 +1,30 @@ +#include +using namespace metal; + +struct TransformationData +{ + float4x4 modelMatrix; + float4x4 viewMatrix; + float4x4 perspectiveMatrix; +}; + +struct VertexOut +{ + float4 position [[position]]; + float4 color; +}; + +vertex VertexOut SpinningCubeVS(uint vertexID [[vertex_id]], constant VertexOut* vertexData, constant TransformationData* transformationData) +{ + VertexOut out; + + float4 vertexPosition = vertexData[vertexID].position; + + float4x4 ModelView = transformationData->viewMatrix * transformationData->modelMatrix; + float4x4 ModelViewProjection = transformationData->perspectiveMatrix * ModelView; + + out.position = ModelViewProjection * vertexPosition; + out.color = vertexData[vertexID].color; + + return out; +} diff --git a/Samples/SpinningCube/SpinningCube.cpp b/Samples/SpinningCube/SpinningCube.cpp index 2d92de7..1e713b5 100644 --- a/Samples/SpinningCube/SpinningCube.cpp +++ b/Samples/SpinningCube/SpinningCube.cpp @@ -1,7 +1,7 @@ #include "SpinningCube.h" #include -#if defined(CGL_RHI_OPENGL) || defined(CGL_RHI_VULKAN) +#if defined(CGL_RHI_OPENGL) || defined(CGL_RHI_VULKAN) || defined(CGL_RHI_METAL) #define CGL_UPLOAD_MATRIX(mat) mat #else #define CGL_UPLOAD_MATRIX(mat) mat.Transpose()