aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2022-09-08 00:35:41 +0200
committerladevieq <ladevie.quentin@gmail.com>2022-09-08 00:36:24 +0200
commitb7c2511e588f1da63413a38a624fd3e6bb8cf54d (patch)
tree582a7090036d2bf6da1673b2675f93211172af79
parent3ab5ce3d2eb2420db08a4f8fa2f0de1c0cc5a803 (diff)
First attempt at uploading textures
-rw-r--r--include/vk-api.hpp2
-rw-r--r--include/vk-renderer.hpp131
-rw-r--r--src/gltf.cpp2
-rw-r--r--src/vk-api.cpp5
-rw-r--r--src/vk-renderer.cpp113
5 files changed, 151 insertions, 102 deletions
diff --git a/include/vk-api.hpp b/include/vk-api.hpp
index 6baaa73..40ccb50 100644
--- a/include/vk-api.hpp
+++ b/include/vk-api.hpp
@@ -115,7 +115,7 @@ class vkapi {
handle create_buffer(size_t data_size, VkBufferUsageFlags buffer_usage, uint32_t mem_usage);
void copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst, size_t size);
- void copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst);
+ void copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst, off_t buffer_offset = 0);
void destroy_buffer(handle buffer);
diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp
index ca4c261..63dcbf7 100644
--- a/include/vk-renderer.hpp
+++ b/include/vk-renderer.hpp
@@ -2,6 +2,7 @@
#define __VK_RENDERER_HPP_
#include <cstdint>
+#include <format>
#include <vector>
#include "vk-context.hpp"
@@ -15,10 +16,28 @@ class Primitive;
class window;
class Texture;
-class Buffer;
class Sampler;
class RingBuffer;
+
+class Buffer {
+ public:
+
+ Buffer(size_t size, VkBufferUsageFlagBits usage);
+ ~Buffer();
+
+ void write(void* data, off_t alloc_offset, size_t data_size) const;
+
+ void resize(size_t new_size);
+
+ handle device_buffer;
+
+ size_t buffer_size;
+
+ VkBufferUsageFlagBits usage;
+};
+
+
class vkrenderer {
public:
vkrenderer(window& wnd);
@@ -28,10 +47,16 @@ class vkrenderer {
void recreate_swapchain();
+ void update_images();
+
+ static void queue_image_update(Texture* texture);
+
static Buffer* create_buffer(size_t size);
static Buffer* create_index_buffer(size_t size);
+ static Buffer* create_staging_buffer(size_t size);
+
static Texture* create_2d_texture(size_t width, size_t height, VkFormat format, Sampler *sampler = nullptr);
static void destroy_2d_texture(Texture* texture);
@@ -47,8 +72,6 @@ class vkrenderer {
void render();
- RingBuffer* get_staging_buffer() { return staging_buffer; }
-
[[nodiscard]]uint32_t frame_index() const { return this->virtual_frame_index; }
[[nodiscard]]Texture* back_buffer() const { return swapchain_textures[swapchain_image_index]; }
@@ -72,14 +95,13 @@ class vkrenderer {
std::vector<Renderpass*> renderpasses;
- static constexpr uint32_t initial_copy_command_buffers = 10U;
uint32_t virtual_frame_index = 0;
uint32_t swapchain_image_index = 0;
VkCommandBuffer graphics_command_buffers[virtual_frames_count];
- std::vector<VkCommandBuffer> copy_command_buffers[virtual_frames_count];
+ VkCommandBuffer copy_command_buffers[virtual_frames_count];
- RingBuffer* staging_buffer;
+ RingBuffer* staging_buffers[virtual_frames_count];
pipeline tonemapping_pipeline;
@@ -96,20 +118,24 @@ class vkrenderer {
std::vector<Texture*> swapchain_textures;
const uint32_t min_swapchain_image_count = 3;
+
+ static std::vector<Texture*> upload_queue;
};
class RingBuffer {
public:
- RingBuffer(size_t size)
- : buffer_size(size) {}
- [[nodiscard]]size_t alloc(size_t alloc_size) const {
+ static const off_t invalid_alloc = -1;
+
+ RingBuffer(size_t size);
+
+ [[nodiscard]]off_t alloc(size_t alloc_size) const {
assert(alloc_size > 0);
if (ptr + alloc_size < buffer_size) {
return ptr;
}
- return 0;
+ return invalid_alloc;
}
void write(void* data, off_t alloc_offset, size_t data_size) const {
@@ -134,66 +160,59 @@ class Sampler {
handle device_sampler;
};
-// TODO: Move those to there own files
class Texture {
public:
- void write(void* data) const {
- auto image = vkrenderer::api.get_image(device_image);
- auto texture_size = image.size.width * image.size.height * 4;
-
- // TODO: Do all this inside vkrenderer
- // auto* buffer = vkrenderer::get_staging_buffer();
- // auto alloc_offset = buffer->alloc(texture_size);
- // assert(alloc_offset > 0);
-
- // // std::memcpy(buffer.device_ptr, data, texture_size);
- // buffer->write(data, alloc_offset, texture_size);
-
- // vkrenderer::api.create_command_buffers
- // submit upload work
- // VKRESULT(vkWaitForFences(vkrenderer::context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
- // VKRESULT(vkResetFences(vkrenderer::context.device, 1, &submission_fences[virtual_frame_index]))
+ Texture(handle image_handle) {
+ auto image = vkrenderer::api.get_image(image_handle);
+ width = image.size.width;
+ height = image.size.height;
+ depth = image.size.depth;
- // auto* cmd_buf = command_buffers[virtual_frame_index];
- // api.start_record(cmd_buf);
-
- // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, device_image);
-
- // api.copy_buffer(cmd_buf, buffer, device_image);
-
- // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, device_image);
-
- // api.end_record(cmd_buf);
-
-
-
- // VKRESULT(vkWaitForFences(vkrenderer::context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
+ device_image = image_handle;
}
- Sampler* sampler = nullptr;
+ Texture(size_t width, size_t height, size_t depth, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM, Sampler* texture_sampler = nullptr)
+ : width(width), height(height), depth(depth) {
+ sampler = texture_sampler;
+ device_image = vkrenderer::api.create_image(
+ { .width = (uint32_t)width, .height = (uint32_t)height, .depth = 1 },
+ format,
+ VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT
+ );
+ }
- handle device_image;
-};
+ void update(void* new_data) {
+ if (data == nullptr) {
+ free(data);
+ }
+ data = new_data;
-class Buffer {
- public:
+ // vkrenderer::update_image(this);
+ }
- Buffer(size_t size);
+ size_t size() const {
+ auto image = vkrenderer::api.get_image(device_image);
+ return width * height * depth * pixel_size(image.format);
+ }
- ~Buffer() {
- vkrenderer::api.destroy_buffer(device_buffer);
+ static size_t pixel_size(VkFormat format) {
+ switch (format) {
+ case VK_FORMAT_R8G8B8A8_UNORM:
+ return 4;
+ default:
+ return 0;
+ }
}
- void write(void* data, off_t alloc_offset, size_t data_size) const {
- auto api_buffer = vkrenderer::api.get_buffer(device_buffer);
+ Sampler* sampler = nullptr;
- std::memcpy((uint8_t*)api_buffer.device_ptr + alloc_offset, data, data_size);
- }
+ void* data = nullptr;
- handle device_buffer;
+ size_t width = 0;
+ size_t height = 0;
+ size_t depth = 0;
- size_t buffer_size;
+ handle device_image;
};
-
#endif // !__VK_RENDERER_HPP_
diff --git a/src/gltf.cpp b/src/gltf.cpp
index 59094d9..882a64b 100644
--- a/src/gltf.cpp
+++ b/src/gltf.cpp
@@ -145,7 +145,7 @@ void gltf::load_textures(const std::filesystem::path &path) {
auto *texture = vkrenderer::create_2d_texture(static_cast<uint32_t>(image.x), static_cast<uint32_t>(image.y), VK_FORMAT_R8G8B8A8_UNORM, sampler);
- texture->write(image.data);
+ texture->update(image.data);
stbi_image_free(image.data);
diff --git a/src/vk-api.cpp b/src/vk-api.cpp
index 81242a5..04e5cc0 100644
--- a/src/vk-api.cpp
+++ b/src/vk-api.cpp
@@ -200,7 +200,8 @@ void vkapi::copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst, size_t
vkCmdCopyBuffer(cmd_buf, buffers[src]->handle, buffers[dst]->handle, 1, &buffer_copy);
}
-void vkapi::copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst) {
+// TODO: Change handle type, here we don't know what type of ressources we are working with
+void vkapi::copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst, off_t buffer_offset) {
auto& dst_image = images[dst];
VkImageSubresourceLayers image_subresource_layers = {};
@@ -210,7 +211,7 @@ void vkapi::copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst) {
image_subresource_layers.layerCount = 1;
VkBufferImageCopy buffer_to_image_copy = {};
- buffer_to_image_copy.bufferOffset = 0;
+ buffer_to_image_copy.bufferOffset = buffer_offset;
buffer_to_image_copy.bufferRowLength = 0;
buffer_to_image_copy.bufferImageHeight = 0;
buffer_to_image_copy.imageSubresource = image_subresource_layers;
diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp
index 91115ba..bfe8e5d 100644
--- a/src/vk-renderer.cpp
+++ b/src/vk-renderer.cpp
@@ -20,6 +20,7 @@
auto vkrenderer::context = vkcontext();
auto vkrenderer::api = vkapi(vkrenderer::context);
+auto vkrenderer::upload_queue = std::vector<Texture*>();
vkrenderer::vkrenderer(window& wnd) {
platform_surface = api.create_surface(wnd);
@@ -34,8 +35,7 @@ vkrenderer::vkrenderer(window& wnd) {
swapchain_textures.resize(swapchain.image_count);
for (size_t index = 0; index < swapchain.image_count; index++) {
- swapchain_textures[index] = new Texture();
- swapchain_textures[index]->device_image = swapchain.images[index];
+ swapchain_textures[index] = new Texture(swapchain.images[index]);
}
tonemapping_pipeline = api.create_compute_pipeline("tonemapping");
@@ -49,12 +49,10 @@ vkrenderer::vkrenderer(window& wnd) {
acquire_semaphores[index] = api.create_semaphore();
copy_command_pools[index] = api.create_command_pool();
- copy_command_buffers[index].resize(initial_copy_command_buffers);
- api.allocate_command_buffers(copy_command_pools[index], copy_command_buffers[index].data(), copy_command_buffers[index].size());
- }
-
+ api.allocate_command_buffers(copy_command_pools[index], &copy_command_buffers[index], 1);
- // staging_buffer = api.create_buffer(4096 * 4096 * 4 * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
+ // staging_buffers[index] = create_staging_buffer(4096 * 4096 * sizeof(uint32_t));
+ }
}
vkrenderer::~vkrenderer() {
@@ -65,12 +63,7 @@ vkrenderer::~vkrenderer() {
}
for(size_t index { 0 }; index < virtual_frames_count; index++) {
- vkFreeCommandBuffers(
- context.device,
- copy_command_pools[index],
- copy_command_buffers[index].size(),
- copy_command_buffers[index].data()
- );
+ vkFreeCommandBuffers(context.device, copy_command_pools[index], 1, &copy_command_buffers[index]);
}
api.destroy_fences(submission_fences, virtual_frames_count);
@@ -102,45 +95,50 @@ void vkrenderer::recreate_swapchain() {
swapchain_textures.resize(swapchain.image_count);
for (size_t index = 0; index < swapchain.image_count; index++) {
- swapchain_textures[index] = new Texture();
- swapchain_textures[index]->device_image = swapchain.images[index];
+ swapchain_textures[index] = new Texture(swapchain.images[index]);
}
}
-void upload_image(void* data, size_t size) {
- // copy to staging buffer
-
- // allocate command buffers
- // get command buffer
- // copy to gpu resident texture
+void vkrenderer::queue_image_update(Texture* texture) {
+ upload_queue.push_back(texture);
}
-Buffer* vkrenderer::create_buffer(size_t size) {
- auto* buffer = new Buffer(size);
+void vkrenderer::update_images() {
+ auto* staging_buffer = staging_buffers[virtual_frame_index];
- buffer->device_buffer = api.create_buffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU);
+ VkCommandBuffer command_buffer = copy_command_buffers[virtual_frame_index];
+ vkrenderer::api.start_record(command_buffer);
- return buffer;
+ for (auto* texture : upload_queue) {
+ auto texture_size = texture->size();
+ auto offset = staging_buffer->alloc(texture_size);
+
+ if (offset == RingBuffer::invalid_alloc) {
+ break;
+ }
+
+ staging_buffer->write(texture->data, offset, texture_size);
+
+ vkrenderer::api.copy_buffer(command_buffer, staging_buffer->device_buffer, texture->device_image, offset);
+ }
+
+ vkrenderer::api.end_record(command_buffer);
}
-Buffer* vkrenderer::create_index_buffer(size_t size) {
- auto* buffer = new Buffer(size);
+Buffer* vkrenderer::create_buffer(size_t size) {
+ return new Buffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
+}
- buffer->device_buffer = api.create_buffer(size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU);
+Buffer* vkrenderer::create_index_buffer(size_t size) {
+ return new Buffer(size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
+}
- return buffer;
+Buffer* vkrenderer::create_staging_buffer(size_t size) {
+ return new Buffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
}
Texture* vkrenderer::create_2d_texture(size_t width, size_t height, VkFormat format, Sampler *sampler) {
- auto* texture = new Texture();
- texture->sampler = sampler;
- texture->device_image = api.create_image(
- { .width = (uint32_t)width, .height = (uint32_t)height, .depth = 1 },
- format,
- VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT
- );
-
- return texture;
+ return new Texture(width, height, 1, format, sampler);
}
void vkrenderer::destroy_2d_texture(Texture* texture) {
@@ -218,8 +216,8 @@ void vkrenderer::finish_frame() {
api.end_record(cmd_buf);
- // wait for acquire + copy semaphores
+ // TODO: Submit copy command buffer
api.submit_graphics(cmd_buf, acquire_semaphores[virtual_frame_index], execution_semaphores[virtual_frame_index], submission_fences[virtual_frame_index]);
auto present_result = api.present(swapchain, swapchain_image_index, execution_semaphores[virtual_frame_index]);
@@ -241,8 +239,39 @@ void vkrenderer::handle_swapchain_result(VkResult function_result) {
}
-Buffer::Buffer(size_t size)
+
+Buffer::Buffer(size_t size, VkBufferUsageFlagBits usage)
+ : buffer_size(size), usage(usage) {
+ device_buffer = vkrenderer::api.create_buffer(size, usage, VMA_MEMORY_USAGE_CPU_TO_GPU);
+}
+
+Buffer::~Buffer() {
+ vkrenderer::api.destroy_buffer(device_buffer);
+}
+
+void Buffer::write(void* data, off_t alloc_offset, size_t data_size) const {
+ auto api_buffer = vkrenderer::api.get_buffer(device_buffer);
+
+ std::memcpy((uint8_t*)api_buffer.device_ptr + alloc_offset, data, data_size);
+}
+
+void Buffer::resize(size_t new_size) {
+ auto old_device_buffer = device_buffer;
+ new_size = static_cast<uint32_t>(exp2(ceil(log2((double)new_size))));
+
+ device_buffer = vkrenderer::api.create_buffer(new_size, usage, VMA_MEMORY_USAGE_CPU_TO_GPU);
+
+ auto old_buffer = vkrenderer::api.get_buffer(device_buffer);
+ auto new_buffer = vkrenderer::api.get_buffer(device_buffer);
+ std::memcpy(new_buffer.device_ptr, old_buffer.device_ptr, buffer_size);
+
+ buffer_size = new_size;
+
+ vkrenderer::api.destroy_buffer(old_device_buffer);
+}
+
+
+RingBuffer::RingBuffer(size_t size)
: buffer_size(size) {
- device_buffer = vkrenderer::api.create_buffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU);
+ device_buffer = vkrenderer::api.create_buffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
}
-