From d67c8ebffe0932179ea709a94122de8e906ea572 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Mon, 15 Apr 2024 13:48:34 +0200 Subject: [PATCH] Basic metal backend --- src/Editor/main.cpp | 6 - src/Engine/Graphics/Descriptor.cpp | 3 +- src/Engine/Graphics/Descriptor.h | 4 +- src/Engine/Graphics/Metal/Buffer.h | 2 +- src/Engine/Graphics/Metal/Command.h | 1 + src/Engine/Graphics/Metal/Command.mm | 24 +- src/Engine/Graphics/Metal/Descriptor.mm | 73 ++++- src/Engine/Graphics/Metal/Graphics.mm | 1 + src/Engine/Graphics/Metal/PipelineCache.mm | 55 ++-- src/Engine/Graphics/Metal/Shader.mm | 10 +- src/Engine/Graphics/Metal/Window.h | 105 +++---- src/Engine/Graphics/Metal/Window.mm | 327 +++++++++----------- src/Engine/Graphics/RenderPass/TextPass.cpp | 3 +- src/Engine/Graphics/RenderPass/UIPass.cpp | 3 +- src/Engine/Material/Material.cpp | 20 +- 15 files changed, 334 insertions(+), 303 deletions(-) diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 1b5402b..5aab290 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -48,12 +48,6 @@ int main() #endif GraphicsInitializer initializer; graphics->init(initializer); - graphics->createVertexShader(ShaderCreateInfo { - .entryPoint = "fragmentMain", - .mainModule = "TextPass", - .additionalModules = {"TextPass"}, - .name = "Test", - }); StaticMeshVertexData* vd = StaticMeshVertexData::getInstance(); vd->init(graphics); OWindowManager windowManager = new WindowManager(); diff --git a/src/Engine/Graphics/Descriptor.cpp b/src/Engine/Graphics/Descriptor.cpp index 7afc611..ce80d03 100644 --- a/src/Engine/Graphics/Descriptor.cpp +++ b/src/Engine/Graphics/Descriptor.cpp @@ -24,7 +24,7 @@ DescriptorLayout& DescriptorLayout::operator=(const DescriptorLayout& other) { DescriptorLayout::~DescriptorLayout() {} -void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, uint32 arrayCount, +void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, SeImageViewType textureType, uint32 arrayCount, SeDescriptorBindingFlags bindingFlags, SeShaderStageFlags shaderStages) { if (descriptorBindings.size() <= bindingIndex) { descriptorBindings.resize(bindingIndex + 1); @@ -32,6 +32,7 @@ void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorTyp descriptorBindings[bindingIndex] = DescriptorBinding{ .binding = bindingIndex, .descriptorType = type, + .textureType = textureType, .descriptorCount = arrayCount, .bindingFlags = bindingFlags, .shaderStages = shaderStages, diff --git a/src/Engine/Graphics/Descriptor.h b/src/Engine/Graphics/Descriptor.h index ca5e700..dc9689b 100644 --- a/src/Engine/Graphics/Descriptor.h +++ b/src/Engine/Graphics/Descriptor.h @@ -8,6 +8,7 @@ namespace Gfx { struct DescriptorBinding { uint32 binding = 0; SeDescriptorType descriptorType = SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + SeImageViewType textureType; uint32 descriptorCount = 0x7fff; SeDescriptorBindingFlags bindingFlags = 0; SeShaderStageFlags shaderStages = SE_SHADER_STAGE_ALL; @@ -22,7 +23,8 @@ public: DescriptorLayout(const DescriptorLayout& other); DescriptorLayout& operator=(const DescriptorLayout& other); virtual ~DescriptorLayout(); - void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1, + void addDescriptorBinding(uint32 binding, SeDescriptorType type, + SeImageViewType textureType = Gfx::SE_IMAGE_VIEW_TYPE_2D, uint32 arrayCount = 1, SeDescriptorBindingFlags bindingFlags = 0, SeShaderStageFlags shaderStages = SeShaderStageFlagBits::SE_SHADER_STAGE_ALL); void reset(); diff --git a/src/Engine/Graphics/Metal/Buffer.h b/src/Engine/Graphics/Metal/Buffer.h index 9be497a..baf1d64 100644 --- a/src/Engine/Graphics/Metal/Buffer.h +++ b/src/Engine/Graphics/Metal/Buffer.h @@ -20,7 +20,7 @@ public: protected: PGraphics graphics; - uint32 currentBuffer; + uint32 currentBuffer = 0; uint64 size; MTL::Buffer *buffers[Gfx::numFramesBuffered]; uint32 numBuffers; diff --git a/src/Engine/Graphics/Metal/Command.h b/src/Engine/Graphics/Metal/Command.h index 40cc22c..2b79270 100644 --- a/src/Engine/Graphics/Metal/Command.h +++ b/src/Engine/Graphics/Metal/Command.h @@ -94,6 +94,7 @@ private: PGraphics graphics; MTL::CommandQueue* queue; OCommand activeCommand; + Array pendingCommands; }; class IOCommandQueue { diff --git a/src/Engine/Graphics/Metal/Command.mm b/src/Engine/Graphics/Metal/Command.mm index 3d1e72f..9fefbcc 100644 --- a/src/Engine/Graphics/Metal/Command.mm +++ b/src/Engine/Graphics/Metal/Command.mm @@ -4,6 +4,7 @@ #include "Enums.h" #include "Graphics/Enums.h" #include "Graphics/Graphics.h" +#include "Metal/MTLCommandBuffer.hpp" #include "Pipeline.h" #include "Resources.h" #include "Window.h" @@ -120,7 +121,7 @@ void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount, int32 f } void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) { - //TODO: + // TODO: encoder->drawMeshThreadgroups(MTL::Size(groupX, groupY, groupZ), MTL::Size(128, 128, 128), MTL::Size(32, 32, 32)); } @@ -135,7 +136,9 @@ void ComputeCommand::bindPipeline(Gfx::PComputePipeline pipeline) { } void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set) { - encoder->setBuffer(set.cast()->getBuffer(), 0, set->getSetIndex()); + auto metalSet = set.cast(); + metalSet->bind(); + encoder->setBuffer(metalSet->getBuffer(), 0, set->getSetIndex()); } void ComputeCommand::bindDescriptor(const Array& sets) { @@ -144,13 +147,13 @@ void ComputeCommand::bindDescriptor(const Array& sets) { } } -void ComputeCommand::pushConstants(Gfx::PPipelineLayout, Gfx::SeShaderStageFlags, uint32 offset, - uint32 size, const void* data) { +void ComputeCommand::pushConstants(Gfx::PPipelineLayout, Gfx::SeShaderStageFlags, uint32 offset, uint32 size, + const void* data) { encoder->setBytes((char*)data + offset, size, 0); } void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) { - //TODO + // TODO encoder->dispatchThreadgroups(MTL::Size(threadX, threadY, threadZ), MTL::Size(32, 32, 32)); } @@ -170,8 +173,19 @@ OComputeCommand CommandQueue::getComputeCommand(const std::string& name) { } void CommandQueue::submitCommands(PEvent signalSemaphore) { + activeCommand->getHandle()->addCompletedHandler(MTL::CommandBufferHandler([&](MTL::CommandBuffer* cmdBuffer) { + for(auto it = pendingCommands.begin(); it != pendingCommands.end(); it++) + { + if((*it)->getHandle() == cmdBuffer) + { + pendingCommands.remove(it); + return; + } + } + })); activeCommand->end(signalSemaphore); PEvent prevCmdEvent = activeCommand->getCompletedEvent(); + pendingCommands.add(std::move(activeCommand)); activeCommand = new Command(graphics, queue->commandBuffer()); activeCommand->waitForEvent(prevCmdEvent); } diff --git a/src/Engine/Graphics/Metal/Descriptor.mm b/src/Engine/Graphics/Metal/Descriptor.mm index 64550f1..632e0c7 100644 --- a/src/Engine/Graphics/Metal/Descriptor.mm +++ b/src/Engine/Graphics/Metal/Descriptor.mm @@ -1,18 +1,28 @@ #include "Descriptor.h" #include "Buffer.h" #include "Enums.h" +#include "Graphics/Descriptor.h" #include "Graphics/Initializer.h" +#include "Metal/MTLArgument.hpp" +#include "Metal/MTLDevice.hpp" +#include "Metal/MTLResource.hpp" +#include "Metal/MTLTexture.hpp" #include "Texture.h" +#include +#include using namespace Seele; using namespace Seele::Metal; DescriptorLayout::DescriptorLayout(PGraphics graphics, const std::string& name) - : Gfx::DescriptorLayout(name), graphics(graphics) {} + : Gfx::DescriptorLayout(name), graphics(graphics), arguments(nullptr) {} DescriptorLayout::~DescriptorLayout() {} void DescriptorLayout::create() { + if (arguments != nullptr) { + return; + } Array descriptors; for (size_t i = 0; i < descriptorBindings.size(); ++i) { const auto& binding = descriptorBindings[i]; @@ -35,7 +45,7 @@ void DescriptorLayout::create() { case Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: case Gfx::SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: - dataType = MTL::DataTypeStruct; + dataType = MTL::DataTypePointer; break; case Gfx::SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: dataType = MTL::DataTypePrimitiveAccelerationStructure; @@ -44,10 +54,38 @@ void DescriptorLayout::create() { throw std::logic_error("Nooo"); } desc->setDataType(dataType); + desc->setIndex(i); + if (dataType == MTL::DataTypeTexture) { + switch (binding.textureType) { + case Gfx::SE_IMAGE_VIEW_TYPE_1D: + desc->setTextureType(MTL::TextureType1D); + break; + case Gfx::SE_IMAGE_VIEW_TYPE_2D: + desc->setTextureType(MTL::TextureType2D); + break; + case Gfx::SE_IMAGE_VIEW_TYPE_3D: + desc->setTextureType(MTL::TextureType3D); + break; + case Gfx::SE_IMAGE_VIEW_TYPE_CUBE: + desc->setTextureType(MTL::TextureTypeCube); + break; + case Gfx::SE_IMAGE_VIEW_TYPE_1D_ARRAY: + desc->setTextureType(MTL::TextureType1DArray); + break; + case Gfx::SE_IMAGE_VIEW_TYPE_2D_ARRAY: + desc->setTextureType(MTL::TextureType2DArray); + break; + case Gfx::SE_IMAGE_VIEW_TYPE_CUBE_ARRAY: + desc->setTextureType(MTL::TextureTypeCubeArray); + break; + } + } descriptors.add(desc); } arguments = NS::Array::array(descriptors.data(), descriptors.size()); pool = new DescriptorPool(graphics, this); + hash = CRC::Calculate(descriptorBindings.data(), sizeof(Gfx::DescriptorBinding) * descriptorBindings.size(), + CRC::CRC_32()); } DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout) : graphics(graphics), layout(layout) {} @@ -66,6 +104,7 @@ Gfx::PDescriptorSet DescriptorPool::allocateDescriptorSet() { return PDescriptorSet(allocatedSets[setIndex]); } allocatedSets.add(new DescriptorSet(graphics, this)); + allocatedSets.back()->allocate(); return PDescriptorSet(allocatedSets.back()); } @@ -77,9 +116,16 @@ void DescriptorPool::reset() { DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner) : Gfx::DescriptorSet(owner->getLayout()), graphics(graphics), owner(owner), bindCount(0), currentlyInUse(false) { - encoder = graphics->getDevice()->newArgumentEncoder(owner->getArguments()); - buffer = graphics->getDevice()->newBuffer(encoder->encodedLength(), MTL::ResourceOptionCPUCacheModeDefault); - encoder->setArgumentBuffer(buffer, 0); + // auto desc = (MTL::ArgumentDescriptor*)owner->getArguments()->object(0); + // std::cout << desc->access() << " " << desc->arrayLength() << " " << desc->index() << " " << desc->textureType() << + // " " << desc->dataType() << std::endl; + if (owner->getArguments()->count() == 0) { + buffer = graphics->getDevice()->newBuffer(0, MTL::ResourceOptionCPUCacheModeDefault); + } else { + encoder = graphics->getDevice()->newArgumentEncoder(owner->getArguments()); + buffer = graphics->getDevice()->newBuffer(encoder->encodedLength(), MTL::ResourceOptionCPUCacheModeDefault); + encoder->setArgumentBuffer(buffer, 0); + } } DescriptorSet::~DescriptorSet() {} @@ -100,9 +146,11 @@ void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState) } void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler samplerState) { PTextureBase base = texture.cast(); - PSampler sampler = samplerState.cast(); encoder->setTexture(base->getTexture(), binding); - encoder->setSamplerState(sampler->getHandle(), binding); + if (samplerState != nullptr) { + PSampler sampler = samplerState.cast(); + encoder->setSamplerState(sampler->getHandle(), binding); + } } void DescriptorSet::updateTextureArray(uint32_t binding, Array array) { @@ -115,14 +163,13 @@ void DescriptorSet::updateTextureArray(uint32_t binding, Array ar bool DescriptorSet::operator<(Gfx::PDescriptorSet other) { return this < other.getHandle(); } PipelineLayout::PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout) - : Gfx::PipelineLayout(baseLayout), graphics(graphics) {} + : Gfx::PipelineLayout(baseLayout), graphics(graphics) {} -PipelineLayout::~PipelineLayout(){} +PipelineLayout::~PipelineLayout() {} -void PipelineLayout::create() -{ - for(auto& set : descriptorSetLayouts) - { +void PipelineLayout::create() { + for (auto& set : descriptorSetLayouts) { + set->create(); uint32 setHash = set->getHash(); layoutHash = CRC::Calculate(&setHash, sizeof(uint32), CRC::CRC_32(), layoutHash); } diff --git a/src/Engine/Graphics/Metal/Graphics.mm b/src/Engine/Graphics/Metal/Graphics.mm index 156caee..ff30c83 100644 --- a/src/Engine/Graphics/Metal/Graphics.mm +++ b/src/Engine/Graphics/Metal/Graphics.mm @@ -26,6 +26,7 @@ Graphics::~Graphics() void Graphics::init(GraphicsInitializer) { + glfwInit(); device = MTL::CreateSystemDefaultDevice(); queue = new CommandQueue(this); ioQueue = new IOCommandQueue(this); diff --git a/src/Engine/Graphics/Metal/PipelineCache.mm b/src/Engine/Graphics/Metal/PipelineCache.mm index 644b2e3..6f82584 100644 --- a/src/Engine/Graphics/Metal/PipelineCache.mm +++ b/src/Engine/Graphics/Metal/PipelineCache.mm @@ -28,35 +28,38 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo cr MTL::VertexDescriptor* vertexDescriptor = MTL::VertexDescriptor::alloc()->init(); MTL::VertexAttributeDescriptorArray* attributes = vertexDescriptor->attributes(); - const auto& vertexInfo = createInfo.vertexInput->getInfo(); - for (size_t attr = 0; attr < vertexInfo.attributes.size(); ++attr) { - MTL::VertexAttributeDescriptor* attribute = MTL::VertexAttributeDescriptor::alloc()->init(); - attribute->setBufferIndex(vertexInfo.attributes[attr].binding); - switch (vertexInfo.attributes[attr].format) { - case Gfx::SE_FORMAT_R32G32B32_SFLOAT: - attribute->setFormat(MTL::VertexFormatFloat3); - break; - default: - throw std::logic_error("TODO"); + if(createInfo.vertexInput != nullptr) + { + const auto& vertexInfo = createInfo.vertexInput->getInfo(); + for (size_t attr = 0; attr < vertexInfo.attributes.size(); ++attr) { + MTL::VertexAttributeDescriptor* attribute = MTL::VertexAttributeDescriptor::alloc()->init(); + attribute->setBufferIndex(vertexInfo.attributes[attr].binding); + switch (vertexInfo.attributes[attr].format) { + case Gfx::SE_FORMAT_R32G32B32_SFLOAT: + attribute->setFormat(MTL::VertexFormatFloat3); + break; + default: + throw std::logic_error("TODO"); + } + attribute->setOffset(vertexInfo.attributes[attr].offset); + attributes->setObject(attribute, attr); } - attribute->setOffset(vertexInfo.attributes[attr].offset); - attributes->setObject(attribute, attr); - } - MTL::VertexBufferLayoutDescriptorArray* bufferLayout = vertexDescriptor->layouts(); - for (size_t binding = 0; binding < vertexInfo.bindings.size(); ++binding) { - MTL::VertexBufferLayoutDescriptor* buffer = MTL::VertexBufferLayoutDescriptor::alloc()->init(); - buffer->setStride(vertexInfo.bindings[binding].stride); - buffer->setStepRate(1); - switch (vertexInfo.bindings[binding].inputRate) { - case Gfx::SE_VERTEX_INPUT_RATE_VERTEX: - buffer->setStepFunction(MTL::VertexStepFunctionPerVertex); - break; - case Gfx::SE_VERTEX_INPUT_RATE_INSTANCE: - buffer->setStepFunction(MTL::VertexStepFunctionPerInstance); - break; + MTL::VertexBufferLayoutDescriptorArray* bufferLayout = vertexDescriptor->layouts(); + for (size_t binding = 0; binding < vertexInfo.bindings.size(); ++binding) { + MTL::VertexBufferLayoutDescriptor* buffer = MTL::VertexBufferLayoutDescriptor::alloc()->init(); + buffer->setStride(vertexInfo.bindings[binding].stride); + buffer->setStepRate(1); + switch (vertexInfo.bindings[binding].inputRate) { + case Gfx::SE_VERTEX_INPUT_RATE_VERTEX: + buffer->setStepFunction(MTL::VertexStepFunctionPerVertex); + break; + case Gfx::SE_VERTEX_INPUT_RATE_INSTANCE: + buffer->setStepFunction(MTL::VertexStepFunctionPerInstance); + break; + } + bufferLayout->setObject(buffer, binding); } - bufferLayout->setObject(buffer, binding); } pipelineDescriptor->setVertexDescriptor(vertexDescriptor); diff --git a/src/Engine/Graphics/Metal/Shader.mm b/src/Engine/Graphics/Metal/Shader.mm index db3b400..0ec0a0f 100644 --- a/src/Engine/Graphics/Metal/Shader.mm +++ b/src/Engine/Graphics/Metal/Shader.mm @@ -6,6 +6,7 @@ #include "Graphics/slang-compile.h" #include "Metal/MTLDevice.hpp" #include "Metal/MTLLibrary.hpp" +#include #include #include #include @@ -42,7 +43,14 @@ void Shader::create(const ShaderCreateInfo& createInfo) { std::cout << error->debugDescription() << std::endl; assert(false); } - function = library->newFunction(NS::String::string("main", NS::ASCIIStringEncoding)); + function = library->newFunction(NS::String::string("main0", NS::ASCIIStringEncoding)); + if(!function) + { + std::ofstream shaderFile("error.metal"); + shaderFile << metalCode; + shaderFile.close(); + assert(!function); + } mtlOptions->release(); } diff --git a/src/Engine/Graphics/Metal/Window.h b/src/Engine/Graphics/Metal/Window.h index 47302d2..422df3d 100644 --- a/src/Engine/Graphics/Metal/Window.h +++ b/src/Engine/Graphics/Metal/Window.h @@ -13,66 +13,63 @@ #include #include -namespace Seele -{ -namespace Metal -{ -class Window : public Gfx::Window -{ +namespace Seele { +namespace Metal { +class Window : public Gfx::Window { public: - Window(PGraphics graphics, const WindowCreateInfo& createInfo); - virtual ~Window(); - virtual void pollInput() override; - virtual void beginFrame() override; - virtual void endFrame() override; - virtual Gfx::PTexture2D getBackBuffer() const override; - virtual void onWindowCloseEvent() override; - virtual void setKeyCallback(std::function callback) override; - virtual void setMouseMoveCallback(std::function callback) override; - virtual void setMouseButtonCallback(std::function callback) override; - virtual void setScrollCallback(std::function callback) override; - virtual void setFileCallback(std::function callback) override; - virtual void setCloseCallback(std::function callback) override; - virtual void setResizeCallback(std::function callback) override; - - void keyPress(KeyCode code, InputAction action, KeyModifier modifier); - void mouseMove(double x, double y); - void mouseButton(MouseButton button, InputAction action, KeyModifier modifier); - void scroll(double x, double y); - void fileDrop(int num, const char** files); - void close(); - void resize(int width, int height); -private: - PGraphics graphics; - WindowCreateInfo preferences; - GLFWwindow* windowHandle; - NSWindow* metalWindow; - CAMetalLayer* metalLayer; - CA::MetalDrawable* drawable; - OTexture2D backBuffer; + Window(PGraphics graphics, const WindowCreateInfo& createInfo); + virtual ~Window(); + virtual void pollInput() override; + virtual void beginFrame() override; + virtual void endFrame() override; + virtual Gfx::PTexture2D getBackBuffer() const override; + virtual void onWindowCloseEvent() override; + virtual void setKeyCallback(std::function callback) override; + virtual void setMouseMoveCallback(std::function callback) override; + virtual void setMouseButtonCallback(std::function callback) override; + virtual void setScrollCallback(std::function callback) override; + virtual void setFileCallback(std::function callback) override; + virtual void setCloseCallback(std::function callback) override; + virtual void setResizeCallback(std::function callback) override; - std::function keyCallback; - std::function mouseMoveCallback; - std::function mouseButtonCallback; - std::function scrollCallback; - std::function fileCallback; - std::function closeCallback; - std::function resizeCallback; + void keyPress(KeyCode code, InputAction action, KeyModifier modifier); + void mouseMove(double x, double y); + void mouseButton(MouseButton button, InputAction action, KeyModifier modifier); + void scroll(double x, double y); + void fileDrop(int num, const char** files); + void close(); + void resize(int width, int height); + +private: + void createBackBuffer(); + + PGraphics graphics; + WindowCreateInfo preferences; + GLFWwindow* windowHandle; + NSWindow* metalWindow; + CAMetalLayer* metalLayer; + CA::MetalDrawable* drawable; + OTexture2D backBuffer; + + std::function keyCallback; + std::function mouseMoveCallback; + std::function mouseButtonCallback; + std::function scrollCallback; + std::function fileCallback; + std::function closeCallback; + std::function resizeCallback; }; DEFINE_REF(Window); -class Viewport : public Gfx::Viewport -{ +class Viewport : public Gfx::Viewport { public: - Viewport(PWindow owner, const ViewportCreateInfo& createInfo); - virtual ~Viewport(); - constexpr MTL::Viewport getHandle() const - { - return viewport; - } - virtual void resize(uint32 newX, uint32 newY); - virtual void move(uint32 newOffset, uint32 newOffsetY); + Viewport(PWindow owner, const ViewportCreateInfo& createInfo); + virtual ~Viewport(); + constexpr MTL::Viewport getHandle() const { return viewport; } + virtual void resize(uint32 newX, uint32 newY); + virtual void move(uint32 newOffset, uint32 newOffsetY); + private: - MTL::Viewport viewport; + MTL::Viewport viewport; }; } // namespace Metal } // namespace Seele diff --git a/src/Engine/Graphics/Metal/Window.mm b/src/Engine/Graphics/Metal/Window.mm index f91bd69..191f6e5 100644 --- a/src/Engine/Graphics/Metal/Window.mm +++ b/src/Engine/Graphics/Metal/Window.mm @@ -1,234 +1,189 @@ #include "Window.h" +#include "Command.h" #include "Graphics/Initializer.h" #include "Graphics/Metal/Enums.h" #include "Graphics/Texture.h" -#include "Command.h" #include "Metal/MTLTexture.hpp" +#include +#include + using namespace Seele; using namespace Seele::Metal; double currentFrameDelta = 0; -double Gfx::getCurrentFrameDelta() -{ - return currentFrameDelta; +double Gfx::getCurrentFrameDelta() { return currentFrameDelta; } + +void glfwKeyCallback(GLFWwindow* handle, int key, int, int action, int modifier) { + if (key == -1) { + return; + } + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->keyPress((KeyCode)key, (InputAction)action, (KeyModifier)modifier); } -void glfwKeyCallback(GLFWwindow* handle, int key, int, int action, int modifier) -{ - if (key == -1) - { - return; - } - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->keyPress((KeyCode)key, (InputAction)action, (KeyModifier)modifier); +void glfwMouseMoveCallback(GLFWwindow* handle, double xpos, double ypos) { + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->mouseMove(xpos, ypos); } -void glfwMouseMoveCallback(GLFWwindow* handle, double xpos, double ypos) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->mouseMove(xpos, ypos); +void glfwMouseButtonCallback(GLFWwindow* handle, int button, int action, int modifier) { + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->mouseButton((MouseButton)button, (InputAction)action, (KeyModifier)modifier); } -void glfwMouseButtonCallback(GLFWwindow* handle, int button, int action, int modifier) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->mouseButton((MouseButton)button, (InputAction)action, (KeyModifier)modifier); +void glfwScrollCallback(GLFWwindow* handle, double xoffset, double yoffset) { + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->scroll(xoffset, yoffset); } -void glfwScrollCallback(GLFWwindow* handle, double xoffset, double yoffset) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->scroll(xoffset, yoffset); +void glfwFileCallback(GLFWwindow* handle, int count, const char** paths) { + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->fileDrop(count, paths); } -void glfwFileCallback(GLFWwindow* handle, int count, const char** paths) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->fileDrop(count, paths); +void glfwCloseCallback(GLFWwindow* handle) { + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->close(); } -void glfwCloseCallback(GLFWwindow* handle) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->close(); +void glfwFramebufferResizeCallback(GLFWwindow* handle, int width, int height) { + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->resize(width, height); } -void glfwFramebufferResizeCallback(GLFWwindow* handle, int width, int height) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->resize(width, height); +Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo) : graphics(graphics), preferences(createInfo) { + glfwSetErrorCallback([](int, const char* description) { std::cout << description << std::endl; }); + float xscale = 1, yscale = 1; + glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xscale, &yscale); + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + GLFWwindow* handle = + glfwCreateWindow(createInfo.width / xscale, createInfo.height / yscale, createInfo.title, nullptr, nullptr); + windowHandle = handle; + glfwSetWindowUserPointer(handle, this); + + glfwSetKeyCallback(handle, &glfwKeyCallback); + glfwSetCursorPosCallback(handle, &glfwMouseMoveCallback); + glfwSetMouseButtonCallback(handle, &glfwMouseButtonCallback); + glfwSetScrollCallback(handle, &glfwScrollCallback); + glfwSetDropCallback(handle, &glfwFileCallback); + glfwSetWindowCloseCallback(handle, &glfwCloseCallback); + glfwSetFramebufferSizeCallback(handle, &glfwFramebufferResizeCallback); + int width, height; + glfwGetFramebufferSize(handle, &width, &height); + framebufferWidth = width; + framebufferHeight = height; + + metalWindow = glfwGetCocoaWindow(handle); + metalLayer = [CAMetalLayer layer]; + metalLayer.device = (__bridge id)graphics->getDevice(); + metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; + metalLayer.drawableSize = CGSizeMake(createInfo.width, createInfo.height); + metalWindow.contentView.layer = metalLayer; + metalWindow.contentView.wantsLayer = YES; + drawable = (__bridge CA::MetalDrawable*)[metalLayer nextDrawable]; + createBackBuffer(); } -Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo) - : graphics(graphics) - , preferences(createInfo) -{ - float xscale, yscale; - glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xscale, &yscale); - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - GLFWwindow *handle = glfwCreateWindow(createInfo.width / xscale, createInfo.height / yscale, createInfo.title, nullptr, nullptr); - windowHandle = handle; - glfwSetWindowUserPointer(handle, this); +Window::~Window() { glfwDestroyWindow(static_cast(windowHandle)); } - glfwSetKeyCallback(handle, &glfwKeyCallback); - glfwSetCursorPosCallback(handle, &glfwMouseMoveCallback); - glfwSetMouseButtonCallback(handle, &glfwMouseButtonCallback); - glfwSetScrollCallback(handle, &glfwScrollCallback); - glfwSetDropCallback(handle, &glfwFileCallback); - glfwSetWindowCloseCallback(handle, &glfwCloseCallback); - glfwSetFramebufferSizeCallback(handle, &glfwFramebufferResizeCallback); +void Window::pollInput() { glfwPollEvents(); } - metalWindow = glfwGetCocoaWindow(handle); - metalLayer = [CAMetalLayer layer]; - metalLayer.device = (__bridge id)graphics->getDevice(); - metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; - metalLayer.drawableSize = CGSizeMake(createInfo.width, createInfo.height); - metalWindow.contentView.layer = metalLayer; - metalWindow.contentView.wantsLayer = YES; +void Window::beginFrame() { + if (drawable) { + drawable->release(); + } + drawable = (__bridge CA::MetalDrawable*)[metalLayer nextDrawable]; + createBackBuffer(); } -Window::~Window() -{ - glfwDestroyWindow(static_cast(windowHandle)); +void Window::endFrame() { + graphics->getQueue()->getCommands()->present(drawable); + graphics->getQueue()->submitCommands(); } -void Window::pollInput() -{ - glfwPollEvents(); +void Window::onWindowCloseEvent() {} + +Gfx::PTexture2D Window::getBackBuffer() const { return PTexture2D(backBuffer); } + +void Window::setKeyCallback(std::function callback) { keyCallback = callback; } + +void Window::setMouseMoveCallback(std::function callback) { mouseMoveCallback = callback; } + +void Window::setMouseButtonCallback(std::function callback) { + mouseButtonCallback = callback; } -void Window::beginFrame() -{ - @autoreleasepool { - drawable = (__bridge CA::MetalDrawable*)[metalLayer nextDrawable]; - MTL::Texture* buf = drawable->texture(); - backBuffer = new Texture2D(graphics, TextureCreateInfo { - .width = static_cast(buf->width()), - .height = static_cast(buf->height()), - .depth = static_cast(buf->depth()), - .elements = static_cast(buf->arrayLength()), - .mipLevels = static_cast(buf->mipmapLevelCount()), - .format = cast(buf->pixelFormat()), - .usage = MTL::TextureUsageRenderTarget, - .samples = static_cast(buf->sampleCount()), - }, buf); - } +void Window::setScrollCallback(std::function callback) { scrollCallback = callback; } + +void Window::setFileCallback(std::function callback) { fileCallback = callback; } + +void Window::setCloseCallback(std::function callback) { closeCallback = callback; } + +void Window::setResizeCallback(std::function callback) { resizeCallback = callback; } + +void Window::keyPress(KeyCode code, InputAction action, KeyModifier modifier) { keyCallback(code, action, modifier); } + +void Window::mouseMove(double x, double y) { mouseMoveCallback(x, y); } + +void Window::mouseButton(MouseButton button, InputAction action, KeyModifier modifier) { + mouseButtonCallback(button, action, modifier); } -void Window::endFrame() -{ - graphics->getQueue()->getCommands()->present(drawable); -} +void Window::scroll(double x, double y) { scrollCallback(x, y); } -void Window::onWindowCloseEvent() -{ -} +void Window::fileDrop(int num, const char** files) { fileCallback(num, files); } -Gfx::PTexture2D Window::getBackBuffer() const -{ - return PTexture2D(backBuffer); -} +void Window::close() { closeCallback(); } -void Window::setKeyCallback(std::function callback) -{ - keyCallback = callback; -} - -void Window::setMouseMoveCallback(std::function callback) -{ - mouseMoveCallback = callback; -} - -void Window::setMouseButtonCallback(std::function callback) -{ - mouseButtonCallback = callback; -} - -void Window::setScrollCallback(std::function callback) -{ - scrollCallback = callback; -} - -void Window::setFileCallback(std::function callback) -{ - fileCallback = callback; -} - -void Window::setCloseCallback(std::function callback) -{ - closeCallback = callback; -} - -void Window::setResizeCallback(std::function callback) -{ - resizeCallback = callback; -} - -void Window::keyPress(KeyCode code, InputAction action, KeyModifier modifier) -{ - keyCallback(code, action, modifier); -} - -void Window::mouseMove(double x, double y) -{ - mouseMoveCallback(x, y); -} - -void Window::mouseButton(MouseButton button, InputAction action, KeyModifier modifier) -{ - mouseButtonCallback(button, action, modifier); -} - -void Window::scroll(double x, double y) -{ - scrollCallback(x, y); -} - -void Window::fileDrop(int num, const char** files) -{ - fileCallback(num, files); -} - -void Window::close() -{ - closeCallback(); -} - -void Window::resize(int width, int height) -{ - if(width == 0 || height == 0) - { - paused = true; - return; - } +void Window::resize(int width, int height) { + if (width == 0 || height == 0) { paused = true; - resizeCallback(width, height); + return; + } + paused = true; + metalLayer.drawableSize = CGSizeMake(width, height); + drawable->release(); + framebufferWidth = width; + framebufferHeight = height; + // Deallocate the textures if they have been created + drawable = (__bridge CA::MetalDrawable*)[metalLayer nextDrawable]; + createBackBuffer(); + resizeCallback(width, height); } -Viewport::Viewport(PWindow owner, const ViewportCreateInfo& createInfo) - : Gfx::Viewport(owner, createInfo) -{ - viewport.width = sizeX; - viewport.height = sizeY; - viewport.originX = offsetX; - viewport.originY = offsetY; - viewport.znear = 0.0f; - viewport.zfar = 1.0f; +void Window::createBackBuffer() { + MTL::Texture* buf = drawable->texture(); + backBuffer = new Texture2D(graphics, + TextureCreateInfo{ + .width = static_cast(buf->width()), + .height = static_cast(buf->height()), + .depth = static_cast(buf->depth()), + .elements = static_cast(buf->arrayLength()), + .mipLevels = static_cast(buf->mipmapLevelCount()), + .format = cast(buf->pixelFormat()), + .usage = MTL::TextureUsageRenderTarget, + .samples = static_cast(buf->sampleCount()), + }, + buf); } -Viewport::~Viewport() -{ - +Viewport::Viewport(PWindow owner, const ViewportCreateInfo& createInfo) : Gfx::Viewport(owner, createInfo) { + viewport.width = sizeX; + viewport.height = sizeY; + viewport.originX = offsetX; + viewport.originY = offsetY; + viewport.znear = 0.0f; + viewport.zfar = 1.0f; } -void Viewport::resize(uint32 newX, uint32 newY) -{ - viewport.width = newX; - viewport.height = newY; +Viewport::~Viewport() {} + +void Viewport::resize(uint32 newX, uint32 newY) { + viewport.width = newX; + viewport.height = newY; } -void Viewport::move(uint32 newOffset, uint32 newOffsetY) -{ - viewport.originX = newOffset; - viewport.originY = newOffsetY; +void Viewport::move(uint32 newOffset, uint32 newOffsetY) { + viewport.originX = newOffset; + viewport.originY = newOffsetY; } diff --git a/src/Engine/Graphics/RenderPass/TextPass.cpp b/src/Engine/Graphics/RenderPass/TextPass.cpp index 4a6907f..c28a92d 100644 --- a/src/Engine/Graphics/RenderPass/TextPass.cpp +++ b/src/Engine/Graphics/RenderPass/TextPass.cpp @@ -1,4 +1,5 @@ #include "TextPass.h" +#include "Graphics/Enums.h" #include "RenderGraph.h" #include "Graphics/Graphics.h" #include "Graphics/RenderTarget.h" @@ -125,7 +126,7 @@ void TextPass::createRenderPass() generalLayout->create(); textureArrayLayout = graphics->createDescriptorLayout("TextTextureArray"); - textureArrayLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 256, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT); + textureArrayLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, Gfx::SE_IMAGE_VIEW_TYPE_2D_ARRAY, 256, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT); textureArrayLayout->create(); projectionBuffer = graphics->createUniformBuffer({ diff --git a/src/Engine/Graphics/RenderPass/UIPass.cpp b/src/Engine/Graphics/RenderPass/UIPass.cpp index b98571e..f268d26 100644 --- a/src/Engine/Graphics/RenderPass/UIPass.cpp +++ b/src/Engine/Graphics/RenderPass/UIPass.cpp @@ -1,4 +1,5 @@ #include "UIPass.h" +#include "Graphics/Enums.h" #include "RenderGraph.h" #include "Graphics/Graphics.h" #include "Graphics/RenderTarget.h" @@ -109,7 +110,7 @@ void UIPass::createRenderPass() descriptorLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); descriptorLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_SAMPLER); descriptorLayout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - descriptorLayout->addDescriptorBinding(3, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 256, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT | Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT); + descriptorLayout->addDescriptorBinding(3, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, Gfx::SE_IMAGE_VIEW_TYPE_2D_ARRAY, 256, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT | Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT); descriptorLayout->create(); Matrix4 projectionMatrix = glm::ortho(0, 1, 1, 0); diff --git a/src/Engine/Material/Material.cpp b/src/Engine/Material/Material.cpp index d5877d0..74eb317 100644 --- a/src/Engine/Material/Material.cpp +++ b/src/Engine/Material/Material.cpp @@ -1,4 +1,6 @@ #include "Material.h" +#include "Graphics/Enums.h" +#include "Serialization/Serialization.h" #include "Window/WindowManager.h" #include "MaterialInstance.h" #include "Graphics/Graphics.h" @@ -61,9 +63,10 @@ void Material::save(ArchiveBuffer& buffer) const for (const auto& binding : bindings) { Serialization::save(buffer, binding.binding); - Serialization::save(buffer, binding.bindingFlags); - Serialization::save(buffer, binding.descriptorCount); Serialization::save(buffer, binding.descriptorType); + Serialization::save(buffer, binding.textureType); + Serialization::save(buffer, binding.descriptorCount); + Serialization::save(buffer, binding.bindingFlags); Serialization::save(buffer, binding.shaderStages); } } @@ -88,19 +91,22 @@ void Material::load(ArchiveBuffer& buffer) uint32 binding; Serialization::load(buffer, binding); - Gfx::SeDescriptorBindingFlags bindingFlags; - Serialization::load(buffer, bindingFlags); + Gfx::SeDescriptorType descriptorType; + Serialization::load(buffer, descriptorType); + + Gfx::SeImageViewType textureType; + Serialization::load(buffer, textureType); uint32 descriptorCount; Serialization::load(buffer, descriptorCount); - Gfx::SeDescriptorType descriptorType; - Serialization::load(buffer, descriptorType); + Gfx::SeDescriptorBindingFlags bindingFlags; + Serialization::load(buffer, bindingFlags); Gfx::SeShaderStageFlags shaderStages; Serialization::load(buffer, shaderStages); - layout->addDescriptorBinding(binding, descriptorType, descriptorCount, bindingFlags, shaderStages); + layout->addDescriptorBinding(binding, descriptorType, textureType, descriptorCount, bindingFlags, shaderStages); } layout->create(); }