Change the PushBuffer API a bit to not take explicit memory types.

This commit is contained in:
Henrik Rydgård 2021-11-22 09:04:05 +01:00
parent c2f594cc73
commit 0cbb7ab027
6 changed files with 35 additions and 35 deletions

View file

@ -26,8 +26,8 @@
using namespace PPSSPP_VK;
VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, size_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryPropertyMask)
: vulkan_(vulkan), memoryPropertyMask_(memoryPropertyMask), size_(size), usage_(usage) {
VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, size_t size, VkBufferUsageFlags usage, PushBufferType type)
: vulkan_(vulkan), size_(size), usage_(usage), type_(type) {
bool res = AddBuffer();
_assert_(res);
}
@ -54,6 +54,13 @@ bool VulkanPushBuffer::AddBuffer() {
return false;
}
VkMemoryPropertyFlags memoryPropertyMask_;
if (type_ == PushBufferType::CPU_TO_GPU) {
memoryPropertyMask_ = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
} else {
memoryPropertyMask_ = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
}
// Get the buffer memory requirements. None of this can be cached!
VkMemoryRequirements reqs;
vkGetBufferMemoryRequirements(device, info.buffer, &reqs);
@ -92,7 +99,7 @@ void VulkanPushBuffer::Destroy(VulkanContext *vulkan) {
void VulkanPushBuffer::NextBuffer(size_t minSize) {
// First, unmap the current memory.
if (memoryPropertyMask_ & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
if (type_ == PushBufferType::CPU_TO_GPU)
Unmap();
buf_++;
@ -112,7 +119,7 @@ void VulkanPushBuffer::NextBuffer(size_t minSize) {
// Now, move to the next buffer and map it.
offset_ = 0;
if (memoryPropertyMask_ & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
if (type_ == PushBufferType::CPU_TO_GPU)
Map();
}
@ -150,6 +157,8 @@ void VulkanPushBuffer::Unmap() {
if (!writePtr_)
return;
/*
// We could never hit this path before because we specified the mask explicitly.
if ((memoryPropertyMask_ & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0) {
VkMappedMemoryRange range{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
range.offset = 0;
@ -157,6 +166,7 @@ void VulkanPushBuffer::Unmap() {
range.memory = buffers_[buf_].deviceMemory;
vkFlushMappedMemoryRanges(vulkan_->GetDevice(), 1, &range);
}
*/
vkUnmapMemory(vulkan_->GetDevice(), buffers_[buf_].deviceMemory);
writePtr_ = nullptr;

View file

@ -6,10 +6,18 @@
#include "Common/Log.h"
#include "Common/GPU/Vulkan/VulkanContext.h"
// Forward declaration
VK_DEFINE_HANDLE(VmaAllocation);
// VulkanMemory
//
// Vulkan memory management utils.
enum class PushBufferType {
CPU_TO_GPU,
GPU_ONLY,
};
// VulkanPushBuffer
// Simple incrementing allocator.
// Use these to push vertex, index and uniform data. Generally you'll have two of these
@ -24,10 +32,10 @@ class VulkanPushBuffer {
};
public:
// NOTE: If you create a push buffer with only VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
// NOTE: If you create a push buffer with PushBufferType::GPU_ONLY,
// then you can't use any of the push functions as pointers will not be reachable from the CPU.
// You must in this case use Allocate() only, and pass the returned offset and the VkBuffer to Vulkan APIs.
VulkanPushBuffer(VulkanContext *vulkan, size_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryPropertyMask = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
VulkanPushBuffer(VulkanContext *vulkan, size_t size, VkBufferUsageFlags usage, PushBufferType type);
~VulkanPushBuffer();
void Destroy(VulkanContext *vulkan);
@ -40,17 +48,17 @@ public:
offset_ = 0;
// Note: we must defrag because some buffers may be smaller than size_.
Defragment(vulkan);
if (memoryPropertyMask_ & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
if (type_ == PushBufferType::CPU_TO_GPU)
Map();
}
void BeginNoReset() {
if (memoryPropertyMask_ & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
if (type_ == PushBufferType::CPU_TO_GPU)
Map();
}
void End() {
if (memoryPropertyMask_ & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
if (type_ == PushBufferType::CPU_TO_GPU)
Unmap();
}
@ -117,7 +125,7 @@ private:
void Defragment(VulkanContext *vulkan);
VulkanContext *vulkan_;
VkMemoryPropertyFlags memoryPropertyMask_;
PushBufferType type_;
std::vector<BufInfo> buffers_;
size_t buf_ = 0;

View file

@ -835,7 +835,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
frame_[i].pushBuffer = new VulkanPushBuffer(vulkan_, 1024 * 1024, usage);
frame_[i].pushBuffer = new VulkanPushBuffer(vulkan_, 1024 * 1024, usage, PushBufferType::CPU_TO_GPU);
VkResult res = RecreateDescriptorPool(&frame_[i]);
_assert_(res == VK_SUCCESS);
}

View file

@ -148,11 +148,9 @@ void DrawEngineVulkan::InitDeviceObjects() {
// We now create descriptor pools on demand, so removed from here.
// Note that pushUBO is also used for tessellation data (search for SetPushBuffer), and to upload
// the null texture. This should be cleaned up...
frame_[i].pushUBO = new VulkanPushBuffer(vulkan, 8 * 1024 * 1024, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
frame_[i].pushVertex = new VulkanPushBuffer(vulkan, 2 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
frame_[i].pushIndex = new VulkanPushBuffer(vulkan, 1 * 1024 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
frame_[i].pushLocal = new VulkanPushBuffer(vulkan, 1 * 1024 * 1024, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
frame_[i].pushUBO = new VulkanPushBuffer(vulkan, 8 * 1024 * 1024, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, PushBufferType::CPU_TO_GPU);
frame_[i].pushVertex = new VulkanPushBuffer(vulkan, 2 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, PushBufferType::CPU_TO_GPU);
frame_[i].pushIndex = new VulkanPushBuffer(vulkan, 1 * 1024 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, PushBufferType::CPU_TO_GPU);
}
VkPipelineLayoutCreateInfo pl{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
@ -177,7 +175,7 @@ void DrawEngineVulkan::InitDeviceObjects() {
res = vkCreateSampler(device, &samp, nullptr, &nullSampler_);
_dbg_assert_(VK_SUCCESS == res);
vertexCache_ = new VulkanPushBuffer(vulkan, VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
vertexCache_ = new VulkanPushBuffer(vulkan, VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, PushBufferType::CPU_TO_GPU);
tessDataTransferVulkan = new TessellationDataTransferVulkan(vulkan);
tessDataTransfer = tessDataTransferVulkan;
@ -210,11 +208,6 @@ void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) {
delete pushIndex;
pushIndex = nullptr;
}
if (pushLocal) {
pushLocal->Destroy(vulkan);
delete pushLocal;
pushLocal = nullptr;
}
}
void DrawEngineVulkan::DestroyDeviceObjects() {
@ -272,13 +265,11 @@ void DrawEngineVulkan::BeginFrame() {
frame->pushUBO->Reset();
frame->pushVertex->Reset();
frame->pushIndex->Reset();
frame->pushLocal->Reset();
VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT);
frame->pushUBO->Begin(vulkan);
frame->pushVertex->Begin(vulkan);
frame->pushIndex->Begin(vulkan);
frame->pushLocal->Begin(vulkan);
// TODO: How can we make this nicer...
tessDataTransferVulkan->SetPushBuffer(frame->pushUBO);
@ -289,7 +280,7 @@ void DrawEngineVulkan::BeginFrame() {
if (vertexCache_->GetTotalSize() > VERTEX_CACHE_SIZE) {
vertexCache_->Destroy(vulkan);
delete vertexCache_; // orphans the buffers, they'll get deleted once no longer used by an in-flight frame.
vertexCache_ = new VulkanPushBuffer(vulkan, VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
vertexCache_ = new VulkanPushBuffer(vulkan, VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, PushBufferType::CPU_TO_GPU);
vai_.Iterate([&](uint32_t hash, VertexArrayInfoVulkan *vai) {
delete vai;
});
@ -338,7 +329,6 @@ void DrawEngineVulkan::EndFrame() {
frame->pushUBO->End();
frame->pushVertex->End();
frame->pushIndex->End();
frame->pushLocal->End();
vertexCache_->End();
}

View file

@ -177,11 +177,6 @@ public:
return GetCurFrame().pushUBO;
}
// Only use Allocate on this one.
VulkanPushBuffer *GetPushBufferLocal() {
return GetCurFrame().pushLocal;
}
const DrawEngineVulkanStats &GetStats() const {
return stats_;
}
@ -250,9 +245,6 @@ private:
VulkanPushBuffer *pushVertex = nullptr;
VulkanPushBuffer *pushIndex = nullptr;
// Special push buffer in GPU local memory, for texture data conversion and similar tasks.
VulkanPushBuffer *pushLocal;
// We do rolling allocation and reset instead of caching across frames. That we might do later.
DenseHashMap<DescriptorSetKey, VkDescriptorSet, (VkDescriptorSet)VK_NULL_HANDLE> descSets;

View file

@ -501,7 +501,7 @@ void GPU_Vulkan::InitDeviceObjects() {
for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
_assert_(!frameData_[i].push_);
VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
frameData_[i].push_ = new VulkanPushBuffer(vulkan, 256 * 1024, usage);
frameData_[i].push_ = new VulkanPushBuffer(vulkan, 256 * 1024, usage, PushBufferType::CPU_TO_GPU);
}
VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);