diff --git a/config/visual-studio/renderer.vcxproj b/config/visual-studio/renderer.vcxproj
index 0d592d3..c071283 100644
--- a/config/visual-studio/renderer.vcxproj
+++ b/config/visual-studio/renderer.vcxproj
@@ -104,7 +104,6 @@
-
@@ -136,7 +135,6 @@
-
diff --git a/config/visual-studio/renderer.vcxproj.filters b/config/visual-studio/renderer.vcxproj.filters
index 573c97b..17ad847 100644
--- a/config/visual-studio/renderer.vcxproj.filters
+++ b/config/visual-studio/renderer.vcxproj.filters
@@ -92,9 +92,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -148,9 +145,6 @@
Header Files
-
- Source Files
-
Source Files
diff --git a/src/engine/renderer/tr_backend.c b/src/engine/renderer/tr_backend.c
index ce26b84..6666f7a 100644
--- a/src/engine/renderer/tr_backend.c
+++ b/src/engine/renderer/tr_backend.c
@@ -736,8 +736,8 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
Vk_Image& vk_image = tr.vk_resources.images[tr.scratchImage[client]->index];
vkDestroyImage(vk.device, vk_image.image, nullptr);
vkDestroyImageView(vk.device, vk_image.image_view, nullptr);
- vk_image.image = vk_create_cinematic_image(cols, rows, vk_image.staging_buffer, vk_image.image_view);
- vk_update_cinematic_image(vk_image.image, vk_image.staging_buffer, cols, rows, data);
+ vk_image.image = vk_create_cinematic_image(cols, rows, vk_image.image_view);
+ vk_update_cinematic_image(vk_image.image, cols, rows, data);
VkDescriptorImageInfo image_info;
image_info.sampler = vk.sampler;
@@ -765,7 +765,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
// VULKAN
const Vk_Image& vk_image = tr.vk_resources.images[tr.scratchImage[client]->index];
- vk_update_cinematic_image(vk_image.image, vk_image.staging_buffer, cols, rows, data);
+ vk_update_cinematic_image(vk_image.image, cols, rows, data);
}
}
diff --git a/src/engine/renderer/vk.cpp b/src/engine/renderer/vk.cpp
index cf3d653..e72274d 100644
--- a/src/engine/renderer/vk.cpp
+++ b/src/engine/renderer/vk.cpp
@@ -1,10 +1,9 @@
#include "tr_local.h"
-#include "vk_allocator.h"
-
#include
#include
#include
+#include
FILE* vk_log_file;
@@ -492,25 +491,46 @@ static void allocate_and_bind_image_memory(VkImage image) {
VK_CHECK(vkBindImageMemory(vk.device, image, chunk->memory, chunk->used - memory_requirements.size));
}
-static void ensure_allocation_for_staging_buffer(VkBuffer buffer) {
+static void ensure_staging_buffer_allocation(VkDeviceSize size) {
+ if (tr.vk_resources.staging_buffer_size >= size)
+ return;
+
+ if (tr.vk_resources.staging_buffer != VK_NULL_HANDLE)
+ vkDestroyBuffer(vk.device, tr.vk_resources.staging_buffer, nullptr);
+
+ if (tr.vk_resources.staging_buffer_memory != VK_NULL_HANDLE)
+ vkFreeMemory(vk.device, tr.vk_resources.staging_buffer_memory, nullptr);
+
+ tr.vk_resources.staging_buffer_size = size;
+
+ VkBufferCreateInfo buffer_desc;
+ buffer_desc.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ buffer_desc.pNext = nullptr;
+ buffer_desc.flags = 0;
+ buffer_desc.size = size;
+ buffer_desc.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+ buffer_desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ buffer_desc.queueFamilyIndexCount = 0;
+ buffer_desc.pQueueFamilyIndices = nullptr;
+ VK_CHECK(vkCreateBuffer(vk.device, &buffer_desc, nullptr, &tr.vk_resources.staging_buffer));
+
VkMemoryRequirements memory_requirements;
- vkGetBufferMemoryRequirements(vk.device, buffer, &memory_requirements);
+ vkGetBufferMemoryRequirements(vk.device, tr.vk_resources.staging_buffer, &memory_requirements);
- if (tr.vk_resources.texture_staging_memory_size < memory_requirements.size) {
- if (tr.vk_resources.texture_staging_memory != VK_NULL_HANDLE) {
- vkFreeMemory(vk.device, tr.vk_resources.texture_staging_memory, nullptr);
- }
+ uint32_t memory_type = find_memory_type(vk.physical_device, memory_requirements.memoryTypeBits,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
- VkMemoryAllocateInfo alloc_info;
- alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- alloc_info.pNext = nullptr;
- alloc_info.allocationSize = memory_requirements.size;
- alloc_info.memoryTypeIndex = find_memory_type(vk.physical_device, memory_requirements.memoryTypeBits,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+ VkMemoryAllocateInfo alloc_info;
+ alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ alloc_info.pNext = nullptr;
+ alloc_info.allocationSize = memory_requirements.size;
+ alloc_info.memoryTypeIndex = memory_type;
+ VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &tr.vk_resources.staging_buffer_memory));
+ VK_CHECK(vkBindBufferMemory(vk.device, tr.vk_resources.staging_buffer, tr.vk_resources.staging_buffer_memory, 0));
- VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &tr.vk_resources.texture_staging_memory));
- tr.vk_resources.texture_staging_memory_size = memory_requirements.size;
- }
+ void* data;
+ VK_CHECK(vkMapMemory(vk.device, tr.vk_resources.staging_buffer_memory, 0, VK_WHOLE_SIZE, 0, &data));
+ tr.vk_resources.staging_buffer_ptr = (byte*)data;
}
static void deallocate_image_chunks() {
@@ -864,7 +884,6 @@ void vk_deinitialize() {
fclose(vk_log_file);
vk_log_file = nullptr;
- get_allocator()->deallocate_all();
deallocate_image_chunks();
vkDestroyImage(vk.device, vk.depth_image, nullptr);
@@ -931,27 +950,8 @@ static void record_buffer_memory_barrier(VkCommandBuffer cb, VkBuffer buffer,
VkImage vk_create_texture(const uint8_t* rgba_pixels, int image_width, int image_height, VkImageView& image_view) {
int image_size = image_width * image_height * 4;
- // create staging buffer
- VkBufferCreateInfo buffer_desc;
- buffer_desc.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- buffer_desc.pNext = nullptr;
- buffer_desc.flags = 0;
- buffer_desc.size = image_size;
- buffer_desc.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- buffer_desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- buffer_desc.queueFamilyIndexCount = 0;
- buffer_desc.pQueueFamilyIndices = nullptr;
-
- VkBuffer staging_buffer;
- VK_CHECK(vkCreateBuffer(vk.device, &buffer_desc, nullptr, &staging_buffer));
-
- ensure_allocation_for_staging_buffer(staging_buffer);
- VK_CHECK(vkBindBufferMemory(vk.device, staging_buffer, tr.vk_resources.texture_staging_memory, 0));
-
- void* buffer_data;
- VK_CHECK(vkMapMemory(vk.device, tr.vk_resources.texture_staging_memory, 0, image_size, 0, &buffer_data));
- Com_Memcpy(buffer_data, rgba_pixels, image_size);
- vkUnmapMemory(vk.device, tr.vk_resources.texture_staging_memory);
+ ensure_staging_buffer_allocation(image_size);
+ Com_Memcpy(tr.vk_resources.staging_buffer_ptr, rgba_pixels, image_size);
// create texture image
VkImageCreateInfo desc;
@@ -979,9 +979,9 @@ VkImage vk_create_texture(const uint8_t* rgba_pixels, int image_width, int image
// copy buffer's content to texture
record_and_run_commands(vk.command_pool, vk.queue,
- [&texture_image, &staging_buffer, &image_width, &image_height](VkCommandBuffer command_buffer) {
+ [&texture_image, &image_width, &image_height](VkCommandBuffer command_buffer) {
- record_buffer_memory_barrier(command_buffer, staging_buffer,
+ record_buffer_memory_barrier(command_buffer, tr.vk_resources.staging_buffer,
VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
@@ -999,35 +999,17 @@ VkImage vk_create_texture(const uint8_t* rgba_pixels, int image_width, int image
region.imageOffset = VkOffset3D{ 0, 0, 0 };
region.imageExtent = VkExtent3D{ (uint32_t)image_width, (uint32_t)image_height, 1 };
- vkCmdCopyBufferToImage(command_buffer, staging_buffer, texture_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
+ vkCmdCopyBufferToImage(command_buffer, tr.vk_resources.staging_buffer, texture_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
record_image_layout_transition(command_buffer, texture_image, VK_FORMAT_R8G8B8A8_UNORM,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
});
- vkDestroyBuffer(vk.device, staging_buffer, nullptr);
-
image_view = create_image_view(texture_image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
return texture_image;
}
-VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& staging_buffer, VkImageView& image_view) {
- VkBufferCreateInfo buffer_desc;
- buffer_desc.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- buffer_desc.pNext = nullptr;
- buffer_desc.flags = 0;
- buffer_desc.size = width * height * 4;
- buffer_desc.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- buffer_desc.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- buffer_desc.queueFamilyIndexCount = 0;
- buffer_desc.pQueueFamilyIndices = nullptr;
-
- VkBuffer buffer;
- VK_CHECK(vkCreateBuffer(vk.device, &buffer_desc, nullptr, &buffer));
-
- VkDeviceMemory buffer_memory = get_allocator()->allocate_staging_memory(buffer);
- VK_CHECK(vkBindBufferMemory(vk.device, buffer, buffer_memory, 0));
-
+VkImage vk_create_cinematic_image(int width, int height, VkImageView& image_view) {
VkImageCreateInfo image_desc;
image_desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
image_desc.pNext = nullptr;
@@ -1049,27 +1031,23 @@ VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& stag
VkImage image;
VK_CHECK(vkCreateImage(vk.device, &image_desc, nullptr, &image));
-
allocate_and_bind_image_memory(image);
-
- staging_buffer.handle = buffer;
- staging_buffer.memory = buffer_memory;
- staging_buffer.offset = 0;
- staging_buffer.size = width * height * 4;
-
image_view = create_image_view(image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
-
return image;
}
-void vk_update_cinematic_image(VkImage image, const Vk_Staging_Buffer& staging_buffer, int width, int height, const uint8_t* rgba_pixels) {
- void* buffer_data;
- VK_CHECK(vkMapMemory(vk.device, staging_buffer.memory, staging_buffer.offset, staging_buffer.size, 0, &buffer_data));
- memcpy(buffer_data, rgba_pixels, staging_buffer.size);
- vkUnmapMemory(vk.device, staging_buffer.memory);
+void vk_update_cinematic_image(VkImage image, int width, int height, const uint8_t* rgba_pixels) {
+ VkDeviceSize size = width * height * 4;
+
+ ensure_staging_buffer_allocation(size);
+ Com_Memcpy(tr.vk_resources.staging_buffer_ptr, rgba_pixels, size);
record_and_run_commands(vk.command_pool, vk.queue,
- [&image, &staging_buffer, &width, &height](VkCommandBuffer command_buffer) {
+ [&image, &width, &height](VkCommandBuffer command_buffer) {
+
+ record_buffer_memory_barrier(command_buffer, tr.vk_resources.staging_buffer,
+ VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
record_image_layout_transition(command_buffer, image, VK_FORMAT_R8G8B8A8_UNORM,
0, VK_IMAGE_LAYOUT_UNDEFINED, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
@@ -1085,7 +1063,7 @@ void vk_update_cinematic_image(VkImage image, const Vk_Staging_Buffer& staging_b
region.imageOffset = VkOffset3D{ 0, 0, 0 };
region.imageExtent = VkExtent3D{ (uint32_t)width, (uint32_t)height, 1 };
- vkCmdCopyBufferToImage(command_buffer, staging_buffer.handle, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
+ vkCmdCopyBufferToImage(command_buffer, tr.vk_resources.staging_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
record_image_layout_transition(command_buffer, image, VK_FORMAT_R8G8B8A8_UNORM,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
@@ -1477,8 +1455,11 @@ void vk_destroy_resources() {
auto& res = tr.vk_resources;
- if (res.texture_staging_memory != VK_NULL_HANDLE)
- vkFreeMemory(vk.device, res.texture_staging_memory, nullptr);
+ if (res.staging_buffer != VK_NULL_HANDLE)
+ vkDestroyBuffer(vk.device, res.staging_buffer, nullptr);
+
+ if (res.staging_buffer_memory != VK_NULL_HANDLE)
+ vkFreeMemory(vk.device, res.staging_buffer_memory, nullptr);
// Destroy pipelines
for (int i = 0; i < tr.vk_resources.num_pipelines; i++) {
@@ -1495,9 +1476,6 @@ void vk_destroy_resources() {
vkDestroyImage(vk.device, vk_image.image, nullptr);
vkDestroyImageView(vk.device, vk_image.image_view, nullptr);
-
- if (vk_image.staging_buffer.handle != VK_NULL_HANDLE)
- vkDestroyBuffer(vk.device, vk_image.staging_buffer.handle, nullptr);
}
Com_Memset(&res, 0, sizeof(res));
diff --git a/src/engine/renderer/vk.h b/src/engine/renderer/vk.h
index aab991b..46089a6 100644
--- a/src/engine/renderer/vk.h
+++ b/src/engine/renderer/vk.h
@@ -41,13 +41,6 @@ struct Vk_Pipeline_Desc {
}
};
-struct Vk_Staging_Buffer {
- VkBuffer handle = VK_NULL_HANDLE;
- VkDeviceMemory memory = VK_NULL_HANDLE; // memory associated with a buffer
- VkDeviceSize offset = -1;
- VkDeviceSize size = 0;
-};
-
struct Vk_Image {
VkImage image = VK_NULL_HANDLE;
VkImageView image_view = VK_NULL_HANDLE;
@@ -55,9 +48,6 @@ struct Vk_Image {
// One to one correspondence between images and descriptor sets.
// We update descriptor set during image initialization and then never touch it again (except for cinematic images).
VkDescriptorSet descriptor_set;
-
- // Staging buffer for cinematic images.
- Vk_Staging_Buffer staging_buffer;
};
bool vk_initialize(HWND hwnd);
@@ -65,8 +55,8 @@ void vk_deinitialize();
void vk_destroy_resources();
VkImage vk_create_texture(const uint8_t* rgba_pixels, int width, int height, VkImageView& image_view);
-VkImage vk_create_cinematic_image(int width, int height, Vk_Staging_Buffer& staging_buffer, VkImageView& image_view);
-void vk_update_cinematic_image(VkImage image, const Vk_Staging_Buffer& staging_buffer, int width, int height, const uint8_t* rgba_pixels);
+VkImage vk_create_cinematic_image(int width, int height, VkImageView& image_view);
+void vk_update_cinematic_image(VkImage image, int width, int height, const uint8_t* rgba_pixels);
VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc);
VkDescriptorSet vk_create_descriptor_set(VkImageView image_view);
@@ -135,7 +125,7 @@ struct Vulkan_Instance {
byte* index_buffer_ptr = nullptr; // pointer to mapped index buffer
VkDeviceSize index_buffer_offset = 0;
- // host visible memory that holds vertex/index data
+ // host visible memory that holds both vertex and index data
VkDeviceMemory geometry_buffer_memory = VK_NULL_HANDLE;
VkSemaphore image_acquired = VK_NULL_HANDLE;
@@ -169,6 +159,9 @@ struct Vulkan_Resources {
int num_image_chunks = 0;
Chunk image_chunks[MAX_IMAGE_CHUNKS];
- VkDeviceMemory texture_staging_memory = VK_NULL_HANDLE;
- VkDeviceSize texture_staging_memory_size = 0;
+ // Host visible memory used to copy image data to device local memory.
+ VkBuffer staging_buffer = VK_NULL_HANDLE;
+ VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE;
+ VkDeviceSize staging_buffer_size = 0;
+ byte* staging_buffer_ptr = nullptr; // pointer to mapped staging buffer
};
diff --git a/src/engine/renderer/vk_allocator.cpp b/src/engine/renderer/vk_allocator.cpp
deleted file mode 100644
index 0595e33..0000000
--- a/src/engine/renderer/vk_allocator.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include "vk_allocator.h"
-#include "tr_local.h"
-
-static Device_Memory_Allocator allocator;
-
-Device_Memory_Allocator* get_allocator() {
- return &allocator;
-}
-
-void Device_Memory_Allocator::deallocate_all() {
- for (auto chunk : chunks) {
- vkFreeMemory(vk.device, chunk, nullptr);
- }
- chunks.clear();
-}
-
-static uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t memory_type_bits, VkMemoryPropertyFlags properties) {
- VkPhysicalDeviceMemoryProperties memory_properties;
- vkGetPhysicalDeviceMemoryProperties(physical_device, &memory_properties);
-
- for (uint32_t i = 0; i < memory_properties.memoryTypeCount; i++) {
- if ((memory_type_bits & (1 << i)) != 0 &&
- (memory_properties.memoryTypes[i].propertyFlags & properties) == properties) {
- return i;
- }
- }
- ri.Error(ERR_FATAL, "Vulkan error: failed to find matching memory type with requested properties");
- return -1;
-}
-
-VkDeviceMemory Device_Memory_Allocator::allocate_staging_memory(VkBuffer buffer) {
- VkMemoryRequirements memory_requirements;
- vkGetBufferMemoryRequirements(vk.device, buffer, &memory_requirements);
-
- VkMemoryAllocateInfo alloc_info;
- alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- alloc_info.pNext = nullptr;
- alloc_info.allocationSize = memory_requirements.size;
- alloc_info.memoryTypeIndex = find_memory_type(vk.physical_device, memory_requirements.memoryTypeBits,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
-
- VkDeviceMemory chunk;
- VK_CHECK(vkAllocateMemory(vk.device, &alloc_info, nullptr, &chunk));
- chunks.push_back(chunk);
- return chunk;
-}
diff --git a/src/engine/renderer/vk_allocator.h b/src/engine/renderer/vk_allocator.h
deleted file mode 100644
index 8118b3f..0000000
--- a/src/engine/renderer/vk_allocator.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include "vk.h"
-#include
-
-// NOTE: in this implementation I do memory allocation for each allocation request.
-// TODO: sub-allocate from larger chunks and return chunk handle plus offset withing corresponding chunk.
-class Device_Memory_Allocator {
-public:
- void deallocate_all();
-
- VkDeviceMemory allocate_staging_memory(VkBuffer buffer);
-
-private:
- std::vector chunks;
-};
-
-Device_Memory_Allocator* get_allocator();