renderer_vulkan: Drop VK prefix
* All the classes are in the Vulkan namespace, thus making it superfluous
This commit is contained in:
@@ -238,7 +238,7 @@ void RendererVulkan::CreateVulkanObjects() {
|
|||||||
//ReloadSampler();
|
//ReloadSampler();
|
||||||
|
|
||||||
// Generate VBO handle for drawing
|
// Generate VBO handle for drawing
|
||||||
VKBuffer::Info vertex_info{
|
Buffer::Info vertex_info{
|
||||||
.size = sizeof(ScreenRectVertex) * 10,
|
.size = sizeof(ScreenRectVertex) * 10,
|
||||||
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
||||||
.usage = vk::BufferUsageFlagBits::eVertexBuffer |
|
.usage = vk::BufferUsageFlagBits::eVertexBuffer |
|
||||||
@@ -250,7 +250,7 @@ void RendererVulkan::CreateVulkanObjects() {
|
|||||||
void RendererVulkan::ConfigureFramebufferTexture(ScreenInfo& screen, const GPU::Regs::FramebufferConfig& framebuffer) {
|
void RendererVulkan::ConfigureFramebufferTexture(ScreenInfo& screen, const GPU::Regs::FramebufferConfig& framebuffer) {
|
||||||
screen.format = framebuffer.color_format;
|
screen.format = framebuffer.color_format;
|
||||||
|
|
||||||
VKTexture::Info texture_info{
|
Texture::Info texture_info{
|
||||||
.width = framebuffer.width,
|
.width = framebuffer.width,
|
||||||
.height = framebuffer.height,
|
.height = framebuffer.height,
|
||||||
.type = vk::ImageType::e2D,
|
.type = vk::ImageType::e2D,
|
||||||
@@ -582,13 +582,13 @@ VideoCore::ResultStatus RendererVulkan::Init() {
|
|||||||
|
|
||||||
// Create global instance
|
// Create global instance
|
||||||
auto surface = CreateSurface(instance, render_window);
|
auto surface = CreateSurface(instance, render_window);
|
||||||
g_vk_instace = std::make_unique<VKInstance>();
|
g_vk_instace = std::make_unique<Instance>();
|
||||||
g_vk_task_scheduler = std::make_unique<VKTaskScheduler>();
|
g_vk_task_scheduler = std::make_unique<TaskScheduler>();
|
||||||
g_vk_instace->Create(instance, physical_devices[1], surface, true);
|
g_vk_instace->Create(instance, physical_devices[1], surface, true);
|
||||||
g_vk_task_scheduler->Create();
|
g_vk_task_scheduler->Create();
|
||||||
|
|
||||||
//auto& layout = render_window.GetFramebufferLayout();
|
//auto& layout = render_window.GetFramebufferLayout();
|
||||||
swapchain = std::make_shared<VKSwapChain>(surface);
|
swapchain = std::make_shared<Swapchain>(surface);
|
||||||
//swapchain->Create(layout.width, layout.height, false);
|
//swapchain->Create(layout.width, layout.height, false);
|
||||||
|
|
||||||
// Create Vulkan state
|
// Create Vulkan state
|
||||||
|
@@ -20,9 +20,9 @@ namespace Vulkan {
|
|||||||
|
|
||||||
/// Structure used for storing information about the display target for each 3DS screen
|
/// Structure used for storing information about the display target for each 3DS screen
|
||||||
struct ScreenInfo {
|
struct ScreenInfo {
|
||||||
VKTexture* display_texture;
|
Texture* display_texture;
|
||||||
Common::Rectangle<float> display_texcoords;
|
Common::Rectangle<float> display_texcoords;
|
||||||
VKTexture texture;
|
Texture texture;
|
||||||
GPU::Regs::PixelFormat format;
|
GPU::Regs::PixelFormat format;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ private:
|
|||||||
|
|
||||||
/// Display information for top and bottom screens respectively
|
/// Display information for top and bottom screens respectively
|
||||||
std::array<ScreenInfo, 3> screen_infos;
|
std::array<ScreenInfo, 3> screen_infos;
|
||||||
std::shared_ptr<VKSwapChain> swapchain;
|
std::shared_ptr<Swapchain> swapchain;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
@@ -12,11 +12,11 @@
|
|||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
VKBuffer::~VKBuffer() {
|
Buffer::~Buffer() {
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKBuffer::Create(const VKBuffer::Info& info) {
|
void Buffer::Create(const Buffer::Info& info) {
|
||||||
auto device = g_vk_instace->GetDevice();
|
auto device = g_vk_instace->GetDevice();
|
||||||
buffer_info = info;
|
buffer_info = info;
|
||||||
|
|
||||||
@@ -43,12 +43,12 @@ void VKBuffer::Create(const VKBuffer::Info& info) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKBuffer::Recreate() {
|
void Buffer::Recreate() {
|
||||||
Destroy();
|
Destroy();
|
||||||
Create(buffer_info);
|
Create(buffer_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKBuffer::Destroy() {
|
void Buffer::Destroy() {
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
if (host_ptr != nullptr) {
|
if (host_ptr != nullptr) {
|
||||||
g_vk_instace->GetDevice().unmapMemory(memory);
|
g_vk_instace->GetDevice().unmapMemory(memory);
|
||||||
@@ -71,7 +71,7 @@ void VKBuffer::Destroy() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 VKBuffer::FindMemoryType(u32 type_filter, vk::MemoryPropertyFlags properties) {
|
u32 Buffer::FindMemoryType(u32 type_filter, vk::MemoryPropertyFlags properties) {
|
||||||
vk::PhysicalDeviceMemoryProperties mem_properties = g_vk_instace->GetPhysicalDevice().getMemoryProperties();
|
vk::PhysicalDeviceMemoryProperties mem_properties = g_vk_instace->GetPhysicalDevice().getMemoryProperties();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mem_properties.memoryTypeCount; i++)
|
for (uint32_t i = 0; i < mem_properties.memoryTypeCount; i++)
|
||||||
@@ -85,7 +85,7 @@ u32 VKBuffer::FindMemoryType(u32 type_filter, vk::MemoryPropertyFlags properties
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKBuffer::Upload(std::span<const std::byte> data, u32 offset,
|
void Buffer::Upload(std::span<const std::byte> data, u32 offset,
|
||||||
vk::AccessFlags access_to_block,
|
vk::AccessFlags access_to_block,
|
||||||
vk::PipelineStageFlags stage_to_block) {
|
vk::PipelineStageFlags stage_to_block) {
|
||||||
auto cmdbuffer = g_vk_task_scheduler->GetUploadCommandBuffer();
|
auto cmdbuffer = g_vk_task_scheduler->GetUploadCommandBuffer();
|
||||||
|
@@ -17,7 +17,7 @@ constexpr u32 MAX_BUFFER_VIEWS = 5;
|
|||||||
constexpr u32 MAX_COMMIT_CHUNKS = 6;
|
constexpr u32 MAX_COMMIT_CHUNKS = 6;
|
||||||
|
|
||||||
/// Generic Vulkan buffer object used by almost every resource
|
/// Generic Vulkan buffer object used by almost every resource
|
||||||
class VKBuffer : public NonCopyable {
|
class Buffer : public NonCopyable {
|
||||||
public:
|
public:
|
||||||
struct Info {
|
struct Info {
|
||||||
u32 size;
|
u32 size;
|
||||||
@@ -26,12 +26,12 @@ public:
|
|||||||
std::array<vk::Format, MAX_BUFFER_VIEWS> view_formats{};
|
std::array<vk::Format, MAX_BUFFER_VIEWS> view_formats{};
|
||||||
};
|
};
|
||||||
|
|
||||||
VKBuffer() = default;
|
Buffer() = default;
|
||||||
~VKBuffer();
|
~Buffer();
|
||||||
|
|
||||||
/// Enable move operations
|
/// Enable move operations
|
||||||
VKBuffer(VKBuffer&&) = default;
|
Buffer(Buffer&&) = default;
|
||||||
VKBuffer& operator=(VKBuffer&&) = default;
|
Buffer& operator=(Buffer&&) = default;
|
||||||
|
|
||||||
/// Create a new Vulkan buffer object
|
/// Create a new Vulkan buffer object
|
||||||
void Create(const Info& info);
|
void Create(const Info& info);
|
||||||
@@ -60,7 +60,7 @@ protected:
|
|||||||
u32 view_count{};
|
u32 view_count{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class StreamBuffer : public VKBuffer {
|
class StreamBuffer : public Buffer {
|
||||||
public:
|
public:
|
||||||
/*
|
/*
|
||||||
* Allocates a linear chunk of memory in the GPU buffer with at least "size" bytes
|
* Allocates a linear chunk of memory in the GPU buffer with at least "size" bytes
|
||||||
|
@@ -9,16 +9,16 @@
|
|||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
std::unique_ptr<VKInstance> g_vk_instace;
|
std::unique_ptr<Instance> g_vk_instace;
|
||||||
|
|
||||||
VKInstance::~VKInstance() {
|
Instance::~Instance() {
|
||||||
device.waitIdle();
|
device.waitIdle();
|
||||||
|
|
||||||
device.destroy();
|
device.destroy();
|
||||||
instance.destroy();
|
instance.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VKInstance::Create(vk::Instance new_instance, vk::PhysicalDevice gpu,
|
bool Instance::Create(vk::Instance new_instance, vk::PhysicalDevice gpu,
|
||||||
vk::SurfaceKHR surface, bool enable_validation_layer) {
|
vk::SurfaceKHR surface, bool enable_validation_layer) {
|
||||||
instance = new_instance;
|
instance = new_instance;
|
||||||
physical_device = gpu;
|
physical_device = gpu;
|
||||||
@@ -34,7 +34,7 @@ bool VKInstance::Create(vk::Instance new_instance, vk::PhysicalDevice gpu,
|
|||||||
return CreateDevice(surface, enable_validation_layer);
|
return CreateDevice(surface, enable_validation_layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VKInstance::CreateDevice(vk::SurfaceKHR surface, bool validation_enabled) {
|
bool Instance::CreateDevice(vk::SurfaceKHR surface, bool validation_enabled) {
|
||||||
// Can't create an instance without a valid surface
|
// Can't create an instance without a valid surface
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
LOG_CRITICAL(Render_Vulkan, "Invalid surface provided during instance creation!");
|
LOG_CRITICAL(Render_Vulkan, "Invalid surface provided during instance creation!");
|
||||||
@@ -106,7 +106,7 @@ bool VKInstance::CreateDevice(vk::SurfaceKHR surface, bool validation_enabled) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VKInstance::FindFeatures() {
|
bool Instance::FindFeatures() {
|
||||||
auto available = physical_device.getFeatures();
|
auto available = physical_device.getFeatures();
|
||||||
|
|
||||||
// Not having geometry shaders or wide lines will cause issues with rendering.
|
// Not having geometry shaders or wide lines will cause issues with rendering.
|
||||||
@@ -146,7 +146,7 @@ bool VKInstance::FindFeatures() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VKInstance::FindExtensions() {
|
bool Instance::FindExtensions() {
|
||||||
auto available = physical_device.enumerateDeviceExtensionProperties();
|
auto available = physical_device.enumerateDeviceExtensionProperties();
|
||||||
if (available.empty()) {
|
if (available.empty()) {
|
||||||
LOG_CRITICAL(Render_Vulkan, "No extensions supported by device.");
|
LOG_CRITICAL(Render_Vulkan, "No extensions supported by device.");
|
||||||
|
@@ -13,10 +13,10 @@
|
|||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
/// The global Vulkan instance
|
/// The global Vulkan instance
|
||||||
class VKInstance {
|
class Instance {
|
||||||
public:
|
public:
|
||||||
VKInstance() = default;
|
Instance() = default;
|
||||||
~VKInstance();
|
~Instance();
|
||||||
|
|
||||||
/// Construct global Vulkan context
|
/// Construct global Vulkan context
|
||||||
bool Create(vk::Instance instance, vk::PhysicalDevice gpu,
|
bool Create(vk::Instance instance, vk::PhysicalDevice gpu,
|
||||||
@@ -65,6 +65,6 @@ public:
|
|||||||
vk::PhysicalDeviceColorWriteEnableFeaturesEXT color_write_features{};
|
vk::PhysicalDeviceColorWriteEnableFeaturesEXT color_write_features{};
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::unique_ptr<VKInstance> g_vk_instace;
|
extern std::unique_ptr<Instance> g_vk_instace;
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@@ -66,7 +66,7 @@ RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window) {
|
|||||||
uniform_size_aligned_fs = Common::AlignUp<std::size_t>(sizeof(UniformData),
|
uniform_size_aligned_fs = Common::AlignUp<std::size_t>(sizeof(UniformData),
|
||||||
uniform_buffer_alignment);
|
uniform_buffer_alignment);
|
||||||
// Allocate texture buffer LUTs
|
// Allocate texture buffer LUTs
|
||||||
VKBuffer::Info texel_buffer_info = {
|
Buffer::Info texel_buffer_info = {
|
||||||
.size = TEXTURE_BUFFER_SIZE,
|
.size = TEXTURE_BUFFER_SIZE,
|
||||||
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
||||||
.usage = vk::BufferUsageFlagBits::eUniformTexelBuffer |
|
.usage = vk::BufferUsageFlagBits::eUniformTexelBuffer |
|
||||||
@@ -80,7 +80,7 @@ RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window) {
|
|||||||
texture_buffer_lut.Create(texel_buffer_info);
|
texture_buffer_lut.Create(texel_buffer_info);
|
||||||
|
|
||||||
// Create and bind uniform buffers
|
// Create and bind uniform buffers
|
||||||
VKBuffer::Info uniform_info = {
|
Buffer::Info uniform_info = {
|
||||||
.size = UNIFORM_BUFFER_SIZE,
|
.size = UNIFORM_BUFFER_SIZE,
|
||||||
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
||||||
.usage = vk::BufferUsageFlagBits::eUniformBuffer |
|
.usage = vk::BufferUsageFlagBits::eUniformBuffer |
|
||||||
@@ -98,14 +98,14 @@ RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window) {
|
|||||||
state.SetTexelBuffer(2, 0, TEXTURE_BUFFER_SIZE, texture_buffer_lut, 1);
|
state.SetTexelBuffer(2, 0, TEXTURE_BUFFER_SIZE, texture_buffer_lut, 1);
|
||||||
|
|
||||||
// Create vertex and index buffers
|
// Create vertex and index buffers
|
||||||
VKBuffer::Info vertex_info = {
|
Buffer::Info vertex_info = {
|
||||||
.size = VERTEX_BUFFER_SIZE,
|
.size = VERTEX_BUFFER_SIZE,
|
||||||
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
||||||
.usage = vk::BufferUsageFlagBits::eVertexBuffer |
|
.usage = vk::BufferUsageFlagBits::eVertexBuffer |
|
||||||
vk::BufferUsageFlagBits::eTransferDst
|
vk::BufferUsageFlagBits::eTransferDst
|
||||||
};
|
};
|
||||||
|
|
||||||
VKBuffer::Info index_info = {
|
Buffer::Info index_info = {
|
||||||
.size = INDEX_BUFFER_SIZE,
|
.size = INDEX_BUFFER_SIZE,
|
||||||
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
||||||
.usage = vk::BufferUsageFlagBits::eIndexBuffer |
|
.usage = vk::BufferUsageFlagBits::eIndexBuffer |
|
||||||
@@ -328,7 +328,7 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sync and bind the texture surfaces
|
// Sync and bind the texture surfaces
|
||||||
VKTexture temp_tex;
|
Texture temp_tex;
|
||||||
const auto pica_textures = regs.texturing.GetTextures();
|
const auto pica_textures = regs.texturing.GetTextures();
|
||||||
for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) {
|
for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) {
|
||||||
const auto& texture = pica_textures[texture_index];
|
const auto& texture = pica_textures[texture_index];
|
||||||
|
@@ -276,7 +276,7 @@ private:
|
|||||||
static constexpr std::size_t UNIFORM_BUFFER_SIZE = 2 * 1024 * 1024;
|
static constexpr std::size_t UNIFORM_BUFFER_SIZE = 2 * 1024 * 1024;
|
||||||
static constexpr std::size_t TEXTURE_BUFFER_SIZE = 1 * 1024 * 1024;
|
static constexpr std::size_t TEXTURE_BUFFER_SIZE = 1 * 1024 * 1024;
|
||||||
|
|
||||||
VKBuffer vertex_buffer, index_buffer;
|
Buffer vertex_buffer, index_buffer;
|
||||||
StreamBuffer uniform_buffer, texture_buffer_lut_lf, texture_buffer_lut;
|
StreamBuffer uniform_buffer, texture_buffer_lut_lf, texture_buffer_lut;
|
||||||
|
|
||||||
u32 uniform_buffer_alignment;
|
u32 uniform_buffer_alignment;
|
||||||
|
@@ -374,7 +374,7 @@ static vk::Rect2D FromRect(Common::Rectangle<u32> rect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate an uninitialized texture of appropriate size and format for the surface
|
// Allocate an uninitialized texture of appropriate size and format for the surface
|
||||||
void RasterizerCacheVulkan::AllocateTexture(VKTexture& target, SurfaceType type, vk::Format format,
|
void RasterizerCacheVulkan::AllocateTexture(Texture& target, SurfaceType type, vk::Format format,
|
||||||
u32 width, u32 height) {
|
u32 width, u32 height) {
|
||||||
// First check if the texture can be recycled
|
// First check if the texture can be recycled
|
||||||
auto recycled_tex = host_texture_recycler.find({format, width, height});
|
auto recycled_tex = host_texture_recycler.find({format, width, height});
|
||||||
@@ -408,7 +408,7 @@ void RasterizerCacheVulkan::AllocateTexture(VKTexture& target, SurfaceType type,
|
|||||||
|
|
||||||
// Otherwise create a brand new texture
|
// Otherwise create a brand new texture
|
||||||
u32 levels = std::log2(std::max(width, height)) + 1;
|
u32 levels = std::log2(std::max(width, height)) + 1;
|
||||||
VKTexture::Info texture_info{
|
Texture::Info texture_info{
|
||||||
.width = width,
|
.width = width,
|
||||||
.height = height,
|
.height = height,
|
||||||
.format = format,
|
.format = format,
|
||||||
|
@@ -176,7 +176,7 @@ struct CachedSurface : SurfaceParams, std::enable_shared_from_this<CachedSurface
|
|||||||
u32 fill_size = 0; /// Number of bytes to read from fill_data
|
u32 fill_size = 0; /// Number of bytes to read from fill_data
|
||||||
std::array<u8, 4> fill_data;
|
std::array<u8, 4> fill_data;
|
||||||
|
|
||||||
VKTexture texture;
|
Texture texture;
|
||||||
|
|
||||||
/// max mipmap level that has been attached to the texture
|
/// max mipmap level that has been attached to the texture
|
||||||
u32 max_level = 0;
|
u32 max_level = 0;
|
||||||
@@ -234,7 +234,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct CachedTextureCube {
|
struct CachedTextureCube {
|
||||||
VKTexture texture;
|
Texture texture;
|
||||||
u16 res_scale = 1;
|
u16 res_scale = 1;
|
||||||
std::shared_ptr<SurfaceWatcher> px;
|
std::shared_ptr<SurfaceWatcher> px;
|
||||||
std::shared_ptr<SurfaceWatcher> nx;
|
std::shared_ptr<SurfaceWatcher> nx;
|
||||||
@@ -298,7 +298,7 @@ public:
|
|||||||
// in the driver
|
// in the driver
|
||||||
// this must be placed above the surface_cache to ensure all cached surfaces are destroyed
|
// this must be placed above the surface_cache to ensure all cached surfaces are destroyed
|
||||||
// before destroying the recycler
|
// before destroying the recycler
|
||||||
std::unordered_multimap<HostTextureTag, VKTexture> host_texture_recycler;
|
std::unordered_multimap<HostTextureTag, Texture> host_texture_recycler;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DuplicateSurface(const Surface& src_surface, const Surface& dest_surface);
|
void DuplicateSurface(const Surface& src_surface, const Surface& dest_surface);
|
||||||
@@ -342,7 +342,7 @@ private:
|
|||||||
std::recursive_mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void AllocateTexture(VKTexture& target, SurfaceParams::SurfaceType type, vk::Format format,
|
void AllocateTexture(Texture& target, SurfaceParams::SurfaceType type, vk::Format format,
|
||||||
u32 width, u32 height);
|
u32 width, u32 height);
|
||||||
std::unique_ptr<FormatReinterpreterVulkan> format_reinterpreter;
|
std::unique_ptr<FormatReinterpreterVulkan> format_reinterpreter;
|
||||||
};
|
};
|
||||||
|
@@ -78,9 +78,9 @@ void DescriptorUpdater::PushBufferUpdate(vk::DescriptorSet set, u32 binding,
|
|||||||
view ? &view : nullptr};
|
view ? &view : nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanState::VulkanState(const std::shared_ptr<VKSwapChain>& swapchain) : swapchain(swapchain) {
|
VulkanState::VulkanState(const std::shared_ptr<Swapchain>& swapchain) : swapchain(swapchain) {
|
||||||
// Create a placeholder texture which can be used in place of a real binding.
|
// Create a placeholder texture which can be used in place of a real binding.
|
||||||
VKTexture::Info info{
|
Texture::Info info{
|
||||||
.width = 1,
|
.width = 1,
|
||||||
.height = 1,
|
.height = 1,
|
||||||
.format = vk::Format::eR8G8B8A8Unorm,
|
.format = vk::Format::eR8G8B8A8Unorm,
|
||||||
@@ -158,7 +158,7 @@ VulkanState::~VulkanState() {
|
|||||||
device.destroyPipeline(present_pipeline);
|
device.destroyPipeline(present_pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanState::Create(const std::shared_ptr<VKSwapChain>& swapchain) {
|
void VulkanState::Create(const std::shared_ptr<Swapchain>& swapchain) {
|
||||||
if (!s_vulkan_state) {
|
if (!s_vulkan_state) {
|
||||||
s_vulkan_state = std::make_unique<VulkanState>(swapchain);
|
s_vulkan_state = std::make_unique<VulkanState>(swapchain);
|
||||||
}
|
}
|
||||||
@@ -169,12 +169,12 @@ VulkanState& VulkanState::Get() {
|
|||||||
return *s_vulkan_state;
|
return *s_vulkan_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanState::SetVertexBuffer(const VKBuffer& buffer, vk::DeviceSize offset) {
|
void VulkanState::SetVertexBuffer(const Buffer& buffer, vk::DeviceSize offset) {
|
||||||
auto cmdbuffer = g_vk_task_scheduler->GetRenderCommandBuffer();
|
auto cmdbuffer = g_vk_task_scheduler->GetRenderCommandBuffer();
|
||||||
cmdbuffer.bindVertexBuffers(0, buffer.GetBuffer(), offset);
|
cmdbuffer.bindVertexBuffers(0, buffer.GetBuffer(), offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanState::SetUniformBuffer(u32 binding, u32 offset, u32 size, const VKBuffer& buffer) {
|
void VulkanState::SetUniformBuffer(u32 binding, u32 offset, u32 size, const Buffer& buffer) {
|
||||||
auto& set = descriptor_sets[0];
|
auto& set = descriptor_sets[0];
|
||||||
updater.PushBufferUpdate(set, binding,
|
updater.PushBufferUpdate(set, binding,
|
||||||
vk::DescriptorType::eUniformBuffer,
|
vk::DescriptorType::eUniformBuffer,
|
||||||
@@ -182,14 +182,14 @@ void VulkanState::SetUniformBuffer(u32 binding, u32 offset, u32 size, const VKBu
|
|||||||
descriptors_dirty = true;
|
descriptors_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanState::SetTexture(u32 binding, const VKTexture& image) {
|
void VulkanState::SetTexture(u32 binding, const Texture& image) {
|
||||||
auto& set = descriptor_sets[1];
|
auto& set = descriptor_sets[1];
|
||||||
updater.PushCombinedImageSamplerUpdate(set, binding, render_sampler, image.GetView());
|
updater.PushCombinedImageSamplerUpdate(set, binding, render_sampler, image.GetView());
|
||||||
render_views[binding] = image.GetView();
|
render_views[binding] = image.GetView();
|
||||||
descriptors_dirty = true;
|
descriptors_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanState::SetTexelBuffer(u32 binding, u32 offset, u32 size, const VKBuffer& buffer, u32 view_index) {
|
void VulkanState::SetTexelBuffer(u32 binding, u32 offset, u32 size, const Buffer& buffer, u32 view_index) {
|
||||||
auto& set = descriptor_sets[2];
|
auto& set = descriptor_sets[2];
|
||||||
updater.PushBufferUpdate(set, binding,
|
updater.PushBufferUpdate(set, binding,
|
||||||
vk::DescriptorType::eUniformTexelBuffer,
|
vk::DescriptorType::eUniformTexelBuffer,
|
||||||
@@ -218,7 +218,7 @@ void VulkanState::SetPlaceholderColor(u8 red, u8 green, u8 blue, u8 alpha) {
|
|||||||
placeholder.Upload(0, 0, 1, placeholder.GetArea(), color);
|
placeholder.Upload(0, 0, 1, placeholder.GetArea(), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanState::UnbindTexture(const VKTexture& image) {
|
void VulkanState::UnbindTexture(const Texture& image) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (render_views[i] == image.GetView()) {
|
if (render_views[i] == image.GetView()) {
|
||||||
render_views[i] = placeholder.GetView();
|
render_views[i] = placeholder.GetView();
|
||||||
@@ -243,7 +243,7 @@ void VulkanState::UnbindTexture(u32 unit) {
|
|||||||
descriptors_dirty = true;
|
descriptors_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanState::BeginRendering(VKTexture* color, VKTexture* depth, bool update_pipeline_formats,
|
void VulkanState::BeginRendering(Texture* color, Texture* depth, bool update_pipeline_formats,
|
||||||
vk::ClearColorValue color_clear, vk::AttachmentLoadOp color_load_op,
|
vk::ClearColorValue color_clear, vk::AttachmentLoadOp color_load_op,
|
||||||
vk::AttachmentStoreOp color_store_op, vk::ClearDepthStencilValue depth_clear,
|
vk::AttachmentStoreOp color_store_op, vk::ClearDepthStencilValue depth_clear,
|
||||||
vk::AttachmentLoadOp depth_load_op, vk::AttachmentStoreOp depth_store_op,
|
vk::AttachmentLoadOp depth_load_op, vk::AttachmentStoreOp depth_store_op,
|
||||||
|
@@ -54,16 +54,16 @@ private:
|
|||||||
u32 image_count{0}, buffer_count{0}, write_count{0};
|
u32 image_count{0}, buffer_count{0}, write_count{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
class VKSwapChain;
|
class Swapchain;
|
||||||
|
|
||||||
/// Tracks global Vulkan state
|
/// Tracks global Vulkan state
|
||||||
class VulkanState {
|
class VulkanState {
|
||||||
public:
|
public:
|
||||||
VulkanState(const std::shared_ptr<VKSwapChain>& swapchain);
|
VulkanState(const std::shared_ptr<Swapchain>& swapchain);
|
||||||
~VulkanState();
|
~VulkanState();
|
||||||
|
|
||||||
/// Initialize object to its initial state
|
/// Initialize object to its initial state
|
||||||
static void Create(const std::shared_ptr<VKSwapChain>& swapchain);
|
static void Create(const std::shared_ptr<Swapchain>& swapchain);
|
||||||
static VulkanState& Get();
|
static VulkanState& Get();
|
||||||
|
|
||||||
/// Query state
|
/// Query state
|
||||||
@@ -71,7 +71,7 @@ public:
|
|||||||
bool StencilTestEnabled() const { return stencil_enabled && stencil_writes; }
|
bool StencilTestEnabled() const { return stencil_enabled && stencil_writes; }
|
||||||
|
|
||||||
/// Configure drawing state
|
/// Configure drawing state
|
||||||
void SetVertexBuffer(const VKBuffer& buffer, vk::DeviceSize offset);
|
void SetVertexBuffer(const Buffer& buffer, vk::DeviceSize offset);
|
||||||
void SetViewport(vk::Viewport viewport);
|
void SetViewport(vk::Viewport viewport);
|
||||||
void SetScissor(vk::Rect2D scissor);
|
void SetScissor(vk::Rect2D scissor);
|
||||||
void SetCullMode(vk::CullModeFlags flags);
|
void SetCullMode(vk::CullModeFlags flags);
|
||||||
@@ -90,7 +90,7 @@ public:
|
|||||||
vk::BlendFactor src_alpha, vk::BlendFactor dst_alpha);
|
vk::BlendFactor src_alpha, vk::BlendFactor dst_alpha);
|
||||||
|
|
||||||
/// Rendering
|
/// Rendering
|
||||||
void BeginRendering(VKTexture* color, VKTexture* depth, bool update_pipeline_formats = false,
|
void BeginRendering(Texture* color, Texture* depth, bool update_pipeline_formats = false,
|
||||||
vk::ClearColorValue color_clear = {},
|
vk::ClearColorValue color_clear = {},
|
||||||
vk::AttachmentLoadOp color_load_op = vk::AttachmentLoadOp::eLoad,
|
vk::AttachmentLoadOp color_load_op = vk::AttachmentLoadOp::eLoad,
|
||||||
vk::AttachmentStoreOp color_store_op = vk::AttachmentStoreOp::eStore,
|
vk::AttachmentStoreOp color_store_op = vk::AttachmentStoreOp::eStore,
|
||||||
@@ -102,13 +102,13 @@ public:
|
|||||||
void EndRendering();
|
void EndRendering();
|
||||||
|
|
||||||
/// Configure shader resources
|
/// Configure shader resources
|
||||||
void SetUniformBuffer(u32 binding, u32 offset, u32 size, const VKBuffer& buffer);
|
void SetUniformBuffer(u32 binding, u32 offset, u32 size, const Buffer& buffer);
|
||||||
void SetTexture(u32 binding, const VKTexture& texture);
|
void SetTexture(u32 binding, const Texture& texture);
|
||||||
void SetTexelBuffer(u32 binding, u32 offset, u32 size, const VKBuffer& buffer, u32 view_index);
|
void SetTexelBuffer(u32 binding, u32 offset, u32 size, const Buffer& buffer, u32 view_index);
|
||||||
void SetPresentTextures(vk::ImageView view0, vk::ImageView view1, vk::ImageView view2);
|
void SetPresentTextures(vk::ImageView view0, vk::ImageView view1, vk::ImageView view2);
|
||||||
void SetPresentData(DrawInfo data);
|
void SetPresentData(DrawInfo data);
|
||||||
void SetPlaceholderColor(u8 red, u8 green, u8 blue, u8 alpha);
|
void SetPlaceholderColor(u8 red, u8 green, u8 blue, u8 alpha);
|
||||||
void UnbindTexture(const VKTexture& image);
|
void UnbindTexture(const Texture& image);
|
||||||
void UnbindTexture(u32 unit);
|
void UnbindTexture(u32 unit);
|
||||||
|
|
||||||
/// Apply all dirty state to the current Vulkan command buffer
|
/// Apply all dirty state to the current Vulkan command buffer
|
||||||
@@ -124,12 +124,12 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Render targets
|
// Render targets
|
||||||
std::shared_ptr<VKSwapChain> swapchain;
|
std::shared_ptr<Swapchain> swapchain;
|
||||||
bool rendering{false};
|
bool rendering{false};
|
||||||
vk::ImageView present_view;
|
vk::ImageView present_view;
|
||||||
std::array<vk::ImageView, 4> render_views;
|
std::array<vk::ImageView, 4> render_views;
|
||||||
vk::Sampler render_sampler, present_sampler;
|
vk::Sampler render_sampler, present_sampler;
|
||||||
VKTexture placeholder;
|
Texture placeholder;
|
||||||
|
|
||||||
// Render state
|
// Render state
|
||||||
bool descriptors_dirty{};
|
bool descriptors_dirty{};
|
||||||
|
@@ -13,11 +13,11 @@
|
|||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
VKSwapChain::VKSwapChain(vk::SurfaceKHR surface_) : surface(surface_) {
|
Swapchain::Swapchain(vk::SurfaceKHR surface_) : surface(surface_) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VKSwapChain::~VKSwapChain() {
|
Swapchain::~Swapchain() {
|
||||||
auto device = g_vk_instace->GetDevice();
|
auto device = g_vk_instace->GetDevice();
|
||||||
auto instance = g_vk_instace->GetInstance();
|
auto instance = g_vk_instace->GetInstance();
|
||||||
device.waitIdle();
|
device.waitIdle();
|
||||||
@@ -28,7 +28,7 @@ VKSwapChain::~VKSwapChain() {
|
|||||||
instance.destroySurfaceKHR(surface);
|
instance.destroySurfaceKHR(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VKSwapChain::Create(u32 width, u32 height, bool vsync_enabled) {
|
bool Swapchain::Create(u32 width, u32 height, bool vsync_enabled) {
|
||||||
is_outdated = false;
|
is_outdated = false;
|
||||||
is_suboptimal = false;
|
is_suboptimal = false;
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ bool VKSwapChain::Create(u32 width, u32 height, bool vsync_enabled) {
|
|||||||
// Wait for maximum of 1 second
|
// Wait for maximum of 1 second
|
||||||
constexpr u64 ACQUIRE_TIMEOUT = 1000000000;
|
constexpr u64 ACQUIRE_TIMEOUT = 1000000000;
|
||||||
|
|
||||||
void VKSwapChain::AcquireNextImage() {
|
void Swapchain::AcquireNextImage() {
|
||||||
auto result = g_vk_instace->GetDevice().acquireNextImageKHR(swapchain, ACQUIRE_TIMEOUT,
|
auto result = g_vk_instace->GetDevice().acquireNextImageKHR(swapchain, ACQUIRE_TIMEOUT,
|
||||||
image_available, VK_NULL_HANDLE,
|
image_available, VK_NULL_HANDLE,
|
||||||
&image_index);
|
&image_index);
|
||||||
@@ -99,7 +99,7 @@ void VKSwapChain::AcquireNextImage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKSwapChain::Present() {
|
void Swapchain::Present() {
|
||||||
const auto present_queue = g_vk_instace->GetPresentQueue();
|
const auto present_queue = g_vk_instace->GetPresentQueue();
|
||||||
|
|
||||||
vk::PresentInfoKHR present_info(render_finished, swapchain, image_index);
|
vk::PresentInfoKHR present_info(render_finished, swapchain, image_index);
|
||||||
@@ -122,7 +122,7 @@ void VKSwapChain::Present() {
|
|||||||
frame_index = (frame_index + 1) % swapchain_images.size();
|
frame_index = (frame_index + 1) % swapchain_images.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKSwapChain::PopulateSwapchainDetails(vk::SurfaceKHR surface, u32 width, u32 height) {
|
void Swapchain::PopulateSwapchainDetails(vk::SurfaceKHR surface, u32 width, u32 height) {
|
||||||
auto gpu = g_vk_instace->GetPhysicalDevice();
|
auto gpu = g_vk_instace->GetPhysicalDevice();
|
||||||
|
|
||||||
// Choose surface format
|
// Choose surface format
|
||||||
@@ -184,12 +184,12 @@ void VKSwapChain::PopulateSwapchainDetails(vk::SurfaceKHR surface, u32 width, u3
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKSwapChain::SetupImages() {
|
void Swapchain::SetupImages() {
|
||||||
// Get the swap chain images
|
// Get the swap chain images
|
||||||
auto device = g_vk_instace->GetDevice();
|
auto device = g_vk_instace->GetDevice();
|
||||||
auto images = device.getSwapchainImagesKHR(swapchain);
|
auto images = device.getSwapchainImagesKHR(swapchain);
|
||||||
|
|
||||||
VKTexture::Info image_info{
|
Texture::Info image_info{
|
||||||
.width = details.extent.width,
|
.width = details.extent.width,
|
||||||
.height = details.extent.height,
|
.height = details.extent.height,
|
||||||
.format = details.format.format,
|
.format = details.format.format,
|
||||||
@@ -201,7 +201,7 @@ void VKSwapChain::SetupImages() {
|
|||||||
// Create the swapchain buffers containing the image and imageview
|
// Create the swapchain buffers containing the image and imageview
|
||||||
swapchain_images.resize(images.size());
|
swapchain_images.resize(images.size());
|
||||||
for (int i = 0; i < swapchain_images.size(); i++) {
|
for (int i = 0; i < swapchain_images.size(); i++) {
|
||||||
// Wrap swapchain images with VKTexture
|
// Wrap swapchain images with Texture
|
||||||
swapchain_images[i].Adopt(image_info, images[i]);
|
swapchain_images[i].Adopt(image_info, images[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,10 +18,10 @@ struct SwapChainDetails {
|
|||||||
u32 image_count;
|
u32 image_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VKSwapChain {
|
class Swapchain {
|
||||||
public:
|
public:
|
||||||
VKSwapChain(vk::SurfaceKHR surface);
|
Swapchain(vk::SurfaceKHR surface);
|
||||||
~VKSwapChain();
|
~Swapchain();
|
||||||
|
|
||||||
/// Creates (or recreates) the swapchain with a given size.
|
/// Creates (or recreates) the swapchain with a given size.
|
||||||
bool Create(u32 width, u32 height, bool vsync_enabled);
|
bool Create(u32 width, u32 height, bool vsync_enabled);
|
||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
vk::SwapchainKHR GetSwapChain() const { return swapchain; }
|
vk::SwapchainKHR GetSwapChain() const { return swapchain; }
|
||||||
const vk::Semaphore& GetAvailableSemaphore() const { return image_available; }
|
const vk::Semaphore& GetAvailableSemaphore() const { return image_available; }
|
||||||
const vk::Semaphore& GetRenderSemaphore() const { return render_finished; }
|
const vk::Semaphore& GetRenderSemaphore() const { return render_finished; }
|
||||||
VKTexture& GetCurrentImage() { return swapchain_images[image_index]; }
|
Texture& GetCurrentImage() { return swapchain_images[image_index]; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PopulateSwapchainDetails(vk::SurfaceKHR surface, u32 width, u32 height);
|
void PopulateSwapchainDetails(vk::SurfaceKHR surface, u32 width, u32 height);
|
||||||
@@ -57,7 +57,7 @@ private:
|
|||||||
bool vsync_enabled{false}, is_outdated{true}, is_suboptimal{true};
|
bool vsync_enabled{false}, is_outdated{true}, is_suboptimal{true};
|
||||||
|
|
||||||
vk::SwapchainKHR swapchain{VK_NULL_HANDLE};
|
vk::SwapchainKHR swapchain{VK_NULL_HANDLE};
|
||||||
std::vector<VKTexture> swapchain_images;
|
std::vector<Texture> swapchain_images;
|
||||||
u32 image_index{0}, frame_index{0};
|
u32 image_index{0}, frame_index{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
VKTaskScheduler::~VKTaskScheduler() {
|
TaskScheduler::~TaskScheduler() {
|
||||||
// Destroy Vulkan resources
|
// Destroy Vulkan resources
|
||||||
auto device = g_vk_instace->GetDevice();
|
auto device = g_vk_instace->GetDevice();
|
||||||
device.waitIdle();
|
device.waitIdle();
|
||||||
@@ -25,7 +25,7 @@ VKTaskScheduler::~VKTaskScheduler() {
|
|||||||
device.destroySemaphore(timeline);
|
device.destroySemaphore(timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<u8*, u32> VKTaskScheduler::RequestStaging(u32 size) {
|
std::tuple<u8*, u32> TaskScheduler::RequestStaging(u32 size) {
|
||||||
auto& task = tasks[current_task];
|
auto& task = tasks[current_task];
|
||||||
if (size > STAGING_BUFFER_SIZE - task.current_offset) {
|
if (size > STAGING_BUFFER_SIZE - task.current_offset) {
|
||||||
// If we run out of space, allocate a new buffer.
|
// If we run out of space, allocate a new buffer.
|
||||||
@@ -43,11 +43,11 @@ std::tuple<u8*, u32> VKTaskScheduler::RequestStaging(u32 size) {
|
|||||||
return std::make_tuple(ptr, task.current_offset - size);
|
return std::make_tuple(ptr, task.current_offset - size);
|
||||||
}
|
}
|
||||||
|
|
||||||
VKBuffer& VKTaskScheduler::GetStaging() {
|
Buffer& TaskScheduler::GetStaging() {
|
||||||
return tasks[current_task].staging;
|
return tasks[current_task].staging;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VKTaskScheduler::Create() {
|
bool TaskScheduler::Create() {
|
||||||
auto device = g_vk_instace->GetDevice();
|
auto device = g_vk_instace->GetDevice();
|
||||||
|
|
||||||
// Create command pool
|
// Create command pool
|
||||||
@@ -61,7 +61,7 @@ bool VKTaskScheduler::Create() {
|
|||||||
|
|
||||||
timeline = device.createSemaphore(semaphore_info);
|
timeline = device.createSemaphore(semaphore_info);
|
||||||
|
|
||||||
VKBuffer::Info staging_info{
|
Buffer::Info staging_info{
|
||||||
.size = STAGING_BUFFER_SIZE,
|
.size = STAGING_BUFFER_SIZE,
|
||||||
.properties = vk::MemoryPropertyFlagBits::eHostVisible |
|
.properties = vk::MemoryPropertyFlagBits::eHostVisible |
|
||||||
vk::MemoryPropertyFlagBits::eHostCoherent,
|
vk::MemoryPropertyFlagBits::eHostCoherent,
|
||||||
@@ -89,12 +89,12 @@ bool VKTaskScheduler::Create() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::CommandBuffer VKTaskScheduler::GetRenderCommandBuffer() const {
|
vk::CommandBuffer TaskScheduler::GetRenderCommandBuffer() const {
|
||||||
const auto& task = tasks[current_task];
|
const auto& task = tasks[current_task];
|
||||||
return task.command_buffers[1];
|
return task.command_buffers[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::CommandBuffer VKTaskScheduler::GetUploadCommandBuffer() {
|
vk::CommandBuffer TaskScheduler::GetUploadCommandBuffer() {
|
||||||
auto& task = tasks[current_task];
|
auto& task = tasks[current_task];
|
||||||
if (!task.use_upload_buffer) {
|
if (!task.use_upload_buffer) {
|
||||||
auto& cmdbuffer = task.command_buffers[0];
|
auto& cmdbuffer = task.command_buffers[0];
|
||||||
@@ -105,12 +105,12 @@ vk::CommandBuffer VKTaskScheduler::GetUploadCommandBuffer() {
|
|||||||
return task.command_buffers[0];
|
return task.command_buffers[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::DescriptorPool VKTaskScheduler::GetDescriptorPool() const {
|
vk::DescriptorPool TaskScheduler::GetDescriptorPool() const {
|
||||||
const auto& task = tasks[current_task];
|
const auto& task = tasks[current_task];
|
||||||
return task.pool;
|
return task.pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTaskScheduler::SyncToGPU(u64 task_index) {
|
void TaskScheduler::SyncToGPU(u64 task_index) {
|
||||||
// No need to sync if the GPU already has finished the task
|
// No need to sync if the GPU already has finished the task
|
||||||
auto tick = GetGPUTick();
|
auto tick = GetGPUTick();
|
||||||
if (tasks[task_index].task_id <= tick) {
|
if (tasks[task_index].task_id <= tick) {
|
||||||
@@ -140,20 +140,20 @@ void VKTaskScheduler::SyncToGPU(u64 task_index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTaskScheduler::SyncToGPU() {
|
void TaskScheduler::SyncToGPU() {
|
||||||
SyncToGPU(current_task);
|
SyncToGPU(current_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 VKTaskScheduler::GetCPUTick() const {
|
u64 TaskScheduler::GetCPUTick() const {
|
||||||
return current_task_id;
|
return current_task_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 VKTaskScheduler::GetGPUTick() const {
|
u64 TaskScheduler::GetGPUTick() const {
|
||||||
auto device = g_vk_instace->GetDevice();
|
auto device = g_vk_instace->GetDevice();
|
||||||
return device.getSemaphoreCounterValue(timeline);
|
return device.getSemaphoreCounterValue(timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTaskScheduler::Submit(bool wait_completion, bool present, VKSwapChain* swapchain) {
|
void TaskScheduler::Submit(bool wait_completion, bool present, Swapchain* swapchain) {
|
||||||
// End the current task recording.
|
// End the current task recording.
|
||||||
auto& task = tasks[current_task];
|
auto& task = tasks[current_task];
|
||||||
|
|
||||||
@@ -209,12 +209,12 @@ void VKTaskScheduler::Submit(bool wait_completion, bool present, VKSwapChain* sw
|
|||||||
BeginTask();
|
BeginTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTaskScheduler::Schedule(std::function<void()> func) {
|
void TaskScheduler::Schedule(std::function<void()> func) {
|
||||||
auto& task = tasks[current_task];
|
auto& task = tasks[current_task];
|
||||||
task.cleanups.push_back(func);
|
task.cleanups.push_back(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTaskScheduler::BeginTask() {
|
void TaskScheduler::BeginTask() {
|
||||||
u32 next_task_index = (current_task + 1) % TASK_COUNT;
|
u32 next_task_index = (current_task + 1) % TASK_COUNT;
|
||||||
auto& task = tasks[next_task_index];
|
auto& task = tasks[next_task_index];
|
||||||
auto device = g_vk_instace->GetDevice();
|
auto device = g_vk_instace->GetDevice();
|
||||||
@@ -234,6 +234,6 @@ void VKTaskScheduler::BeginTask() {
|
|||||||
state.InitDescriptorSets();
|
state.InitDescriptorSets();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<VKTaskScheduler> g_vk_task_scheduler;
|
std::unique_ptr<TaskScheduler> g_vk_task_scheduler;
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@@ -23,17 +23,17 @@ namespace Vulkan {
|
|||||||
constexpr u32 TASK_COUNT = 5;
|
constexpr u32 TASK_COUNT = 5;
|
||||||
constexpr u32 STAGING_BUFFER_SIZE = 16 * 1024 * 1024;
|
constexpr u32 STAGING_BUFFER_SIZE = 16 * 1024 * 1024;
|
||||||
|
|
||||||
class VKSwapChain;
|
class Swapchain;
|
||||||
|
|
||||||
/// Wrapper class around command buffer execution. Handles an arbitrary
|
/// Wrapper class around command buffer execution. Handles an arbitrary
|
||||||
/// number of tasks that can be submitted concurrently. This allows the host
|
/// number of tasks that can be submitted concurrently. This allows the host
|
||||||
/// to start recording the next frame while the GPU is working on the
|
/// to start recording the next frame while the GPU is working on the
|
||||||
/// current one. Larger values can be used with caution, as they can cause
|
/// current one. Larger values can be used with caution, as they can cause
|
||||||
/// frame latency if the CPU is too far ahead of the GPU
|
/// frame latency if the CPU is too far ahead of the GPU
|
||||||
class VKTaskScheduler {
|
class TaskScheduler {
|
||||||
public:
|
public:
|
||||||
VKTaskScheduler() = default;
|
TaskScheduler() = default;
|
||||||
~VKTaskScheduler();
|
~TaskScheduler();
|
||||||
|
|
||||||
/// Create and initialize the work scheduler
|
/// Create and initialize the work scheduler
|
||||||
bool Create();
|
bool Create();
|
||||||
@@ -45,7 +45,7 @@ public:
|
|||||||
|
|
||||||
/// Access the staging buffer of the current task
|
/// Access the staging buffer of the current task
|
||||||
std::tuple<u8*, u32> RequestStaging(u32 size);
|
std::tuple<u8*, u32> RequestStaging(u32 size);
|
||||||
VKBuffer& GetStaging();
|
Buffer& GetStaging();
|
||||||
|
|
||||||
/// Query and/or synchronization CPU and GPU
|
/// Query and/or synchronization CPU and GPU
|
||||||
u64 GetCPUTick() const;
|
u64 GetCPUTick() const;
|
||||||
@@ -54,7 +54,7 @@ public:
|
|||||||
void SyncToGPU(u64 task_index);
|
void SyncToGPU(u64 task_index);
|
||||||
|
|
||||||
void Schedule(std::function<void()> func);
|
void Schedule(std::function<void()> func);
|
||||||
void Submit(bool wait_completion = false, bool present = false, VKSwapChain* swapchain = nullptr);
|
void Submit(bool wait_completion = false, bool present = false, Swapchain* swapchain = nullptr);
|
||||||
|
|
||||||
void BeginTask();
|
void BeginTask();
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ private:
|
|||||||
std::array<vk::CommandBuffer, 2> command_buffers;
|
std::array<vk::CommandBuffer, 2> command_buffers;
|
||||||
std::vector<std::function<void()>> cleanups;
|
std::vector<std::function<void()>> cleanups;
|
||||||
vk::DescriptorPool pool;
|
vk::DescriptorPool pool;
|
||||||
VKBuffer staging;
|
Buffer staging;
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::Semaphore timeline;
|
vk::Semaphore timeline;
|
||||||
@@ -77,6 +77,6 @@ private:
|
|||||||
u64 current_task = TASK_COUNT - 1;
|
u64 current_task = TASK_COUNT - 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::unique_ptr<VKTaskScheduler> g_vk_task_scheduler;
|
extern std::unique_ptr<TaskScheduler> g_vk_task_scheduler;
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@@ -54,11 +54,11 @@ vk::ImageAspectFlags GetImageAspect(vk::Format format) {
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
VKTexture::~VKTexture() {
|
Texture::~Texture() {
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
VKTexture::VKTexture(VKTexture&& other) noexcept {
|
Texture::Texture(Texture&& other) noexcept {
|
||||||
info = std::exchange(other.info, Info{});
|
info = std::exchange(other.info, Info{});
|
||||||
texture = std::exchange(other.texture, VK_NULL_HANDLE);
|
texture = std::exchange(other.texture, VK_NULL_HANDLE);
|
||||||
aspect = std::exchange(other.aspect, vk::ImageAspectFlagBits::eNone);
|
aspect = std::exchange(other.aspect, vk::ImageAspectFlagBits::eNone);
|
||||||
@@ -70,7 +70,7 @@ VKTexture::VKTexture(VKTexture&& other) noexcept {
|
|||||||
is_d24s8 = std::exchange(other.is_d24s8, false);
|
is_d24s8 = std::exchange(other.is_d24s8, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
VKTexture& VKTexture::operator=(VKTexture&& other) noexcept {
|
Texture& Texture::operator=(Texture&& other) noexcept {
|
||||||
Destroy();
|
Destroy();
|
||||||
info = std::exchange(other.info, Info{});
|
info = std::exchange(other.info, Info{});
|
||||||
texture = std::exchange(other.texture, VK_NULL_HANDLE);
|
texture = std::exchange(other.texture, VK_NULL_HANDLE);
|
||||||
@@ -84,7 +84,7 @@ VKTexture& VKTexture::operator=(VKTexture&& other) noexcept {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::Create(const Info& create_info) {
|
void Texture::Create(const Info& create_info) {
|
||||||
auto device = g_vk_instace->GetDevice();
|
auto device = g_vk_instace->GetDevice();
|
||||||
info = create_info;
|
info = create_info;
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ void VKTexture::Create(const Info& create_info) {
|
|||||||
|
|
||||||
// Create texture memory
|
// Create texture memory
|
||||||
auto requirements = device.getImageMemoryRequirements(texture);
|
auto requirements = device.getImageMemoryRequirements(texture);
|
||||||
auto memory_index = VKBuffer::FindMemoryType(requirements.memoryTypeBits,
|
auto memory_index = Buffer::FindMemoryType(requirements.memoryTypeBits,
|
||||||
vk::MemoryPropertyFlagBits::eDeviceLocal);
|
vk::MemoryPropertyFlagBits::eDeviceLocal);
|
||||||
vk::MemoryAllocateInfo alloc_info(requirements.size, memory_index);
|
vk::MemoryAllocateInfo alloc_info(requirements.size, memory_index);
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ void VKTexture::Create(const Info& create_info) {
|
|||||||
view = device.createImageView(view_info);
|
view = device.createImageView(view_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::Create(VKTexture& other) {
|
void Texture::Create(Texture& other) {
|
||||||
auto info = other.info;
|
auto info = other.info;
|
||||||
Create(info);
|
Create(info);
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ void VKTexture::Create(VKTexture& other) {
|
|||||||
other.Transition(cmdbuffer, old_layout);
|
other.Transition(cmdbuffer, old_layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::Adopt(const Info& create_info, vk::Image image) {
|
void Texture::Adopt(const Info& create_info, vk::Image image) {
|
||||||
info = create_info;
|
info = create_info;
|
||||||
image_size = info.width * info.height * BytesPerPixel(info.format);
|
image_size = info.width * info.height * BytesPerPixel(info.format);
|
||||||
aspect = GetImageAspect(info.format);
|
aspect = GetImageAspect(info.format);
|
||||||
@@ -184,7 +184,7 @@ void VKTexture::Adopt(const Info& create_info, vk::Image image) {
|
|||||||
adopted = true;
|
adopted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::Destroy() {
|
void Texture::Destroy() {
|
||||||
if (texture && !adopted) {
|
if (texture && !adopted) {
|
||||||
// Make sure to unbind the texture before destroying it
|
// Make sure to unbind the texture before destroying it
|
||||||
auto& state = VulkanState::Get();
|
auto& state = VulkanState::Get();
|
||||||
@@ -216,11 +216,11 @@ void VKTexture::Destroy() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::Transition(vk::CommandBuffer cmdbuffer, vk::ImageLayout new_layout) {
|
void Texture::Transition(vk::CommandBuffer cmdbuffer, vk::ImageLayout new_layout) {
|
||||||
Transition(cmdbuffer, new_layout, 0, info.levels, 0, info.layers);
|
Transition(cmdbuffer, new_layout, 0, info.levels, 0, info.layers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::Transition(vk::CommandBuffer cmdbuffer, vk::ImageLayout new_layout,
|
void Texture::Transition(vk::CommandBuffer cmdbuffer, vk::ImageLayout new_layout,
|
||||||
u32 start_level, u32 level_count, u32 start_layer, u32 layer_count) {
|
u32 start_level, u32 level_count, u32 start_layer, u32 layer_count) {
|
||||||
if (new_layout == layout) {
|
if (new_layout == layout) {
|
||||||
return;
|
return;
|
||||||
@@ -305,11 +305,11 @@ void VKTexture::Transition(vk::CommandBuffer cmdbuffer, vk::ImageLayout new_layo
|
|||||||
layout = new_layout;
|
layout = new_layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::OverrideImageLayout(vk::ImageLayout new_layout) {
|
void Texture::OverrideImageLayout(vk::ImageLayout new_layout) {
|
||||||
layout = new_layout;
|
layout = new_layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::Upload(u32 level, u32 layer, u32 row_length, vk::Rect2D region, std::span<u8> pixels) {
|
void Texture::Upload(u32 level, u32 layer, u32 row_length, vk::Rect2D region, std::span<u8> pixels) {
|
||||||
u32 request_size = is_rgb ? (pixels.size() / 3) * 4 :
|
u32 request_size = is_rgb ? (pixels.size() / 3) * 4 :
|
||||||
(is_d24s8 ? (pixels.size() / 4) * 5 : pixels.size());
|
(is_d24s8 ? (pixels.size() / 4) * 5 : pixels.size());
|
||||||
auto [buffer, offset] = g_vk_task_scheduler->RequestStaging(request_size);
|
auto [buffer, offset] = g_vk_task_scheduler->RequestStaging(request_size);
|
||||||
@@ -367,7 +367,7 @@ void VKTexture::Upload(u32 level, u32 layer, u32 row_length, vk::Rect2D region,
|
|||||||
Transition(cmdbuffer, vk::ImageLayout::eShaderReadOnlyOptimal);
|
Transition(cmdbuffer, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::Download(u32 level, u32 layer, u32 row_length, vk::Rect2D region, std::span<u8> memory) {
|
void Texture::Download(u32 level, u32 layer, u32 row_length, vk::Rect2D region, std::span<u8> memory) {
|
||||||
u32 request_size = is_rgb ? (memory.size() / 3) * 4 :
|
u32 request_size = is_rgb ? (memory.size() / 3) * 4 :
|
||||||
(is_d24s8 ? (memory.size() / 4) * 8 : memory.size());
|
(is_d24s8 ? (memory.size() / 4) * 8 : memory.size());
|
||||||
auto [buffer, offset] = g_vk_task_scheduler->RequestStaging(request_size);
|
auto [buffer, offset] = g_vk_task_scheduler->RequestStaging(request_size);
|
||||||
@@ -434,7 +434,7 @@ std::span<Out> SpanCast(std::span<In> span) {
|
|||||||
return std::span(reinterpret_cast<Out*>(span.data()), span.size_bytes() / sizeof(Out));
|
return std::span(reinterpret_cast<Out*>(span.data()), span.size_bytes() / sizeof(Out));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> VKTexture::RGBToRGBA(std::span<u8> data) {
|
std::vector<u8> Texture::RGBToRGBA(std::span<u8> data) {
|
||||||
ASSERT(data.size() % 3 == 0);
|
ASSERT(data.size() % 3 == 0);
|
||||||
|
|
||||||
u32 new_size = (data.size() / 3) * 4;
|
u32 new_size = (data.size() / 3) * 4;
|
||||||
@@ -450,7 +450,7 @@ std::vector<u8> VKTexture::RGBToRGBA(std::span<u8> data) {
|
|||||||
return rgba;
|
return rgba;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u64> VKTexture::D24S8ToD32S8(std::span<u8> data) {
|
std::vector<u64> Texture::D24S8ToD32S8(std::span<u8> data) {
|
||||||
ASSERT(data.size() % 4 == 0);
|
ASSERT(data.size() % 4 == 0);
|
||||||
|
|
||||||
std::vector<u64> d32s8;
|
std::vector<u64> d32s8;
|
||||||
@@ -471,7 +471,7 @@ std::vector<u64> VKTexture::D24S8ToD32S8(std::span<u8> data) {
|
|||||||
return d32s8;
|
return d32s8;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> VKTexture::RGBAToRGB(std::span<u8> data) {
|
std::vector<u8> Texture::RGBAToRGB(std::span<u8> data) {
|
||||||
ASSERT(data.size() % 4 == 0);
|
ASSERT(data.size() % 4 == 0);
|
||||||
|
|
||||||
u32 new_size = (data.size() / 4) * 3;
|
u32 new_size = (data.size() / 4) * 3;
|
||||||
@@ -486,7 +486,7 @@ std::vector<u8> VKTexture::RGBAToRGB(std::span<u8> data) {
|
|||||||
return rgb;
|
return rgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u32> VKTexture::D32S8ToD24S8(std::span<u8> data) {
|
std::vector<u32> Texture::D32S8ToD24S8(std::span<u8> data) {
|
||||||
ASSERT(data.size() % 8 == 0);
|
ASSERT(data.size() % 8 == 0);
|
||||||
|
|
||||||
std::vector<u32> d24s8;
|
std::vector<u32> d24s8;
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
/// Vulkan texture object
|
/// Vulkan texture object
|
||||||
class VKTexture final : public NonCopyable {
|
class Texture final : public NonCopyable {
|
||||||
public:
|
public:
|
||||||
/// Information for the creation of the target texture
|
/// Information for the creation of the target texture
|
||||||
struct Info {
|
struct Info {
|
||||||
@@ -28,16 +28,16 @@ public:
|
|||||||
u32 levels = 1, layers = 1;
|
u32 levels = 1, layers = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
VKTexture() = default;
|
Texture() = default;
|
||||||
~VKTexture();
|
~Texture();
|
||||||
|
|
||||||
/// Enable move operations
|
/// Enable move operations
|
||||||
VKTexture(VKTexture&& other) noexcept;
|
Texture(Texture&& other) noexcept;
|
||||||
VKTexture& operator=(VKTexture&& other) noexcept;
|
Texture& operator=(Texture&& other) noexcept;
|
||||||
|
|
||||||
/// Create a new Vulkan texture object
|
/// Create a new Vulkan texture object
|
||||||
void Create(const Info& info);
|
void Create(const Info& info);
|
||||||
void Create(VKTexture& texture);
|
void Create(Texture& texture);
|
||||||
void Adopt(const Info& info, vk::Image image);
|
void Adopt(const Info& info, vk::Image image);
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ private:
|
|||||||
std::vector<u32> D32S8ToD24S8(std::span<u8> data);
|
std::vector<u32> D32S8ToD24S8(std::span<u8> data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VKTexture::Info info{};
|
Texture::Info info{};
|
||||||
vk::ImageLayout layout{};
|
vk::ImageLayout layout{};
|
||||||
vk::ImageAspectFlags aspect{};
|
vk::ImageAspectFlags aspect{};
|
||||||
vk::Image texture;
|
vk::Image texture;
|
||||||
|
Reference in New Issue
Block a user