2022-09-17 01:34:38 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
|
|
#include <mutex>
|
|
|
|
|
#include <condition_variable>
|
|
|
|
|
|
|
|
|
|
#include "Common/GPU/Vulkan/VulkanContext.h"
|
2023-02-05 16:59:23 +01:00
|
|
|
#include "Common/Data/Collections/Hashmaps.h"
|
2022-09-17 01:34:38 +02:00
|
|
|
|
2022-09-19 18:07:50 +02:00
|
|
|
enum {
|
|
|
|
|
MAX_TIMESTAMP_QUERIES = 128,
|
|
|
|
|
};
|
|
|
|
|
|
2022-09-17 01:34:38 +02:00
|
|
|
enum class VKRRunType {
|
2023-08-10 09:50:01 +02:00
|
|
|
SUBMIT,
|
2022-09-23 19:39:00 +02:00
|
|
|
PRESENT,
|
2022-09-17 01:34:38 +02:00
|
|
|
SYNC,
|
2022-09-23 19:39:00 +02:00
|
|
|
EXIT,
|
2022-09-17 01:34:38 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct QueueProfileContext {
|
2023-06-14 00:19:58 +02:00
|
|
|
bool enabled = false;
|
|
|
|
|
bool timestampsEnabled = false;
|
2022-09-17 01:34:38 +02:00
|
|
|
VkQueryPool queryPool;
|
|
|
|
|
std::vector<std::string> timestampDescriptions;
|
|
|
|
|
std::string profileSummary;
|
|
|
|
|
double cpuStartTime;
|
|
|
|
|
double cpuEndTime;
|
2023-06-14 00:19:58 +02:00
|
|
|
double descWriteTime;
|
2022-09-17 01:34:38 +02:00
|
|
|
};
|
|
|
|
|
|
2023-02-05 16:59:23 +01:00
|
|
|
class VKRFramebuffer;
|
|
|
|
|
|
|
|
|
|
struct ReadbackKey {
|
|
|
|
|
const VKRFramebuffer *framebuf;
|
|
|
|
|
int width;
|
|
|
|
|
int height;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct CachedReadback {
|
|
|
|
|
VkBuffer buffer;
|
|
|
|
|
VmaAllocation allocation;
|
|
|
|
|
VkDeviceSize bufferSize;
|
|
|
|
|
bool isCoherent;
|
|
|
|
|
|
|
|
|
|
void Destroy(VulkanContext *vulkan);
|
|
|
|
|
};
|
|
|
|
|
|
2022-09-19 18:07:50 +02:00
|
|
|
struct FrameDataShared {
|
|
|
|
|
// Permanent objects
|
|
|
|
|
VkSemaphore acquireSemaphore = VK_NULL_HANDLE;
|
|
|
|
|
VkSemaphore renderingCompleteSemaphore = VK_NULL_HANDLE;
|
|
|
|
|
|
2023-02-05 00:35:30 +01:00
|
|
|
// For synchronous readbacks.
|
|
|
|
|
VkFence readbackFence = VK_NULL_HANDLE;
|
2023-07-23 19:20:55 +02:00
|
|
|
bool useMultiThreading;
|
2023-08-30 10:47:20 +02:00
|
|
|
bool measurePresentTime;
|
2023-02-05 00:35:30 +01:00
|
|
|
|
2023-08-30 10:47:20 +02:00
|
|
|
void Init(VulkanContext *vulkan, bool useMultiThreading, bool measurePresentTime);
|
2022-09-19 18:07:50 +02:00
|
|
|
void Destroy(VulkanContext *vulkan);
|
|
|
|
|
};
|
|
|
|
|
|
2022-09-20 14:49:39 +02:00
|
|
|
enum class FrameSubmitType {
|
|
|
|
|
Pending,
|
|
|
|
|
Sync,
|
|
|
|
|
Present,
|
|
|
|
|
};
|
|
|
|
|
|
2022-09-17 01:34:38 +02:00
|
|
|
// Per-frame data, round-robin so we can overlap submission with execution of the previous frame.
|
|
|
|
|
struct FrameData {
|
|
|
|
|
bool skipSwap = false;
|
|
|
|
|
|
2022-09-23 20:44:47 +02:00
|
|
|
std::mutex fenceMutex;
|
|
|
|
|
std::condition_variable fenceCondVar;
|
|
|
|
|
bool readyForFence = true;
|
|
|
|
|
|
2022-09-26 22:51:16 +02:00
|
|
|
VkFence fence = VK_NULL_HANDLE;
|
2022-09-17 01:34:38 +02:00
|
|
|
|
|
|
|
|
// These are on different threads so need separate pools.
|
2022-09-26 22:51:16 +02:00
|
|
|
VkCommandPool cmdPoolInit = VK_NULL_HANDLE; // Written to from main thread
|
|
|
|
|
VkCommandPool cmdPoolMain = VK_NULL_HANDLE; // Written to from render thread, which also submits
|
2022-09-17 01:34:38 +02:00
|
|
|
|
2022-09-26 22:51:16 +02:00
|
|
|
VkCommandBuffer initCmd = VK_NULL_HANDLE;
|
|
|
|
|
VkCommandBuffer mainCmd = VK_NULL_HANDLE;
|
|
|
|
|
VkCommandBuffer presentCmd = VK_NULL_HANDLE;
|
2022-09-17 01:34:38 +02:00
|
|
|
|
|
|
|
|
bool hasInitCommands = false;
|
2022-09-20 14:49:39 +02:00
|
|
|
bool hasMainCommands = false;
|
2022-09-17 01:34:38 +02:00
|
|
|
bool hasPresentCommands = false;
|
2022-09-20 14:49:39 +02:00
|
|
|
|
2022-09-23 19:39:00 +02:00
|
|
|
bool hasFencePending = false;
|
2022-09-18 12:09:56 +02:00
|
|
|
bool hasAcquired = false;
|
2022-09-17 01:34:38 +02:00
|
|
|
|
2022-09-23 19:39:00 +02:00
|
|
|
bool syncDone = false;
|
2022-09-17 01:34:38 +02:00
|
|
|
|
|
|
|
|
// Swapchain.
|
|
|
|
|
uint32_t curSwapchainImage = -1;
|
|
|
|
|
|
2023-08-02 11:38:31 +02:00
|
|
|
// Frames need unique IDs to wait for present on, let's keep them here.
|
|
|
|
|
// Also used for indexing into the frame timing history buffer.
|
2023-09-11 12:02:56 +02:00
|
|
|
uint64_t frameId = 0;
|
2023-08-02 11:38:31 +02:00
|
|
|
|
2022-09-17 01:34:38 +02:00
|
|
|
// Profiling.
|
2023-06-14 00:19:58 +02:00
|
|
|
QueueProfileContext profile{};
|
2022-09-17 01:34:38 +02:00
|
|
|
|
2023-02-05 16:59:23 +01:00
|
|
|
// Async readback cache.
|
2023-09-11 12:02:56 +02:00
|
|
|
DenseHashMap<ReadbackKey, CachedReadback *> readbacks_;
|
2023-02-05 16:59:23 +01:00
|
|
|
|
|
|
|
|
FrameData() : readbacks_(8) {}
|
|
|
|
|
|
2022-09-19 19:27:50 +02:00
|
|
|
void Init(VulkanContext *vulkan, int index);
|
2022-09-19 18:07:50 +02:00
|
|
|
void Destroy(VulkanContext *vulkan);
|
|
|
|
|
|
|
|
|
|
void AcquireNextImage(VulkanContext *vulkan, FrameDataShared &shared);
|
2022-09-20 14:49:39 +02:00
|
|
|
VkResult QueuePresent(VulkanContext *vulkan, FrameDataShared &shared);
|
2022-10-03 12:13:11 +02:00
|
|
|
|
|
|
|
|
// Generally called from the main thread, unlike most of the rest.
|
2022-09-20 14:49:39 +02:00
|
|
|
VkCommandBuffer GetInitCmd(VulkanContext *vulkan);
|
2022-09-19 18:07:50 +02:00
|
|
|
|
|
|
|
|
// This will only submit if we are actually recording init commands.
|
2022-09-20 14:49:39 +02:00
|
|
|
void SubmitPending(VulkanContext *vulkan, FrameSubmitType type, FrameDataShared &shared);
|
2022-09-20 16:27:05 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// Metadata for logging etc
|
2023-02-05 16:59:23 +01:00
|
|
|
int index = -1;
|
2022-09-17 01:34:38 +02:00
|
|
|
};
|