Use dynamic buffer offsets to update ubo per draw.
This commit is contained in:
parent
d0700752eb
commit
103bc0462b
|
|
@ -191,7 +191,7 @@ void Vulkan_Demo::create_command_pool() {
|
||||||
|
|
||||||
void Vulkan_Demo::create_descriptor_pool() {
|
void Vulkan_Demo::create_descriptor_pool() {
|
||||||
std::array<VkDescriptorPoolSize, 2> pool_sizes;
|
std::array<VkDescriptorPoolSize, 2> pool_sizes;
|
||||||
pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
||||||
pool_sizes[0].descriptorCount = 1024;
|
pool_sizes[0].descriptorCount = 1024;
|
||||||
pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
pool_sizes[1].descriptorCount = 1024;
|
pool_sizes[1].descriptorCount = 1024;
|
||||||
|
|
@ -208,9 +208,14 @@ void Vulkan_Demo::create_descriptor_pool() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan_Demo::create_uniform_buffer() {
|
void Vulkan_Demo::create_uniform_buffer() {
|
||||||
auto size = static_cast<VkDeviceSize>(sizeof(Uniform_Buffer_Object));
|
auto size = static_cast<VkDeviceSize>(sizeof(Uniform_Buffer_Object)) * 1024;
|
||||||
uniform_staging_buffer = create_permanent_staging_buffer(size, uniform_staging_buffer_memory);
|
uniform_staging_buffer = create_permanent_staging_buffer(size, uniform_staging_buffer_memory);
|
||||||
uniform_buffer = create_buffer(size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
|
uniform_buffer = create_buffer(size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
|
||||||
|
|
||||||
|
VkPhysicalDeviceProperties props;
|
||||||
|
vkGetPhysicalDeviceProperties(get_physical_device(), &props);
|
||||||
|
VkDeviceSize offset_align = props.limits.minUniformBufferOffsetAlignment;
|
||||||
|
tess_ubo_offset_step = (uint32_t)((sizeof(Uniform_Buffer_Object) + offset_align - 1) / offset_align * offset_align);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImage Vulkan_Demo::create_texture(const uint8_t* pixels, int bytes_per_pixel, int image_width, int image_height, VkImageView& image_view) {
|
VkImage Vulkan_Demo::create_texture(const uint8_t* pixels, int bytes_per_pixel, int image_width, int image_height, VkImageView& image_view) {
|
||||||
|
|
@ -299,7 +304,7 @@ void Vulkan_Demo::create_depth_buffer_resources() {
|
||||||
void Vulkan_Demo::create_descriptor_set_layout() {
|
void Vulkan_Demo::create_descriptor_set_layout() {
|
||||||
std::array<VkDescriptorSetLayoutBinding, 2> descriptor_bindings;
|
std::array<VkDescriptorSetLayoutBinding, 2> descriptor_bindings;
|
||||||
descriptor_bindings[0].binding = 0;
|
descriptor_bindings[0].binding = 0;
|
||||||
descriptor_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
descriptor_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
||||||
descriptor_bindings[0].descriptorCount = 1;
|
descriptor_bindings[0].descriptorCount = 1;
|
||||||
descriptor_bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
descriptor_bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
descriptor_bindings[0].pImmutableSamplers = nullptr;
|
descriptor_bindings[0].pImmutableSamplers = nullptr;
|
||||||
|
|
@ -692,7 +697,7 @@ void Vulkan_Demo::update_ubo_descriptor(VkDescriptorSet set) {
|
||||||
descriptor_writes[0].dstBinding = 0;
|
descriptor_writes[0].dstBinding = 0;
|
||||||
descriptor_writes[0].dstArrayElement = 0;
|
descriptor_writes[0].dstArrayElement = 0;
|
||||||
descriptor_writes[0].descriptorCount = 1;
|
descriptor_writes[0].descriptorCount = 1;
|
||||||
descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
||||||
descriptor_writes[0].pImageInfo = nullptr;
|
descriptor_writes[0].pImageInfo = nullptr;
|
||||||
descriptor_writes[0].pBufferInfo = &buffer_info;
|
descriptor_writes[0].pBufferInfo = &buffer_info;
|
||||||
descriptor_writes[0].pTexelBufferView = nullptr;
|
descriptor_writes[0].pTexelBufferView = nullptr;
|
||||||
|
|
@ -700,77 +705,22 @@ void Vulkan_Demo::update_ubo_descriptor(VkDescriptorSet set) {
|
||||||
vkUpdateDescriptorSets(get_device(), (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
|
vkUpdateDescriptorSets(get_device(), (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan_Demo::update_image_descriptor(bool cinematic) {
|
void Vulkan_Demo::update_uniform_buffer() {
|
||||||
VkImageView image_view;
|
|
||||||
|
|
||||||
if (cinematic) {
|
|
||||||
image_view = cinematic_image_view;
|
|
||||||
} else {
|
|
||||||
static auto start_time = std::chrono::high_resolution_clock::now();
|
|
||||||
auto current_time = std::chrono::high_resolution_clock::now();
|
|
||||||
int time = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();
|
|
||||||
static int image_index = 0;
|
|
||||||
|
|
||||||
if (time > 200) {
|
|
||||||
start_time = current_time;
|
|
||||||
image_index = (image_index + 1) % tr.numImages;
|
|
||||||
}
|
|
||||||
image_view = tr.images[image_index]->vk_image_view;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkDescriptorImageInfo image_info;
|
|
||||||
image_info.sampler = texture_image_sampler;
|
|
||||||
image_info.imageView = image_view;
|
|
||||||
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
||||||
|
|
||||||
std::array<VkWriteDescriptorSet, 1> descriptor_writes;
|
|
||||||
descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
||||||
descriptor_writes[0].dstSet = descriptor_set;
|
|
||||||
descriptor_writes[0].dstBinding = 1;
|
|
||||||
descriptor_writes[0].dstArrayElement = 0;
|
|
||||||
descriptor_writes[0].descriptorCount = 1;
|
|
||||||
descriptor_writes[0].pNext = nullptr;
|
|
||||||
descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
||||||
descriptor_writes[0].pImageInfo = &image_info;
|
|
||||||
descriptor_writes[0].pBufferInfo = nullptr;
|
|
||||||
descriptor_writes[0].pTexelBufferView = nullptr;
|
|
||||||
|
|
||||||
vkUpdateDescriptorSets(get_device(), (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vulkan_Demo::update_uniform_buffer(bool cinematic) {
|
|
||||||
static auto start_time = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
auto current_time = std::chrono::high_resolution_clock::now();
|
|
||||||
float time = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count() / 1000.f;
|
|
||||||
if (cinematic) time = 0.0;
|
|
||||||
|
|
||||||
Uniform_Buffer_Object ubo;
|
Uniform_Buffer_Object ubo;
|
||||||
//ubo.model = glm::rotate(glm::mat4(), time * glm::radians(30.0f), glm::vec3(0, 1, 0));
|
|
||||||
//ubo.view = glm::lookAt(glm::vec3(0.0, 0.0, 2.8), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
|
|
||||||
|
|
||||||
ubo.model = glm::mat4();
|
ubo.model = glm::mat4();
|
||||||
ubo.view = glm::mat4();
|
ubo.view = glm::mat4();
|
||||||
|
|
||||||
// Vulkan clip space has inverted Y and half Z.
|
|
||||||
/*const glm::mat4 clip(
|
|
||||||
1.0f, 0.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, -1.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, 0.0f, 0.5f, 0.0f,
|
|
||||||
0.0f, 0.0f, 0.5f, 1.0f);*/
|
|
||||||
|
|
||||||
const glm::mat4 ortho_proj(
|
const glm::mat4 ortho_proj(
|
||||||
2.0f / glConfig.vidWidth, 0.0f, 0.f, 0.0f,
|
2.0f / glConfig.vidWidth, 0.0f, 0.f, 0.0f,
|
||||||
0.0, 2.0f / glConfig.vidHeight, 0.0f, 0.0f,
|
0.0, 2.0f / glConfig.vidHeight, 0.0f, 0.0f,
|
||||||
0.0f, 0.0f, 1.0f, 0.0f,
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
-1.0f, -1.0f, 0.0f, 1.0f
|
-1.0f, -1.0f, 0.0f, 1.0f
|
||||||
);
|
);
|
||||||
|
|
||||||
//ubo.proj = clip * glm::perspective(glm::radians(45.0f), window_width / (float)window_height, 0.1f, 50.0f);
|
|
||||||
ubo.proj = ortho_proj;
|
ubo.proj = ortho_proj;
|
||||||
|
|
||||||
void* data;
|
void* data;
|
||||||
VkResult result = vkMapMemory(get_device(), uniform_staging_buffer_memory, 0, sizeof(ubo), 0, &data);
|
VkResult result = vkMapMemory(get_device(), uniform_staging_buffer_memory, tess_ubo_offset, sizeof(ubo), 0, &data);
|
||||||
check_vk_result(result, "vkMapMemory");
|
check_vk_result(result, "vkMapMemory");
|
||||||
memcpy(data, &ubo, sizeof(ubo));
|
memcpy(data, &ubo, sizeof(ubo));
|
||||||
vkUnmapMemory(get_device(), uniform_staging_buffer_memory);
|
vkUnmapMemory(get_device(), uniform_staging_buffer_memory);
|
||||||
|
|
@ -779,12 +729,11 @@ void Vulkan_Demo::update_uniform_buffer(bool cinematic) {
|
||||||
void Vulkan_Demo::begin_frame() {
|
void Vulkan_Demo::begin_frame() {
|
||||||
fprintf(logfile, "begin_frame\n");
|
fprintf(logfile, "begin_frame\n");
|
||||||
fflush(logfile);
|
fflush(logfile);
|
||||||
update_image_descriptor(false);
|
|
||||||
|
|
||||||
VkBufferCopy region;
|
VkBufferCopy region;
|
||||||
region.srcOffset = 0;
|
region.srcOffset = 0;
|
||||||
region.dstOffset = 0;
|
region.dstOffset = 0;
|
||||||
region.size = sizeof(Uniform_Buffer_Object);
|
region.size = sizeof(Uniform_Buffer_Object) * 1024;
|
||||||
vkCmdCopyBuffer(command_buffer, uniform_staging_buffer, uniform_buffer, 1, ®ion);
|
vkCmdCopyBuffer(command_buffer, uniform_staging_buffer, uniform_buffer, 1, ®ion);
|
||||||
|
|
||||||
VkBufferMemoryBarrier barrier;
|
VkBufferMemoryBarrier barrier;
|
||||||
|
|
@ -796,7 +745,7 @@ void Vulkan_Demo::begin_frame() {
|
||||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
barrier.buffer = uniform_buffer;
|
barrier.buffer = uniform_buffer;
|
||||||
barrier.offset = 0;
|
barrier.offset = 0;
|
||||||
barrier.size = sizeof(Uniform_Buffer_Object);
|
barrier.size = sizeof(Uniform_Buffer_Object) * 1024;
|
||||||
|
|
||||||
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0,
|
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0,
|
||||||
0, nullptr, 1, &barrier, 0, nullptr);
|
0, nullptr, 1, &barrier, 0, nullptr);
|
||||||
|
|
@ -819,10 +768,11 @@ void Vulkan_Demo::begin_frame() {
|
||||||
|
|
||||||
tess_vertex_buffer_offset = 0;
|
tess_vertex_buffer_offset = 0;
|
||||||
tess_index_buffer_offset = 0;
|
tess_index_buffer_offset = 0;
|
||||||
|
tess_ubo_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan_Demo::end_frame() {
|
void Vulkan_Demo::end_frame() {
|
||||||
fprintf(logfile, "end_frame (vb_size %d, ib_size %d)\n", (int)tess_vertex_buffer_offset, (int)tess_index_buffer_offset);
|
fprintf(logfile, "end_frame (vb_size %d, ib_size %d, ubo_size %d)\n", (int)tess_vertex_buffer_offset, (int)tess_index_buffer_offset, (int)tess_ubo_offset);
|
||||||
fflush(logfile);
|
fflush(logfile);
|
||||||
vkCmdEndRenderPass(command_buffer);
|
vkCmdEndRenderPass(command_buffer);
|
||||||
}
|
}
|
||||||
|
|
@ -863,27 +813,49 @@ void Vulkan_Demo::render_tess(const image_t* image) {
|
||||||
set = &image_set;
|
set = &image_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, set, 0, nullptr);
|
update_uniform_buffer();
|
||||||
|
|
||||||
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, set, 1, &tess_ubo_offset);
|
||||||
|
tess_ubo_offset += tess_ubo_offset_step;
|
||||||
|
|
||||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
|
||||||
vkCmdDrawIndexed(command_buffer, tess.numIndexes, 1, 0, 0, 0);
|
vkCmdDrawIndexed(command_buffer, tess.numIndexes, 1, 0, 0, 0);
|
||||||
tess_vertex_buffer_offset += tess.numVertexes * sizeof(Vertex);
|
tess_vertex_buffer_offset += tess.numVertexes * sizeof(Vertex);
|
||||||
tess_index_buffer_offset += tess.numIndexes * sizeof(uint32_t);
|
tess_index_buffer_offset += tess.numIndexes * sizeof(uint32_t);
|
||||||
|
|
||||||
update_uniform_buffer(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan_Demo::render_cinematic_frame() {
|
void Vulkan_Demo::render_cinematic_frame() {
|
||||||
fprintf(logfile, "render_cinematic_frame\n");
|
fprintf(logfile, "render_cinematic_frame\n");
|
||||||
fflush(logfile);
|
fflush(logfile);
|
||||||
|
|
||||||
update_image_descriptor(true);
|
VkDescriptorImageInfo image_info;
|
||||||
|
image_info.sampler = texture_image_sampler;
|
||||||
|
image_info.imageView = cinematic_image_view;
|
||||||
|
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
|
||||||
|
std::array<VkWriteDescriptorSet, 1> descriptor_writes;
|
||||||
|
descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
|
descriptor_writes[0].dstSet = descriptor_set;
|
||||||
|
descriptor_writes[0].dstBinding = 1;
|
||||||
|
descriptor_writes[0].dstArrayElement = 0;
|
||||||
|
descriptor_writes[0].descriptorCount = 1;
|
||||||
|
descriptor_writes[0].pNext = nullptr;
|
||||||
|
descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
descriptor_writes[0].pImageInfo = &image_info;
|
||||||
|
descriptor_writes[0].pBufferInfo = nullptr;
|
||||||
|
descriptor_writes[0].pTexelBufferView = nullptr;
|
||||||
|
|
||||||
|
vkUpdateDescriptorSets(get_device(), (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
|
||||||
|
|
||||||
const VkDeviceSize offset = 0;
|
const VkDeviceSize offset = 0;
|
||||||
vkCmdBindVertexBuffers(command_buffer, 0, 1, &vertex_buffer, &offset);
|
vkCmdBindVertexBuffers(command_buffer, 0, 1, &vertex_buffer, &offset);
|
||||||
vkCmdBindIndexBuffer(command_buffer, index_buffer, 0, VK_INDEX_TYPE_UINT32);
|
vkCmdBindIndexBuffer(command_buffer, index_buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set, 0, nullptr);
|
|
||||||
|
update_uniform_buffer();
|
||||||
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set, 1, &tess_ubo_offset);
|
||||||
|
tess_ubo_offset += tess_ubo_offset_step;
|
||||||
|
|
||||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
vkCmdDrawIndexed(command_buffer, model_indices_count, 1, 0, 0, 0);
|
vkCmdDrawIndexed(command_buffer, model_indices_count, 1, 0, 0, 0);
|
||||||
|
|
||||||
update_uniform_buffer(true);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,7 @@ public:
|
||||||
|
|
||||||
void upload_geometry();
|
void upload_geometry();
|
||||||
void update_ubo_descriptor(VkDescriptorSet set);
|
void update_ubo_descriptor(VkDescriptorSet set);
|
||||||
void update_image_descriptor(bool cinematic);
|
void update_uniform_buffer();
|
||||||
void update_uniform_buffer(bool cinematic);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const int window_width = 0;
|
const int window_width = 0;
|
||||||
|
|
@ -78,6 +77,9 @@ public:
|
||||||
VkDeviceMemory tess_index_buffer_memory = VK_NULL_HANDLE;
|
VkDeviceMemory tess_index_buffer_memory = VK_NULL_HANDLE;
|
||||||
VkDeviceSize tess_index_buffer_offset = 0;
|
VkDeviceSize tess_index_buffer_offset = 0;
|
||||||
|
|
||||||
|
uint32_t tess_ubo_offset = 0;
|
||||||
|
uint32_t tess_ubo_offset_step = -1;
|
||||||
|
|
||||||
std::map<const image_t*, VkDescriptorSet> image_descriptor_sets; // quick UI prototyping
|
std::map<const image_t*, VkDescriptorSet> image_descriptor_sets; // quick UI prototyping
|
||||||
|
|
||||||
VkCommandBuffer command_buffer = VK_NULL_HANDLE;
|
VkCommandBuffer command_buffer = VK_NULL_HANDLE;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user