diff --git a/CMakeLists.txt b/CMakeLists.txt
index af616d3e2a..af32e9ec3f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -712,6 +712,8 @@ add_library(Common STATIC
Common/GPU/Vulkan/VulkanDebug.h
Common/GPU/Vulkan/VulkanContext.cpp
Common/GPU/Vulkan/VulkanContext.h
+ Common/GPU/Vulkan/VulkanDescSet.cpp
+ Common/GPU/Vulkan/VulkanDescSet.h
Common/GPU/Vulkan/VulkanFramebuffer.cpp
Common/GPU/Vulkan/VulkanFramebuffer.h
Common/GPU/Vulkan/VulkanImage.cpp
diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj
index e83ebfd5d3..93e91681b0 100644
--- a/Common/Common.vcxproj
+++ b/Common/Common.vcxproj
@@ -472,6 +472,7 @@
+
@@ -900,6 +901,7 @@
+
diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index a0852244ba..73aefb9323 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -515,6 +515,9 @@
Render\Text
+
+ GPU\Vulkan
+
@@ -966,6 +969,9 @@
Render\Text
+
+ GPU\Vulkan
+
diff --git a/Common/GPU/Vulkan/VulkanDescSet.cpp b/Common/GPU/Vulkan/VulkanDescSet.cpp
new file mode 100644
index 0000000000..b4a654bb67
--- /dev/null
+++ b/Common/GPU/Vulkan/VulkanDescSet.cpp
@@ -0,0 +1,97 @@
+#include "Common/GPU/Vulkan/VulkanDescSet.h"
+
+VulkanDescSetPool::~VulkanDescSetPool() {
+ _assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool %s never destroyed", tag_);
+}
+
+void VulkanDescSetPool::Create(VulkanContext *vulkan, const VkDescriptorPoolCreateInfo &info, const std::vector &sizes) {
+ _assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool::Create when already exists");
+
+ vulkan_ = vulkan;
+ info_ = info;
+ sizes_ = sizes;
+
+ VkResult res = Recreate(false);
+ _assert_msg_(res == VK_SUCCESS, "Could not create VulkanDescSetPool %s", tag_);
+}
+
+VkDescriptorSet VulkanDescSetPool::Allocate(int n, const VkDescriptorSetLayout *layouts, const char *tag) {
+ if (descPool_ == VK_NULL_HANDLE || usage_ + n >= info_.maxSets) {
+ // Missing or out of space, need to recreate.
+ VkResult res = Recreate(grow_);
+ _assert_msg_(res == VK_SUCCESS, "Could not grow VulkanDescSetPool %s on usage %d", tag_, (int)usage_);
+ }
+
+ VkDescriptorSet desc;
+ VkDescriptorSetAllocateInfo descAlloc{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
+ descAlloc.descriptorPool = descPool_;
+ descAlloc.descriptorSetCount = n;
+ descAlloc.pSetLayouts = layouts;
+ VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc);
+
+ if (result == VK_ERROR_FRAGMENTED_POOL || result < 0) {
+ // There seems to have been a spec revision. Here we should apparently recreate the descriptor pool,
+ // so let's do that. See https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkAllocateDescriptorSets.html
+ // Fragmentation shouldn't really happen though since we wipe the pool every frame.
+ VkResult res = Recreate(false);
+ _assert_msg_(res == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to recreate a descriptor pool. sz=%d res=%d", usage_, (int)res);
+
+ // Need to update this pointer since we have allocated a new one.
+ descAlloc.descriptorPool = descPool_;
+ result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc);
+ _assert_msg_(result == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to allocate after recreating a descriptor pool. res=%d", (int)result);
+ }
+
+ if (result != VK_SUCCESS) {
+ return VK_NULL_HANDLE;
+ }
+
+ vulkan_->SetDebugName(desc, VK_OBJECT_TYPE_DESCRIPTOR_SET, tag);
+ return desc;
+}
+
+void VulkanDescSetPool::Reset() {
+ _assert_msg_(descPool_ != VK_NULL_HANDLE, "VulkanDescSetPool::Reset without valid pool");
+ vkResetDescriptorPool(vulkan_->GetDevice(), descPool_, 0);
+
+ clear_();
+ usage_ = 0;
+}
+
+void VulkanDescSetPool::Destroy() {
+ _assert_msg_(vulkan_ != nullptr, "VulkanDescSetPool::Destroy without VulkanContext");
+
+ if (descPool_ != VK_NULL_HANDLE) {
+ vulkan_->Delete().QueueDeleteDescriptorPool(descPool_);
+ clear_();
+ usage_ = 0;
+ }
+}
+
+VkResult VulkanDescSetPool::Recreate(bool grow) {
+ _assert_msg_(vulkan_ != nullptr, "VulkanDescSetPool::Recreate without VulkanContext");
+
+ uint32_t prevSize = info_.maxSets;
+ if (grow) {
+ info_.maxSets *= 2;
+ for (auto &size : sizes_)
+ size.descriptorCount *= 2;
+ }
+
+ // Delete the pool if it already exists.
+ if (descPool_ != VK_NULL_HANDLE) {
+ DEBUG_LOG(G3D, "Reallocating %s desc pool from %d to %d", tag_, prevSize, info_.maxSets);
+ vulkan_->Delete().QueueDeleteDescriptorPool(descPool_);
+ clear_();
+ usage_ = 0;
+ }
+
+ info_.pPoolSizes = &sizes_[0];
+ info_.poolSizeCount = (uint32_t)sizes_.size();
+
+ VkResult result = vkCreateDescriptorPool(vulkan_->GetDevice(), &info_, nullptr, &descPool_);
+ if (result == VK_SUCCESS) {
+ vulkan_->SetDebugName(descPool_, VK_OBJECT_TYPE_DESCRIPTOR_POOL, tag_);
+ }
+ return result;
+}
diff --git a/Common/GPU/Vulkan/VulkanDescSet.h b/Common/GPU/Vulkan/VulkanDescSet.h
new file mode 100644
index 0000000000..8c9ae70c39
--- /dev/null
+++ b/Common/GPU/Vulkan/VulkanDescSet.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "Common/Data/Collections/FastVec.h"
+#include "Common/GPU/Vulkan/VulkanContext.h"
+
+#include
+#include
+
+// Only appropriate for use in a per-frame pool.
+class VulkanDescSetPool {
+public:
+ VulkanDescSetPool(const char *tag, bool grow) : tag_(tag), grow_(grow) {}
+ ~VulkanDescSetPool();
+
+ // Must call this before use: defines how to clear cache of ANY returned values from Allocate().
+ void Setup(const std::function &clear) {
+ clear_ = clear;
+ }
+ void Create(VulkanContext *vulkan, const VkDescriptorPoolCreateInfo &info, const std::vector &sizes);
+ // Allocate a new set, which may resize and empty the current sets.
+ // Use only for the current frame, unless in a cache cleared by clear_.
+ VkDescriptorSet Allocate(int n, const VkDescriptorSetLayout *layouts, const char *tag);
+ void Reset();
+ void Destroy();
+
+private:
+ VkResult Recreate(bool grow);
+
+ const char *tag_;
+ VulkanContext *vulkan_ = nullptr;
+ VkDescriptorPool descPool_ = VK_NULL_HANDLE;
+ VkDescriptorPoolCreateInfo info_{};
+ std::vector sizes_;
+ std::function clear_;
+ uint32_t usage_ = 0;
+ bool grow_;
+};
diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp
index f29fc33d0b..7f11aabccd 100644
--- a/Common/GPU/Vulkan/VulkanMemory.cpp
+++ b/Common/GPU/Vulkan/VulkanMemory.cpp
@@ -156,102 +156,6 @@ void VulkanPushBuffer::Unmap() {
writePtr_ = nullptr;
}
-VulkanDescSetPool::~VulkanDescSetPool() {
- _assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool %s never destroyed", tag_);
-}
-
-void VulkanDescSetPool::Create(VulkanContext *vulkan, const VkDescriptorPoolCreateInfo &info, const std::vector &sizes) {
- _assert_msg_(descPool_ == VK_NULL_HANDLE, "VulkanDescSetPool::Create when already exists");
-
- vulkan_ = vulkan;
- info_ = info;
- sizes_ = sizes;
-
- VkResult res = Recreate(false);
- _assert_msg_(res == VK_SUCCESS, "Could not create VulkanDescSetPool %s", tag_);
-}
-
-VkDescriptorSet VulkanDescSetPool::Allocate(int n, const VkDescriptorSetLayout *layouts, const char *tag) {
- if (descPool_ == VK_NULL_HANDLE || usage_ + n >= info_.maxSets) {
- // Missing or out of space, need to recreate.
- VkResult res = Recreate(grow_);
- _assert_msg_(res == VK_SUCCESS, "Could not grow VulkanDescSetPool %s on usage %d", tag_, (int)usage_);
- }
-
- VkDescriptorSet desc;
- VkDescriptorSetAllocateInfo descAlloc{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
- descAlloc.descriptorPool = descPool_;
- descAlloc.descriptorSetCount = n;
- descAlloc.pSetLayouts = layouts;
- VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc);
-
- if (result == VK_ERROR_FRAGMENTED_POOL || result < 0) {
- // There seems to have been a spec revision. Here we should apparently recreate the descriptor pool,
- // so let's do that. See https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkAllocateDescriptorSets.html
- // Fragmentation shouldn't really happen though since we wipe the pool every frame.
- VkResult res = Recreate(false);
- _assert_msg_(res == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to recreate a descriptor pool. sz=%d res=%d", usage_, (int)res);
-
- // Need to update this pointer since we have allocated a new one.
- descAlloc.descriptorPool = descPool_;
- result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc);
- _assert_msg_(result == VK_SUCCESS, "Ran out of descriptor space (frag?) and failed to allocate after recreating a descriptor pool. res=%d", (int)result);
- }
-
- if (result != VK_SUCCESS) {
- return VK_NULL_HANDLE;
- }
-
- vulkan_->SetDebugName(desc, VK_OBJECT_TYPE_DESCRIPTOR_SET, tag);
- return desc;
-}
-
-void VulkanDescSetPool::Reset() {
- _assert_msg_(descPool_ != VK_NULL_HANDLE, "VulkanDescSetPool::Reset without valid pool");
- vkResetDescriptorPool(vulkan_->GetDevice(), descPool_, 0);
-
- clear_();
- usage_ = 0;
-}
-
-void VulkanDescSetPool::Destroy() {
- _assert_msg_(vulkan_ != nullptr, "VulkanDescSetPool::Destroy without VulkanContext");
-
- if (descPool_ != VK_NULL_HANDLE) {
- vulkan_->Delete().QueueDeleteDescriptorPool(descPool_);
- clear_();
- usage_ = 0;
- }
-}
-
-VkResult VulkanDescSetPool::Recreate(bool grow) {
- _assert_msg_(vulkan_ != nullptr, "VulkanDescSetPool::Recreate without VulkanContext");
-
- uint32_t prevSize = info_.maxSets;
- if (grow) {
- info_.maxSets *= 2;
- for (auto &size : sizes_)
- size.descriptorCount *= 2;
- }
-
- // Delete the pool if it already exists.
- if (descPool_ != VK_NULL_HANDLE) {
- DEBUG_LOG(G3D, "Reallocating %s desc pool from %d to %d", tag_, prevSize, info_.maxSets);
- vulkan_->Delete().QueueDeleteDescriptorPool(descPool_);
- clear_();
- usage_ = 0;
- }
-
- info_.pPoolSizes = &sizes_[0];
- info_.poolSizeCount = (uint32_t)sizes_.size();
-
- VkResult result = vkCreateDescriptorPool(vulkan_->GetDevice(), &info_, nullptr, &descPool_);
- if (result == VK_SUCCESS) {
- vulkan_->SetDebugName(descPool_, VK_OBJECT_TYPE_DESCRIPTOR_POOL, tag_);
- }
- return result;
-}
-
VulkanPushPool::VulkanPushPool(VulkanContext *vulkan, const char *name, size_t originalBlockSize, VkBufferUsageFlags usage)
: vulkan_(vulkan), name_(name), originalBlockSize_(originalBlockSize), usage_(usage) {
RegisterGPUMemoryManager(this);
diff --git a/Common/GPU/Vulkan/VulkanMemory.h b/Common/GPU/Vulkan/VulkanMemory.h
index f218de3605..fc8f9a19fe 100644
--- a/Common/GPU/Vulkan/VulkanMemory.h
+++ b/Common/GPU/Vulkan/VulkanMemory.h
@@ -176,33 +176,3 @@ private:
int curBlockIndex_ = -1;
const char *name_;
};
-
-// Only appropriate for use in a per-frame pool.
-class VulkanDescSetPool {
-public:
- VulkanDescSetPool(const char *tag, bool grow) : tag_(tag), grow_(grow) {}
- ~VulkanDescSetPool();
-
- // Must call this before use: defines how to clear cache of ANY returned values from Allocate().
- void Setup(const std::function &clear) {
- clear_ = clear;
- }
- void Create(VulkanContext *vulkan, const VkDescriptorPoolCreateInfo &info, const std::vector &sizes);
- // Allocate a new set, which may resize and empty the current sets.
- // Use only for the current frame, unless in a cache cleared by clear_.
- VkDescriptorSet Allocate(int n, const VkDescriptorSetLayout *layouts, const char *tag);
- void Reset();
- void Destroy();
-
-private:
- VkResult Recreate(bool grow);
-
- const char *tag_;
- VulkanContext *vulkan_ = nullptr;
- VkDescriptorPool descPool_ = VK_NULL_HANDLE;
- VkDescriptorPoolCreateInfo info_{};
- std::vector sizes_;
- std::function clear_;
- uint32_t usage_ = 0;
- bool grow_;
-};
diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp
index c5b4d87876..a4cdeedf8d 100644
--- a/Common/GPU/Vulkan/thin3d_vulkan.cpp
+++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp
@@ -20,20 +20,19 @@
#include
#include