diff --git a/src/backend/CMakeLists.txt b/src/backend/CMakeLists.txt index a9053403a3..01bdf93dc2 100644 --- a/src/backend/CMakeLists.txt +++ b/src/backend/CMakeLists.txt @@ -297,6 +297,8 @@ if (NXT_ENABLE_VULKAN) ${VULKAN_DIR}/CommandBufferVk.h ${VULKAN_DIR}/FencedDeleter.cpp ${VULKAN_DIR}/FencedDeleter.h + ${VULKAN_DIR}/FramebufferVk.cpp + ${VULKAN_DIR}/FramebufferVk.h ${VULKAN_DIR}/InputStateVk.cpp ${VULKAN_DIR}/InputStateVk.h ${VULKAN_DIR}/MemoryAllocator.cpp diff --git a/src/backend/Framebuffer.h b/src/backend/Framebuffer.h index 2c858002a4..a4dc4cb538 100644 --- a/src/backend/Framebuffer.h +++ b/src/backend/Framebuffer.h @@ -18,6 +18,7 @@ #include "backend/Builder.h" #include "backend/Forward.h" #include "backend/RefCounted.h" +#include "backend/Texture.h" #include "nxt/nxtcpp.h" diff --git a/src/backend/vulkan/FencedDeleter.cpp b/src/backend/vulkan/FencedDeleter.cpp index 7a911cb5d5..778c3fabfe 100644 --- a/src/backend/vulkan/FencedDeleter.cpp +++ b/src/backend/vulkan/FencedDeleter.cpp @@ -23,7 +23,9 @@ namespace backend { namespace vulkan { FencedDeleter::~FencedDeleter() { ASSERT(mBuffersToDelete.Empty()); + ASSERT(mFramebuffersToDelete.Empty()); ASSERT(mImagesToDelete.Empty()); + ASSERT(mImageViewsToDelete.Empty()); ASSERT(mMemoriesToDelete.Empty()); ASSERT(mPipelineLayoutsToDelete.Empty()); ASSERT(mRenderPassesToDelete.Empty()); @@ -37,10 +39,18 @@ namespace backend { namespace vulkan { mMemoriesToDelete.Enqueue(memory, mDevice->GetSerial()); } + void FencedDeleter::DeleteWhenUnused(VkFramebuffer framebuffer) { + mFramebuffersToDelete.Enqueue(framebuffer, mDevice->GetSerial()); + } + void FencedDeleter::DeleteWhenUnused(VkImage image) { mImagesToDelete.Enqueue(image, mDevice->GetSerial()); } + void FencedDeleter::DeleteWhenUnused(VkImageView view) { + mImageViewsToDelete.Enqueue(view, mDevice->GetSerial()); + } + void FencedDeleter::DeleteWhenUnused(VkPipelineLayout layout) { mPipelineLayoutsToDelete.Enqueue(layout, mDevice->GetSerial()); } @@ -77,6 +87,17 @@ namespace backend { namespace vulkan { mDevice->fn.DestroyRenderPass(vkDevice, renderPass, nullptr); } mRenderPassesToDelete.ClearUpTo(completedSerial); + + for (VkFramebuffer framebuffer : mFramebuffersToDelete.IterateUpTo(completedSerial)) { + mDevice->fn.DestroyFramebuffer(vkDevice, framebuffer, nullptr); + } + mFramebuffersToDelete.ClearUpTo(completedSerial); + + for (VkImageView view : mImageViewsToDelete.IterateUpTo(completedSerial)) { + mDevice->fn.DestroyImageView(vkDevice, view, nullptr); + } + mImageViewsToDelete.ClearUpTo(completedSerial); + } }} // namespace backend::vulkan diff --git a/src/backend/vulkan/FencedDeleter.h b/src/backend/vulkan/FencedDeleter.h index 5de4cf9495..6b8e2a1099 100644 --- a/src/backend/vulkan/FencedDeleter.h +++ b/src/backend/vulkan/FencedDeleter.h @@ -29,7 +29,9 @@ namespace backend { namespace vulkan { void DeleteWhenUnused(VkBuffer buffer); void DeleteWhenUnused(VkDeviceMemory memory); + void DeleteWhenUnused(VkFramebuffer framebuffer); void DeleteWhenUnused(VkImage image); + void DeleteWhenUnused(VkImageView view); void DeleteWhenUnused(VkPipelineLayout layout); void DeleteWhenUnused(VkRenderPass renderPass); @@ -38,8 +40,10 @@ namespace backend { namespace vulkan { private: Device* mDevice = nullptr; SerialQueue mBuffersToDelete; + SerialQueue mFramebuffersToDelete; SerialQueue mMemoriesToDelete; SerialQueue mImagesToDelete; + SerialQueue mImageViewsToDelete; SerialQueue mPipelineLayoutsToDelete; SerialQueue mRenderPassesToDelete; }; diff --git a/src/backend/vulkan/FramebufferVk.cpp b/src/backend/vulkan/FramebufferVk.cpp new file mode 100644 index 0000000000..16d53f2b76 --- /dev/null +++ b/src/backend/vulkan/FramebufferVk.cpp @@ -0,0 +1,66 @@ +// Copyright 2018 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "backend/vulkan/FramebufferVk.h" + +#include "backend/vulkan/FencedDeleter.h" +#include "backend/vulkan/RenderPassVk.h" +#include "backend/vulkan/TextureVk.h" +#include "backend/vulkan/VulkanBackend.h" + +namespace backend { namespace vulkan { + + Framebuffer::Framebuffer(FramebufferBuilder* builder) : FramebufferBase(builder) { + ASSERT(GetRenderPass()->GetAttachmentCount() <= kMaxColorAttachments + 1); + + Device* device = ToBackend(GetDevice()); + + // Fill in the attachment info that will be chained in the create info. + std::array attachments; + for (uint32_t i = 0; i < GetRenderPass()->GetAttachmentCount(); ++i) { + attachments[i] = ToBackend(GetTextureView(i))->GetHandle(); + } + + // Chain attachments and create the framebuffer + VkFramebufferCreateInfo createInfo; + createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + createInfo.pNext = nullptr; + createInfo.flags = 0; + createInfo.renderPass = ToBackend(GetRenderPass())->GetHandle(); + createInfo.attachmentCount = GetRenderPass()->GetAttachmentCount(); + createInfo.pAttachments = attachments.data(); + createInfo.width = GetWidth(); + createInfo.height = GetHeight(); + createInfo.layers = 1; + + if (device->fn.CreateFramebuffer(device->GetVkDevice(), &createInfo, nullptr, &mHandle) != + VK_SUCCESS) { + ASSERT(false); + } + } + + Framebuffer::~Framebuffer() { + Device* device = ToBackend(GetDevice()); + + if (mHandle != VK_NULL_HANDLE) { + device->GetFencedDeleter()->DeleteWhenUnused(mHandle); + mHandle = VK_NULL_HANDLE; + } + } + + VkFramebuffer Framebuffer::GetHandle() const { + return mHandle; + } + +}} // namespace backend::vulkan diff --git a/src/backend/vulkan/FramebufferVk.h b/src/backend/vulkan/FramebufferVk.h new file mode 100644 index 0000000000..f994089172 --- /dev/null +++ b/src/backend/vulkan/FramebufferVk.h @@ -0,0 +1,37 @@ +// Copyright 2018 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BACKEND_VULKAN_FRAMEBUFFERVK_H_ +#define BACKEND_VULKAN_FRAMEBUFFERVK_H_ + +#include "backend/Framebuffer.h" + +#include "backend/vulkan/vulkan_platform.h" + +namespace backend { namespace vulkan { + + class Framebuffer : public FramebufferBase { + public: + Framebuffer(FramebufferBuilder* builder); + ~Framebuffer(); + + VkFramebuffer GetHandle() const; + + private: + VkFramebuffer mHandle = VK_NULL_HANDLE; + }; + +}} // namespace backend::vulkan + +#endif // BACKEND_VULKAN_FRAMEBUFFERVK_H_ diff --git a/src/backend/vulkan/GeneratedCodeIncludes.h b/src/backend/vulkan/GeneratedCodeIncludes.h index 7e83209018..a0fbdbeeac 100644 --- a/src/backend/vulkan/GeneratedCodeIncludes.h +++ b/src/backend/vulkan/GeneratedCodeIncludes.h @@ -14,6 +14,7 @@ #include "backend/vulkan/BufferVk.h" #include "backend/vulkan/CommandBufferVk.h" +#include "backend/vulkan/FramebufferVk.h" #include "backend/vulkan/InputStateVk.h" #include "backend/vulkan/PipelineLayoutVk.h" #include "backend/vulkan/RenderPassVk.h" diff --git a/src/backend/vulkan/TextureVk.cpp b/src/backend/vulkan/TextureVk.cpp index 5ae7ab3efc..fd985bf3b7 100644 --- a/src/backend/vulkan/TextureVk.cpp +++ b/src/backend/vulkan/TextureVk.cpp @@ -32,6 +32,17 @@ namespace backend { namespace vulkan { } } + // Converts an NXT texture dimension to a Vulkan image view type. + // Contrary to image types, image view types include arrayness and cubemapness + VkImageViewType VulkanImageViewType(nxt::TextureDimension dimension) { + switch (dimension) { + case nxt::TextureDimension::e2D: + return VK_IMAGE_VIEW_TYPE_2D; + default: + UNREACHABLE(); + } + } + // Converts the NXT usage flags to Vulkan usage flags. Also needs the format to choose // between color and depth attachment usages. VkImageUsageFlags VulkanImageUsage(nxt::TextureUsageBit usage, nxt::TextureFormat format) { @@ -302,4 +313,41 @@ namespace backend { namespace vulkan { RecordBarrier(commands, currentUsage, targetUsage); } + TextureView::TextureView(TextureViewBuilder* builder) : TextureViewBase(builder) { + Device* device = ToBackend(builder->GetDevice()); + + VkImageViewCreateInfo createInfo; + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.pNext = nullptr; + createInfo.flags = 0; + createInfo.image = ToBackend(GetTexture())->GetHandle(); + createInfo.viewType = VulkanImageViewType(GetTexture()->GetDimension()); + createInfo.format = VulkanImageFormat(GetTexture()->GetFormat()); + createInfo.components = VkComponentMapping{VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}; + createInfo.subresourceRange.aspectMask = VulkanAspectMask(GetTexture()->GetFormat()); + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = GetTexture()->GetNumMipLevels(); + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + + if (device->fn.CreateImageView(device->GetVkDevice(), &createInfo, nullptr, &mHandle) != + VK_SUCCESS) { + ASSERT(false); + } + } + + TextureView::~TextureView() { + Device* device = ToBackend(GetTexture()->GetDevice()); + + if (mHandle != VK_NULL_HANDLE) { + device->GetFencedDeleter()->DeleteWhenUnused(mHandle); + mHandle = VK_NULL_HANDLE; + } + } + + VkImageView TextureView::GetHandle() const { + return mHandle; + } + }} // namespace backend::vulkan diff --git a/src/backend/vulkan/TextureVk.h b/src/backend/vulkan/TextureVk.h index bf48a65105..1dc5767ca6 100644 --- a/src/backend/vulkan/TextureVk.h +++ b/src/backend/vulkan/TextureVk.h @@ -44,6 +44,17 @@ namespace backend { namespace vulkan { DeviceMemoryAllocation mMemoryAllocation; }; + class TextureView : public TextureViewBase { + public: + TextureView(TextureViewBuilder* builder); + ~TextureView(); + + VkImageView GetHandle() const; + + private: + VkImageView mHandle = VK_NULL_HANDLE; + }; + }} // namespace backend::vulkan #endif // BACKEND_VULKAN_TEXTUREVK_H_ diff --git a/src/backend/vulkan/VulkanBackend.cpp b/src/backend/vulkan/VulkanBackend.cpp index 5aa0cc0aeb..5036afaed0 100644 --- a/src/backend/vulkan/VulkanBackend.cpp +++ b/src/backend/vulkan/VulkanBackend.cpp @@ -19,6 +19,7 @@ #include "backend/vulkan/BufferVk.h" #include "backend/vulkan/CommandBufferVk.h" #include "backend/vulkan/FencedDeleter.h" +#include "backend/vulkan/FramebufferVk.h" #include "backend/vulkan/InputStateVk.h" #include "backend/vulkan/PipelineLayoutVk.h" #include "backend/vulkan/RenderPassVk.h" diff --git a/src/backend/vulkan/VulkanBackend.h b/src/backend/vulkan/VulkanBackend.h index 34215379da..80cd3c9fac 100644 --- a/src/backend/vulkan/VulkanBackend.h +++ b/src/backend/vulkan/VulkanBackend.h @@ -23,7 +23,6 @@ #include "backend/ComputePipeline.h" #include "backend/DepthStencilState.h" #include "backend/Device.h" -#include "backend/Framebuffer.h" #include "backend/Queue.h" #include "backend/RenderPipeline.h" #include "backend/Sampler.h" @@ -49,7 +48,7 @@ namespace backend { namespace vulkan { using ComputePipeline = ComputePipelineBase; using DepthStencilState = DepthStencilStateBase; class Device; - using Framebuffer = FramebufferBase; + class Framebuffer; class InputState; class PipelineLayout; class Queue; @@ -59,7 +58,7 @@ namespace backend { namespace vulkan { using ShaderModule = ShaderModuleBase; class SwapChain; class Texture; - using TextureView = TextureViewBase; + class TextureView; class BufferUploader; class FencedDeleter;