Merge branch 'blender-v4.5-release'

This commit is contained in:
Jeroen Bakker
2025-06-06 10:22:11 +02:00
25 changed files with 730 additions and 131 deletions

View File

@@ -306,6 +306,7 @@ class GHOST_DeviceVK {
vulkan_12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
vulkan_12_features.shaderOutputLayer = features_12.shaderOutputLayer;
vulkan_12_features.shaderOutputViewportIndex = features_12.shaderOutputViewportIndex;
vulkan_12_features.bufferDeviceAddress = features_12.bufferDeviceAddress;
vulkan_12_features.timelineSemaphore = VK_TRUE;
feature_struct_ptr.push_back(&vulkan_12_features);
@@ -365,6 +366,18 @@ class GHOST_DeviceVK {
use_vk_ext_swapchain_maintenance_1 = true;
}
/* Descriptor buffers */
VkPhysicalDeviceDescriptorBufferPropertiesEXT descriptor_buffer = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT,
nullptr,
VK_TRUE,
VK_FALSE,
VK_FALSE,
VK_FALSE};
if (extension_requested(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME)) {
feature_struct_ptr.push_back(&descriptor_buffer);
}
/* Query and enable Fragment Shader Barycentrics. */
VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR fragment_shader_barycentric = {};
fragment_shader_barycentric.sType =
@@ -1220,6 +1233,8 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
optional_device_extensions.push_back(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);
optional_device_extensions.push_back(VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME);
optional_device_extensions.push_back(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
optional_device_extensions.push_back(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
optional_device_extensions.push_back(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
VkInstance instance = VK_NULL_HANDLE;
if (!vulkan_device.has_value()) {

View File

@@ -55,6 +55,40 @@ void vk_pipeline_data_build_commands(VKCommandBufferInterface &command_buffer,
nullptr);
}
if (assign_if_different(r_bound_pipeline.descriptor_buffer_device_address,
pipeline_data.descriptor_buffer_device_address) &&
r_bound_pipeline.descriptor_buffer_device_address != 0)
{
r_bound_pipeline.descriptor_buffer_offset = pipeline_data.descriptor_buffer_offset;
VkDescriptorBufferBindingInfoEXT descriptor_buffer_binding_info = {
VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT,
nullptr,
r_bound_pipeline.descriptor_buffer_device_address,
VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT |
VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT};
command_buffer.bind_descriptor_buffers(1, &descriptor_buffer_binding_info);
uint32_t buffer_index = 0;
command_buffer.set_descriptor_buffer_offsets(vk_pipeline_bind_point,
pipeline_data.vk_pipeline_layout,
0,
1,
&buffer_index,
&r_bound_pipeline.descriptor_buffer_offset);
}
else if (assign_if_different(r_bound_pipeline.descriptor_buffer_offset,
pipeline_data.descriptor_buffer_offset) &&
r_bound_pipeline.descriptor_buffer_device_address != 0)
{
uint32_t buffer_index = 0;
command_buffer.set_descriptor_buffer_offsets(vk_pipeline_bind_point,
pipeline_data.vk_pipeline_layout,
0,
1,
&buffer_index,
&r_bound_pipeline.descriptor_buffer_offset);
}
if (pipeline_data.push_constants_size) {
command_buffer.push_constants(pipeline_data.vk_pipeline_layout,
vk_shader_stage_flags,

View File

@@ -24,6 +24,10 @@ struct VKPipelineData {
VkPipeline vk_pipeline;
VkPipelineLayout vk_pipeline_layout;
VkDescriptorSet vk_descriptor_set;
/* VK_EXT_descriptor_buffer */
VkDeviceAddress descriptor_buffer_device_address;
VkDeviceSize descriptor_buffer_offset;
uint32_t push_constants_size;
const void *push_constants_data;
};
@@ -65,6 +69,8 @@ struct VKViewportData {
struct VKBoundPipeline {
VkPipeline vk_pipeline;
VkDescriptorSet vk_descriptor_set;
VkDeviceAddress descriptor_buffer_device_address;
VkDeviceSize descriptor_buffer_offset;
};
struct VKIndexBufferBinding {

View File

@@ -476,6 +476,21 @@ class CommandBufferLog : public VKCommandBufferInterface {
void begin_debug_utils_label(const VkDebugUtilsLabelEXT * /*vk_debug_utils_label*/) override {}
void end_debug_utils_label() override {}
/* VK_EXT_descriptor_buffer */
void bind_descriptor_buffers(
uint32_t /*buffer_count*/,
const VkDescriptorBufferBindingInfoEXT * /*p_binding_infos*/) override
{
}
void set_descriptor_buffer_offsets(VkPipelineBindPoint /*pipeline_bind_point*/,
VkPipelineLayout /*layout*/,
uint32_t /*first_set*/,
uint32_t /*set_count*/,
const uint32_t * /*p_buffer_indices*/,
const VkDeviceSize * /*p_offsets*/) override
{
}
};
class VKRenderGraphTest : public ::testing::Test {

View File

@@ -326,4 +326,28 @@ void VKCommandBufferWrapper::end_debug_utils_label()
}
}
/* VK_EXT_descriptor_buffer */
void VKCommandBufferWrapper::bind_descriptor_buffers(
uint32_t buffer_count, const VkDescriptorBufferBindingInfoEXT *p_binding_infos)
{
const VKDevice &device = VKBackend::get().device;
device.functions.vkCmdBindDescriptorBuffers(vk_command_buffer_, buffer_count, p_binding_infos);
}
void VKCommandBufferWrapper::set_descriptor_buffer_offsets(VkPipelineBindPoint pipeline_bind_point,
VkPipelineLayout layout,
uint32_t first_set,
uint32_t set_count,
const uint32_t *p_buffer_indices,
const VkDeviceSize *p_offsets)
{
const VKDevice &device = VKBackend::get().device;
device.functions.vkCmdSetDescriptorBufferOffsets(vk_command_buffer_,
pipeline_bind_point,
layout,
first_set,
set_count,
p_buffer_indices,
p_offsets);
}
} // namespace blender::gpu::render_graph

View File

@@ -141,6 +141,16 @@ class VKCommandBufferInterface {
/* VK_EXT_debug_utils */
virtual void begin_debug_utils_label(const VkDebugUtilsLabelEXT *vk_debug_utils_label) = 0;
virtual void end_debug_utils_label() = 0;
/* VK_EXT_descriptor_buffer */
virtual void bind_descriptor_buffers(
uint32_t buffer_count, const VkDescriptorBufferBindingInfoEXT *p_binding_infos) = 0;
virtual void set_descriptor_buffer_offsets(VkPipelineBindPoint pipeline_bind_point,
VkPipelineLayout layout,
uint32_t first_set,
uint32_t set_count,
const uint32_t *p_buffer_indices,
const VkDeviceSize *p_offsets) = 0;
};
class VKCommandBufferWrapper : public VKCommandBufferInterface {
@@ -261,6 +271,16 @@ class VKCommandBufferWrapper : public VKCommandBufferInterface {
void end_rendering() override;
void begin_debug_utils_label(const VkDebugUtilsLabelEXT *vk_debug_utils_label) override;
void end_debug_utils_label() override;
/* VK_EXT_descriptor_buffer */
void bind_descriptor_buffers(uint32_t buffer_count,
const VkDescriptorBufferBindingInfoEXT *p_binding_infos) override;
void set_descriptor_buffer_offsets(VkPipelineBindPoint pipeline_bind_point,
VkPipelineLayout layout,
uint32_t first_set,
uint32_t set_count,
const uint32_t *p_buffer_indices,
const VkDeviceSize *p_offsets) override;
};
} // namespace blender::gpu::render_graph

View File

@@ -327,7 +327,7 @@ struct VKRenderGraphNode {
}
};
BLI_STATIC_ASSERT(sizeof(VKRenderGraphNode) <= 64,
BLI_STATIC_ASSERT(sizeof(VKRenderGraphNode) <= 96,
"VKRenderGraphNode should be kept small. Consider moving data to the "
"VKRenderGraphStorage class.");

View File

@@ -137,6 +137,9 @@ static Vector<StringRefNull> missing_capabilities_get(VkPhysicalDevice vk_physic
if (features_12.timelineSemaphore == VK_FALSE) {
missing_capabilities.append("timeline semaphores");
}
if (features_12.bufferDeviceAddress == VK_FALSE) {
missing_capabilities.append("buffer device address");
}
/* Check device extensions. */
uint32_t vk_extension_count;
@@ -385,6 +388,7 @@ void VKBackend::detect_workarounds(VKDevice &device)
extensions.dynamic_rendering = false;
extensions.dynamic_rendering_local_read = false;
extensions.dynamic_rendering_unused_attachments = false;
extensions.descriptor_buffer = false;
GCaps.render_pass_workaround = true;
@@ -414,6 +418,8 @@ void VKBackend::detect_workarounds(VKDevice &device)
#else
extensions.external_memory = false;
#endif
extensions.descriptor_buffer = device.supports_extension(
VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
/* AMD GPUs don't support texture formats that use are aligned to 24 or 48 bits. */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY) ||

View File

@@ -77,6 +77,11 @@ bool VKBuffer::create(size_t size_in_bytes,
vma_create_info.pool = device.vma_pools.external_memory;
}
const bool use_descriptor_buffer = device.extensions_get().descriptor_buffer;
if (use_descriptor_buffer) {
create_info.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
}
VkResult result = vmaCreateBuffer(
allocator, &create_info, &vma_create_info, &vk_buffer_, &allocation_, nullptr);
if (result != VK_SUCCESS) {
@@ -88,11 +93,18 @@ bool VKBuffer::create(size_t size_in_bytes,
device.resources.add_buffer(vk_buffer_);
vmaGetAllocationMemoryProperties(allocator, allocation_, &vk_memory_property_flags_);
if (use_descriptor_buffer) {
VkBufferDeviceAddressInfo vk_buffer_device_address_info = {
VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, nullptr, vk_buffer_};
vk_device_address = vkGetBufferDeviceAddress(device.vk_handle(),
&vk_buffer_device_address_info);
}
vmaGetAllocationMemoryProperties(allocator, allocation_, &vk_memory_property_flags_);
if (vk_memory_property_flags_ & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
return map();
}
return true;
}

View File

@@ -33,8 +33,11 @@ class VKBuffer : public NonCopyable {
/* Pointer to the virtually mapped memory. */
void *mapped_memory_ = nullptr;
VkDeviceAddress vk_device_address = 0;
public:
VKBuffer() = default;
VKBuffer(VKBuffer &&other) = default;
virtual ~VKBuffer();
/** Has this buffer been allocated? */
@@ -108,6 +111,11 @@ class VKBuffer : public NonCopyable {
*/
void *mapped_memory_get() const;
VkDeviceAddress device_address_get() const
{
return vk_device_address;
}
/**
* Is this buffer mapped (visible on host)
*/

View File

@@ -157,9 +157,11 @@ TimelineValue VKContext::flush_render_graph(RenderGraphFlushFlags flags,
framebuffer.rendering_end(*this);
}
}
descriptor_set_get().upload_descriptor_sets();
descriptor_pools_get().discard(*this);
VKDevice &device = VKBackend::get().device;
descriptor_set_get().upload_descriptor_sets();
if (!device.extensions_get().descriptor_buffer) {
descriptor_pools_get().discard(*this);
}
TimelineValue timeline = device.render_graph_submit(
&render_graph_.value().get(),
discard_pool,
@@ -317,8 +319,7 @@ void VKContext::update_pipeline_data(VKShader &vk_shader,
r_pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
if (vk_shader.has_descriptor_set()) {
VKDescriptorSetTracker &descriptor_set = descriptor_set_get();
descriptor_set.update_descriptor_set(*this, access_info_);
r_pipeline_data.vk_descriptor_set = descriptor_set.vk_descriptor_set;
descriptor_set.update_descriptor_set(*this, access_info_, r_pipeline_data);
}
}

View File

@@ -17,61 +17,49 @@
namespace blender::gpu {
void VKDescriptorSetTracker::bind_buffer(VkDescriptorType vk_descriptor_type,
VkBuffer vk_buffer,
VkDeviceSize buffer_offset,
VkDeviceSize size_in_bytes,
VKDescriptorSet::Location location)
void VKDescriptorSetTracker::update_descriptor_set(VKContext &context,
render_graph::VKResourceAccessInfo &access_info,
render_graph::VKPipelineData &r_pipeline_data)
{
vk_descriptor_buffer_infos_.append({vk_buffer, buffer_offset, size_in_bytes});
vk_write_descriptor_sets_.append({VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
nullptr,
vk_descriptor_set,
location,
0,
1,
vk_descriptor_type,
nullptr,
nullptr,
nullptr});
VKShader &shader = *unwrap(context.shader);
VKStateManager &state_manager = context.state_manager_get();
/* Can we reuse previous descriptor set. */
if (!state_manager.is_dirty &&
!assign_if_different(vk_descriptor_set_layout_, shader.vk_descriptor_set_layout_get()) &&
shader.push_constants.layout_get().storage_type_get() !=
VKPushConstants::StorageType::UNIFORM_BUFFER)
{
return;
}
state_manager.is_dirty = false;
VKDevice &device = VKBackend::get().device;
VkDescriptorSetLayout vk_descriptor_set_layout = shader.vk_descriptor_set_layout_get();
VKDescriptorSetUpdator *updator = &descriptor_sets;
if (device.extensions_get().descriptor_buffer) {
updator = &descriptor_buffers;
}
updator->allocate_new_descriptor_set(
device, context, shader, vk_descriptor_set_layout, r_pipeline_data);
updator->bind_shader_resources(device, state_manager, shader, access_info);
}
void VKDescriptorSetTracker::bind_texel_buffer(VkBufferView vk_buffer_view,
const VKDescriptorSet::Location location)
void VKDescriptorSetTracker::upload_descriptor_sets()
{
vk_buffer_views_.append(vk_buffer_view);
vk_write_descriptor_sets_.append({VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
nullptr,
vk_descriptor_set,
location,
0,
1,
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
nullptr,
nullptr,
nullptr});
VKDevice &device = VKBackend::get().device;
VKDescriptorSetUpdator &updator = descriptor_sets;
if (device.extensions_get().descriptor_buffer) {
updator = descriptor_buffers;
}
updator.upload_descriptor_sets();
}
void VKDescriptorSetTracker::bind_image(VkDescriptorType vk_descriptor_type,
VkSampler vk_sampler,
VkImageView vk_image_view,
VkImageLayout vk_image_layout,
VKDescriptorSet::Location location)
{
vk_descriptor_image_infos_.append({vk_sampler, vk_image_view, vk_image_layout});
vk_write_descriptor_sets_.append({VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
nullptr,
vk_descriptor_set,
location,
0,
1,
vk_descriptor_type,
nullptr,
nullptr,
nullptr});
}
/* -------------------------------------------------------------------- */
/** \name VKDescriptorSetUpdator
* \{ */
void VKDescriptorSetTracker::bind_image_resource(const VKStateManager &state_manager,
void VKDescriptorSetUpdator::bind_image_resource(const VKStateManager &state_manager,
const VKResourceBinding &resource_binding,
render_graph::VKResourceAccessInfo &access_info)
{
@@ -97,7 +85,7 @@ void VKDescriptorSetTracker::bind_image_resource(const VKStateManager &state_man
layer_count});
}
void VKDescriptorSetTracker::bind_texture_resource(const VKDevice &device,
void VKDescriptorSetUpdator::bind_texture_resource(const VKDevice &device,
const VKStateManager &state_manager,
const VKResourceBinding &resource_binding,
render_graph::VKResourceAccessInfo &access_info)
@@ -105,11 +93,10 @@ void VKDescriptorSetTracker::bind_texture_resource(const VKDevice &device,
const BindSpaceTextures::Elem &elem = state_manager.textures_.get(resource_binding.binding);
switch (elem.resource_type) {
case BindSpaceTextures::Type::VertexBuffer: {
VKVertexBuffer *vertex_buffer = static_cast<VKVertexBuffer *>(elem.resource);
vertex_buffer->ensure_updated();
vertex_buffer->ensure_buffer_view();
bind_texel_buffer(vertex_buffer->vk_buffer_view_get(), resource_binding.location);
access_info.buffers.append({vertex_buffer->vk_handle(), resource_binding.access_mask});
VKVertexBuffer &vertex_buffer = *static_cast<VKVertexBuffer *>(elem.resource);
vertex_buffer.ensure_updated();
bind_texel_buffer(vertex_buffer, resource_binding.location);
access_info.buffers.append({vertex_buffer.vk_handle(), resource_binding.access_mask});
break;
}
case BindSpaceTextures::Type::Texture: {
@@ -118,11 +105,10 @@ void VKDescriptorSetTracker::bind_texture_resource(const VKDevice &device,
/* Texture buffers are no textures, but wrap around vertex buffers and need to be
* bound as texel buffers. */
/* TODO: Investigate if this can be improved in the API. */
VKVertexBuffer *vertex_buffer = texture->source_buffer_;
vertex_buffer->ensure_updated();
vertex_buffer->ensure_buffer_view();
bind_texel_buffer(vertex_buffer->vk_buffer_view_get(), resource_binding.location);
access_info.buffers.append({vertex_buffer->vk_handle(), resource_binding.access_mask});
VKVertexBuffer &vertex_buffer = *texture->source_buffer_;
vertex_buffer.ensure_updated();
bind_texel_buffer(vertex_buffer, resource_binding.location);
access_info.buffers.append({vertex_buffer.vk_handle(), resource_binding.access_mask});
}
else {
const VKSampler &sampler = device.samplers().get(elem.sampler);
@@ -146,7 +132,7 @@ void VKDescriptorSetTracker::bind_texture_resource(const VKDevice &device,
}
}
void VKDescriptorSetTracker::bind_input_attachment_resource(
void VKDescriptorSetUpdator::bind_input_attachment_resource(
const VKDevice &device,
const VKStateManager &state_manager,
const VKResourceBinding &resource_binding,
@@ -215,7 +201,7 @@ void VKDescriptorSetTracker::bind_input_attachment_resource(
}
}
void VKDescriptorSetTracker::bind_storage_buffer_resource(
void VKDescriptorSetUpdator::bind_storage_buffer_resource(
const VKStateManager &state_manager,
const VKResourceBinding &resource_binding,
render_graph::VKResourceAccessInfo &access_info)
@@ -224,12 +210,14 @@ void VKDescriptorSetTracker::bind_storage_buffer_resource(
resource_binding.binding);
VkBuffer vk_buffer = VK_NULL_HANDLE;
VkDeviceSize vk_device_size = 0;
VkDeviceAddress vk_device_address = 0;
switch (elem.resource_type) {
case BindSpaceStorageBuffers::Type::IndexBuffer: {
VKIndexBuffer *index_buffer = static_cast<VKIndexBuffer *>(elem.resource);
index_buffer->ensure_updated();
vk_buffer = index_buffer->vk_handle();
vk_device_size = index_buffer->size_get();
vk_device_address = index_buffer->device_address_get();
break;
}
case BindSpaceStorageBuffers::Type::VertexBuffer: {
@@ -237,6 +225,7 @@ void VKDescriptorSetTracker::bind_storage_buffer_resource(
vertex_buffer->ensure_updated();
vk_buffer = vertex_buffer->vk_handle();
vk_device_size = vertex_buffer->size_used_get();
vk_device_address = vertex_buffer->device_address_get();
break;
}
case BindSpaceStorageBuffers::Type::UniformBuffer: {
@@ -244,6 +233,7 @@ void VKDescriptorSetTracker::bind_storage_buffer_resource(
uniform_buffer->ensure_updated();
vk_buffer = uniform_buffer->vk_handle();
vk_device_size = uniform_buffer->size_in_bytes();
vk_device_address = uniform_buffer->device_address_get();
break;
}
case BindSpaceStorageBuffers::Type::StorageBuffer: {
@@ -251,12 +241,14 @@ void VKDescriptorSetTracker::bind_storage_buffer_resource(
storage_buffer->ensure_allocated();
vk_buffer = storage_buffer->vk_handle();
vk_device_size = storage_buffer->size_in_bytes();
vk_device_address = storage_buffer->device_address_get();
break;
}
case BindSpaceStorageBuffers::Type::Buffer: {
VKBuffer *buffer = static_cast<VKBuffer *>(elem.resource);
vk_buffer = buffer->vk_handle();
vk_device_size = buffer->size_in_bytes();
vk_device_address = buffer->device_address_get();
break;
}
case BindSpaceStorageBuffers::Type::Unused: {
@@ -266,6 +258,7 @@ void VKDescriptorSetTracker::bind_storage_buffer_resource(
bind_buffer(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
vk_buffer,
vk_device_address,
elem.offset,
vk_device_size - elem.offset,
resource_binding.location);
@@ -274,7 +267,7 @@ void VKDescriptorSetTracker::bind_storage_buffer_resource(
}
}
void VKDescriptorSetTracker::bind_uniform_buffer_resource(
void VKDescriptorSetUpdator::bind_uniform_buffer_resource(
const VKStateManager &state_manager,
const VKResourceBinding &resource_binding,
render_graph::VKResourceAccessInfo &access_info)
@@ -283,13 +276,14 @@ void VKDescriptorSetTracker::bind_uniform_buffer_resource(
uniform_buffer.ensure_updated();
bind_buffer(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
uniform_buffer.vk_handle(),
uniform_buffer.device_address_get(),
0,
uniform_buffer.size_in_bytes(),
resource_binding.location);
access_info.buffers.append({uniform_buffer.vk_handle(), resource_binding.access_mask});
}
void VKDescriptorSetTracker::bind_push_constants(VKPushConstants &push_constants,
void VKDescriptorSetUpdator::bind_push_constants(VKPushConstants &push_constants,
render_graph::VKResourceAccessInfo &access_info)
{
if (push_constants.layout_get().storage_type_get() !=
@@ -301,13 +295,14 @@ void VKDescriptorSetTracker::bind_push_constants(VKPushConstants &push_constants
const VKUniformBuffer &uniform_buffer = *push_constants.uniform_buffer_get().get();
bind_buffer(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
uniform_buffer.vk_handle(),
uniform_buffer.device_address_get(),
0,
uniform_buffer.size_in_bytes(),
push_constants.layout_get().descriptor_set_location_get());
access_info.buffers.append({uniform_buffer.vk_handle(), VK_ACCESS_UNIFORM_READ_BIT});
}
void VKDescriptorSetTracker::bind_shader_resources(const VKDevice &device,
void VKDescriptorSetUpdator::bind_shader_resources(const VKDevice &device,
const VKStateManager &state_manager,
VKShader &shader,
render_graph::VKResourceAccessInfo &access_info)
@@ -345,32 +340,83 @@ void VKDescriptorSetTracker::bind_shader_resources(const VKDevice &device,
bind_push_constants(shader.push_constants, access_info);
}
void VKDescriptorSetTracker::update_descriptor_set(VKContext &context,
render_graph::VKResourceAccessInfo &access_info)
/** \} */
/* -------------------------------------------------------------------- */
/** \name VKDescriptorSetPoolUpdator
* \{ */
void VKDescriptorSetPoolUpdator::allocate_new_descriptor_set(
VKDevice & /*device*/,
VKContext &context,
VKShader &shader,
VkDescriptorSetLayout vk_descriptor_set_layout,
render_graph::VKPipelineData &r_pipeline_data)
{
VKShader &shader = *unwrap(context.shader);
VKStateManager &state_manager = context.state_manager_get();
/* Can we reuse previous descriptor set. */
if (!state_manager.is_dirty &&
!assign_if_different(vk_descriptor_set_layout_, shader.vk_descriptor_set_layout_get()) &&
shader.push_constants.layout_get().storage_type_get() !=
VKPushConstants::StorageType::UNIFORM_BUFFER)
{
return;
}
state_manager.is_dirty = false;
/* Allocate a new descriptor set. */
VkDescriptorSetLayout vk_descriptor_set_layout = shader.vk_descriptor_set_layout_get();
/* Use descriptor pools/sets. */
vk_descriptor_set = context.descriptor_pools_get().allocate(vk_descriptor_set_layout);
BLI_assert(vk_descriptor_set != VK_NULL_HANDLE);
debug::object_label(vk_descriptor_set, shader.name_get());
const VKDevice &device = VKBackend::get().device;
bind_shader_resources(device, state_manager, shader, access_info);
r_pipeline_data.vk_descriptor_set = vk_descriptor_set;
}
void VKDescriptorSetTracker::upload_descriptor_sets()
void VKDescriptorSetPoolUpdator::bind_buffer(VkDescriptorType vk_descriptor_type,
VkBuffer vk_buffer,
VkDeviceAddress /*vk_device_address*/,
VkDeviceSize buffer_offset,
VkDeviceSize size_in_bytes,
VKDescriptorSet::Location location)
{
vk_descriptor_buffer_infos_.append({vk_buffer, buffer_offset, size_in_bytes});
vk_write_descriptor_sets_.append({VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
nullptr,
vk_descriptor_set,
location,
0,
1,
vk_descriptor_type,
nullptr,
nullptr,
nullptr});
}
void VKDescriptorSetPoolUpdator::bind_texel_buffer(VKVertexBuffer &vertex_buffer,
const VKDescriptorSet::Location location)
{
vertex_buffer.ensure_buffer_view();
vk_buffer_views_.append(vertex_buffer.vk_buffer_view_get());
vk_write_descriptor_sets_.append({VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
nullptr,
vk_descriptor_set,
location,
0,
1,
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
nullptr,
nullptr,
nullptr});
}
void VKDescriptorSetPoolUpdator::bind_image(VkDescriptorType vk_descriptor_type,
VkSampler vk_sampler,
VkImageView vk_image_view,
VkImageLayout vk_image_layout,
VKDescriptorSet::Location location)
{
vk_descriptor_image_infos_.append({vk_sampler, vk_image_view, vk_image_layout});
vk_write_descriptor_sets_.append({VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
nullptr,
vk_descriptor_set,
location,
0,
1,
vk_descriptor_type,
nullptr,
nullptr,
nullptr});
}
void VKDescriptorSetPoolUpdator::upload_descriptor_sets()
{
if (vk_write_descriptor_sets_.is_empty()) {
return;
@@ -464,4 +510,164 @@ void VKDescriptorSetTracker::upload_descriptor_sets()
vk_write_descriptor_sets_.clear();
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name VKDescriptorBufferUpdator
* \{ */
void VKDescriptorBufferUpdator::allocate_new_descriptor_set(
VKDevice &device,
VKContext & /*context*/,
VKShader & /*shader*/,
VkDescriptorSetLayout vk_descriptor_set_layout,
render_graph::VKPipelineData &r_pipeline_data)
{
/* Use descriptor buffer. */
descriptor_set_head = descriptor_set_tail;
layout = device.descriptor_set_layouts_get().descriptor_buffer_layout_get(
vk_descriptor_set_layout);
/* Ensure if there is still place left in the current buffer. */
if (buffers.is_empty() || layout.size > buffers.last().size_in_bytes() - descriptor_set_head) {
const VkDeviceSize default_buffer_size = 8 * 1024 * 1024;
buffers.append({});
VKBuffer &buffer = buffers.last();
buffer.create(default_buffer_size,
VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT |
VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT,
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
0,
VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT);
debug::object_label(buffer.vk_handle(), "DescriptorBuffer");
descriptor_buffer_data = static_cast<uint8_t *>(buffer.mapped_memory_get());
descriptor_buffer_device_address = buffer.device_address_get();
descriptor_buffer_offset = 0;
descriptor_set_head = 0;
descriptor_set_tail = 0;
}
descriptor_set_tail = descriptor_set_head + layout.size;
/* Update the current descriptor buffer and its offset to point to the active descriptor set. */
descriptor_buffer_offset = descriptor_set_head;
r_pipeline_data.descriptor_buffer_device_address = descriptor_buffer_device_address;
r_pipeline_data.descriptor_buffer_offset = descriptor_buffer_offset;
}
void VKDescriptorBufferUpdator::bind_buffer(VkDescriptorType vk_descriptor_type,
VkBuffer /*vk_buffer*/,
VkDeviceAddress vk_device_address,
VkDeviceSize buffer_offset,
VkDeviceSize size_in_bytes,
VKDescriptorSet::Location location)
{
BLI_assert(vk_device_address != 0);
VKDevice &device = VKBackend::get().device;
const VkPhysicalDeviceDescriptorBufferPropertiesEXT &vk_descriptor_buffer_properties =
device.physical_device_descriptor_buffer_properties_get();
VkDescriptorAddressInfoEXT descriptor_address_info = {
VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT,
nullptr,
vk_device_address + buffer_offset,
size_in_bytes};
VkDescriptorGetInfoEXT vk_descriptor_get_info{
VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT, nullptr, vk_descriptor_type};
VkDeviceSize descriptor_size = 0;
switch (vk_descriptor_type) {
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
vk_descriptor_get_info.data.pUniformBuffer = &descriptor_address_info;
descriptor_size = vk_descriptor_buffer_properties.uniformBufferDescriptorSize;
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
vk_descriptor_get_info.data.pStorageBuffer = &descriptor_address_info;
descriptor_size = vk_descriptor_buffer_properties.storageBufferDescriptorSize;
break;
default:
BLI_assert_unreachable();
}
uint8_t *descriptor_ptr = get_descriptor_binding_ptr(location);
device.functions.vkGetDescriptor(
device.vk_handle(), &vk_descriptor_get_info, descriptor_size, descriptor_ptr);
}
void VKDescriptorBufferUpdator::bind_texel_buffer(VKVertexBuffer &vertex_buffer,
const VKDescriptorSet::Location location)
{
VkDeviceAddress vk_device_address = vertex_buffer.device_address_get();
BLI_assert(vk_device_address != 0);
VKDevice &device = VKBackend::get().device;
const VkPhysicalDeviceDescriptorBufferPropertiesEXT &vk_descriptor_buffer_properties =
device.physical_device_descriptor_buffer_properties_get();
VkDescriptorAddressInfoEXT descriptor_address_info = {
VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT,
nullptr,
vk_device_address,
vertex_buffer.size_used_get(),
vertex_buffer.to_vk_format()};
VkDescriptorGetInfoEXT vk_descriptor_get_info{
VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT, nullptr, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER};
vk_descriptor_get_info.data.pUniformTexelBuffer = &descriptor_address_info;
VkDeviceSize descriptor_size = vk_descriptor_buffer_properties.uniformTexelBufferDescriptorSize;
uint8_t *descriptor_ptr = get_descriptor_binding_ptr(location);
device.functions.vkGetDescriptor(
device.vk_handle(), &vk_descriptor_get_info, descriptor_size, descriptor_ptr);
}
void VKDescriptorBufferUpdator::bind_image(VkDescriptorType vk_descriptor_type,
VkSampler vk_sampler,
VkImageView vk_image_view,
VkImageLayout vk_image_layout,
VKDescriptorSet::Location location)
{
VKDevice &device = VKBackend::get().device;
const VkPhysicalDeviceDescriptorBufferPropertiesEXT &vk_descriptor_buffer_properties =
device.physical_device_descriptor_buffer_properties_get();
VkDescriptorImageInfo vk_descriptor_image_info = {vk_sampler, vk_image_view, vk_image_layout};
VkDescriptorGetInfoEXT vk_descriptor_get_info{
VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT, nullptr, vk_descriptor_type};
VkDeviceSize descriptor_size = 0;
switch (vk_descriptor_type) {
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
vk_descriptor_get_info.data.pCombinedImageSampler = &vk_descriptor_image_info;
descriptor_size = vk_descriptor_buffer_properties.combinedImageSamplerDescriptorSize;
break;
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
vk_descriptor_get_info.data.pStorageImage = &vk_descriptor_image_info;
descriptor_size = vk_descriptor_buffer_properties.storageImageDescriptorSize;
break;
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
vk_descriptor_get_info.data.pInputAttachmentImage = &vk_descriptor_image_info;
descriptor_size = vk_descriptor_buffer_properties.inputAttachmentDescriptorSize;
break;
default:
BLI_assert_unreachable();
}
uint8_t *descriptor_ptr = get_descriptor_binding_ptr(location);
device.functions.vkGetDescriptor(
device.vk_handle(), &vk_descriptor_get_info, descriptor_size, descriptor_ptr);
}
void VKDescriptorBufferUpdator::upload_descriptor_sets()
{
/* Buffers have already been updated. only need to discard the buffers. */
buffers.clear();
descriptor_buffer_data = nullptr;
descriptor_buffer_device_address = 0;
descriptor_buffer_offset = 0;
}
/** \} */
} // namespace blender::gpu

View File

@@ -13,9 +13,11 @@
#include "gpu_shader_private.hh"
#include "render_graph/nodes/vk_pipeline_data.hh"
#include "render_graph/vk_resource_access_info.hh"
#include "vk_buffer.hh"
#include "vk_common.hh"
#include "vk_descriptor_set_layouts.hh"
#include "vk_resource_tracker.hh"
#include "vk_uniform_buffer.hh"
@@ -25,6 +27,8 @@ class VKStateManager;
class VKDevice;
class VKPushConstants;
class VKShader;
class VKDescriptorSetTracker;
class VKVertexBuffer;
/**
* In vulkan shader resources (images and buffers) are grouped in descriptor sets.
@@ -76,42 +80,22 @@ class VKDescriptorSet : NonCopyable {
};
};
class VKDescriptorSetTracker {
friend class VKDescriptorSet;
Vector<VkBufferView> vk_buffer_views_;
Vector<VkDescriptorBufferInfo> vk_descriptor_buffer_infos_;
Vector<VkDescriptorImageInfo> vk_descriptor_image_infos_;
Vector<VkWriteDescriptorSet> vk_write_descriptor_sets_;
/* Last used layout to identify changes. */
VkDescriptorSetLayout vk_descriptor_set_layout_ = VK_NULL_HANDLE;
class VKDescriptorSetUpdator {
public:
VkDescriptorSet vk_descriptor_set = VK_NULL_HANDLE;
virtual ~VKDescriptorSetUpdator(){};
VKDescriptorSetTracker() {}
/**
* Update the descriptor set. Reuses previous descriptor set when no changes are detected. This
* improves performance when working with large grease pencil scenes.
*/
void update_descriptor_set(VKContext &context,
render_graph::VKResourceAccessInfo &resource_access_info);
/**
* Upload all descriptor sets to the device.
*
* NOTE: Caller should discard the associated descriptor pools. (VKDescriptorPools::discard)
*/
void upload_descriptor_sets();
private:
virtual void allocate_new_descriptor_set(VKDevice &device,
VKContext &context,
VKShader &shader,
VkDescriptorSetLayout vk_descriptor_set_layout,
render_graph::VKPipelineData &r_pipeline_data) = 0;
void bind_shader_resources(const VKDevice &device,
const VKStateManager &state_manager,
VKShader &shader,
render_graph::VKResourceAccessInfo &access_info);
virtual void upload_descriptor_sets() = 0;
private:
void bind_image_resource(const VKStateManager &state_manager,
const VKResourceBinding &resource_binding,
render_graph::VKResourceAccessInfo &access_info);
@@ -129,21 +113,134 @@ class VKDescriptorSetTracker {
const VKStateManager &state_manager,
const VKResourceBinding &resource_binding,
render_graph::VKResourceAccessInfo &access_info);
void bind_push_constants(VKPushConstants &push_constants,
void bind_push_constants(VKPushConstants &push_constants,
render_graph::VKResourceAccessInfo &access_info);
void bind_texel_buffer(VkBufferView vk_buffer_view, VKDescriptorSet::Location location);
protected:
virtual void bind_texel_buffer(VKVertexBuffer &vertex_buffer,
VKDescriptorSet::Location location) = 0;
virtual void bind_buffer(VkDescriptorType vk_descriptor_type,
VkBuffer vk_buffer,
VkDeviceAddress vk_device_address,
VkDeviceSize buffer_offset,
VkDeviceSize size_in_bytes,
VKDescriptorSet::Location location) = 0;
virtual void bind_image(VkDescriptorType vk_descriptor_type,
VkSampler vk_sampler,
VkImageView vk_image_view,
VkImageLayout vk_image_layout,
VKDescriptorSet::Location location) = 0;
};
class VKDescriptorSetPoolUpdator : public VKDescriptorSetUpdator {
public:
VkDescriptorSet vk_descriptor_set = VK_NULL_HANDLE;
void allocate_new_descriptor_set(VKDevice &device,
VKContext &context,
VKShader &shader,
VkDescriptorSetLayout vk_descriptor_set_layout,
render_graph::VKPipelineData &r_pipeline_data) override;
void upload_descriptor_sets() override;
protected:
void bind_texel_buffer(VKVertexBuffer &vertex_buffer,
VKDescriptorSet::Location location) override;
void bind_buffer(VkDescriptorType vk_descriptor_type,
VkBuffer vk_buffer,
VkDeviceAddress vk_device_address,
VkDeviceSize buffer_offset,
VkDeviceSize size_in_bytes,
VKDescriptorSet::Location location);
VKDescriptorSet::Location location) override;
void bind_image(VkDescriptorType vk_descriptor_type,
VkSampler vk_sampler,
VkImageView vk_image_view,
VkImageLayout vk_image_layout,
VKDescriptorSet::Location location);
VKDescriptorSet::Location location) override;
private:
Vector<VkBufferView> vk_buffer_views_;
Vector<VkDescriptorBufferInfo> vk_descriptor_buffer_infos_;
Vector<VkDescriptorImageInfo> vk_descriptor_image_infos_;
Vector<VkWriteDescriptorSet> vk_write_descriptor_sets_;
};
class VKDescriptorBufferUpdator : public VKDescriptorSetUpdator {
public:
/* Offset to the beginning of the current descriptor set. */
VkDeviceSize descriptor_set_head = 0;
/* Offset to the end (+1) of the current descriptor set. */
VkDeviceSize descriptor_set_tail = 0;
/* Current layout of the descriptor set being filled. */
VKDescriptorBufferLayout layout;
/* Descriptor buffers */
Vector<VKBuffer> buffers;
/* Current descriptor buffer handle and offset. */
VkDeviceAddress descriptor_buffer_device_address = 0;
uint8_t *descriptor_buffer_data = nullptr;
VkDeviceSize descriptor_buffer_offset = 0;
void allocate_new_descriptor_set(VKDevice &device,
VKContext &context,
VKShader &shader,
VkDescriptorSetLayout vk_descriptor_set_layout,
render_graph::VKPipelineData &r_pipeline_data) override;
void upload_descriptor_sets() override;
protected:
void bind_texel_buffer(VKVertexBuffer &vertex_buffer,
VKDescriptorSet::Location location) override;
void bind_buffer(VkDescriptorType vk_descriptor_type,
VkBuffer vk_buffer,
VkDeviceAddress vk_device_address,
VkDeviceSize buffer_offset,
VkDeviceSize size_in_bytes,
VKDescriptorSet::Location location) override;
void bind_image(VkDescriptorType vk_descriptor_type,
VkSampler vk_sampler,
VkImageView vk_image_view,
VkImageLayout vk_image_layout,
VKDescriptorSet::Location location) override;
private:
inline uint8_t *get_descriptor_binding_ptr(uint32_t binding) const
{
return descriptor_buffer_data + descriptor_buffer_offset + layout.binding_offsets[binding];
}
};
class VKDescriptorSetTracker {
friend class VKDescriptorSet;
/* Last used layout to identify changes. */
VkDescriptorSetLayout vk_descriptor_set_layout_ = VK_NULL_HANDLE;
public:
class VKDescriptorBufferUpdator descriptor_buffers;
class VKDescriptorSetPoolUpdator descriptor_sets;
VKDescriptorSetTracker() {}
/**
* Update the descriptor set. Reuses previous descriptor set when no changes are detected. This
* improves performance when working with large grease pencil scenes.
*/
void update_descriptor_set(VKContext &context,
render_graph::VKResourceAccessInfo &resource_access_info,
render_graph::VKPipelineData &r_pipeline_data);
/**
* Upload all descriptor sets to the device.
*
* NOTE: Caller should discard the associated descriptor pools. (VKDescriptorPools::discard)
*/
void upload_descriptor_sets();
private:
};
} // namespace blender::gpu

View File

@@ -40,11 +40,16 @@ VkDescriptorSetLayout VKDescriptorSetLayouts::get_or_create(const VKDescriptorSe
}
update_layout_bindings(info);
const VKDevice &device = VKBackend::get().device;
const bool use_descriptor_buffer = device.extensions_get().descriptor_buffer;
vk_descriptor_set_layout_create_info_.bindingCount = vk_descriptor_set_layout_bindings_.size();
vk_descriptor_set_layout_create_info_.pBindings = vk_descriptor_set_layout_bindings_.data();
if (use_descriptor_buffer) {
vk_descriptor_set_layout_create_info_.flags =
VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
}
const VKDevice &device = VKBackend::get().device;
VkDescriptorSetLayout vk_descriptor_set_layout = VK_NULL_HANDLE;
vkCreateDescriptorSetLayout(device.vk_handle(),
&vk_descriptor_set_layout_create_info_,
@@ -58,6 +63,12 @@ VkDescriptorSetLayout VKDescriptorSetLayouts::get_or_create(const VKDescriptorSe
vk_descriptor_set_layouts_.add(info, vk_descriptor_set_layout);
r_created = true;
if (use_descriptor_buffer) {
descriptor_buffer_layouts_.add(
vk_descriptor_set_layout,
create_descriptor_buffer_layout(device, info, vk_descriptor_set_layout));
}
return vk_descriptor_set_layout;
}
@@ -90,4 +101,32 @@ void VKDescriptorSetLayouts::deinit()
vk_descriptor_set_layouts_.clear();
}
static void align_size(VkDeviceSize &r_size, VkDeviceSize alignment)
{
if (alignment > 1) {
r_size = (r_size + alignment - 1) & ~(alignment - 1);
}
}
VKDescriptorBufferLayout VKDescriptorSetLayouts::create_descriptor_buffer_layout(
const VKDevice &device,
const VKDescriptorSetLayoutInfo &info,
VkDescriptorSetLayout vk_descriptor_set_layout) const
{
const VkPhysicalDeviceDescriptorBufferPropertiesEXT &properties =
device.physical_device_descriptor_buffer_properties_get();
VKDescriptorBufferLayout result = {};
device.functions.vkGetDescriptorSetLayoutSize(
device.vk_handle(), vk_descriptor_set_layout, &result.size);
align_size(result.size, properties.descriptorBufferOffsetAlignment);
result.binding_offsets.resize(info.bindings.size());
for (uint32_t binding : IndexRange(info.bindings.size())) {
device.functions.vkGetDescriptorSetLayoutBindingOffset(
device.vk_handle(), vk_descriptor_set_layout, binding, &result.binding_offsets[binding]);
}
return result;
}
} // namespace blender::gpu

View File

@@ -25,6 +25,9 @@
#include "vk_common.hh"
namespace blender::gpu {
class VKDevice;
/**
* Key of descriptor set layout
*
@@ -63,6 +66,25 @@ template<> struct DefaultHash<gpu::VKDescriptorSetLayoutInfo> {
} // namespace blender
namespace blender::gpu {
struct VKDescriptorBufferLayout {
/**
* Total size of the descriptor buffer.
*
* Size is aligned to
* VkPhysicalDeviceDescriptorBufferProperties.descriptorBufferOffsetAlignment.
*/
VkDeviceSize size;
/**
* Offsets of each binding inside the buffer.
*
* Offsets are aligned to
* VkPhysicalDeviceDescriptorBufferProperties.descriptorBufferOffsetAlignment.
*/
Vector<VkDeviceSize> binding_offsets;
};
/**
* Registries of descriptor set layouts.
*/
@@ -74,6 +96,7 @@ class VKDescriptorSetLayouts : NonCopyable {
* Map containing all created descriptor set layouts.
*/
Map<VKDescriptorSetLayoutInfo, VkDescriptorSetLayout> vk_descriptor_set_layouts_;
Map<VkDescriptorSetLayout, VKDescriptorBufferLayout> descriptor_buffer_layouts_;
/**
* Reusable descriptor set layout create info.
@@ -96,6 +119,23 @@ class VKDescriptorSetLayouts : NonCopyable {
bool &r_created,
bool &r_needed);
/**
* Return the descriptor buffer layout offsets and alignment for the given
* vk_descriptor_set_layout handle.
*
* A copy of the buffer layout is returned due to other threads can alter the location of the
* items.
*
* This function has undefined behavior when descriptor buffers extension isn't enabled on the
* VKDevice.
*/
VKDescriptorBufferLayout descriptor_buffer_layout_get(
VkDescriptorSetLayout vk_descriptor_set_layout)
{
std::scoped_lock lock(mutex_);
return descriptor_buffer_layouts_.lookup(vk_descriptor_set_layout);
}
/**
* Free all descriptor set layouts.
*
@@ -113,6 +153,10 @@ class VKDescriptorSetLayouts : NonCopyable {
private:
void update_layout_bindings(const VKDescriptorSetLayoutInfo &info);
VKDescriptorBufferLayout create_descriptor_buffer_layout(
const VKDevice &device,
const VKDescriptorSetLayoutInfo &info,
VkDescriptorSetLayout vk_descriptor_set_layout) const;
};
} // namespace blender::gpu

View File

@@ -39,6 +39,7 @@ void VKExtensions::log() const
" - [%c] shader output layer\n"
" - [%c] fragment shader barycentric\n"
"Device extensions\n"
" - [%c] descriptor buffer\n"
" - [%c] dynamic rendering\n"
" - [%c] dynamic rendering local read\n"
" - [%c] dynamic rendering unused attachments\n"
@@ -47,6 +48,7 @@ void VKExtensions::log() const
shader_output_viewport_index ? 'X' : ' ',
shader_output_layer ? 'X' : ' ',
fragment_shader_barycentric ? 'X' : ' ',
descriptor_buffer ? 'X' : ' ',
dynamic_rendering ? 'X' : ' ',
dynamic_rendering_local_read ? 'X' : ' ',
dynamic_rendering_unused_attachments ? 'X' : ' ',
@@ -126,10 +128,10 @@ void VKDevice::init(void *ghost_context)
vk_queue_ = handles.queue;
queue_mutex_ = static_cast<std::mutex *>(handles.queue_mutex);
init_physical_device_extensions();
init_physical_device_properties();
init_physical_device_memory_properties();
init_physical_device_features();
init_physical_device_extensions();
VKBackend::platform_init(*this);
VKBackend::capabilities_init(*this);
init_functions();
@@ -177,6 +179,14 @@ void VKDevice::init_functions()
#endif
}
/* VK_EXT_descriptor_buffer */
functions.vkGetDescriptorSetLayoutSize = LOAD_FUNCTION(vkGetDescriptorSetLayoutSizeEXT);
functions.vkGetDescriptorSetLayoutBindingOffset = LOAD_FUNCTION(
vkGetDescriptorSetLayoutBindingOffsetEXT);
functions.vkGetDescriptor = LOAD_FUNCTION(vkGetDescriptorEXT);
functions.vkCmdBindDescriptorBuffers = LOAD_FUNCTION(vkCmdBindDescriptorBuffersEXT);
functions.vkCmdSetDescriptorBufferOffsets = LOAD_FUNCTION(vkCmdSetDescriptorBufferOffsetsEXT);
#undef LOAD_FUNCTION
}
@@ -197,6 +207,15 @@ void VKDevice::init_physical_device_properties()
vk_physical_device_properties.pNext = &vk_physical_device_driver_properties_;
vk_physical_device_driver_properties_.pNext = &vk_physical_device_id_properties_;
if (supports_extension(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME)) {
vk_physical_device_descriptor_buffer_properties_ = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT};
vk_physical_device_descriptor_buffer_properties_.pNext =
vk_physical_device_driver_properties_.pNext;
vk_physical_device_driver_properties_.pNext =
&vk_physical_device_descriptor_buffer_properties_;
}
vkGetPhysicalDeviceProperties2(vk_physical_device_, &vk_physical_device_properties);
vk_physical_device_properties_ = vk_physical_device_properties.properties;
}
@@ -251,6 +270,9 @@ void VKDevice::init_memory_allocator()
info.physicalDevice = vk_physical_device_;
info.device = vk_device_;
info.instance = vk_instance_;
if (extensions_.descriptor_buffer) {
info.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
}
vmaCreateAllocator(&info, &mem_allocator_);
if (!extensions_.external_memory) {

View File

@@ -59,6 +59,11 @@ struct VKExtensions {
*/
bool external_memory = false;
/**
* Does the device support VK_EXT_descriptor_buffer.
*/
bool descriptor_buffer = false;
/**
* Does the device support logic ops.
*/
@@ -208,6 +213,8 @@ class VKDevice : public NonCopyable {
VkPhysicalDeviceDriverProperties vk_physical_device_driver_properties_ = {};
VkPhysicalDeviceIDProperties vk_physical_device_id_properties_ = {};
VkPhysicalDeviceMemoryProperties vk_physical_device_memory_properties_ = {};
VkPhysicalDeviceDescriptorBufferPropertiesEXT vk_physical_device_descriptor_buffer_properties_ =
{};
/** Features support. */
VkPhysicalDeviceFeatures vk_physical_device_features_ = {};
VkPhysicalDeviceVulkan11Features vk_physical_device_vulkan_11_features_ = {};
@@ -258,6 +265,14 @@ class VKDevice : public NonCopyable {
/* Extension: VK_KHR_external_memory_win32 */
PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32Handle = nullptr;
#endif
/* Extension: VK_EXT_descriptor_buffer */
PFN_vkGetDescriptorSetLayoutSizeEXT vkGetDescriptorSetLayoutSize = nullptr;
PFN_vkGetDescriptorSetLayoutBindingOffsetEXT vkGetDescriptorSetLayoutBindingOffset = nullptr;
PFN_vkGetDescriptorEXT vkGetDescriptor = nullptr;
PFN_vkCmdBindDescriptorBuffersEXT vkCmdBindDescriptorBuffers = nullptr;
PFN_vkCmdSetDescriptorBufferOffsetsEXT vkCmdSetDescriptorBufferOffsets = nullptr;
} functions;
struct {
@@ -288,6 +303,12 @@ class VKDevice : public NonCopyable {
return vk_physical_device_id_properties_;
}
inline const VkPhysicalDeviceDescriptorBufferPropertiesEXT &
physical_device_descriptor_buffer_properties_get() const
{
return vk_physical_device_descriptor_buffer_properties_;
}
const VkPhysicalDeviceFeatures &physical_device_features_get() const
{
return vk_physical_device_features_;
@@ -365,7 +386,7 @@ class VKDevice : public NonCopyable {
{
return workarounds_;
}
const VKExtensions &extensions_get() const
inline const VKExtensions &extensions_get() const
{
return extensions_;
}

View File

@@ -31,6 +31,10 @@ class VKIndexBuffer : public IndexBuf {
{
return buffer_get().vk_handle();
}
inline VkDeviceAddress device_address_get() const
{
return buffer_get().device_address_get();
}
VkIndexType vk_index_type() const
{
return to_vk_index_type(index_type_);

View File

@@ -202,6 +202,9 @@ VkPipeline VKPipelinePool::get_or_create_compute_pipeline(VKComputeInfo &compute
/* Build pipeline. */
VKBackend &backend = VKBackend::get();
VKDevice &device = backend.device;
if (device.extensions_get().descriptor_buffer) {
vk_compute_pipeline_create_info_.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
}
VkPipeline pipeline = VK_NULL_HANDLE;
vkCreateComputePipelines(device.vk_handle(),
@@ -214,6 +217,7 @@ VkPipeline VKPipelinePool::get_or_create_compute_pipeline(VKComputeInfo &compute
compute_pipelines_.add(compute_info, pipeline);
/* Reset values to initial value. */
vk_compute_pipeline_create_info_.flags = 0;
vk_compute_pipeline_create_info_.layout = VK_NULL_HANDLE;
vk_compute_pipeline_create_info_.stage.module = VK_NULL_HANDLE;
vk_compute_pipeline_create_info_.stage.pSpecializationInfo = nullptr;
@@ -586,6 +590,9 @@ VkPipeline VKPipelinePool::get_or_create_graphics_pipeline(VKGraphicsInfo &graph
/* Build pipeline. */
VKBackend &backend = VKBackend::get();
VKDevice &device = backend.device;
if (device.extensions_get().descriptor_buffer) {
vk_graphics_pipeline_create_info_.flags = VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
}
VkPipeline pipeline = VK_NULL_HANDLE;
vkCreateGraphicsPipelines(device.vk_handle(),
@@ -599,6 +606,7 @@ VkPipeline VKPipelinePool::get_or_create_graphics_pipeline(VKGraphicsInfo &graph
/* Reset values to initial value. */
specialization_info_reset();
vk_graphics_pipeline_create_info_.flags = 0;
vk_graphics_pipeline_create_info_.stageCount = 0;
vk_graphics_pipeline_create_info_.layout = VK_NULL_HANDLE;
vk_graphics_pipeline_create_info_.basePipelineHandle = VK_NULL_HANDLE;

View File

@@ -204,7 +204,7 @@ class BindSpaceTextures {
};
class VKStateManager : public StateManager {
friend class VKDescriptorSetTracker;
friend class VKDescriptorSetUpdator;
uint texture_unpack_row_length_ = 0;

View File

@@ -43,6 +43,10 @@ class VKStorageBuffer : public StorageBuf {
{
return buffer_.vk_handle();
}
inline VkDeviceAddress device_address_get() const
{
return buffer_.device_address_get();
}
int64_t size_in_bytes() const
{

View File

@@ -29,7 +29,7 @@ enum class VKImageViewFlags {
ENUM_OPERATORS(VKImageViewFlags, VKImageViewFlags::NO_SWIZZLING)
class VKTexture : public Texture {
friend class VKDescriptorSetTracker;
friend class VKDescriptorSetUpdator;
/**
* Texture format how the texture is stored on the device.

View File

@@ -42,6 +42,10 @@ class VKUniformBuffer : public UniformBuf, NonCopyable {
{
return buffer_.vk_handle();
}
inline VkDeviceAddress device_address_get() const
{
return buffer_.device_address_get();
}
size_t size_in_bytes() const
{

View File

@@ -48,11 +48,9 @@ void VKVertexBuffer::ensure_buffer_view()
}
VkBufferViewCreateInfo buffer_view_info = {};
eGPUTextureFormat texture_format = to_texture_format(&format);
buffer_view_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
buffer_view_info.buffer = buffer_.vk_handle();
buffer_view_info.format = to_vk_format(texture_format);
buffer_view_info.format = to_vk_format();
buffer_view_info.range = buffer_.size_in_bytes();
const VKDevice &device = VKBackend::get().device;

View File

@@ -11,6 +11,7 @@
#include "GPU_vertex_buffer.hh"
#include "vk_buffer.hh"
#include "vk_common.hh"
#include "vk_data_conversion.hh"
namespace blender::gpu {
@@ -38,6 +39,11 @@ class VKVertexBuffer : public VertBuf {
return buffer_.vk_handle();
}
inline VkDeviceAddress device_address_get() const
{
return buffer_.device_address_get();
}
VkBufferView vk_buffer_view_get() const
{
BLI_assert(vk_buffer_view_ != VK_NULL_HANDLE);
@@ -47,6 +53,11 @@ class VKVertexBuffer : public VertBuf {
void ensure_updated();
void ensure_buffer_view();
inline VkFormat to_vk_format()
{
return blender::gpu::to_vk_format(to_texture_format(&format));
}
protected:
void acquire_data() override;
void resize_data() override;