diff --git a/src/modules/graphics/vulkan/Buffer.cpp b/src/modules/graphics/vulkan/Buffer.cpp index eade4fda3..7217b512a 100644 --- a/src/modules/graphics/vulkan/Buffer.cpp +++ b/src/modules/graphics/vulkan/Buffer.cpp @@ -25,7 +25,7 @@ namespace love { return vkFlags; } - Buffer::Buffer(VmaAllocator allocator, love::graphics::Graphics* gfx, const Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength) + Buffer::Buffer(love::graphics::Graphics* gfx, const Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength) : love::graphics::Buffer(gfx, settings, format, size, arraylength), usageFlags(settings.usageFlags), allocator(allocator), gfx(gfx) { loadVolatile(); } diff --git a/src/modules/graphics/vulkan/Buffer.h b/src/modules/graphics/vulkan/Buffer.h index 854250006..20985dc00 100644 --- a/src/modules/graphics/vulkan/Buffer.h +++ b/src/modules/graphics/vulkan/Buffer.h @@ -9,7 +9,7 @@ namespace love { namespace vulkan { class Buffer : public love::graphics::Buffer, public Volatile { public: - Buffer(VmaAllocator allocator, love::graphics::Graphics* gfx, const Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength); + Buffer(love::graphics::Graphics* gfx, const Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength); virtual ~Buffer(); virtual bool loadVolatile() override; diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index f1c8fe248..3c0385d5a 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -38,12 +38,14 @@ namespace love { }; #ifdef NDEBUG - const bool enableValidationLayers = false; + constexpr bool enableValidationLayers = false; #else - const bool enableValidationLayers = true; + constexpr bool enableValidationLayers = true; #endif - const int MAX_FRAMES_IN_FLIGHT = 2; + constexpr int MAX_FRAMES_IN_FLIGHT = 2; + + constexpr uint32_t vulkanApiVersion = VK_API_VERSION_1_3; const char* Graphics::getName() const { return "love.graphics.vulkan"; @@ -77,8 +79,7 @@ namespace love { } love::graphics::Buffer* Graphics::newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength) { - std::cout << "newBuffer "; - return new Buffer(vmaAllocator, this, settings, format, data, size, arraylength); + return new Buffer(this, settings, format, data, size, arraylength); } void Graphics::present(void* screenshotCallbackdata) { @@ -135,8 +136,6 @@ namespace love { throw love::Exception("failed to present swap chain image"); } - std::cout << "present" << std::endl; - currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; updatedBatchedDrawBuffers(); @@ -144,7 +143,6 @@ namespace love { } void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) { - std::cout << "setViewPortSize "; this->width = width; this->height = height; this->pixelWidth = pixelwidth; @@ -156,8 +154,6 @@ namespace love { } bool Graphics::setMode(void* context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) { - std::cout << "setMode "; - createVulkanInstance(); createSurface(); pickPhysicalDevice(); @@ -166,10 +162,8 @@ namespace love { initCapabilities(); createSwapChain(); createImageViews(); - createRenderPass(); createDefaultShaders(); createDescriptorSetLayout(); - createFramebuffers(); createCommandPool(); createCommandBuffers(); createDefaultTexture(); @@ -211,8 +205,6 @@ namespace love { } void Graphics::initCapabilities() { - std::cout << "initCapabilities "; - // todo capabilities.features[FEATURE_MULTI_RENDER_TARGET_FORMATS] = false; capabilities.features[FEATURE_CLAMP_ZERO] = false; @@ -258,8 +250,6 @@ namespace love { } void Graphics::unSetMode() { - std::cout << "unSetMode "; - created = false; vkDeviceWaitIdle(device); Volatile::unloadAll(); @@ -291,8 +281,6 @@ namespace love { } void Graphics::setPointSize(float size) { - std::cout << "setPointSize "; - if (size != states.back().pointSize) flushBatchedDraws(); @@ -300,8 +288,6 @@ namespace love { } bool Graphics::usesGLSLES() const { - std::cout << "usesGLSLES "; - return false; } @@ -319,16 +305,12 @@ namespace love { } void Graphics::draw(const DrawCommand& cmd) { - std::cout << "draw "; - prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType, cmd.cullMode); vkCmdDraw(commandBuffers.at(imageIndex), static_cast(cmd.vertexCount), static_cast(cmd.instanceCount), static_cast(cmd.vertexStart), 0); } void Graphics::draw(const DrawIndexedCommand& cmd) { - std::cout << "drawIndexed "; - prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType, cmd.cullMode); vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer)cmd.indexBuffer->getHandle(), static_cast(cmd.indexBufferOffset), getVulkanIndexBufferType(cmd.indexType)); @@ -336,8 +318,6 @@ namespace love { } void Graphics::setColor(Colorf c) { - std::cout << "setColor "; - c.r = std::min(std::max(c.r, 0.0f), 1.0f); c.g = std::min(std::max(c.g, 0.0f), 1.0f); c.b = std::min(std::max(c.b, 0.0f), 1.0f); @@ -347,8 +327,6 @@ namespace love { } void Graphics::setWireframe(bool enable) { - std::cout << "setWireframe "; - flushBatchedDraws(); if (enable) { @@ -362,8 +340,6 @@ namespace love { } PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const { - std::cout << "getSizedFormat "; - switch (format) { PIXELFORMAT_NORMAL: if (isGammaCorrect()) { @@ -380,20 +356,14 @@ namespace love { } bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) { - std::cout << "isPixelFormatSupported "; - return true; } Renderer Graphics::getRenderer() const { - std::cout << "getRenderer "; - return RENDERER_VULKAN; } void Graphics::drawQuads(int start, int count, const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture) { - std::cout << "drawQuads "; - const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX; const int MAX_QUADS_PER_DRAW = MAX_VERTICES_PER_DRAW / 4; @@ -412,7 +382,6 @@ namespace love { } graphics::StreamBuffer* Graphics::newStreamBuffer(BufferUsage type, size_t size) { - std::cout << "newStreamBuffer "; return new StreamBuffer(this, type, size); } @@ -420,6 +389,9 @@ namespace love { uint32 flags = DEVICE_PROJECTION_DEFAULT; return calculateDeviceProjection(projection, flags); } + + void Graphics::setRenderTargetsInternal(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture) { + } // END IMPLEMENTATION OVERRIDDEN FUNCTIONS @@ -444,29 +416,39 @@ namespace love { beginInfo.flags = 0; beginInfo.pInheritanceInfo = nullptr; - std::cout << "beginCommandBuffer(imageIndex=" << imageIndex << ") "; if (vkBeginCommandBuffer(commandBuffers.at(imageIndex), &beginInfo) != VK_SUCCESS) { throw love::Exception("failed to begin recording command buffer"); } - VkRenderPassBeginInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassInfo.renderPass = renderPass; - renderPassInfo.framebuffer = swapChainFramBuffers.at(imageIndex); - renderPassInfo.renderArea.offset = { 0, 0 }; - renderPassInfo.renderArea.extent = swapChainExtent; - renderPassInfo.clearValueCount = 1; - renderPassInfo.pClearValues = &clearColor; + VkRenderingAttachmentInfo colorAttachmentInfo{}; + colorAttachmentInfo.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; + colorAttachmentInfo.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL; + colorAttachmentInfo.imageView = swapChainImageViews[imageIndex]; + colorAttachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorAttachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachmentInfo.clearValue = clearColor; + + VkRenderingInfo renderingInfo{}; + renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + renderingInfo.renderArea.extent = swapChainExtent; + renderingInfo.layerCount = 1; + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachments = &colorAttachmentInfo; + + Vulkan::cmdTransitionImageLayout(commandBuffers.at(imageIndex), swapChainImages[imageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + vkCmdBeginRendering(commandBuffers.at(imageIndex), &renderingInfo); - vkCmdBeginRenderPass(commandBuffers.at(imageIndex), &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); currentGraphicsPipeline = VK_NULL_HANDLE; } void Graphics::endRecordingGraphicsCommands() { const auto& commandBuffer = commandBuffers.at(imageIndex); - std::cout << "endCommandBuffer(imageIndex=" << imageIndex << ") "; - vkCmdEndRenderPass(commandBuffers.at(imageIndex)); + vkCmdEndRendering(commandBuffer); + + Vulkan::cmdTransitionImageLayout(commandBuffer, swapChainImages[imageIndex], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + if (vkEndCommandBuffer(commandBuffers.at(imageIndex)) != VK_SUCCESS) { throw love::Exception("failed to record command buffer"); } @@ -601,7 +583,7 @@ namespace love { appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); //todo, get this version from somewhere else? appInfo.pEngineName = "LOVE Engine"; appInfo.engineVersion = VK_MAKE_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_REV); - appInfo.apiVersion = VK_API_VERSION_1_0; + appInfo.apiVersion = vulkanApiVersion; VkInstanceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; @@ -809,6 +791,10 @@ namespace love { queueCreateInfos.push_back(queueCreateInfo); } + VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeature{}; + dynamicRenderingFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES; + dynamicRenderingFeature.dynamicRendering = VK_TRUE; + VkPhysicalDeviceFeatures deviceFeatures{}; deviceFeatures.samplerAnisotropy = VK_TRUE; @@ -817,7 +803,7 @@ namespace love { createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); createInfo.pQueueCreateInfos = queueCreateInfos.data(); createInfo.pEnabledFeatures = &deviceFeatures; - createInfo.pNext = nullptr; + createInfo.pNext = &dynamicRenderingFeature; createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); createInfo.ppEnabledExtensionNames = deviceExtensions.data(); @@ -845,7 +831,7 @@ namespace love { vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr; VmaAllocatorCreateInfo allocatorCreateInfo = {}; - allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_0; + allocatorCreateInfo.vulkanApiVersion = vulkanApiVersion; allocatorCreateInfo.physicalDevice = physicalDevice; allocatorCreateInfo.device = device; allocatorCreateInfo.instance = instance; @@ -1013,48 +999,6 @@ namespace love { } } - void Graphics::createRenderPass() { - VkAttachmentDescription colorAttachment{}; - colorAttachment.format = swapChainImageFormat; - colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference colorAttachmentRef{}; - colorAttachmentRef.attachment = 0; - colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass{}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorAttachmentRef; - - VkSubpassDependency dependency{}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - VkRenderPassCreateInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = 1; - renderPassInfo.pAttachments = &colorAttachment; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 1; - renderPassInfo.pDependencies = &dependency; - - if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) { - throw love::Exception("failed to create render pass"); - } - } - void Graphics::createDefaultShaders() { for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++) { auto stype = (Shader::StandardShader)i; @@ -1379,6 +1323,11 @@ namespace love { } graphicsPipelineLayouts.push_back(pipelineLayout); + VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo{}; + pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; + pipelineRenderingCreateInfo.colorAttachmentCount = 1; + pipelineRenderingCreateInfo.pColorAttachmentFormats = &swapChainImageFormat; + VkGraphicsPipelineCreateInfo pipelineInfo{}; pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; pipelineInfo.stageCount = static_cast(shaderStages.size()); @@ -1392,10 +1341,10 @@ namespace love { pipelineInfo.pColorBlendState = &colorBlending; pipelineInfo.pDynamicState = nullptr; pipelineInfo.layout = pipelineLayout; - pipelineInfo.renderPass = renderPass; pipelineInfo.subpass = 0; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; pipelineInfo.basePipelineIndex = -1; + pipelineInfo.pNext = &pipelineRenderingCreateInfo; VkPipeline graphicsPipeline; if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) { @@ -1425,35 +1374,13 @@ namespace love { } } - void Graphics::createFramebuffers() { - swapChainFramBuffers.resize(swapChainImageViews.size()); - for (size_t i = 0; i < swapChainImageViews.size(); i++) { - VkImageView attachments[] = { - swapChainImageViews.at(i) - }; - - VkFramebufferCreateInfo framebufferInfo{}; - framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.renderPass = renderPass; - framebufferInfo.attachmentCount = 1; - framebufferInfo.pAttachments = attachments; - framebufferInfo.width = swapChainExtent.width; - framebufferInfo.height = swapChainExtent.height; - framebufferInfo.layers = 1; - - if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramBuffers.at(i)) != VK_SUCCESS) { - throw love::Exception("failed to create framebuffers"); - } - } - } - void Graphics::createCommandPool() { QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); VkCommandPoolCreateInfo poolInfo{}; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value(); - poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) { throw love::Exception("failed to create command pool"); @@ -1461,7 +1388,7 @@ namespace love { } void Graphics::createCommandBuffers() { - commandBuffers.resize(swapChainFramBuffers.size()); + commandBuffers.resize(swapChainImages.size()); VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; @@ -1591,12 +1518,7 @@ namespace love { } void Graphics::cleanupSwapChain() { - std::cout << "cleanupSwapChain "; - vkDestroyDescriptorPool(device, descriptorPool, nullptr); - for (size_t i = 0; i < swapChainFramBuffers.size(); i++) { - vkDestroyFramebuffer(device, swapChainFramBuffers[i], nullptr); - } vkFreeCommandBuffers(device, commandPool, static_cast(commandBuffers.size()), commandBuffers.data()); for (auto const& p : graphicsPipelines) { vkDestroyPipeline(device, p.second, nullptr); @@ -1607,7 +1529,6 @@ namespace love { vkDestroyPipelineLayout(device, pipelineLayout, nullptr); } graphicsPipelineLayouts.clear(); - vkDestroyRenderPass(device, renderPass, nullptr); for (size_t i = 0; i < swapChainImageViews.size(); i++) { vkDestroyImageView(device, swapChainImageViews[i], nullptr); } @@ -1626,8 +1547,6 @@ namespace love { createSwapChain(); createImageViews(); - createRenderPass(); - createFramebuffers(); createDescriptorPool(); createCommandBuffers(); startRecordingGraphicsCommands(); diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index 5408f8647..f945a2e6e 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -85,22 +85,22 @@ namespace love { // implementation for virtual functions love::graphics::Texture* newTexture(const love::graphics::Texture::Settings& settings, const love::graphics::Texture::Slices* data = nullptr) override; love::graphics::Buffer* newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector& format, const void* data, size_t size, size_t arraylength) override; - void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override { std::cout << "clear1 "; } - void clear(const std::vector& colors, OptionalInt stencil, OptionalDouble depth) override { std::cout << "clear2 "; } + void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override { } + void clear(const std::vector& colors, OptionalInt stencil, OptionalDouble depth) override { } Matrix4 computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const override; - void discard(const std::vector& colorbuffers, bool depthstencil) override { std::cout << "discard "; } + void discard(const std::vector& colorbuffers, bool depthstencil) override { } void present(void* screenshotCallbackdata) override; void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override; bool setMode(void* context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override; void unSetMode() override; - void setActive(bool active) override { std::cout << "setActive "; } - int getRequestedBackbufferMSAA() const override { std::cout << "getRequestedBackbufferMSAA "; return 0; } - int getBackbufferMSAA() const override { std::cout << "getBackbufferMSAA "; return 0; } + void setActive(bool active) override { } + int getRequestedBackbufferMSAA() const override { return 0; } + int getBackbufferMSAA() const override { return 0; } void setColor(Colorf c) override; - void setScissor(const Rect& rect) override { std::cout << "setScissor "; } - void setScissor() override { std::cout << "setScissor2 "; } - void setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) override { std::cout << "setStencilMode "; } - void setDepthMode(CompareMode compare, bool write) override { std::cout << "setDepthMode "; } + void setScissor(const Rect& rect) override { } + void setScissor() override { } + void setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) override { } + void setDepthMode(CompareMode compare, bool write) override { } void setFrontFaceWinding(Winding winding) override; void setColorMask(ColorChannelMask mask) override; void setBlendState(const BlendState& blend) override; @@ -123,18 +123,16 @@ namespace love { protected: graphics::ShaderStage* newShaderStageInternal(ShaderStageType stage, const std::string& cachekey, const std::string& source, bool gles) override { - std::cout << "newShaderStageInternal "; return new ShaderStage(this, stage, source, gles, cachekey); } graphics::Shader* newShaderInternal(StrongRef stages[SHADERSTAGE_MAX_ENUM]) override { - std::cout << "newShaderInternal "; return new Shader(stages); } graphics::StreamBuffer* newStreamBuffer(BufferUsage type, size_t size) override; - bool dispatch(int x, int y, int z) override { std::cout << "dispatch "; return false; } + bool dispatch(int x, int y, int z) override { return false; } void initCapabilities() override; - void getAPIStats(int& shaderswitches) const override { std::cout << "getAPIStats "; } - void setRenderTargetsInternal(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture) override { std::cout << "setRenderTargetsInternal "; } + void getAPIStats(int& shaderswitches) const override { } + void setRenderTargetsInternal(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture) override; private: void createVulkanInstance(); @@ -152,13 +150,11 @@ namespace love { VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); void createSwapChain(); void createImageViews(); - void createRenderPass(); void createDefaultShaders(); void createDescriptorSetLayout(); void createDescriptorPool(); std::vector createDescriptorSets(DecriptorSetConfiguration); VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration); - void createFramebuffers(); void createCommandPool(); void createCommandBuffers(); void createSyncObjects(); @@ -192,11 +188,9 @@ namespace love { std::vector swapChainImageViews; VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE; VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; - VkRenderPass renderPass = VK_NULL_HANDLE; VkPipeline currentGraphicsPipeline = VK_NULL_HANDLE; std::vector> graphicsPipelines; // FIXME improve performance by using a hash map std::vector graphicsPipelineLayouts; - std::vector swapChainFramBuffers; VkCommandPool commandPool = VK_NULL_HANDLE; std::vector commandBuffers; VkClearValue clearColor = { {{0.0f, 0.0f, 0.0f, 1.0f}} }; @@ -218,6 +212,8 @@ namespace love { std::vector> uniformBufferMap; std::vector>> descriptorSetsMap; VkPolygonMode currentPolygonMode = VK_POLYGON_MODE_FILL; + + VkCommandBuffer offscreenRendertargetCommandBuffer; }; } } diff --git a/src/modules/graphics/vulkan/Texture.cpp b/src/modules/graphics/vulkan/Texture.cpp index 8f26c6cbe..9cdf05ada 100644 --- a/src/modules/graphics/vulkan/Texture.cpp +++ b/src/modules/graphics/vulkan/Texture.cpp @@ -53,11 +53,25 @@ namespace love { rect.h = sliceData->getHeight(); uploadByteData(format, dataPtr, size, 0, 0, rect); - } - else { - uint8 defaultPixel[] = { 255, 255, 255, 255 }; - Rect rect = { 0, 0, 1, 1 }; - uploadByteData(PIXELFORMAT_RGBA8_UNORM, defaultPixel, sizeof(defaultPixel), 0, 0, rect); + } else { + if (isRenderTarget()) { + std::vector defaultPixels; + defaultPixels.reserve(width * height * 4); + for (size_t i = 0; i < width * height; i++) { + // transparent white + defaultPixels.push_back(255); + defaultPixels.push_back(255); + defaultPixels.push_back(255); + defaultPixels.push_back(0); + } + Rect rect = { 0, 0, width, height }; + uploadByteData(PIXELFORMAT_RGBA8_UNORM, defaultPixels.data(), defaultPixels.size(), 0, 0, rect); + } + else { + std::vector defaultPixels(width * height * 4, 255); + Rect rect = { 0, 0, width, height }; + uploadByteData(PIXELFORMAT_RGBA8_UNORM, defaultPixels.data(), defaultPixels.size(), 0, 0, rect); + } } createTextureImageView(); createTextureSampler(); @@ -137,61 +151,7 @@ namespace love { void Texture::transitionImageLayout(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout) { auto commandBuffer = vgfx->beginSingleTimeCommands(); - VkPipelineStageFlags sourceStage; - VkPipelineStageFlags destinationStage; - - VkImageMemoryBarrier barrier{}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.oldLayout = oldLayout; - barrier.newLayout = newLayout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = image; - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - - if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - barrier.srcAccessMask = 0; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - - sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } - else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_GENERAL) { - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } - else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_GENERAL) { - barrier.srcAccessMask = 0; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT; - - sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT; - destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } - else { - throw love::Exception("unsupported lay transition"); - } - - vkCmdPipelineBarrier( - commandBuffer, - sourceStage, destinationStage, - 0, - 0, nullptr, - 0, nullptr, - 1, &barrier - ); + Vulkan::cmdTransitionImageLayout(commandBuffer, image, oldLayout, newLayout); vgfx->endSingleTimeCommands(commandBuffer); } diff --git a/src/modules/graphics/vulkan/Texture.h b/src/modules/graphics/vulkan/Texture.h index c3310dd07..e123f3271 100644 --- a/src/modules/graphics/vulkan/Texture.h +++ b/src/modules/graphics/vulkan/Texture.h @@ -20,18 +20,18 @@ namespace love { virtual bool loadVolatile() override; virtual void unloadVolatile() override; - void copyFromBuffer(graphics::Buffer* source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect& rect) override { std::cout << "Texture::copyFromBuffer "; }; - void copyToBuffer(graphics::Buffer* dest, int slice, int mipmap, const Rect& rect, size_t destoffset, int destwidth, size_t size) override { std::cout << "Texture::copyToBuffer "; }; + void copyFromBuffer(graphics::Buffer* source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect& rect) override { }; + void copyToBuffer(graphics::Buffer* dest, int slice, int mipmap, const Rect& rect, size_t destoffset, int destwidth, size_t size) override { }; - ptrdiff_t getRenderTargetHandle() const override { std::cout << "Texture::getRenderTargetHandle "; return (ptrdiff_t)0; }; - ptrdiff_t getSamplerHandle() const override { std::cout << "Texture::getSamplerHandle "; return (ptrdiff_t)0; }; + ptrdiff_t getRenderTargetHandle() const override { return (ptrdiff_t)textureImage; }; + ptrdiff_t getSamplerHandle() const override { return (ptrdiff_t)textureSampler; }; void uploadByteData(PixelFormat pixelformat, const void* data, size_t size, int level, int slice, const Rect& r) override; - void generateMipmapsInternal() override { std::cout << "Texture::generateMipmapsInternal "; }; + void generateMipmapsInternal() override { }; - int getMSAA() const override { std::cout << "Texture::getMSAA "; return 0; }; - ptrdiff_t getHandle() const override { std::cout << "Texture::getHandle "; return (ptrdiff_t)textureImage; } + int getMSAA() const override { return 0; }; + ptrdiff_t getHandle() const override { return (ptrdiff_t)textureImage; } VkImageView getImageView() const { return textureImageView; } VkSampler getSampler() const { return textureSampler; } diff --git a/src/modules/graphics/vulkan/Vulkan.cpp b/src/modules/graphics/vulkan/Vulkan.cpp index 7dd097409..21e7e15ec 100644 --- a/src/modules/graphics/vulkan/Vulkan.cpp +++ b/src/modules/graphics/vulkan/Vulkan.cpp @@ -398,6 +398,79 @@ namespace love { throw love::Exception("unknown cull mode"); } } + + void Vulkan::cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout) { + VkImageMemoryBarrier barrier{}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = oldLayout; + barrier.newLayout = newLayout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + + VkPipelineStageFlags sourceStage; + VkPipelineStageFlags destinationStage; + + if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + + sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + } + else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } + else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_GENERAL) { + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } + else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_GENERAL) { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT; + + sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT; + destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } + else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + sourceStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + destinationStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + } + else if (oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { + barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + barrier.dstAccessMask = 0; + + sourceStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + destinationStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + } + else { + throw std::invalid_argument("unsupported layout transition!"); + } + + vkCmdPipelineBarrier( + commandBuffer, + sourceStage, destinationStage, + 0, + 0, nullptr, + 0, nullptr, + 1, &barrier + ); + } } } } diff --git a/src/modules/graphics/vulkan/Vulkan.h b/src/modules/graphics/vulkan/Vulkan.h index 9f62b2dd2..e4d9e9136 100644 --- a/src/modules/graphics/vulkan/Vulkan.h +++ b/src/modules/graphics/vulkan/Vulkan.h @@ -29,6 +29,8 @@ namespace love { static VkColorComponentFlags getColorMask(ColorChannelMask); static VkFrontFace getFrontFace(Winding); static VkCullModeFlags getCullMode(CullMode); + + static void cmdTransitionImageLayout(VkCommandBuffer, VkImage, VkImageLayout oldLayout, VkImageLayout newLayout); }; } }