diff --git a/MetalLearning/MetalLearning.xcodeproj/project.pbxproj b/MetalLearning/MetalLearning.xcodeproj/project.pbxproj index 590f1ee..ec537ba 100644 --- a/MetalLearning/MetalLearning.xcodeproj/project.pbxproj +++ b/MetalLearning/MetalLearning.xcodeproj/project.pbxproj @@ -10,8 +10,13 @@ 1817955824A247CA9F871398 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA5C1300C9792D32A5828940 /* CoreFoundation.framework */; }; 1EA5B05892FFF54A10E37E98 /* LayerStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD1D7500EF4751B223383B40 /* LayerStack.cpp */; }; 40821283ADAA20F5AF3D10C3 /* Sandbox.mm in Sources */ = {isa = PBXBuildFile; fileRef = DB139FCB287695FD9E95960B /* Sandbox.mm */; }; + 470E4F862E92E62C0001CB6D /* MTKViewDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 470E4F852E92E62C0001CB6D /* MTKViewDelegate.mm */; }; 471F408B2E9048F700A39495 /* Shader.metal in Sources */ = {isa = PBXBuildFile; fileRef = 0EC3D68640BD2138BA9C5CC6 /* Shader.metal */; }; + 472151D42E953F6D00E52696 /* VertexArray.mm in Sources */ = {isa = PBXBuildFile; fileRef = 472151D32E953F6D00E52696 /* VertexArray.mm */; }; 475DDCC62E8D968900D66434 /* ImGuiLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 475DDCC52E8D968900D66434 /* ImGuiLayer.mm */; }; + 479A9D0A2E93ED400019F59F /* Buffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 479A9D092E93ED400019F59F /* Buffer.mm */; }; + 479A9D0D2E942C4E0019F59F /* IndexBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 479A9D0C2E942C4E0019F59F /* IndexBuffer.mm */; }; + 479A9D102E942CBD0019F59F /* VertexBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 479A9D0F2E942CBD0019F59F /* VertexBuffer.mm */; }; 47A97AAA2E8EB34B00293FA8 /* Renderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 47A97AA92E8EB34B00293FA8 /* Renderer.mm */; }; 47A97AAE2E8EDBAD00293FA8 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 47A97AAD2E8EDBAD00293FA8 /* ViewController.mm */; }; 47F2B42A2E918103005D0A7A /* Shader.mm in Sources */ = {isa = PBXBuildFile; fileRef = 47F2B4292E918103005D0A7A /* Shader.mm */; }; @@ -78,8 +83,18 @@ 28A2B695BB308087240924D5 /* MacWindow.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objc; name = MacWindow.mm; path = src/MEL/Window/MacWindow.mm; sourceTree = ""; }; 333B5CED59618C9FC068832D /* Log.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Log.h; path = src/MEL/Log/Log.h; sourceTree = ""; }; 38BBC2DB812CA70DC5CB791B /* MetalLearning.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MetalLearning.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 470E4F842E92E62C0001CB6D /* MTKViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MTKViewDelegate.h; path = src/MEL/Renderer/MTKViewDelegate.h; sourceTree = ""; }; + 470E4F852E92E62C0001CB6D /* MTKViewDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MTKViewDelegate.mm; path = src/MEL/Renderer/MTKViewDelegate.mm; sourceTree = ""; }; + 472151D22E953F6D00E52696 /* VertexArray.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VertexArray.h; sourceTree = ""; }; + 472151D32E953F6D00E52696 /* VertexArray.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = VertexArray.mm; sourceTree = ""; }; 475DDCC42E8D968900D66434 /* ImGuiLayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImGuiLayer.h; sourceTree = ""; }; 475DDCC52E8D968900D66434 /* ImGuiLayer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ImGuiLayer.mm; sourceTree = ""; }; + 479A9D082E93ED400019F59F /* Buffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Buffer.h; sourceTree = ""; }; + 479A9D092E93ED400019F59F /* Buffer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Buffer.mm; sourceTree = ""; }; + 479A9D0B2E942C4E0019F59F /* IndexBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IndexBuffer.h; sourceTree = ""; }; + 479A9D0C2E942C4E0019F59F /* IndexBuffer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = IndexBuffer.mm; sourceTree = ""; }; + 479A9D0E2E942CBD0019F59F /* VertexBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VertexBuffer.h; sourceTree = ""; }; + 479A9D0F2E942CBD0019F59F /* VertexBuffer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = VertexBuffer.mm; sourceTree = ""; }; 47A97AA82E8EB31500293FA8 /* Renderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Renderer.h; path = src/MEL/Renderer/Renderer.h; sourceTree = ""; }; 47A97AA92E8EB34B00293FA8 /* Renderer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = Renderer.mm; path = src/MEL/Renderer/Renderer.mm; sourceTree = ""; }; 47A97AAC2E8EDBAD00293FA8 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; @@ -155,6 +170,8 @@ 2C8FAEDB7CA3438DFF21751B /* MEL */ = { isa = PBXGroup; children = ( + 472151D12E953F5900E52696 /* VertexArray */, + 479A9D072E93ED2A0019F59F /* Buffer */, 47F2B4272E9180E3005D0A7A /* Shader */, 7B436A80AD3CB532271BF0C0 /* Application.h */, 6038CC64F5AF8B96644BE2A4 /* Application.mm */, @@ -188,6 +205,16 @@ name = backends; sourceTree = ""; }; + 472151D12E953F5900E52696 /* VertexArray */ = { + isa = PBXGroup; + children = ( + 472151D22E953F6D00E52696 /* VertexArray.h */, + 472151D32E953F6D00E52696 /* VertexArray.mm */, + ); + name = VertexArray; + path = src/MEL/VertexArray; + sourceTree = ""; + }; 475DDCC32E8D966F00D66434 /* ImGuiLayer */ = { isa = PBXGroup; children = ( @@ -198,6 +225,20 @@ path = src/MEL/ImGuiLayer; sourceTree = ""; }; + 479A9D072E93ED2A0019F59F /* Buffer */ = { + isa = PBXGroup; + children = ( + 479A9D082E93ED400019F59F /* Buffer.h */, + 479A9D092E93ED400019F59F /* Buffer.mm */, + 479A9D0B2E942C4E0019F59F /* IndexBuffer.h */, + 479A9D0C2E942C4E0019F59F /* IndexBuffer.mm */, + 479A9D0E2E942CBD0019F59F /* VertexBuffer.h */, + 479A9D0F2E942CBD0019F59F /* VertexBuffer.mm */, + ); + name = Buffer; + path = src/MEL/Buffer; + sourceTree = ""; + }; 47A97AAB2E8EDB8A00293FA8 /* ViewController */ = { isa = PBXGroup; children = ( @@ -293,6 +334,8 @@ 6188BCBA2816B42C9618DAFA /* AppDelegate.mm */, 47A97AA82E8EB31500293FA8 /* Renderer.h */, 47A97AA92E8EB34B00293FA8 /* Renderer.mm */, + 470E4F842E92E62C0001CB6D /* MTKViewDelegate.h */, + 470E4F852E92E62C0001CB6D /* MTKViewDelegate.mm */, ); name = Renderer; sourceTree = ""; @@ -432,6 +475,7 @@ buildActionMask = 2147483647; files = ( 471F408B2E9048F700A39495 /* Shader.metal in Sources */, + 472151D42E953F6D00E52696 /* VertexArray.mm in Sources */, CE38F4BC94C6EC2E02C912FC /* Application.mm in Sources */, CA73010C21D873FED3E68F4C /* Entrypoint.mm in Sources */, 969729155D252087CB274755 /* MacInput.mm in Sources */, @@ -444,7 +488,11 @@ 47F2B42A2E918103005D0A7A /* Shader.mm in Sources */, 70B86CF5705B5027AAB00335 /* CocoaWindow.mm in Sources */, BC2CC98D9B49E3BF77533FCD /* MacWindow.mm in Sources */, + 479A9D0A2E93ED400019F59F /* Buffer.mm in Sources */, + 470E4F862E92E62C0001CB6D /* MTKViewDelegate.mm in Sources */, + 479A9D102E942CBD0019F59F /* VertexBuffer.mm in Sources */, 40821283ADAA20F5AF3D10C3 /* Sandbox.mm in Sources */, + 479A9D0D2E942C4E0019F59F /* IndexBuffer.mm in Sources */, B24E4279E3323A6BF64A70B9 /* melpch.mm in Sources */, 93CEE37D2C46D0EF582DC1BD /* imgui_impl_metal.mm in Sources */, FF1219CB5B991E3DE43BD80B /* imgui_impl_osx.mm in Sources */, diff --git a/MetalLearning/MetalLearning.xcodeproj/xcuserdata/xudianhuan.xcuserdatad/xcschemes/xcschememanagement.plist b/MetalLearning/MetalLearning.xcodeproj/xcuserdata/xudianhuan.xcuserdatad/xcschemes/xcschememanagement.plist index 0fb8bdc..d23cc99 100644 --- a/MetalLearning/MetalLearning.xcodeproj/xcuserdata/xudianhuan.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/MetalLearning/MetalLearning.xcodeproj/xcuserdata/xudianhuan.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,7 +7,7 @@ MetalLearning.xcscheme_^#shared#^_ orderHint - 0 + 1 diff --git a/MetalLearning/ShaderSrc/Shader.metal b/MetalLearning/ShaderSrc/Shader.metal index 90b0f53..fff6fb0 100644 --- a/MetalLearning/ShaderSrc/Shader.metal +++ b/MetalLearning/ShaderSrc/Shader.metal @@ -1,27 +1,20 @@ #include using namespace metal; +struct VertexIn { + float3 position [[attribute(0)]]; + float3 color [[attribute(1)]]; +}; + struct VertexOut{ float4 position [[position]]; float4 color; }; -vertex VertexOut vertexShader(uint vertexID [[vertex_id]]){ - float2 positions[3]={ - float2(0.0,0.5), - float2(-0.5,-0.5), - float2(0.5,-0.5) - }; - - float4 colors[3]={ - float4(1.0,0.0,0.0,1.0), - float4(0.0,1.0,0.0,1.0), - float4(0.0,0.0,1.0,1.0) - }; - +vertex VertexOut vertexShader(const VertexIn in [[stage_in]]){ VertexOut out; - out.position=float4(positions[vertexID],0.0,1.0); - out.color=colors[vertexID]; + out.position=float4(in.position,1.0); + out.color=float4(in.color,1.0); return out; } diff --git a/MetalLearning/src/MEL/Application.h b/MetalLearning/src/MEL/Application.h index f2a2948..16baa92 100644 --- a/MetalLearning/src/MEL/Application.h +++ b/MetalLearning/src/MEL/Application.h @@ -4,10 +4,13 @@ #include "Events/ApplicationEvent.h" #include "Layer/LayerStack.h" #include "ImGuiLayer/ImGuiLayer.h" - +#include "Shader/Shader.h" +#include "MTKViewDelegate.h" namespace MEL{ class Window; class Renderer; + class Shader; + class VertexArray; } namespace MEL { class Application{ @@ -25,14 +28,22 @@ namespace MEL { inline Renderer* GetRenderer(){return m_Renderer;} private: bool OnWindowClose(WindowCloseEvent& event); + public: + //Metal unique render + void RenderOneFrame(); private: std::unique_ptr m_Window; + + MELMTKViewDelegate* m_ViewDelegate; Renderer* m_Renderer; ImGuiLayer* m_ImGuiLayer; bool m_Running=true; LayerStack m_LayerStack; + std::shared_ptr m_CurrentShader; static Application* s_Instance; + + std::shared_ptr m_VertexArray; }; Application* CreateApplication(); } diff --git a/MetalLearning/src/MEL/Application.mm b/MetalLearning/src/MEL/Application.mm index a7c581f..7badd1c 100644 --- a/MetalLearning/src/MEL/Application.mm +++ b/MetalLearning/src/MEL/Application.mm @@ -3,6 +3,10 @@ #include "Application.h" #include "MacWindow.h" +#import "Buffer/VertexBuffer.h" +#import "Buffer/IndexBuffer.h" +#import "VertexArray/VertexArray.h" + namespace MEL{ Application* Application::s_Instance=nullptr; @@ -10,11 +14,46 @@ namespace MEL{ s_Instance=this; m_Window=std::unique_ptr(Window::Create()); m_Window->SetEventCallback(MEL_BIND_EVENT_FN(Application::OnEvent)); - + //Get Renderer first auto* macWindow=static_cast(m_Window.get()); m_Renderer=macWindow->GetRenderer(); + //then push imgui layer m_ImGuiLayer=new ImGuiLayer(); PushOverlay(m_ImGuiLayer); + //create vertex array + m_VertexArray=MEL::VertexArray::Create(); + //set vertex and index buffer + + float vertices[]={ + -0.5f,-0.5f,0.0f, + 0.4f,0.2f,0.4f, + + 0.5f,-0.5f,0.0f, + 0.1f,0.7f,0.1f, + + 0.0f,0.5f,0.0f, + 0.1f,0.3f,0.4f + }; + + uint32_t indices[]={0,1,2}; + + auto basicVB=VertexBuffer::Create(vertices, sizeof(vertices)); + auto basicIB=IndexBuffer::Create(indices, 3); + basicVB->SetSlot(0); + + m_VertexArray->AddVertexBuffer(basicVB); + m_VertexArray->SetIndexBuffer(basicIB); + + //create shader(this can be done in sandbox) + auto defaultShader=MEL::Shader::CreateFromDefaultLibrary("DefaultShader", + @"vertexShader",@"fragmentShader"); + if(defaultShader) + defaultShader->CreatePipelineState(); + m_CurrentShader=defaultShader; + + //initialize layers + for(Layer* layer:m_LayerStack) + layer->OnAttach(); } Application::~Application(){ @@ -44,8 +83,15 @@ namespace MEL{ NSApplication* application=[NSApplication sharedApplication]; AppDelegate* appDelegate=[[AppDelegate alloc] init]; [application setDelegate:appDelegate]; + + MTKView* mtkView=m_Renderer->GetMTKView(); + + m_ViewDelegate=[[MELMTKViewDelegate alloc] initWithApplication:this]; + [mtkView setDelegate:m_ViewDelegate]; + [application finishLaunching]; [application activateIgnoringOtherApps:YES]; + while (m_Running){ @autoreleasepool { NSEvent* event; @@ -56,33 +102,12 @@ namespace MEL{ [application sendEvent:event]; } - if(m_Renderer){ - m_Renderer->BeginFrame(); - m_Renderer->BeginScene(); - m_Renderer->CreatePipelineState(); - m_ImGuiLayer->Begin(); - - m_Renderer->DrawIndexed(3); - for(Layer* layer:m_LayerStack) - layer->OnUpdate(); - - for (Layer* layer :m_LayerStack) - layer->OnImGuiRender(); - - m_ImGuiLayer->End(); - - - - m_Renderer->EndScene(); - m_Renderer->EndFrame(); - } - - m_Window->OnUpdate(); + [NSThread sleepForTimeInterval:0.001]; - [NSThread sleepForTimeInterval:0.016]; m_Window->Show(); } } + [m_ViewDelegate release]; [application stop:nil]; } @@ -96,4 +121,36 @@ namespace MEL{ overlay->OnAttach(); } + void Application::RenderOneFrame(){ + if(m_Renderer){ + //begin frame(command buffer) + m_Renderer->BeginFrame(); + //begin scene(pipeline desc,encoder,with sets) + m_Renderer->BeginScene(); + //ImGui UI frame begin + m_ImGuiLayer->Begin(); + //upper three must call + + if(m_CurrentShader&&m_VertexArray){ + m_CurrentShader->Bind(); + m_Renderer->DrawIndexed(m_VertexArray); + } + + //layers + for(Layer* layer:m_LayerStack) + layer->OnUpdate(); + + //ImGui draw + for (Layer* layer :m_LayerStack) + layer->OnImGuiRender(); + + //end ImGui + m_ImGuiLayer->End(); + //end scene + m_Renderer->EndScene(); + //end frame + m_Renderer->EndFrame(); + } + } + } diff --git a/MetalLearning/src/MEL/Buffer/Buffer.h b/MetalLearning/src/MEL/Buffer/Buffer.h new file mode 100644 index 0000000..993d011 --- /dev/null +++ b/MetalLearning/src/MEL/Buffer/Buffer.h @@ -0,0 +1,35 @@ +#pragma once +#include +#include "Application.h" + +namespace MEL{ + enum class BufferUsage{ + Static, + Dynamic, + Stream + }; + enum class BufferType{ + Vertex, + Index, + Uniform + }; + + class Buffer{ + public: + virtual ~Buffer(); + + virtual void Bind()=0; + virtual void SetData(void* data,uint32_t size)=0; + + id GetBuffer()const{return m_MetalBuffer;} + BufferType GetType()const{return m_Type;} + BufferUsage GetUsage()const{return m_Usage;} + uint32_t GetSize()const{return m_Size;} + protected: + Buffer(BufferType type,BufferUsage usage); + id m_MetalBuffer=nil; + BufferType m_Type; + BufferUsage m_Usage; + uint32_t m_Size=0; + }; +} diff --git a/MetalLearning/src/MEL/Buffer/Buffer.mm b/MetalLearning/src/MEL/Buffer/Buffer.mm new file mode 100644 index 0000000..fb58cd8 --- /dev/null +++ b/MetalLearning/src/MEL/Buffer/Buffer.mm @@ -0,0 +1,12 @@ +#include "Buffer.h" + +namespace MEL { + Buffer::Buffer(BufferType type,BufferUsage usage) + :m_Type(type),m_Usage(usage){ + } + Buffer::~Buffer(){ + if(m_MetalBuffer){ + m_MetalBuffer=nil; + } + } +} diff --git a/MetalLearning/src/MEL/Buffer/IndexBuffer.h b/MetalLearning/src/MEL/Buffer/IndexBuffer.h new file mode 100644 index 0000000..1e9061a --- /dev/null +++ b/MetalLearning/src/MEL/Buffer/IndexBuffer.h @@ -0,0 +1,22 @@ +#pragma once +#include +#import "Buffer.h" + +namespace MEL { + class IndexBuffer: public Buffer{ + public: + static std::shared_ptr Create(uint32_t* indices,uint32_t count); + + IndexBuffer(uint32_t* indices,uint32_t count); + ~IndexBuffer(){}; + + void Bind() override; + void SetData(void* data,uint32_t size)override; + + uint32_t GetCount()const {return m_Count;} + MTLIndexType GetIndexType()const {return MTLIndexTypeUInt32;} + + private: + uint32_t m_Count=0; + }; +} diff --git a/MetalLearning/src/MEL/Buffer/IndexBuffer.mm b/MetalLearning/src/MEL/Buffer/IndexBuffer.mm new file mode 100644 index 0000000..efad446 --- /dev/null +++ b/MetalLearning/src/MEL/Buffer/IndexBuffer.mm @@ -0,0 +1,43 @@ +#include "IndexBuffer.h" + +namespace MEL{ + /////////////IndexBuffer//////////////////// + std::shared_ptr IndexBuffer::Create(uint32_t *indices, uint32_t count){ + return std::make_shared(indices,count); + } + + IndexBuffer::IndexBuffer(uint32_t* indices,uint32_t count) + :Buffer(BufferType::Index, BufferUsage::Static),m_Count(count){ + m_Size=count*sizeof(uint32_t); + auto renderer=Application::Get().GetRenderer(); + id device=renderer->GetMetalDevice(); + + MTLResourceOptions options=MTLResourceStorageModeShared; + m_MetalBuffer=[device newBufferWithBytes:indices + length:m_Size + options:options]; + if(m_MetalBuffer){ + [m_MetalBuffer retain]; + MEL_CORE_INFO("Created IndexBuffer:{} indices({} bytes)",count,m_Size); + } + else{ + MEL_CORE_ERROR("Failed to create IndexBuffer:{} indices",count); + } + } + + void IndexBuffer::Bind(){}//Index don't need to bind manually + + void IndexBuffer::SetData(void *data, uint32_t size){ + if(m_MetalBuffer)return; + + if(size>m_Size){ + MEL_CORE_WARN("IndexBuffer::SetData: size{} exceeds buffer capacity{}",size,m_Size); + return; + } + + void* BufferContents=[m_MetalBuffer contents]; + if(BufferContents&&data){ + memcpy(BufferContents, data, size); + } + } +} diff --git a/MetalLearning/src/MEL/Buffer/VertexBuffer.h b/MetalLearning/src/MEL/Buffer/VertexBuffer.h new file mode 100644 index 0000000..fef75ba --- /dev/null +++ b/MetalLearning/src/MEL/Buffer/VertexBuffer.h @@ -0,0 +1,21 @@ +#pragma once +#include +#import "Buffer.h" + +namespace MEL { + class VertexBuffer: public Buffer{ + public: + static std::shared_ptr Create(void *data, uint32_t size,BufferUsage usage=BufferUsage::Static); + + static std::shared_ptr Create(uint32_t size); + + VertexBuffer(void* data,uint32_t size,BufferUsage usage); + void Bind() override; + void SetData(void *data, uint32_t size) override; + + void SetSlot(uint32_t slot){m_Slot=slot;} + uint32_t GetSlot()const{return m_Slot;} + private: + uint32_t m_Slot=0; + }; +} diff --git a/MetalLearning/src/MEL/Buffer/VertexBuffer.mm b/MetalLearning/src/MEL/Buffer/VertexBuffer.mm new file mode 100644 index 0000000..cfe692b --- /dev/null +++ b/MetalLearning/src/MEL/Buffer/VertexBuffer.mm @@ -0,0 +1,63 @@ +#include "VertexBuffer.h" + +namespace MEL{ + /////////////VertexBuffer//////////////////// + std::shared_ptr VertexBuffer::Create(void *data, uint32_t size,BufferUsage usage){ + return std::make_shared(data,size,usage); + } + + std::shared_ptr VertexBuffer::Create(uint32_t size){ + return std::make_shared(nullptr,size,BufferUsage::Dynamic); + } + + VertexBuffer::VertexBuffer(void* data,uint32_t size,BufferUsage usage) + :Buffer(BufferType::Vertex, usage){ + auto renderer=Application::Get().GetRenderer(); + id device=renderer->GetMetalDevice(); + + MTLResourceOptions options=MTLResourceStorageModeShared; + + if(data){ + m_MetalBuffer=[device newBufferWithBytes:data + length:size + options:options]; + } + else{ + m_MetalBuffer=[device newBufferWithLength:size + options:options]; + } + + if(m_MetalBuffer){ + [m_MetalBuffer retain]; + MEL_CORE_INFO("Created VertexBuffer:{} bytes",size); + } + else{ + MEL_CORE_ERROR("Failed to create VertexBuffer:{} bytes",size); + } + } + + void VertexBuffer::Bind(){ + auto renderer=Application::Get().GetRenderer(); + id encoder=renderer->GetCurrentEncoder(); + + if(encoder&&m_MetalBuffer){ + [encoder setVertexBuffer:m_MetalBuffer + offset:0 + atIndex:m_Slot]; + } + } + + void VertexBuffer::SetData(void *data, uint32_t size){ + if(!m_MetalBuffer)return; + + if(size>m_Size){ + MEL_CORE_WARN("VertexBuffer::SetData: size{} exceeds buffer capacity{}",size,m_Size); + return; + } + + void* BufferContents=[m_MetalBuffer contents]; + if(BufferContents&&data){ + memcpy(BufferContents, data, size); + } + } +} diff --git a/MetalLearning/src/MEL/Renderer/MTKViewDelegate.h b/MetalLearning/src/MEL/Renderer/MTKViewDelegate.h new file mode 100644 index 0000000..b609919 --- /dev/null +++ b/MetalLearning/src/MEL/Renderer/MTKViewDelegate.h @@ -0,0 +1,11 @@ +#import "melpch.h" +namespace MEL{ + class Application; +} + +@interface MELMTKViewDelegate : NSObject + +-(instancetype)initWithApplication: +(MEL::Application*)application; + +@end diff --git a/MetalLearning/src/MEL/Renderer/MTKViewDelegate.mm b/MetalLearning/src/MEL/Renderer/MTKViewDelegate.mm new file mode 100644 index 0000000..b4c1f03 --- /dev/null +++ b/MetalLearning/src/MEL/Renderer/MTKViewDelegate.mm @@ -0,0 +1,31 @@ +#import "MTKViewDelegate.h" +#include "Application.h" +#include "Renderer/Renderer.h" +#include "Shader/Shader.h" + +@implementation MELMTKViewDelegate{ + MEL::Application* _application; +} + +-(instancetype)initWithApplication:(MEL::Application*)application{ + self=[super init]; + if(self){ + _application=application; + } + return self; +} + +-(void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size{ + MEL_CORE_INFO("Drawable Size Will change to:{}x{}",(int)size.width,(int)size.height); + + if(_application&&_application->GetRenderer()){ + _application->GetRenderer()->OnResize((uint32_t)size.width, (uint32_t)size.height); + } +} + +-(void)drawInMTKView:(MTKView *)view{ + if(!_application)return; + + _application->RenderOneFrame(); +} +@end diff --git a/MetalLearning/src/MEL/Renderer/Renderer.h b/MetalLearning/src/MEL/Renderer/Renderer.h index 40ec72b..e322720 100644 --- a/MetalLearning/src/MEL/Renderer/Renderer.h +++ b/MetalLearning/src/MEL/Renderer/Renderer.h @@ -1,8 +1,9 @@ #pragma once #include "MEL.h" - +#include "Shader/Shader.h" #include "Log.h" namespace MEL { + class VertexArray; class Renderer{ public: Renderer(MTKView* mtkview); @@ -12,15 +13,13 @@ namespace MEL { void BeginScene(); void EndScene(); void EndFrame(); - void DrawIndexed(uint32_t indexcount); - void CreatePipelineState(); - void SetVertexBuffer(void* data,size_t size); - void SetIndexBuffer(uint32_t* indices,uint32_t count); + void DrawIndexed(const std::shared_ptr& vertexArray); + + void SetCurrentPipelineState(id pipelineState); void OnResize(uint32_t width,uint32_t height); - void SetupPipeline(); public: void SetImGuiEnabled(bool enabled){m_ImGuiEnabled=enabled;}; bool IsImGuiEnabled(){return m_ImGuiEnabled;} @@ -30,6 +29,8 @@ namespace MEL { public: MTKView* GetMTKView(){return m_View;} id GetMetalDevice(){return m_Device;} + id GetCurrentEncoder(){return m_CurrentEncoder;} + void UpdateViewport(); private: MTKView* m_View; @@ -37,14 +38,13 @@ namespace MEL { id m_CommandQueue; id m_CommandBuffer; id m_CurrentEncoder; - id m_CurrentPipeline; + id m_CurrentPipeline=nil; vector_uint2 m_ViewportSize; - id m_VertexBuffer; - id m_IndexBuffer; - bool m_FrameStarted; + bool is_default=true; - //imgui source + + MTLViewport m_MTLViewportSize; private: bool m_ImGuiEnabled=false; }; diff --git a/MetalLearning/src/MEL/Renderer/Renderer.mm b/MetalLearning/src/MEL/Renderer/Renderer.mm index 2fcb704..8bace2c 100644 --- a/MetalLearning/src/MEL/Renderer/Renderer.mm +++ b/MetalLearning/src/MEL/Renderer/Renderer.mm @@ -3,13 +3,15 @@ #import "imgui_impl_metal.h" #import "imgui_impl_osx.h" +#include "VertexArray/VertexArray.h" +#import "Buffer/VertexBuffer.h" +#import "Buffer/IndexBuffer.h" + namespace MEL{ Renderer::Renderer(MTKView* mtkview): m_View(mtkview), m_Device([mtkview device]), m_CurrentPipeline(nullptr), - m_VertexBuffer(nil), - m_IndexBuffer(nil), m_CommandBuffer(nullptr), m_CurrentEncoder(nullptr) { @@ -28,22 +30,32 @@ namespace MEL{ } void Renderer::BeginFrame(){ - m_CommandBuffer=[m_CommandQueue commandBuffer]; + //debug mode + //MEL_CORE_INFO("====Begin Frame===="); + + if(!m_Device){ + //MEL_CORE_ERROR("NO DEVICE"); + return; + } + if(!m_CommandQueue){ + //MEL_CORE_ERROR("No Command queue"); + return; + } //set viewport in this frame - m_ViewportSize={ - (uint32_t)m_View.drawableSize.width, - (uint32_t)m_View.drawableSize.height - }; - m_FrameStarted=true; + UpdateViewport(); + m_CommandBuffer=[m_CommandQueue commandBuffer]; + //MEL_CORE_INFO("Creates commandbuffer:{}",(void*)m_CommandBuffer); } void Renderer::BeginScene(){ - if(!m_FrameStarted){ - NSLog(@"Call BeginFrame() first"); - return; - } - //create render pass descriptor + //debug mode + //MEL_CORE_INFO("----Begin Scene----"); + + //get render pass descriptor MTLRenderPassDescriptor* renderPassDescriptor=m_View.currentRenderPassDescriptor; + + //MEL_CORE_INFO("Descriptor{}",(void*)renderPassDescriptor); + if(renderPassDescriptor==nil){ NSLog(@"No renderpass"); [m_CommandBuffer commit]; @@ -51,82 +63,82 @@ namespace MEL{ } //create encoder for current scene m_CurrentEncoder=[m_CommandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; + + //MEL_CORE_INFO("encoder{}",(void*)m_CurrentEncoder); + //set viewport and pipeline state - MTLViewport viewport={0,0,(double)m_ViewportSize.x,(double)m_ViewportSize.y,0,1}; - [m_CurrentEncoder setViewport:viewport]; + + [m_CurrentEncoder setViewport:m_MTLViewportSize]; + + //MEL_CORE_INFO("encoder viewport{}x{}",m_MTLViewportSize.width,m_MTLViewportSize.height); if(m_CurrentPipeline){ [m_CurrentEncoder setRenderPipelineState:m_CurrentPipeline]; + + //MEL_CORE_INFO("encoder pipeline set"); } } void Renderer::EndScene(){ [m_CurrentEncoder endEncoding]; - m_CurrentEncoder=nullptr; + //m_CurrentEncoder=nullptr; + //MEL_CORE_INFO("----End Scene----"); } void Renderer::EndFrame(){ - if(!m_FrameStarted)return; if(m_CommandBuffer){ [m_CommandBuffer presentDrawable:[m_View currentDrawable]]; + //MEL_CORE_INFO("commandbuffer drawable{}",(void*)[m_View currentDrawable]); [m_CommandBuffer commit]; + //MEL_CORE_INFO("====End Frame===="); } - m_CommandBuffer=nullptr; - m_CurrentEncoder=nullptr; - m_FrameStarted=false; } - void Renderer::DrawIndexed(uint32_t indexcount){ - if(m_CurrentPipeline) - [m_CurrentEncoder setRenderPipelineState:m_CurrentPipeline]; + void Renderer::DrawIndexed(const std::shared_ptr& vertexArray){ + if(!vertexArray){ + MEL_CORE_ERROR("No array"); + return; + } + if(!m_CurrentEncoder){ + MEL_CORE_ERROR("No encoder"); + return; + } + vertexArray->Bind(); - if(m_VertexBuffer) - [m_CurrentEncoder setVertexBuffer:m_VertexBuffer offset:0 atIndex:0]; - bool using_auto_draw=true; - if(!using_auto_draw){ + auto indexBuffer=vertexArray->GetIndexBuffer(); + if(indexBuffer&&indexBuffer->GetBuffer()){ [m_CurrentEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle - indexCount:indexcount + indexCount:indexBuffer->GetCount() indexType:MTLIndexTypeUInt32 - indexBuffer:m_IndexBuffer + indexBuffer:indexBuffer->GetBuffer() indexBufferOffset:0]; } else{ - [m_CurrentEncoder drawPrimitives:MTLPrimitiveTypeTriangle - vertexStart:0 - vertexCount:indexcount]; + auto vertexBuffers=vertexArray->GetVertexBuffers(); + if(!vertexBuffers.empty()&&vertexBuffers[0]){ + uint32_t vertexCount=vertexBuffers[0]->GetSize()/sizeof(float)/3; + [m_CurrentEncoder drawPrimitives:MTLPrimitiveTypeTriangle + vertexStart:0 + vertexCount:vertexCount]; + } } } - void Renderer::CreatePipelineState(){ - id defaultLibrary=[m_Device newDefaultLibrary]; - - NSError* error=nil; - - if(!defaultLibrary){ - NSLog(@"Failed to load Metal library: %@",error); - } - error=nil; - - id vertexFunction=[defaultLibrary newFunctionWithName:@"vertexShader"]; - id fragmentFunction=[defaultLibrary newFunctionWithName:@"fragmentShader"]; +#pragma mark - Pipeline settings + void Renderer::SetCurrentPipelineState(id pipelineState){ + if(m_CurrentPipeline==pipelineState)return; - if(!vertexFunction || !fragmentFunction){ - NSLog(@"Note:Custom shaders not found,only ImGui rendering will be available!"); - return; + if(m_CurrentPipeline){ + [m_CurrentPipeline release]; + //MEL_CORE_INFO("release pipeline to create new"); } - MTLRenderPipelineDescriptor* pipeLineDescriptor=[[MTLRenderPipelineDescriptor alloc] init]; - - pipeLineDescriptor.vertexFunction=vertexFunction; - pipeLineDescriptor.fragmentFunction=fragmentFunction; - - pipeLineDescriptor.colorAttachments[0].pixelFormat=MTLPixelFormatBGRA8Unorm; - - m_CurrentPipeline=[m_Device newRenderPipelineStateWithDescriptor:pipeLineDescriptor - error:&error]; + m_CurrentPipeline=[pipelineState retain]; + //MEL_CORE_INFO("Pipeline retain{}",(void*)m_CurrentPipeline); - if(!m_CurrentPipeline){ - NSLog(@"create pipeline state failed:%@",error); + if(m_CurrentEncoder&&m_CurrentPipeline){ + [m_CurrentEncoder setRenderPipelineState:m_CurrentPipeline]; + //MEL_CORE_INFO("encoder set pipeline"); } } @@ -134,20 +146,22 @@ namespace MEL{ m_ViewportSize={width,height}; } - void Renderer::SetupPipeline(){ - CreatePipelineState(); - } - #pragma mark - ImGui Controll void Renderer::BeginImGui(){ + ImGuiIO& io=ImGui::GetIO(); + io.DisplaySize=ImVec2(m_ViewportSize.x,m_ViewportSize.y); + //MEL_CORE_INFO("Set ImGui display size{},{}",io.DisplaySize.x,io.DisplaySize.y); + MTLRenderPassDescriptor* renderPassDescriptor=m_View.currentRenderPassDescriptor; if(!renderPassDescriptor){ NSLog(@"no render pass descriptor"); return; } + ImGui_ImplMetal_NewFrame(renderPassDescriptor); ImGui_ImplOSX_NewFrame(m_View); ImGui::NewFrame(); + //MEL_CORE_INFO("ImGui new frame with pipe desc{}",(void*)renderPassDescriptor); } void Renderer::EndImGui(){ @@ -159,21 +173,21 @@ namespace MEL{ ImDrawData* drawData=ImGui::GetDrawData(); ImGui_ImplMetal_RenderDrawData(drawData, m_CommandBuffer, m_CurrentEncoder); - MTLViewport viewport={0,0,(double)m_ViewportSize.x,(double)m_ViewportSize.y,0,1}; - [m_CurrentEncoder setViewport:viewport]; - } -#pragma mark - Buffer sets - void Renderer::SetVertexBuffer(void *data, size_t size){ - is_default=false; - m_VertexBuffer=[m_Device newBufferWithBytes:data - length:size - options:MTLResourceStorageModeShared]; + //MEL_CORE_INFO("ImGui draw with data{}",(void*)drawData); } - - void Renderer::SetIndexBuffer(uint32_t *indices, uint32_t count){ - is_default=false; - m_IndexBuffer=[m_Device newBufferWithBytes:indices - length:count*sizeof(uint32_t) - options:MTLResourceStorageModeShared]; + +#pragma mark - Test methods + void Renderer::UpdateViewport(){ + m_ViewportSize={ + (uint32_t)m_View.currentRenderPassDescriptor.colorAttachments[0].texture.width, + (uint32_t)m_View.currentRenderPassDescriptor.colorAttachments[0].texture.height + }; + m_MTLViewportSize={ + 0,0, + (double)m_ViewportSize.x, + (double)m_ViewportSize.y, + 1,0 + }; + //MEL_CORE_INFO("Viewport size:{}x{}",(double)m_ViewportSize.x,(double)m_ViewportSize.y); } } diff --git a/MetalLearning/src/MEL/Shader/Shader.h b/MetalLearning/src/MEL/Shader/Shader.h index 856406d..ea8c608 100644 --- a/MetalLearning/src/MEL/Shader/Shader.h +++ b/MetalLearning/src/MEL/Shader/Shader.h @@ -2,28 +2,43 @@ #include "MEL.h" #include +#include namespace MEL{ class Shader{ public: + Shader(const std::string& name); ~Shader(); - static std::shared_ptrCreateFromSource(const std::string& name,const std::string& source); - static std::shared_ptrCreateFromLibrary(const std::string& name,const std::string& librarypath); + static std::shared_ptrCreateFromSource(const std::string& name,const std::string& source, + NSString* vertexFuncName,NSString* fragmentFuncName); + static std::shared_ptrCreateFromLibrary(const std::string& name,const std::string& librarypath, + NSString* vertexFuncName,NSString* fragmentFuncName); + static std::shared_ptrCreateFromDefaultLibrary(const std::string& name, + NSString* vertexFuncName,NSString* fragmentFuncName); id GetVertexFunction()const {return m_VertexFunction;} - id GetIndexFunction()const {return m_FragmentFunction;} + id GetFragmentFunction()const {return m_FragmentFunction;} const std::string& GetName(){return m_Name;} + bool CreatePipelineState(); + id GetPipelineState()const{return m_PipelineState;} + void Bind(); private: - Shader(const std::string& name); - bool LoadFromSource(const std::string& source); - bool LoadFromLibrary(const std::string& librarypath); + bool LoadFromSource(const std::string& source, + NSString* vertexFuncName,NSString* fragmentFuncName); + bool LoadFromLibrary(const std::string& librarypath, + NSString* vertexFuncName,NSString* fragmentFuncName); + bool LoadFromDefaultLibrary(NSString* vertexFuncName,NSString* fragmentFuncName); private: std::string m_Name; id m_VertexFunction=nil; id m_FragmentFunction=nil; + + id m_Library; + id m_PipelineState=nil; }; } + diff --git a/MetalLearning/src/MEL/Shader/Shader.mm b/MetalLearning/src/MEL/Shader/Shader.mm index ceae02e..50b887a 100644 --- a/MetalLearning/src/MEL/Shader/Shader.mm +++ b/MetalLearning/src/MEL/Shader/Shader.mm @@ -3,20 +3,30 @@ namespace MEL{ Shader::Shader(const std::string& name):m_Name(name){ } - std::shared_ptr Shader::CreateFromSource(const std::string& name, const std::string &source){ + std::shared_ptr Shader::CreateFromSource(const std::string& name, const std::string &source, + NSString* vertexFuncName,NSString* fragmentFuncName){ auto shader=std::make_shared(name); - if(shader->LoadFromSource(source)) + if(shader->LoadFromSource(source,vertexFuncName,fragmentFuncName)) return shader; return nullptr; } - std::shared_ptr Shader::CreateFromLibrary(const std::string& name,const std::string& librarypath){ + std::shared_ptr Shader::CreateFromLibrary(const std::string& name,const std::string& librarypath, + NSString* vertexFuncName,NSString* fragmentFuncName){ auto shader=std::make_shared(name); - if(shader->LoadFromLibrary(librarypath)) + if(shader->LoadFromLibrary(librarypath,vertexFuncName,fragmentFuncName)) + return shader; + return nullptr; + } + std::shared_ptr Shader::CreateFromDefaultLibrary(const std::string& name, + NSString* vertexFuncName,NSString* fragmentFuncName){ + auto shader=std::make_shared(name); + if(shader->LoadFromDefaultLibrary(vertexFuncName,fragmentFuncName)) return shader; return nullptr; } - bool Shader::LoadFromSource(const std::string &source){ + bool Shader::LoadFromSource(const std::string &source, + NSString* vertexFuncName,NSString* fragmentFuncName){ auto renderer=Application::Get().GetRenderer(); id device=renderer->GetMetalDevice(); @@ -31,23 +41,120 @@ namespace MEL{ return false; } - m_VertexFunction=[library newFunctionWithName:@"vertexShader"]; - m_FragmentFunction=[library newFunctionWithName:@"fragmentShader"]; + m_VertexFunction=[library newFunctionWithName:vertexFuncName]; + m_FragmentFunction=[library newFunctionWithName:fragmentFuncName]; if(!m_VertexFunction||!m_FragmentFunction){ MEL_CORE_ERROR("No vertex or fragment function:{}",m_Name); return false; } - [library retain]; + m_Library=library; MEL_CORE_INFO("Shader from source:{}",m_Name); return true; } + bool Shader::LoadFromLibrary(const std::string &librarypath, + NSString* vertexFuncName,NSString* fragmentFuncName){ + auto renderer=Application::Get().GetRenderer(); + id device=renderer->GetMetalDevice(); + + NSError* error=nil; + NSString* path=[NSString stringWithUTF8String:librarypath.c_str()]; + NSURL* libraryURL=[NSURL fileURLWithPath:path]; + + id library=[device newLibraryWithURL:libraryURL + error:&error]; + if(!library){ + MEL_CORE_ERROR("Failed to load metallib {},{}",librarypath,[[error localizedDescription] UTF8String]); + return false; + } + + m_VertexFunction=[library newFunctionWithName:vertexFuncName]; + m_FragmentFunction=[library newFunctionWithName:fragmentFuncName]; + + if(!m_VertexFunction||!m_FragmentFunction){ + MEL_CORE_ERROR("Metallib '{}' missing required functions",librarypath); + return false; + } + + MEL_CORE_INFO("Load Shader from metlallib:{}",m_Name); + return true; + } + + bool Shader::LoadFromDefaultLibrary(NSString* vertexFuncName,NSString* fragmentFuncName){ + auto renderer=Application::Get().GetRenderer(); + id device=renderer->GetMetalDevice(); + + iddefaultLibrary=[device newDefaultLibrary]; + if(!defaultLibrary){ + MEL_CORE_ERROR("Failed to load default library:{}",m_Name); + return false; + } + + m_VertexFunction=[defaultLibrary newFunctionWithName:vertexFuncName]; + m_FragmentFunction=[defaultLibrary newFunctionWithName:fragmentFuncName]; + + if(!m_VertexFunction||!m_FragmentFunction){ + MEL_CORE_ERROR("Default library missing vertex or fragment function,only render imgui"); + return false; + } + MEL_CORE_INFO("Load Shader from default library:{}",m_Name); + return true; + } + + bool Shader::CreatePipelineState(){ + auto renderer=Application::Get().GetRenderer(); + id device=renderer->GetMetalDevice(); + + if(!m_VertexFunction||!m_FragmentFunction){ + MEL_CORE_WARN("No shader function:{}",m_Name); + return false; + } + + MTLRenderPipelineDescriptor* pipelineDescriptor=[[MTLRenderPipelineDescriptor alloc]init]; + pipelineDescriptor.vertexFunction=m_VertexFunction; + pipelineDescriptor.fragmentFunction=m_FragmentFunction; + pipelineDescriptor.colorAttachments[0].pixelFormat=MTLPixelFormatBGRA8Unorm; + + MTLVertexDescriptor* vertexDescriptor=[[MTLVertexDescriptor alloc]init]; + vertexDescriptor.attributes[0].format=MTLVertexFormatFloat3; + vertexDescriptor.attributes[0].offset=0; + vertexDescriptor.attributes[0].bufferIndex=0; + + vertexDescriptor.attributes[1].format=MTLVertexFormatFloat3; + vertexDescriptor.attributes[1].offset=12; + vertexDescriptor.attributes[1].bufferIndex=0; + + vertexDescriptor.layouts[0].stride=24; + vertexDescriptor.layouts[0].stepFunction=MTLVertexStepFunctionPerVertex; + + pipelineDescriptor.vertexDescriptor=vertexDescriptor; + + + NSError* error=nil; + m_PipelineState=[device newRenderPipelineStateWithDescriptor:pipelineDescriptor + error:&error]; + //[pipelineDescriptor release]; + if(!m_PipelineState){ + MEL_CORE_ERROR("Failed to create pipeline state for shader:{},{}",m_Name,[[error localizedDescription]UTF8String]); + return false; + } + + MEL_CORE_INFO("Create pipeline state for shader:{}",m_Name); + return true; + } + void Shader::Bind(){ + auto renderer=Application::Get().GetRenderer(); + renderer->SetCurrentPipelineState(m_PipelineState); + } Shader::~Shader(){ //maybe auto release + if(m_VertexFunction) + [m_VertexFunction release]; + if(m_FragmentFunction) + [m_FragmentFunction release]; } - - } + diff --git a/MetalLearning/src/MEL/VertexArray/VertexArray.h b/MetalLearning/src/MEL/VertexArray/VertexArray.h new file mode 100644 index 0000000..b495aa7 --- /dev/null +++ b/MetalLearning/src/MEL/VertexArray/VertexArray.h @@ -0,0 +1,29 @@ +#pragma once +#include "Buffer/VertexBuffer.h" +#include "Buffer/IndexBuffer.h" + +namespace MEL{ + class VertexArray{ + public: + static std::shared_ptr Create(); + + VertexArray(); + ~VertexArray(); + + void Bind()const; + void Unbind()const; + + void AddVertexBuffer(const std::shared_ptr& vertexBuffer); + void SetIndexBuffer(const std::shared_ptr& indexBuffer); + + const std::vector>& GetVertexBuffers() const{return m_VertexBuffers;} + const std::shared_ptr& GetIndexBuffer()const {return m_IndexBuffer;} + + uint32_t GetIndexCount()const {return m_IndexBuffer?m_IndexBuffer->GetCount():0;} + + private: + std::vector> m_VertexBuffers; + std::shared_ptr m_IndexBuffer; + mutable uint32_t m_CurrentSlot; + }; +} diff --git a/MetalLearning/src/MEL/VertexArray/VertexArray.mm b/MetalLearning/src/MEL/VertexArray/VertexArray.mm new file mode 100644 index 0000000..ff70aae --- /dev/null +++ b/MetalLearning/src/MEL/VertexArray/VertexArray.mm @@ -0,0 +1,52 @@ +#include "VertexArray.h" +#include "Renderer.h" + +namespace MEL{ + std::shared_ptr VertexArray::Create(){ + return std::make_shared(); + } + + VertexArray::VertexArray():m_CurrentSlot(0){ + } + + VertexArray::~VertexArray(){ + } + + void VertexArray::Bind() const{ + auto renderer=Application::Get().GetRenderer(); + id encoder=renderer->GetCurrentEncoder(); + + if(!encoder){ + MEL_CORE_WARN("VertexArray::Bind: No active render command encoder"); + return; + } + + m_CurrentSlot=0; + for(const auto& vertexBuffer:m_VertexBuffers){ + if(vertexBuffer&&vertexBuffer->GetBuffer()){ + [encoder setVertexBuffer:vertexBuffer->GetBuffer() + offset:0 + atIndex:m_CurrentSlot]; + m_CurrentSlot++; + } + } + + } + + void VertexArray::Unbind()const{ + } + + void VertexArray::AddVertexBuffer(const std::shared_ptr &vertexBuffer){ + if(vertexBuffer){ + m_VertexBuffers.push_back(vertexBuffer); + MEL_CORE_INFO("VertexArray:Added vertex buffer at slot {}",m_VertexBuffers.size()-1); + } + } + + void VertexArray::SetIndexBuffer(const std::shared_ptr &indexBuffer){ + m_IndexBuffer=indexBuffer; + if(indexBuffer){ + MEL_CORE_INFO("VertexArray: Set index buffer with {} indices",indexBuffer->GetCount()); + } + } +} diff --git a/MetalLearning/src/MEL/ViewController/ViewController.mm b/MetalLearning/src/MEL/ViewController/ViewController.mm index 13f1840..2a77523 100644 --- a/MetalLearning/src/MEL/ViewController/ViewController.mm +++ b/MetalLearning/src/MEL/ViewController/ViewController.mm @@ -45,11 +45,11 @@ #pragma mark - MTKViewDelegate -(void)drawInMTKView:(MTKView *)view{ - [_renderer drawInMTKView:view]; + } -(void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size{ - [_renderer mtkView:view drawableSizeWillChange:size]; + auto renderer= } */ -(MTKView*)getMetalView{ diff --git a/MetalLearning/src/MEL/Window/MacWindow.h b/MetalLearning/src/MEL/Window/MacWindow.h index fed9552..4503bf2 100644 --- a/MetalLearning/src/MEL/Window/MacWindow.h +++ b/MetalLearning/src/MEL/Window/MacWindow.h @@ -29,6 +29,7 @@ namespace MEL { void Show()override; virtual Renderer* GetRenderer()const override{return m_Renderer;} + private: virtual void Init(const WindowProps& props); virtual void ShutDown(); diff --git a/MetalLearning/src/Sandbox/Sandbox.mm b/MetalLearning/src/Sandbox/Sandbox.mm index a50542b..7e4420f 100644 --- a/MetalLearning/src/Sandbox/Sandbox.mm +++ b/MetalLearning/src/Sandbox/Sandbox.mm @@ -24,6 +24,10 @@ public: //MEL_INFO("testing update"); } + void OnAttach() override{ + + } + void OnEvent(MEL::Event& e) override{ MEL_INFO("testing event{0}",e.ToString()); }