Skip to content

Commit

Permalink
descriptors
Browse files Browse the repository at this point in the history
  • Loading branch information
TheNumbat committed Jan 14, 2024
1 parent bc39af5 commit 4d2e625
Show file tree
Hide file tree
Showing 14 changed files with 440 additions and 43 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

(WIP; refactoring into new repo)

[rpp](https://github.com/TheNumbat/rpp)-based Vulkan abstraction layer.
[rpp](https://github.com/TheNumbat/rpp)-based Vulkan 1.3 abstraction layer.

Does not seek to redefine the Vulkan API: instead provides a convenient interface for common use cases.
Includes the following features:
rvk does not seek to redefine the Vulkan API, nor expose all of its configurability.
Instead, rvk provides a convenient interface for modern desktop GPUs.
It includes the following features:

- RAII wrappers for Vulkan objects
- GPU heap allocator and buffer sub-allocators
- Multiple frames in flight and resource delete queue
- Multiple frames in flight and resource deletion queue
- Async GPU tasks for coroutines
- Swapchain management and compositor
- Validation layer config and debug messaging
Expand Down
2 changes: 2 additions & 0 deletions rvk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ set(SOURCES_RVK
"swapchain.cpp"
"memory.cpp"
"memory.h"
"descriptors.cpp"
"descriptors.h"
)

if(UNIX AND NOT APPLE)
Expand Down
140 changes: 140 additions & 0 deletions rvk/descriptors.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@

#include <imgui/imgui.h>

#include "descriptors.h"
#include "device.h"

namespace rvk::impl {

using namespace rpp;

Descriptor_Pool::Descriptor_Pool(Arc<Device, Alloc> D, u32 bindings_per_type, bool ray_tracing)
: device(move(D)) {

Profile::Time_Point start = Profile::timestamp();

Region(R) {
Vec<VkDescriptorPoolSize, Mregion<R>> sizes{
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_SAMPLER, bindings_per_type},
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, bindings_per_type},
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, bindings_per_type},
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, bindings_per_type},
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, bindings_per_type},
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, bindings_per_type},
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, bindings_per_type},
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, bindings_per_type},
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, bindings_per_type}};

if(ray_tracing)
sizes.push(VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
bindings_per_type});

VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.poolSizeCount = static_cast<u32>(sizes.length());
pool_info.pPoolSizes = sizes.data();
pool_info.maxSets = static_cast<u32>(sizes.length()) * bindings_per_type;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;

Thread::Lock lock(mutex);
RVK_CHECK(vkCreateDescriptorPool(*device, &pool_info, null, &pool));
}

Profile::Time_Point end = Profile::timestamp();
info("[rvk] Created descriptor pool in %ms.", Profile::ms(end - start));
}

Descriptor_Pool::~Descriptor_Pool() {
Thread::Lock lock(mutex);
if(pool) {
vkDestroyDescriptorPool(*device, pool, null);
info("[rvk] Destroyed descriptor pool.");
}
pool = null;
}

void Descriptor_Pool::release(Descriptor_Set& set) {
Thread::Lock lock(mutex);
vkFreeDescriptorSets(*device, pool, static_cast<u32>(set.sets.length()), set.sets.data());
}

Descriptor_Set Descriptor_Pool::make(Descriptor_Set_Layout& layout, u64 frames_in_flight) {

Vec<VkDescriptorSet, Alloc> sets;

Region(R) {

Vec<VkDescriptorSetLayout, Mregion<R>> layouts(frames_in_flight);
for(u64 i = 0; i < frames_in_flight; ++i) layouts.push(layout);

sets.resize(frames_in_flight);

VkDescriptorSetAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info.descriptorPool = pool;
alloc_info.descriptorSetCount = static_cast<u32>(frames_in_flight);
alloc_info.pSetLayouts = layouts.data();

{
Thread::Lock lock(mutex);
RVK_CHECK(vkAllocateDescriptorSets(*device, &alloc_info, sets.data()));
}
}

return Descriptor_Set{Arc<Descriptor_Pool, Alloc>::from_this(this), move(sets)};
}

Descriptor_Set::Descriptor_Set(Arc<Descriptor_Pool, Alloc> pool, Vec<VkDescriptorSet, Alloc> sets)
: pool(move(pool)), sets(move(sets)) {
}

Descriptor_Set::~Descriptor_Set() {
if(sets.length()) {
pool->release(*this);
}
}

void Descriptor_Set::write(u64 frame_index, Slice<VkWriteDescriptorSet> writes) {
assert(frame_index < sets.length());

Region(R) {
Vec<VkWriteDescriptorSet, Mregion<R>> vk_writes;
for(auto& write : writes) {
vk_writes.push(write).dstSet = sets[frame_index];
}
vkUpdateDescriptorSets(*pool->device, static_cast<u32>(vk_writes.length()),
vk_writes.data(), 0, null);
}
}

Descriptor_Set_Layout::Descriptor_Set_Layout(Arc<Device, Alloc> D,
Slice<VkDescriptorSetLayoutBinding> bindings)
: device(move(D)) {

VkDescriptorSetLayoutCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
info.bindingCount = static_cast<u32>(bindings.length());
info.pBindings = bindings.data();

RVK_CHECK(vkCreateDescriptorSetLayout(*device, &info, null, &layout));
}

Descriptor_Set_Layout::~Descriptor_Set_Layout() {
if(layout) vkDestroyDescriptorSetLayout(*device, layout, null);
layout = null;
}

Descriptor_Set_Layout::Descriptor_Set_Layout(Descriptor_Set_Layout&& src) {
*this = move(src);
}

Descriptor_Set_Layout& Descriptor_Set_Layout::operator=(Descriptor_Set_Layout&& src) {
assert(this != &src);
this->~Descriptor_Set_Layout();
device = move(src.device);
layout = src.layout;
src.layout = null;
return *this;
}

} // namespace rvk::impl
84 changes: 84 additions & 0 deletions rvk/descriptors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@

#pragma once

#include <rpp/base.h>
#include <rpp/rc.h>

#include "fwd.h"

namespace rvk::impl {

using namespace rpp;

struct Descriptor_Set_Layout {

explicit Descriptor_Set_Layout(Arc<Device, Alloc> device,
Slice<VkDescriptorSetLayoutBinding> bindings);
~Descriptor_Set_Layout();

Descriptor_Set_Layout(const Descriptor_Set_Layout&) = delete;
Descriptor_Set_Layout& operator=(const Descriptor_Set_Layout&) = delete;
Descriptor_Set_Layout(Descriptor_Set_Layout&&);
Descriptor_Set_Layout& operator=(Descriptor_Set_Layout&&);

operator VkDescriptorSetLayout() {
return layout;
}

private:
Arc<Device, Alloc> device;
VkDescriptorSetLayout layout = null;
};

struct Descriptor_Set {

explicit Descriptor_Set(Arc<Descriptor_Pool, Alloc> pool, Vec<VkDescriptorSet, Alloc> sets);
~Descriptor_Set();

Descriptor_Set(const Descriptor_Set&) = delete;
Descriptor_Set& operator=(const Descriptor_Set&) = delete;
Descriptor_Set(Descriptor_Set&& src) = default;
Descriptor_Set& operator=(Descriptor_Set&& src) = default;

void write(u64 frame_index, Slice<VkWriteDescriptorSet> writes);

VkDescriptorSet get(u64 frame_index) {
return sets[frame_index];
}

private:
Arc<Descriptor_Pool, Alloc> pool;
Vec<VkDescriptorSet, Alloc> sets;

friend struct Descriptor_Pool;
};

struct Descriptor_Pool {

~Descriptor_Pool();

Descriptor_Pool(const Descriptor_Pool&) = delete;
Descriptor_Pool& operator=(const Descriptor_Pool&) = delete;
Descriptor_Pool(Descriptor_Pool&&) = delete;
Descriptor_Pool& operator=(Descriptor_Pool&&) = delete;

operator VkDescriptorPool() {
return pool;
}

Descriptor_Set make(Descriptor_Set_Layout& layout, u64 frames_in_flight);

private:
explicit Descriptor_Pool(Arc<Device, Alloc> device, u32 bindings_per_type, bool ray_tracing);
friend struct Arc<Descriptor_Pool, Alloc>;

void release(Descriptor_Set& set);

Arc<Device, Alloc> device;
VkDescriptorPool pool = null;
Thread::Mutex mutex;

friend struct Descriptor_Set;
};

} // namespace rvk::impl
14 changes: 10 additions & 4 deletions rvk/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,12 +243,12 @@ Opt<u32> Physical_Device::present_queue_index(VkSurfaceKHR surface) {
return {};
}

bool Physical_Device::is_discrete() {
return properties_.device.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
bool Physical_Device::Properties::is_discrete() const {
return device.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
}

String_View Physical_Device::name() {
return String_View{properties_.device.properties.deviceName};
String_View Physical_Device::Properties::name() const {
return String_View{device.properties.deviceName};
}

bool Physical_Device::supports_extension(String_View name) {
Expand Down Expand Up @@ -315,6 +315,12 @@ Opt<u32> Physical_Device::heap_index(u32 mask, u32 type) {
return {};
}

VkSurfaceCapabilitiesKHR Physical_Device::capabilities(VkSurfaceKHR surface) {
VkSurfaceCapabilitiesKHR capabilities;
RVK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &capabilities));
return capabilities;
}

void Physical_Device::imgui() {
using namespace ImGui;

Expand Down
6 changes: 4 additions & 2 deletions rvk/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ struct Physical_Device {
VkPhysicalDeviceMaintenance3Properties maintenance3 = {};
VkPhysicalDeviceMaintenance4Properties maintenance4 = {};
VkPhysicalDeviceRayTracingPipelinePropertiesKHR ray_tracing = {};

String_View name() const;
bool is_discrete() const;
};

~Physical_Device() = default;
Expand All @@ -42,9 +45,8 @@ struct Physical_Device {
Pair<u64, u64> heap_stat(u32 heap);
Opt<u32> heap_index(u32 mask, u32 properties);

String_View name();
bool is_discrete();
bool supports_extension(String_View name);
VkSurfaceCapabilitiesKHR capabilities(VkSurfaceKHR surface);

const Properties& properties() const {
return properties_;
Expand Down
5 changes: 3 additions & 2 deletions rvk/fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ struct Debug_Callback;
struct Physical_Device;
struct Device;
struct Device_Memory;

struct Image;
struct Image_View;

struct Descriptor_Set_Layout;
struct Descriptor_Set;
struct Descriptor_Pool;
struct Swapchain;

String_View describe(VkResult result);
Expand Down
9 changes: 5 additions & 4 deletions rvk/instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ Arc<Physical_Device, Alloc> Instance::physical_device(VkSurfaceKHR surface, bool
Vec<Arc<Physical_Device, Alloc>, Mregion<R>> compatible_devices;

for(auto& device : physical_devices) {
info("[rvk] Checking device: %", device->name());
info("[rvk] Checking device: %", device->properties().name());
Log_Indent {
auto surface_formats = device->template surface_formats<R>(surface);
if(surface_formats.empty()) {
Expand Down Expand Up @@ -296,7 +296,7 @@ Arc<Physical_Device, Alloc> Instance::physical_device(VkSurfaceKHR surface, bool

Opt<u32> discrete_idx;
for(u32 i = 0; i < compatible_devices.length(); i++) {
if(compatible_devices[i]->is_discrete()) {
if(compatible_devices[i]->properties().is_discrete()) {
discrete_idx = Opt<u32>{i};
break;
}
Expand All @@ -305,11 +305,12 @@ Arc<Physical_Device, Alloc> Instance::physical_device(VkSurfaceKHR surface, bool
if(!discrete_idx) {
info("[rvk] No discrete GPU found, selecting first compatible device.");
} else {
info("[rvk] Found discrete GPU: %.", compatible_devices[*discrete_idx]->name());
info("[rvk] Found discrete GPU: %.",
compatible_devices[*discrete_idx]->properties().name());
}

u32 idx = discrete_idx ? *discrete_idx : 0;
info("[rvk] Selected device: %.", compatible_devices[idx]->name());
info("[rvk] Selected device: %.", compatible_devices[idx]->properties().name());

return move(compatible_devices.front());
}
Expand Down
Loading

0 comments on commit 4d2e625

Please sign in to comment.