WIP: Vulkan: Workbench #107886
|
@ -8,5 +8,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define VMA_IMPLEMENTATION
|
#define VMA_IMPLEMENTATION
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define VMA_ASSERT(test)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "vk_mem_alloc.h"
|
#include "vk_mem_alloc.h"
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
#include "vk_context.hh"
|
#include "vk_context.hh"
|
||||||
#include "vk_index_buffer.hh"
|
#include "vk_index_buffer.hh"
|
||||||
#include "vk_state_manager.hh"
|
#include "vk_state_manager.hh"
|
||||||
|
#include "vk_storage_buffer.hh"
|
||||||
#include "vk_vertex_attribute_object.hh"
|
#include "vk_vertex_attribute_object.hh"
|
||||||
#include "vk_vertex_buffer.hh"
|
#include "vk_vertex_buffer.hh"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
void VKBatch::draw_setup()
|
||||||
void VKBatch::draw(int vertex_first, int vertex_count, int instance_first, int instance_count)
|
|
||||||
{
|
{
|
||||||
/* Currently the pipeline is rebuild on each draw command. Clearing the dirty flag for
|
/* Currently the pipeline is rebuild on each draw command. Clearing the dirty flag for
|
||||||
* consistency with the internals of GPU module. */
|
* consistency with the internals of GPU module. */
|
||||||
|
@ -37,29 +37,53 @@ void VKBatch::draw(int vertex_first, int vertex_count, int instance_first, int i
|
||||||
if (draw_indexed) {
|
if (draw_indexed) {
|
||||||
index_buffer->upload_data();
|
index_buffer->upload_data();
|
||||||
index_buffer->bind(context);
|
index_buffer->bind(context);
|
||||||
context.command_buffer_get().draw(index_buffer->index_len_get(),
|
}
|
||||||
instance_count,
|
}
|
||||||
index_buffer->index_start_get(),
|
|
||||||
vertex_first,
|
void VKBatch::draw(int vertex_first, int vertex_count, int instance_first, int instance_count)
|
||||||
instance_first);
|
{
|
||||||
|
draw_setup();
|
||||||
|
|
||||||
|
VKContext &context = *VKContext::get();
|
||||||
|
VKCommandBuffer &command_buffer = context.command_buffer_get();
|
||||||
|
VKIndexBuffer *index_buffer = index_buffer_get();
|
||||||
|
const bool draw_indexed = index_buffer != nullptr;
|
||||||
|
if (draw_indexed) {
|
||||||
|
command_buffer.draw_indexed(index_buffer->index_len_get(),
|
||||||
|
instance_count,
|
||||||
|
index_buffer->index_start_get(),
|
||||||
|
vertex_first,
|
||||||
|
instance_first);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
context.command_buffer_get().draw(vertex_first, vertex_count, instance_first, instance_count);
|
command_buffer.draw(vertex_first, vertex_count, instance_first, instance_count);
|
||||||
}
|
}
|
||||||
|
command_buffer.submit();
|
||||||
context.command_buffer_get().submit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKBatch::draw_indirect(GPUStorageBuf * /*indirect_buf*/, intptr_t /*offset*/)
|
void VKBatch::draw_indirect(GPUStorageBuf *indirect_buf, intptr_t offset)
|
||||||
{
|
{
|
||||||
NOT_YET_IMPLEMENTED;
|
multi_draw_indirect(indirect_buf, 1, offset, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKBatch::multi_draw_indirect(GPUStorageBuf * /*indirect_buf*/,
|
void VKBatch::multi_draw_indirect(GPUStorageBuf *indirect_buf,
|
||||||
int /*count*/,
|
int count,
|
||||||
intptr_t /*offset*/,
|
intptr_t offset,
|
||||||
intptr_t /*stride*/)
|
intptr_t stride)
|
||||||
{
|
{
|
||||||
|
draw_setup();
|
||||||
|
|
||||||
|
VKStorageBuffer &indirect_buffer = *unwrap(unwrap(indirect_buf));
|
||||||
|
VKContext &context = *VKContext::get();
|
||||||
|
const bool draw_indexed = index_buffer_get() != nullptr;
|
||||||
|
VKCommandBuffer &command_buffer = context.command_buffer_get();
|
||||||
|
if (draw_indexed) {
|
||||||
|
command_buffer.draw_indexed_indirect(indirect_buffer, offset, count, stride);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
command_buffer.draw_indirect(indirect_buffer, offset, count, stride);
|
||||||
|
}
|
||||||
|
command_buffer.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
VKVertexBuffer *VKBatch::vertex_buffer_get(int index)
|
VKVertexBuffer *VKBatch::vertex_buffer_get(int index)
|
||||||
|
|
|
@ -25,6 +25,9 @@ class VKBatch : public Batch {
|
||||||
VKVertexBuffer *vertex_buffer_get(int index);
|
VKVertexBuffer *vertex_buffer_get(int index);
|
||||||
VKVertexBuffer *instance_buffer_get(int index);
|
VKVertexBuffer *instance_buffer_get(int index);
|
||||||
VKIndexBuffer *index_buffer_get();
|
VKIndexBuffer *index_buffer_get();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void draw_setup();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::gpu
|
} // namespace blender::gpu
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "vk_index_buffer.hh"
|
#include "vk_index_buffer.hh"
|
||||||
#include "vk_memory.hh"
|
#include "vk_memory.hh"
|
||||||
#include "vk_pipeline.hh"
|
#include "vk_pipeline.hh"
|
||||||
|
#include "vk_storage_buffer.hh"
|
||||||
#include "vk_texture.hh"
|
#include "vk_texture.hh"
|
||||||
#include "vk_vertex_buffer.hh"
|
#include "vk_vertex_buffer.hh"
|
||||||
|
|
||||||
|
@ -244,7 +245,7 @@ void VKCommandBuffer::draw(int v_first, int v_count, int i_first, int i_count)
|
||||||
state.draw_counts++;
|
state.draw_counts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKCommandBuffer::draw(
|
void VKCommandBuffer::draw_indexed(
|
||||||
int index_count, int instance_count, int first_index, int vertex_offset, int first_instance)
|
int index_count, int instance_count, int first_index, int vertex_offset, int first_instance)
|
||||||
{
|
{
|
||||||
validate_framebuffer_exists();
|
validate_framebuffer_exists();
|
||||||
|
@ -254,6 +255,28 @@ void VKCommandBuffer::draw(
|
||||||
state.draw_counts++;
|
state.draw_counts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VKCommandBuffer::draw_indirect(const VKStorageBuffer &buffer,
|
||||||
|
VkDeviceSize offset,
|
||||||
|
uint32_t draw_count,
|
||||||
|
uint32_t stride)
|
||||||
|
{
|
||||||
|
validate_framebuffer_exists();
|
||||||
|
ensure_active_framebuffer();
|
||||||
|
vkCmdDrawIndirect(vk_command_buffer_, buffer.vk_handle(), offset, draw_count, stride);
|
||||||
|
state.draw_counts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VKCommandBuffer::draw_indexed_indirect(const VKStorageBuffer &buffer,
|
||||||
|
VkDeviceSize offset,
|
||||||
|
uint32_t draw_count,
|
||||||
|
uint32_t stride)
|
||||||
|
{
|
||||||
|
validate_framebuffer_exists();
|
||||||
|
ensure_active_framebuffer();
|
||||||
|
vkCmdDrawIndexedIndirect(vk_command_buffer_, buffer.vk_handle(), offset, draw_count, stride);
|
||||||
|
state.draw_counts++;
|
||||||
|
}
|
||||||
|
|
||||||
void VKCommandBuffer::pipeline_barrier(VkPipelineStageFlags source_stages,
|
void VKCommandBuffer::pipeline_barrier(VkPipelineStageFlags source_stages,
|
||||||
VkPipelineStageFlags destination_stages)
|
VkPipelineStageFlags destination_stages)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,7 @@ class VKPipeline;
|
||||||
class VKPushConstants;
|
class VKPushConstants;
|
||||||
class VKTexture;
|
class VKTexture;
|
||||||
class VKVertexBuffer;
|
class VKVertexBuffer;
|
||||||
|
class VKStorageBuffer;
|
||||||
|
|
||||||
/** Command buffer to keep track of the life-time of a command buffer. */
|
/** Command buffer to keep track of the life-time of a command buffer. */
|
||||||
class VKCommandBuffer : NonCopyable, NonMovable {
|
class VKCommandBuffer : NonCopyable, NonMovable {
|
||||||
|
@ -182,8 +183,16 @@ class VKCommandBuffer : NonCopyable, NonMovable {
|
||||||
void fill(VKBuffer &buffer, uint32_t data);
|
void fill(VKBuffer &buffer, uint32_t data);
|
||||||
|
|
||||||
void draw(int v_first, int v_count, int i_first, int i_count);
|
void draw(int v_first, int v_count, int i_first, int i_count);
|
||||||
void draw(
|
void draw_indexed(
|
||||||
int index_count, int instance_count, int first_index, int vertex_offset, int first_instance);
|
int index_count, int instance_count, int first_index, int vertex_offset, int first_instance);
|
||||||
|
void draw_indirect(const VKStorageBuffer &buffer,
|
||||||
|
VkDeviceSize offset,
|
||||||
|
uint32_t draw_count,
|
||||||
|
uint32_t stride);
|
||||||
|
void draw_indexed_indirect(const VKStorageBuffer &buffer,
|
||||||
|
VkDeviceSize offset,
|
||||||
|
uint32_t draw_count,
|
||||||
|
uint32_t stride);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop recording commands, encode + send the recordings to Vulkan, wait for the until the
|
* Stop recording commands, encode + send the recordings to Vulkan, wait for the until the
|
||||||
|
|
|
@ -38,6 +38,7 @@ class VKDevice : public NonCopyable {
|
||||||
/* Workarounds */
|
/* Workarounds */
|
||||||
struct {
|
struct {
|
||||||
bool depth_component_24 = false;
|
bool depth_component_24 = false;
|
||||||
|
bool texture_format_rgb16f = false;
|
||||||
|
|
||||||
} workarounds_;
|
} workarounds_;
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ void VKStorageBuffer::allocate()
|
||||||
|
|
||||||
void VKStorageBuffer::bind(int slot)
|
void VKStorageBuffer::bind(int slot)
|
||||||
{
|
{
|
||||||
|
/* TODO: move Storage buffer bindings to state manager to reuse bindings.*/
|
||||||
VKContext &context = *VKContext::get();
|
VKContext &context = *VKContext::get();
|
||||||
if (!buffer_.is_allocated()) {
|
if (!buffer_.is_allocated()) {
|
||||||
allocate();
|
allocate();
|
||||||
|
@ -40,8 +41,9 @@ void VKStorageBuffer::bind(int slot)
|
||||||
const std::optional<VKDescriptorSet::Location> location =
|
const std::optional<VKDescriptorSet::Location> location =
|
||||||
shader_interface.descriptor_set_location(
|
shader_interface.descriptor_set_location(
|
||||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, slot);
|
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, slot);
|
||||||
BLI_assert_msg(location, "Locations to SSBOs should always exist.");
|
if (location) {
|
||||||
shader->pipeline_get().descriptor_set_get().bind(*this, *location);
|
shader->pipeline_get().descriptor_set_get().bind(*this, *location);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKStorageBuffer::unbind() {}
|
void VKStorageBuffer::unbind() {}
|
||||||
|
|
|
@ -48,4 +48,9 @@ class VKStorageBuffer : public StorageBuf {
|
||||||
void allocate();
|
void allocate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline VKStorageBuffer *unwrap(StorageBuf *storage_buffer)
|
||||||
|
{
|
||||||
|
return static_cast<VKStorageBuffer *>(storage_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::gpu
|
} // namespace blender::gpu
|
||||||
|
|
|
@ -53,6 +53,7 @@ void VKTexture::copy_to(Texture *tex)
|
||||||
UNUSED_VARS_NDEBUG(src);
|
UNUSED_VARS_NDEBUG(src);
|
||||||
|
|
||||||
VKContext &context = *VKContext::get();
|
VKContext &context = *VKContext::get();
|
||||||
|
ensure_allocated();
|
||||||
layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
dst->ensure_allocated();
|
dst->ensure_allocated();
|
||||||
dst->layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
dst->layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
@ -450,6 +451,7 @@ void VKTexture::current_layout_set(const VkImageLayout new_layout)
|
||||||
|
|
||||||
void VKTexture::layout_ensure(VKContext &context, const VkImageLayout requested_layout)
|
void VKTexture::layout_ensure(VKContext &context, const VkImageLayout requested_layout)
|
||||||
{
|
{
|
||||||
|
BLI_assert(is_allocated());
|
||||||
const VkImageLayout current_layout = current_layout_get();
|
const VkImageLayout current_layout = current_layout_get();
|
||||||
if (current_layout == requested_layout) {
|
if (current_layout == requested_layout) {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue