diff --git a/res/shaders/Skybox.slang b/res/shaders/Skybox.slang index ad5a15e..b191be7 100644 --- a/res/shaders/Skybox.slang +++ b/res/shaders/Skybox.slang @@ -13,72 +13,72 @@ struct SkyboxData layout(set=1) ParameterBlock pSkyboxData; -float3 vertices[] = { - // Back - float3(-512, -512, 512), - float3(-512, 512, 512), - float3( 512, -512, 512), - - float3( 512, -512, 512), - float3(-512, 512, 512), - float3( 512, 512, 512), - - // Front - float3( 512, -512, -512), - float3( 512, 512, -512), - float3(-512, -512, -512), - - float3(-512, -512, -512), - float3( 512, 512, -512), - float3(-512, 512, -512), - - // Top - float3(-512, -512, -512), - float3(-512, -512, 512), - float3( 512, -512, -512), - - float3( 512, -512, -512), - float3(-512, -512, 512), - float3( 512, -512, 512), - - // Bottom - float3(-512, 512, 512), - float3(-512, 512, -512), - float3( 512, 512, 512), - - float3( 512, 512, 512), - float3(-512, 512, -512), - float3( 512, 512, -512), - - // Left - float3(-512, -512, -512), - float3(-512, 512, -512), - float3(-512, -512, 512), - - float3(-512, -512, 512), - float3(-512, 512, -512), - float3(-512, 512, 512), - - // Right - float3( 512, -512, 512), - float3( 512, 512, 512), - float3( 512, -512, -512), - - float3( 512, -512, -512), - float3( 512, 512, 512), - float3( 512, 512, -512), -}; - [shader("vertex")] VertexShaderOutput vertexMain( uint vertexIndex : SV_VertexId) { + const float3 vertices[] = { + // Back + float3(-512, -512, 512), + float3(-512, 512, 512), + float3( 512, -512, 512), + + float3( 512, -512, 512), + float3(-512, 512, 512), + float3( 512, 512, 512), + + // Front + float3( 512, -512, -512), + float3( 512, 512, -512), + float3(-512, -512, -512), + + float3(-512, -512, -512), + float3( 512, 512, -512), + float3(-512, 512, -512), + + // Top + float3(-512, -512, -512), + float3(-512, -512, 512), + float3( 512, -512, -512), + + float3( 512, -512, -512), + float3(-512, -512, 512), + float3( 512, -512, 512), + + // Bottom + float3(-512, 512, 512), + float3(-512, 512, -512), + float3( 512, 512, 512), + + float3( 512, 512, 512), + float3(-512, 512, -512), + float3( 512, 512, -512), + + // Left + float3(-512, -512, -512), + float3(-512, 512, -512), + float3(-512, -512, 512), + + float3(-512, -512, 512), + float3(-512, 512, -512), + float3(-512, 512, 512), + + // Right + float3( 512, -512, 512), + float3( 512, 512, 512), + float3( 512, -512, -512), + + float3( 512, -512, -512), + float3( 512, 512, 512), + float3( 512, 512, -512), + }; + VertexShaderOutput output; float3x3 cameraRotation = float3x3(pViewParams.viewMatrix); float4 worldPos = float4(mul(cameraRotation, vertices[vertexIndex]), 1.0f); //clip(dot(worldPos, clipPlane)); output.clipPos = mul(pViewParams.projectionMatrix, worldPos); - output.texCoords = normalize(input.position); + output.texCoords = normalize(vertices[vertexIndex]); return output; } diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index a630ea7..19eb1eb 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -216,9 +216,8 @@ int main() mainWindowInfo.title = "SeeleEngine"; mainWindowInfo.width = 1280; mainWindowInfo.height = 720; - mainWindowInfo.bFullscreen = false; mainWindowInfo.numSamples = 1; - mainWindowInfo.pixelFormat = Gfx::SE_FORMAT_B8G8R8A8_UNORM; + mainWindowInfo.preferredFormat = Gfx::SE_FORMAT_B8G8R8A8_SRGB; auto window = windowManager->addWindow(graphics, mainWindowInfo); ViewportCreateInfo sceneViewInfo; sceneViewInfo.dimensions.size.x = 1280; diff --git a/src/Engine/Containers/Array.h b/src/Engine/Containers/Array.h index 8a5b643..6af956c 100644 --- a/src/Engine/Containers/Array.h +++ b/src/Engine/Containers/Array.h @@ -746,12 +746,14 @@ public: } StaticArray(std::initializer_list init) { - assert(init.size() == N); auto beg = init.begin(); for (size_t i = 0; i < N; ++i) { _data[i] = *beg; - beg++; + if (init.size() == N) + { + beg++; + } } } ~StaticArray() diff --git a/src/Engine/Containers/List.h b/src/Engine/Containers/List.h index 3b6bb2b..426637d 100644 --- a/src/Engine/Containers/List.h +++ b/src/Engine/Containers/List.h @@ -179,7 +179,6 @@ public: , _size(std::move(other._size)) , allocator(std::move(other.allocator)) { - other.clear(); } List(List&& other, const Allocator& alloc) : root(std::move(other.root)) diff --git a/src/Engine/Containers/Map.h b/src/Engine/Containers/Map.h index 8b81723..580002d 100644 --- a/src/Engine/Containers/Map.h +++ b/src/Engine/Containers/Map.h @@ -260,18 +260,6 @@ public: markIteratorsDirty(); return getNode(root)->pair.value; } - constexpr mapped_type& operator[](key_type&& key) - { - root = splay(root, std::move(key)); - if (!isValid(root) || !equal(getNode(root)->pair.key, key)) - { - root = insert(root, std::move(key)); - _size++; - } - markIteratorsDirty(); - return getNode(root)->pair.value; - } - constexpr const mapped_type& operator[](const key_type& key) const { size_t it = root; @@ -288,23 +276,6 @@ public: } return getNode(it)->pair.value; } - constexpr const mapped_type& operator[](key_type&& key) const - { - size_t it = root; - while (!equal(getNode(it)->pair.key, key)) - { - if (comp(key, getNode(it)->pair.key)) - { - it = getNode(it)->leftChild; - } - else - { - it = getNode(it)->rightChild; - } - } - return getNode(it)->pair.value; - } - constexpr mapped_type& at(const key_type& key) { root = splay(root, key); @@ -361,6 +332,7 @@ public: { root = remove(root, key); refreshIterators(); + assert(root != SIZE_MAX || _size == 0); return iterator(root, &nodeContainer); } constexpr iterator erase(key_type&& key) @@ -528,7 +500,6 @@ private: endIndex = getNode(endIndex)->rightChild; } return Iterator(endIndex, &nodeContainer, std::move(endTraversal)); - } Array nodeContainer = Array(); size_t root; diff --git a/src/Engine/Graphics/CMakeLists.txt b/src/Engine/Graphics/CMakeLists.txt index 883ad83..e06ffbe 100644 --- a/src/Engine/Graphics/CMakeLists.txt +++ b/src/Engine/Graphics/CMakeLists.txt @@ -28,7 +28,9 @@ target_sources(Engine Texture.h Texture.cpp VertexData.h - VertexData.cpp) + VertexData.cpp + Window.h + Window.cpp) target_sources(Engine PUBLIC FILE_SET HEADERS @@ -47,7 +49,8 @@ target_sources(Engine Shader.h StaticMeshVertexData.h Texture.h - VertexData.h) + VertexData.h + Window.h) add_subdirectory(RenderPass/) add_subdirectory(Vulkan/) \ No newline at end of file diff --git a/src/Engine/Graphics/Initializer.cpp b/src/Engine/Graphics/Initializer.cpp index 4a63b4e..79edf0b 100644 --- a/src/Engine/Graphics/Initializer.cpp +++ b/src/Engine/Graphics/Initializer.cpp @@ -8,12 +8,12 @@ LegacyPipelineCreateInfo::LegacyPipelineCreateInfo() : topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) , multisampleState(MultisampleState{ .samples = 1, - }) + }) , rasterizationState(RasterizationState{ .polygonMode = Gfx::SE_POLYGON_MODE_FILL, .cullMode = Gfx::SE_CULL_MODE_BACK_BIT, .frontFace = Gfx::SE_FRONT_FACE_COUNTER_CLOCKWISE, - }) + }) , depthStencilState(DepthStencilState{ .depthTestEnable = true, .depthWriteEnable = true, @@ -21,7 +21,7 @@ LegacyPipelineCreateInfo::LegacyPipelineCreateInfo() .stencilTestEnable = false, .minDepthBounds = 0.0f, .maxDepthBounds = 1.0f, - }) + }) , colorBlend(ColorBlendState{ .logicOpEnable = false, .attachmentCount = 0, @@ -40,7 +40,7 @@ LegacyPipelineCreateInfo::LegacyPipelineCreateInfo() 1.0f, 1.0f, }, - }) + }) { } diff --git a/src/Engine/Graphics/Initializer.h b/src/Engine/Graphics/Initializer.h index 7faaa83..820a537 100644 --- a/src/Engine/Graphics/Initializer.h +++ b/src/Engine/Graphics/Initializer.h @@ -36,9 +36,8 @@ struct WindowCreateInfo int32 width; int32 height; const char *title; - bool bFullscreen; Gfx::SeSampleCountFlags numSamples; - Gfx::SeFormat pixelFormat; + Gfx::SeFormat preferredFormat = Gfx::SE_FORMAT_MAX_ENUM; void *windowHandle; }; struct ViewportCreateInfo diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index a192d97..1239f38 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -48,9 +48,6 @@ void BasePass::beginFrame(const Component::Camera& cam) RenderPass::beginFrame(cam); lightCullingLayout->reset(); - descriptorSets[INDEX_VIEW_PARAMS] = viewParamsSet; - descriptorSets[INDEX_LIGHT_ENV] = scene->getLightEnvironment()->getDescriptorSet(); - descriptorSets[INDEX_LIGHT_CULLING] = lightCullingLayout->allocateDescriptorSet(); } void BasePass::render() @@ -68,6 +65,10 @@ void BasePass::render() Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + descriptorSets[INDEX_VIEW_PARAMS] = viewParamsSet; + descriptorSets[INDEX_LIGHT_ENV] = scene->getLightEnvironment()->getDescriptorSet(); + descriptorSets[INDEX_LIGHT_CULLING] = lightCullingLayout->allocateDescriptorSet(); + descriptorSets[INDEX_LIGHT_CULLING]->updateBuffer(0, oLightIndexList); descriptorSets[INDEX_LIGHT_CULLING]->updateBuffer(1, tLightIndexList); descriptorSets[INDEX_LIGHT_CULLING]->updateTexture(2, oLightGrid); diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp index fdba2cb..64e84c3 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp @@ -145,8 +145,8 @@ void DepthPrepass::publishOutputs() // still match the size of the whole image or their coordinate systems go out of sync TextureCreateInfo depthBufferInfo = { .format = Gfx::SE_FORMAT_D32_SFLOAT, - .width = viewport->getOwner()->getWidth(), - .height = viewport->getOwner()->getHeight(), + .width = viewport->getOwner()->getFramebufferWidth(), + .height = viewport->getOwner()->getFramebufferHeight(), .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, }; depthBuffer = graphics->createTexture2D(depthBufferInfo); diff --git a/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp b/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp index 4770af5..232ac8a 100644 --- a/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp +++ b/src/Engine/Graphics/RenderPass/SkyboxRenderPass.cpp @@ -51,7 +51,6 @@ void SkyboxRenderPass::render() renderCommand->setViewport(viewport); renderCommand->bindPipeline(pipeline); renderCommand->bindDescriptor({viewParamsSet, skyboxDataSet, textureSet}); - renderCommand->bindVertexBuffer({ cubeBuffer }); renderCommand->draw(36, 1, 0, 0); graphics->executeCommands(Array{ renderCommand }); graphics->endRenderPass(); diff --git a/src/Engine/Graphics/RenderTarget.cpp b/src/Engine/Graphics/RenderTarget.cpp index 7efb8ce..5a1e121 100644 --- a/src/Engine/Graphics/RenderTarget.cpp +++ b/src/Engine/Graphics/RenderTarget.cpp @@ -3,40 +3,6 @@ using namespace Seele; using namespace Seele::Gfx; -Window::Window(const WindowCreateInfo& createInfo) - : windowState(createInfo) -{ -} - -Window::~Window() -{ -} - -Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo) - : sizeX(std::min(owner->getWidth(), viewportInfo.dimensions.size.x)) - , sizeY(std::min(owner->getHeight(), viewportInfo.dimensions.size.y)) - , offsetX(viewportInfo.dimensions.offset.x) - , offsetY(viewportInfo.dimensions.offset.y) - , fieldOfView(viewportInfo.fieldOfView) - , owner(owner) -{ -} - -Viewport::~Viewport() -{ -} - -Matrix4 Viewport::getProjectionMatrix() const -{ - if (fieldOfView > 0.0f) - { - return glm::perspective(fieldOfView, sizeX / static_cast(sizeY), 0.1f, 1000.0f); - } - else - { - return glm::ortho(0.0f, (float)sizeX, (float)sizeY, 0.0f); - } -} RenderTargetAttachment::RenderTargetAttachment(PTexture2D texture, SeAttachmentLoadOp loadOp, SeAttachmentStoreOp storeOp, diff --git a/src/Engine/Graphics/RenderTarget.h b/src/Engine/Graphics/RenderTarget.h index f00ec4f..114ce15 100644 --- a/src/Engine/Graphics/RenderTarget.h +++ b/src/Engine/Graphics/RenderTarget.h @@ -1,71 +1,12 @@ #pragma once #include "Resources.h" #include "Texture.h" +#include "Window.h" namespace Seele { namespace Gfx { -class Window -{ -public: - Window(const WindowCreateInfo &createInfo); - virtual ~Window(); - virtual void beginFrame() = 0; - virtual void endFrame() = 0; - virtual void onWindowCloseEvent() = 0; - virtual PTexture2D getBackBuffer() = 0; - virtual void setKeyCallback(std::function callback) = 0; - virtual void setMouseMoveCallback(std::function callback) = 0; - virtual void setMouseButtonCallback(std::function callback) = 0; - virtual void setScrollCallback(std::function callback) = 0; - virtual void setFileCallback(std::function callback) = 0; - virtual void setCloseCallback(std::function callback) = 0; - constexpr SeFormat getSwapchainFormat() const - { - return windowState.pixelFormat; - } - constexpr SeSampleCountFlags getNumSamples() const - { - return windowState.numSamples; - } - constexpr uint32 getWidth() const - { - return windowState.width; - } - constexpr uint32 getHeight() const - { - return windowState.height; - } - -protected: - WindowCreateInfo windowState; -}; -DEFINE_REF(Window) - -class Viewport -{ -public: - Viewport(PWindow owner, const ViewportCreateInfo &createInfo); - virtual ~Viewport(); - virtual void resize(uint32 newX, uint32 newY) = 0; - virtual void move(uint32 newOffsetX, uint32 newOffsetY) = 0; - constexpr PWindow getOwner() const {return owner;} - constexpr uint32 getWidth() const {return sizeX;} - constexpr uint32 getHeight() const {return sizeY;} - constexpr uint32 getOffsetX() const {return offsetX;} - constexpr uint32 getOffsetY() const {return offsetY;} - Matrix4 getProjectionMatrix() const; -protected: - uint32 sizeX; - uint32 sizeY; - uint32 offsetX; - uint32 offsetY; - float fieldOfView; - PWindow owner; -}; -DEFINE_REF(Viewport) - class RenderTargetAttachment { public: @@ -133,11 +74,11 @@ public: } virtual uint32 getWidth() const { - return owner->getWidth(); + return owner->getFramebufferWidth(); } virtual uint32 getHeight() const { - return owner->getHeight(); + return owner->getFramebufferHeight(); } private: PWindow owner; diff --git a/src/Engine/Graphics/Vulkan/Allocator.cpp b/src/Engine/Graphics/Vulkan/Allocator.cpp index e24246a..300c756 100644 --- a/src/Engine/Graphics/Vulkan/Allocator.cpp +++ b/src/Engine/Graphics/Vulkan/Allocator.cpp @@ -44,8 +44,9 @@ Allocation::Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, u VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo) : device(graphics->getDevice()) , pool(pool) - , bytesAllocated(0) + , bytesAllocated(size) , bytesUsed(0) + , mappedPointer(nullptr) , canMap((properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) , isMapped(false) , properties(properties) @@ -59,9 +60,7 @@ Allocation::Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, u }; isDedicated = dedicatedInfo != nullptr; VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory)); - bytesAllocated = size; freeRanges[0] = size; - } Allocation::~Allocation() @@ -95,6 +94,7 @@ OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice VkDeviceSize allocatedSize = requestedSize + (alignedOffset - lower); if (size >= allocatedSize) { + //std::cout << "Allocating " << lower << "-" << lower + allocatedSize << std::endl; VkDeviceSize newSize = size - allocatedSize; VkDeviceSize newLower = lower + allocatedSize; OSubAllocation alloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset); @@ -113,6 +113,7 @@ OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice void Allocation::markFree(PSubAllocation allocation) { + //std::cout << "Freeing " << allocation->allocatedOffset << "-" << allocation->allocatedOffset + allocation->allocatedSize << std::endl; assert(activeAllocations.find(allocation) != activeAllocations.end()); VkDeviceSize lowerBound = allocation->allocatedOffset; VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize; @@ -121,7 +122,7 @@ void Allocation::markFree(PSubAllocation allocation) { if (lower + size == lowerBound) { - freeRanges[lower] = upperBound; + freeRanges[lower] = size + allocation->allocatedSize; freeRanges.erase(lowerBound); lowerBound = lower; break; @@ -134,10 +135,6 @@ void Allocation::markFree(PSubAllocation allocation) } activeAllocations.remove(allocation, false); bytesUsed -= allocation->allocatedSize; - if (bytesUsed == 0) - { - pool->free(this); - } } void Allocation::flushMemory() @@ -205,7 +202,7 @@ OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2 { OAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo); heaps[heapIndex].inUse += newAllocation->bytesAllocated; - std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl; + std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl; heaps[heapIndex].allocations.add(std::move(newAllocation)); return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment); } @@ -225,7 +222,7 @@ OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2 // no suitable allocations found, allocate new block OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > DEFAULT_ALLOCATION) ? requirements.size : DEFAULT_ALLOCATION, memoryTypeIndex, properties, nullptr); heaps[heapIndex].inUse += newAllocation->bytesAllocated; - std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl; + std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl; heaps[heapIndex].allocations.add(std::move(newAllocation)); return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment); } @@ -240,7 +237,7 @@ void Allocator::free(PAllocation allocation) if (heaps[heapIndex].allocations[alloc] == allocation) { heaps[heapIndex].inUse -= allocation->bytesAllocated; - std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl; + std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl; heaps[heapIndex].allocations.removeAt(alloc, false); return; } diff --git a/src/Engine/Graphics/Vulkan/CMakeLists.txt b/src/Engine/Graphics/Vulkan/CMakeLists.txt index a1e02a7..de441bb 100644 --- a/src/Engine/Graphics/Vulkan/CMakeLists.txt +++ b/src/Engine/Graphics/Vulkan/CMakeLists.txt @@ -24,14 +24,14 @@ target_sources(Engine Queue.cpp RenderPass.h RenderPass.cpp - RenderTarget.h - RenderTarget.cpp Resources.h Resources.cpp Shader.h Shader.cpp Texture.h - Texture.cpp) + Texture.cpp + Window.h + Window.cpp) target_sources(Engine PUBLIC FILE_SET HEADERS @@ -48,8 +48,8 @@ target_sources(Engine PipelineCache.h Queue.h RenderPass.h - RenderTarget.h Resources.h Shader.h - Texture.h) + Texture.h + Window.h) \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/Command.cpp b/src/Engine/Graphics/Vulkan/Command.cpp index 177a24e..20119a0 100644 --- a/src/Engine/Graphics/Vulkan/Command.cpp +++ b/src/Engine/Graphics/Vulkan/Command.cpp @@ -6,7 +6,7 @@ #include "RenderPass.h" #include "Pipeline.h" #include "Descriptor.h" -#include "RenderTarget.h" +#include "Window.h" #include using namespace Seele; @@ -58,7 +58,8 @@ void Command::end() void Command::beginRenderPass(PRenderPass renderPass, PFramebuffer framebuffer) { assert(state == State::Begin); - + boundRenderPass = renderPass; + boundFramebuffer = framebuffer; VkRenderPassBeginInfo beginInfo = { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, .pNext = nullptr, @@ -74,6 +75,8 @@ void Command::beginRenderPass(PRenderPass renderPass, PFramebuffer framebuffer) void Command::endRenderPass() { + boundRenderPass = nullptr; + boundFramebuffer = nullptr; vkCmdEndRenderPass(handle); state = State::Begin; } @@ -148,6 +151,7 @@ void Command::checkFence() for(auto& descriptor : boundDescriptors) { descriptor->unbind(); + //std::cout << "Unbinding descriptor " << descriptor.cast()->getHandle() << " to cmd " << handle << std::endl; } boundDescriptors.clear(); graphics->getDestructionManager()->notifyCmdComplete(this); @@ -282,6 +286,7 @@ void RenderCommand::bindDescriptor(const Array& descriptorS assert(descriptorSet->writeDescriptors.size() == 0); descriptorSet->bind(); + //std::cout << "Binding descriptor " << descriptorSet->getHandle() << " to cmd " << handle << std::endl; boundDescriptors.add(descriptorSet.getHandle()); sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle(); } diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index 5dd6125..727be9b 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -6,7 +6,7 @@ #include "PipelineCache.h" #include "Command.h" #include "Descriptor.h" -#include "RenderTarget.h" +#include "Window.h" #include "RenderPass.h" #include "Framebuffer.h" #include "Shader.h" diff --git a/src/Engine/Graphics/Vulkan/Queue.cpp b/src/Engine/Graphics/Vulkan/Queue.cpp index 6775b6f..fa918c7 100644 --- a/src/Engine/Graphics/Vulkan/Queue.cpp +++ b/src/Engine/Graphics/Vulkan/Queue.cpp @@ -23,8 +23,7 @@ void Queue::submitCommandBuffer(PCommand command, uint32 numSignalSemaphores, Vk std::unique_lock lock(queueLock); assert(command->state == Command::State::End); - PFence fence = command->fence; - assert(!fence->isSignaled()); + assert(!(command->fence->isSignaled())); VkCommandBuffer cmdHandle = command->handle; @@ -49,15 +48,15 @@ void Queue::submitCommandBuffer(PCommand command, uint32 numSignalSemaphores, Vk .pSignalSemaphores = signalSemaphores, }; - VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, fence->getHandle())); + VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, command->fence->getHandle())); command->state = Command::State::Submit; command->waitFlags.clear(); command->waitSemaphores.clear(); if (Gfx::waitIdleOnSubmit) { - fence->wait(200 * 1000ull); + command->fence->wait(200 * 1000ull); } - command->checkFence(); + command->checkFence(); } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/RenderPass.cpp b/src/Engine/Graphics/Vulkan/RenderPass.cpp index d348519..f96506d 100644 --- a/src/Engine/Graphics/Vulkan/RenderPass.cpp +++ b/src/Engine/Graphics/Vulkan/RenderPass.cpp @@ -121,7 +121,15 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::ORenderTargetLayout _layout, Gfx }; VK_CHECK(vkCreateRenderPass(graphics->getDevice(), &info, nullptr, &renderPass)); +} +RenderPass::~RenderPass() +{ + vkDestroyRenderPass(graphics->getDevice(), renderPass, nullptr); +} + +uint32 RenderPass::getFramebufferHash() +{ FramebufferDescription description; std::memset(&description, 0, sizeof(FramebufferDescription)); for (auto& inputAttachment : layout->inputAttachments) @@ -139,11 +147,5 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::ORenderTargetLayout _layout, Gfx PTexture2D tex = layout->depthAttachment->getTexture().cast(); description.depthAttachment = tex->getView(); } - framebufferHash = CRC::Calculate(&description, sizeof(FramebufferDescription), CRC::CRC_32()); + return CRC::Calculate(&description, sizeof(FramebufferDescription), CRC::CRC_32()); } - -RenderPass::~RenderPass() -{ - vkDestroyRenderPass(graphics->getDevice(), renderPass, nullptr); -} - diff --git a/src/Engine/Graphics/Vulkan/RenderPass.h b/src/Engine/Graphics/Vulkan/RenderPass.h index eeecbde..7e626fa 100644 --- a/src/Engine/Graphics/Vulkan/RenderPass.h +++ b/src/Engine/Graphics/Vulkan/RenderPass.h @@ -11,10 +11,7 @@ class RenderPass : public Gfx::RenderPass public: RenderPass(PGraphics graphics, Gfx::ORenderTargetLayout layout, Gfx::PViewport viewport); virtual ~RenderPass(); - constexpr uint32 getFramebufferHash() const - { - return framebufferHash; - } + uint32 getFramebufferHash(); constexpr VkRenderPass getHandle() const { return renderPass; diff --git a/src/Engine/Graphics/Vulkan/RenderTarget.cpp b/src/Engine/Graphics/Vulkan/RenderTarget.cpp deleted file mode 100644 index 6badd0e..0000000 --- a/src/Engine/Graphics/Vulkan/RenderTarget.cpp +++ /dev/null @@ -1,412 +0,0 @@ -#include "RenderTarget.h" -#include "Resources.h" -#include "Graphics.h" -#include "Enums.h" -#include "Command.h" -#include - -using namespace Seele; -using namespace Seele::Vulkan; - -double currentFrameDelta = 0; -double Gfx::getCurrentFrameDelta() -{ - return currentFrameDelta; -} - -void glfwKeyCallback(GLFWwindow* handle, int key, int, int action, int modifier) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->keyCallback((KeyCode)key, (InputAction)action, (KeyModifier)modifier); -} - -void glfwMouseMoveCallback(GLFWwindow* handle, double xpos, double ypos) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->mouseMoveCallback(xpos, ypos); -} - -void glfwMouseButtonCallback(GLFWwindow* handle, int button, int action, int modifier) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->mouseButtonCallback((MouseButton)button, (InputAction)action, (KeyModifier)modifier); -} - -void glfwScrollCallback(GLFWwindow* handle, double xoffset, double yoffset) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->scrollCallback(xoffset, yoffset); -} - -void glfwFileCallback(GLFWwindow* handle, int count, const char** paths) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->fileCallback(count, paths); -} - -void glfwCloseCallback(GLFWwindow* handle) -{ - Window* window = (Window*)glfwGetWindowUserPointer(handle); - window->closeCallback(); -} - -Window::Window(PGraphics graphics, const WindowCreateInfo &createInfo) - : Gfx::Window(createInfo) - , graphics(graphics) - , instance(graphics->getInstance()) - , swapchain(VK_NULL_HANDLE) - , numSamples(createInfo.numSamples) -{ - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - GLFWwindow *handle = glfwCreateWindow(createInfo.width, createInfo.height, createInfo.title, createInfo.bFullscreen ? glfwGetPrimaryMonitor() : nullptr, nullptr); - windowHandle = handle; - glfwSetWindowUserPointer(handle, this); - glfwGetWindowSize(handle, &windowState.width, &windowState.height); - - glfwSetKeyCallback(handle, &glfwKeyCallback); - glfwSetCursorPosCallback(handle, &glfwMouseMoveCallback); - glfwSetMouseButtonCallback(handle, &glfwMouseButtonCallback); - glfwSetScrollCallback(handle, &glfwScrollCallback); - glfwSetDropCallback(handle, &glfwFileCallback); - glfwSetWindowCloseCallback(handle, &glfwCloseCallback); - - glfwCreateWindowSurface(instance, handle, nullptr, &surface); - - uint32_t numQueueFamilies = 0; - vkGetPhysicalDeviceQueueFamilyProperties(graphics->getPhysicalDevice(), &numQueueFamilies, nullptr); - Array queueProperties(numQueueFamilies); - vkGetPhysicalDeviceQueueFamilyProperties(graphics->getPhysicalDevice(), &numQueueFamilies, queueProperties.data()); - - bool viableDevice = false; - for (uint32 i = 0; i < numQueueFamilies; ++i) - { - VkBool32 supportsPresent; - vkGetPhysicalDeviceSurfaceSupportKHR(graphics->getPhysicalDevice(), i, surface, &supportsPresent); - if (supportsPresent) - { - viableDevice = true; - break; - } - } - if (!viableDevice) - { - std::cerr << "Device not suitable for presenting to surface " << surface << ", use a different one" << std::endl; - } - - recreateSwapchain(windowState); -} - -Window::~Window() -{ - vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr); - vkDestroySurfaceKHR(instance, surface, nullptr); - glfwDestroyWindow(static_cast(windowHandle)); -} - -void Window::beginFrame() -{ - glfwPollEvents(); - advanceBackBuffer(); -} - -void Window::endFrame() -{ - present(); -} - -void Window::onWindowCloseEvent() -{ -} - -Gfx::PTexture2D Window::getBackBuffer() -{ - return PTexture2D(backBufferImages[currentImageIndex]); -} - -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::advanceBackBuffer() -{ - VkResult res = VK_ERROR_OUT_OF_DATE_KHR; - uint32 imageIndex = 0; - const int32 prevSemaphoreIndex = semaphoreIndex; - semaphoreIndex = (semaphoreIndex + 1) % Gfx::numFramesBuffered; - - while (res != VK_SUCCESS) - { - res = vkAcquireNextImageKHR( - graphics->getDevice(), - swapchain, - UINT64_MAX, - imageAcquired[semaphoreIndex]->getHandle(), - VK_NULL_HANDLE, - &imageIndex); - if (res == VK_ERROR_OUT_OF_DATE_KHR) - { - semaphoreIndex = prevSemaphoreIndex; - } - if (res == VK_ERROR_SURFACE_LOST_KHR) - { - semaphoreIndex = prevSemaphoreIndex; - } - } - imageAcquiredSemaphore = imageAcquired[semaphoreIndex]; - currentImageIndex = imageIndex; - - backBufferImages[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - VkClearColorValue clearColor = {0.0f, 0.0f, 0.0f, 0.0f}; - PCommand command = graphics->getGraphicsCommands()->getCommands(); - VkImageSubresourceRange range = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - }; - vkCmdClearColorImage( - command->getHandle(), - backBufferHandles[currentImageIndex], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - &clearColor, - 1, - &range); - - backBufferImages[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, imageAcquiredSemaphore); - graphics->getGraphicsCommands()->submitCommands(); -} - -void Window::recreateSwapchain(const WindowCreateInfo &windowInfo) -{ - destroySwapchain(); - windowState = windowInfo; - uint32_t numFormats; - VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(graphics->getPhysicalDevice(), surface, &numFormats, nullptr)); - Array formats(numFormats); - VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(graphics->getPhysicalDevice(), surface, &numFormats, formats.data())); - - uint32_t numPresentModes; - VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, nullptr)); - Array modes(numPresentModes); - VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, modes.data())); - - chooseSurfaceFormat(formats, windowInfo.pixelFormat); - choosePresentMode(modes); - createSwapchain(); -} - -static uint32_t currentFrameIndex = 0; - -void Window::present() -{ - backBufferImages[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR); - graphics->getGraphicsCommands()->submitCommands(renderFinished[currentImageIndex]); - VkSemaphore renderFinishedHandle = renderFinished[currentImageIndex]->getHandle(); - VkPresentInfoKHR info = { - .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - .pNext = nullptr, - .waitSemaphoreCount = 1, - .pWaitSemaphores = &renderFinishedHandle, - .swapchainCount = 1, - .pSwapchains = &swapchain, - .pImageIndices = (uint32*)¤tImageIndex, - .pResults = 0, - }; - VkResult presentResult = VK_ERROR_OUT_OF_DATE_KHR; - // Trial and error - while (presentResult != VK_SUCCESS) - { - presentResult = vkQueuePresentKHR(graphics->getGraphicsCommands()->getQueue()->getHandle(), &info); - } - currentFrameIndex = (currentFrameIndex + 1) % Gfx::numFramesBuffered; - static double lastFrameTime = 0.f; - double currentTime = glfwGetTime(); - double currentDelta = currentTime - lastFrameTime; - currentFrameDelta = currentDelta; - lastFrameTime = currentTime; -} - -void Window::createSwapchain() -{ - VkSurfaceCapabilitiesKHR surfProperties; - VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(graphics->getPhysicalDevice(), surface, &surfProperties)); - - uint32 desiredNumBuffers = Gfx::numFramesBuffered; - if (desiredNumBuffers < surfProperties.minImageCount) - { - throw new std::logic_error("Trying to buffer less than the minimal number of frames"); - } - if (desiredNumBuffers > surfProperties.maxImageCount) - { - throw new std::logic_error("Trying to buffer more than the maximum number of frames"); - } - - VkSwapchainCreateInfoKHR swapchainInfo = { - .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .pNext = nullptr, - .flags = 0, - .surface = surface, - .minImageCount = desiredNumBuffers, - .imageFormat = surfaceFormat.format, - .imageColorSpace = surfaceFormat.colorSpace, - .imageExtent = { - .width = getWidth(), - .height = getHeight(), - }, - .imageArrayLayers = 1, - .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, - .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, - .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - .presentMode = presentMode, - .clipped = VK_TRUE, - }; - VK_CHECK(vkCreateSwapchainKHR(graphics->getDevice(), &swapchainInfo, nullptr, &swapchain)); - - uint32 numSwapchainImages; - VK_CHECK(vkGetSwapchainImagesKHR(graphics->getDevice(), swapchain, &numSwapchainImages, nullptr)); - Array swapchainImages(numSwapchainImages); - VK_CHECK(vkGetSwapchainImagesKHR(graphics->getDevice(), swapchain, &numSwapchainImages, swapchainImages.data())); - - - TextureCreateInfo backBufferCreateInfo = { - .sourceData = { - .owner = Gfx::QueueType::GRAPHICS, - }, - .format = cast(surfaceFormat.format), - .width = getWidth(), - .height = getHeight(), - .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - }; - for (uint32 i = 0; i < numSwapchainImages; ++i) - { - imageAcquired[i] = new Semaphore(graphics); - renderFinished[i] = new Semaphore(graphics); - backBufferImages[i] = new Texture2D(graphics, backBufferCreateInfo, swapchainImages[i]); - backBufferHandles[i] = swapchainImages[i]; - - VkClearColorValue clearColor; - std::memset(&clearColor, 0, sizeof(VkClearColorValue)); - backBufferImages[i]->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - VkImageSubresourceRange range = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }; - PCommand command = graphics->getGraphicsCommands()->getCommands(); - vkCmdClearColorImage(command->getHandle(), backBufferHandles[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range); - backBufferImages[i]->changeLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } - graphics->getGraphicsCommands()->submitCommands(); - currentImageIndex = -1; -} - -void Window::destroySwapchain() -{ - if (swapchain != VK_NULL_HANDLE) - { - vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr); - } - for (uint32 i = 0; i < Gfx::numFramesBuffered; ++i) - { - imageAcquired[i] = nullptr; - } -} - -void Window::chooseSurfaceFormat(const Array &available, Gfx::SeFormat preferred) -{ - VkFormat preferredFormat = cast(preferred); - for (auto availabeFormat : available) - { - if (availabeFormat.format == preferredFormat) - { - surfaceFormat = availabeFormat; - return; - } - } - if (available.size() == 1 && available[0].format == VK_FORMAT_UNDEFINED) - { - surfaceFormat = {VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}; - return; - } - for (const auto &availableFormat : available) - { - if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) - { - surfaceFormat = availableFormat; - return; - } - } - surfaceFormat = available[0]; -} -void Window::choosePresentMode(const Array &modes) -{ - for (auto mode : modes) - { - if (mode == VK_PRESENT_MODE_MAILBOX_KHR) - { - presentMode = mode; - return; - } - } - presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; -} - -Viewport::Viewport(PGraphics graphics, PWindow owner, const ViewportCreateInfo &viewportInfo) - : Gfx::Viewport(owner, viewportInfo), graphics(graphics) -{ - handle.width = static_cast(sizeX); - handle.height = static_cast(sizeY); - handle.x = static_cast(offsetX); - handle.y = static_cast(offsetY) + handle.height; - handle.height = -handle.height; - handle.minDepth = 0.f; - handle.maxDepth = 1.f; -} - -Viewport::~Viewport() -{ -} - -void Viewport::resize(uint32 newX, uint32 newY) -{ - sizeX = newX; - sizeY = newY; - handle.width = static_cast(sizeX); - handle.y = static_cast(sizeY + offsetX); - handle.height = -static_cast(sizeY); -} - -void Viewport::move(uint32 newOffsetX, uint32 newOffsetY) -{ - offsetX = newOffsetX; - offsetY = newOffsetY; - handle.x = static_cast(offsetX); - handle.y = static_cast(offsetY + sizeY); -} diff --git a/src/Engine/Graphics/Vulkan/Texture.cpp b/src/Engine/Graphics/Vulkan/Texture.cpp index 6c6f222..8e1a892 100644 --- a/src/Engine/Graphics/Vulkan/Texture.cpp +++ b/src/Engine/Graphics/Vulkan/Texture.cpp @@ -197,7 +197,9 @@ void TextureBase::changeLayout(Gfx::SeImageLayout newLayout) .image = image, .subresourceRange = { .aspectMask = aspect, + .baseMipLevel = 0, .levelCount = 1, + .baseArrayLayer = 0, .layerCount = layerCount, }, }; @@ -328,6 +330,10 @@ void TextureBase::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStag .image = image, .subresourceRange = { .aspectMask = aspect, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, }, }; PCommand command = graphics->getQueueCommands(currentOwner)->getCommands(); diff --git a/src/Engine/Graphics/Vulkan/Window.cpp b/src/Engine/Graphics/Vulkan/Window.cpp new file mode 100644 index 0000000..43ca0b5 --- /dev/null +++ b/src/Engine/Graphics/Vulkan/Window.cpp @@ -0,0 +1,304 @@ +#include "Window.h" +#include "Resources.h" +#include "Graphics.h" +#include "Enums.h" +#include "Command.h" +#include + +using namespace Seele; +using namespace Seele::Vulkan; + +double currentFrameDelta = 0; +double Gfx::getCurrentFrameDelta() +{ + return currentFrameDelta; +} + +void glfwKeyCallback(GLFWwindow* handle, int key, int, int action, int modifier) +{ + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->keyCallback((KeyCode)key, (InputAction)action, (KeyModifier)modifier); +} + +void glfwMouseMoveCallback(GLFWwindow* handle, double xpos, double ypos) +{ + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->mouseMoveCallback(xpos, ypos); +} + +void glfwMouseButtonCallback(GLFWwindow* handle, int button, int action, int modifier) +{ + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->mouseButtonCallback((MouseButton)button, (InputAction)action, (KeyModifier)modifier); +} + +void glfwScrollCallback(GLFWwindow* handle, double xoffset, double yoffset) +{ + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->scrollCallback(xoffset, yoffset); +} + +void glfwFileCallback(GLFWwindow* handle, int count, const char** paths) +{ + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->fileCallback(count, paths); +} + +void glfwCloseCallback(GLFWwindow* handle) +{ + Window* window = (Window*)glfwGetWindowUserPointer(handle); + window->closeCallback(); +} + +Window::Window(PGraphics graphics, const WindowCreateInfo &createInfo) + : graphics(graphics) + , preferences(createInfo) + , instance(graphics->getInstance()) + , swapchain(VK_NULL_HANDLE) + , numSamples(createInfo.numSamples) +{ + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + GLFWwindow *handle = glfwCreateWindow(createInfo.width, createInfo.height, 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); + + glfwCreateWindowSurface(instance, handle, nullptr, &surface); + + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(graphics->getPhysicalDevice(), surface, &capabilities); + + uint32 numFormats; + vkGetPhysicalDeviceSurfaceFormatsKHR(graphics->getPhysicalDevice(), surface, &numFormats, nullptr); + supportedFormats.resize(numFormats); + vkGetPhysicalDeviceSurfaceFormatsKHR(graphics->getPhysicalDevice(), surface, &numFormats, supportedFormats.data()); + + uint32 numPresentModes; + vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, nullptr); + supportedPresentModes.resize(numFormats); + vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, supportedPresentModes.data()); + chooseSwapSurfaceFormat(); + framebufferFormat = cast(format.format); + chooseSwapPresentMode(); + chooseSwapExtent(); + framebufferWidth = extent.width; + framebufferHeight = extent.height; + sampleFlags = createInfo.numSamples; + createSwapChain(); +} + +Window::~Window() +{ + vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr); + vkDestroySurfaceKHR(instance, surface, nullptr); + glfwDestroyWindow(static_cast(windowHandle)); +} + +void Window::beginFrame() +{ + glfwPollEvents(); + vkAcquireNextImageKHR(graphics->getDevice(), swapchain, std::numeric_limits::max(), imageAvailableSemaphores[currentSemaphoreIndex]->getHandle(), VK_NULL_HANDLE, ¤tImageIndex); + swapChainTextures[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, imageAvailableSemaphores[currentSemaphoreIndex]); +} + +void Window::endFrame() +{ + swapChainTextures[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR); + graphics->getGraphicsCommands()->submitCommands(renderingDoneSemaphores[currentSemaphoreIndex]); + VkSemaphore renderDoneHandle = renderingDoneSemaphores[currentSemaphoreIndex]->getHandle(); + VkPresentInfoKHR presentInfo = { + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .pNext = nullptr, + .waitSemaphoreCount = 1, + .pWaitSemaphores = &renderDoneHandle, + .swapchainCount = 1, + .pSwapchains = &swapchain, + .pImageIndices = ¤tImageIndex, + .pResults = nullptr, + }; + VkResult r = vkQueuePresentKHR(graphics->getGraphicsCommands()->getQueue()->getHandle(), &presentInfo); + if(r == VK_SUCCESS) + { } + else if (r == VK_ERROR_OUT_OF_DATE_KHR || r == VK_SUBOPTIMAL_KHR) + { + createSwapChain(); + } + else + { + VK_CHECK(r); + } + currentSemaphoreIndex = (currentSemaphoreIndex + 1) % Gfx::numFramesBuffered; +} + +void Window::onWindowCloseEvent() +{ +} + +Gfx::PTexture2D Window::getBackBuffer() +{ + return PTexture2D(swapChainTextures[currentImageIndex]); +} + +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::chooseSwapSurfaceFormat() +{ + for (const auto& supportedFormat : supportedFormats) + { + if (supportedFormat.format == cast(preferences.preferredFormat)) + { + format = supportedFormat; + return; + } + } + for (const auto& supportedFormat : supportedFormats) + { + if (supportedFormat.format == VK_FORMAT_R8G8B8A8_SRGB && supportedFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + { + format = supportedFormat; + return; + } + } + format = supportedFormats[0]; +} + +void Window::chooseSwapPresentMode() +{ + for (const auto& supportedPresentMode : supportedPresentModes) + { + if (supportedPresentMode == VK_PRESENT_MODE_MAILBOX_KHR) + { + presentMode = supportedPresentMode; + return; + } + } + presentMode = VK_PRESENT_MODE_FIFO_KHR; +} + +void Window::chooseSwapExtent() +{ + if (capabilities.currentExtent.width != std::numeric_limits::max()) { + extent = capabilities.currentExtent; + return; + } + int width, height; + glfwGetFramebufferSize(static_cast(windowHandle), &width, &height); + + extent = { + static_cast(width), + static_cast(height), + }; + extent.width = std::clamp(extent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); + extent.height = std::clamp(extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); +} + +void Window::createSwapChain() +{ + uint32 imageCount = Gfx::numFramesBuffered; + VkSwapchainCreateInfoKHR createInfo = { + .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + .pNext = nullptr, + .surface = surface, + .minImageCount = Gfx::numFramesBuffered, + .imageFormat = format.format, + .imageColorSpace = format.colorSpace, + .imageExtent = extent, + .imageArrayLayers = 1, + .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, + .preTransform = capabilities.currentTransform, + .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + .presentMode = presentMode, + .clipped = VK_TRUE, + .oldSwapchain = swapchain, + }; + VK_CHECK(vkCreateSwapchainKHR(graphics->getDevice(), &createInfo, nullptr, &swapchain)); + + uint32 numImages; + vkGetSwapchainImagesKHR(graphics->getDevice(), swapchain, &numImages, swapChainImages.data()); + + assert(numImages == Gfx::numFramesBuffered); + for (uint32 i = 0; i < numImages; ++i) + { + swapChainTextures[i] = new Texture2D(graphics, TextureCreateInfo{ + .format = cast(format.format), + .width = extent.width, + .height = extent.height, + .depth = 1, + .mipLevels = 1, + .layers = 1, + .elements = 1, + .samples = 1, + .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + }, swapChainImages[i]); + imageAvailableSemaphores[i] = new Semaphore(graphics); + renderingDoneSemaphores[i] = new Semaphore(graphics); + } +} + +Viewport::Viewport(PGraphics graphics, PWindow owner, const ViewportCreateInfo &viewportInfo) + : Gfx::Viewport(owner, viewportInfo), graphics(graphics) +{ + handle.width = static_cast(sizeX); + handle.height = static_cast(sizeY); + handle.x = static_cast(offsetX); + handle.y = static_cast(offsetY) + handle.height; + handle.height = -handle.height; + handle.minDepth = 0.f; + handle.maxDepth = 1.f; +} + +Viewport::~Viewport() +{ +} + +void Viewport::resize(uint32 newX, uint32 newY) +{ + sizeX = newX; + sizeY = newY; + handle.width = static_cast(sizeX); + handle.y = static_cast(sizeY + offsetX); + handle.height = -static_cast(sizeY); +} + +void Viewport::move(uint32 newOffsetX, uint32 newOffsetY) +{ + offsetX = newOffsetX; + offsetY = newOffsetY; + handle.x = static_cast(offsetX); + handle.y = static_cast(offsetY + sizeY); +} diff --git a/src/Engine/Graphics/Vulkan/RenderTarget.h b/src/Engine/Graphics/Vulkan/Window.h similarity index 71% rename from src/Engine/Graphics/Vulkan/RenderTarget.h rename to src/Engine/Graphics/Vulkan/Window.h index 1b96bca..088b7be 100644 --- a/src/Engine/Graphics/Vulkan/RenderTarget.h +++ b/src/Engine/Graphics/Vulkan/Window.h @@ -24,11 +24,6 @@ public: virtual void setFileCallback(std::function callback) override; virtual void setCloseCallback(std::function callback); - VkFormat getPixelFormat() const - { - return cast(windowState.pixelFormat); - } - std::function keyCallback; std::function mouseMoveCallback; std::function mouseButtonCallback; @@ -36,32 +31,30 @@ public: std::function fileCallback; std::function closeCallback; protected: - void advanceBackBuffer(); - void recreateSwapchain(const WindowCreateInfo &createInfo); - void present(); - void destroySwapchain(); - void createSwapchain(); - void chooseSurfaceFormat(const Array &available, Gfx::SeFormat preferred); - void choosePresentMode(const Array &modes); - - OTexture2D backBufferImages[Gfx::numFramesBuffered]; - VkImage backBufferHandles[Gfx::numFramesBuffered]; - OSemaphore renderFinished[Gfx::numFramesBuffered]; - OSemaphore imageAcquired[Gfx::numFramesBuffered]; - PSemaphore imageAcquiredSemaphore; - + void chooseSwapSurfaceFormat(); + void chooseSwapPresentMode(); + void chooseSwapExtent(); + void createSwapChain(); PGraphics graphics; + WindowCreateInfo preferences; VkInstance instance; VkSwapchainKHR swapchain; VkSampleCountFlags numSamples; - VkPresentModeKHR presentMode; VkSurfaceKHR surface; - VkSurfaceFormatKHR surfaceFormat; + VkSurfaceCapabilitiesKHR capabilities; + Array supportedFormats; + Array supportedPresentModes; + // the values used for the current swapchain + VkSurfaceFormatKHR format; + VkPresentModeKHR presentMode; + VkExtent2D extent; void *windowHandle; - int32 currentImageIndex; - int32 acquiredImageIndex; - int32 preAcquiredImageIndex; - int32 semaphoreIndex; + StaticArray swapChainImages; + StaticArray swapChainTextures; + StaticArray imageAvailableSemaphores; + StaticArray renderingDoneSemaphores; + uint32 currentImageIndex = 0; + uint32 currentSemaphoreIndex = 0; }; DEFINE_REF(Window) diff --git a/src/Engine/Graphics/Window.cpp b/src/Engine/Graphics/Window.cpp new file mode 100644 index 0000000..4148c4f --- /dev/null +++ b/src/Engine/Graphics/Window.cpp @@ -0,0 +1,39 @@ +#include "Window.h" + +using namespace Seele; +using namespace Seele::Gfx; + + +Window::Window() +{ +} + +Window::~Window() +{ +} + +Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo) + : sizeX(std::min(owner->getFramebufferWidth(), viewportInfo.dimensions.size.x)) + , sizeY(std::min(owner->getFramebufferHeight(), viewportInfo.dimensions.size.y)) + , offsetX(viewportInfo.dimensions.offset.x) + , offsetY(viewportInfo.dimensions.offset.y) + , fieldOfView(viewportInfo.fieldOfView) + , owner(owner) +{ +} + +Viewport::~Viewport() +{ +} + +Matrix4 Viewport::getProjectionMatrix() const +{ + if (fieldOfView > 0.0f) + { + return glm::perspective(fieldOfView, sizeX / static_cast(sizeY), 0.1f, 1000.0f); + } + else + { + return glm::ortho(0.0f, (float)sizeX, (float)sizeY, 0.0f); + } +} \ No newline at end of file diff --git a/src/Engine/Graphics/Window.h b/src/Engine/Graphics/Window.h new file mode 100644 index 0000000..32e7faa --- /dev/null +++ b/src/Engine/Graphics/Window.h @@ -0,0 +1,73 @@ +#pragma once +#include "Initializer.h" +#include "Texture.h" + +namespace Seele +{ +namespace Gfx +{ +class Window +{ +public: + Window(); + virtual ~Window(); + virtual void beginFrame() = 0; + virtual void endFrame() = 0; + virtual void onWindowCloseEvent() = 0; + virtual PTexture2D getBackBuffer() = 0; + virtual void setKeyCallback(std::function callback) = 0; + virtual void setMouseMoveCallback(std::function callback) = 0; + virtual void setMouseButtonCallback(std::function callback) = 0; + virtual void setScrollCallback(std::function callback) = 0; + virtual void setFileCallback(std::function callback) = 0; + virtual void setCloseCallback(std::function callback) = 0; + constexpr SeFormat getSwapchainFormat() const + { + return framebufferFormat; + } + constexpr SeSampleCountFlags getNumSamples() const + { + return sampleFlags; + } + constexpr uint32 getFramebufferWidth() const + { + return framebufferWidth; + } + constexpr uint32 getFramebufferHeight() const + { + return framebufferHeight; + } + +protected: + SeFormat framebufferFormat; + SeSampleCountFlags sampleFlags; + uint32 framebufferWidth; + uint32 framebufferHeight; +}; +DEFINE_REF(Window) + + class Viewport +{ +public: + Viewport(PWindow owner, const ViewportCreateInfo& createInfo); + virtual ~Viewport(); + virtual void resize(uint32 newX, uint32 newY) = 0; + virtual void move(uint32 newOffsetX, uint32 newOffsetY) = 0; + constexpr PWindow getOwner() const { return owner; } + constexpr uint32 getWidth() const { return sizeX; } + constexpr uint32 getHeight() const { return sizeY; } + constexpr uint32 getOffsetX() const { return offsetX; } + constexpr uint32 getOffsetY() const { return offsetY; } + Matrix4 getProjectionMatrix() const; +protected: + uint32 sizeX; + uint32 sizeY; + uint32 offsetX; + uint32 offsetY; + float fieldOfView; + PWindow owner; +}; +DEFINE_REF(Viewport) + +} +} \ No newline at end of file diff --git a/src/Engine/Window/Window.cpp b/src/Engine/Window/Window.cpp index bf01e3d..20cae77 100644 --- a/src/Engine/Window/Window.cpp +++ b/src/Engine/Window/Window.cpp @@ -33,6 +33,7 @@ void Window::render() view->render(); } gfxHandle->endFrame(); + std::cout << "Render" << std::endl; } }