update parallel rdp

This commit is contained in:
Logan McNaughton
2024-08-25 16:51:49 +02:00
parent 80376fafd5
commit 4f239cbc7d
21 changed files with 49460 additions and 54257 deletions
+1 -1
View File
@@ -1 +1 @@
43bc31642cc70d04adb828a285e68cdbde7110a9
a2b0e8503ba525d70c61bccbe59c87d14daf89a6
@@ -716,7 +716,7 @@ static int normalize_dzpix(int dz)
else if (dz == 0)
return 1;
unsigned bit = 31 - leading_zeroes(dz);
unsigned bit = 31 - Util::leading_zeroes(dz);
return 1 << (bit + 1);
}
@@ -1680,7 +1680,7 @@ void Renderer::submit_span_setup_jobs(Vulkan::CommandBuffer &cmd, bool upscale)
cmd.set_buffer_view(1, 0, *instance.gpu.span_info_jobs_view);
cmd.set_specialization_constant_mask(3);
cmd.set_specialization_constant(0, (upscale ? caps.upscaling : 1) * ImplementationConstants::DefaultWorkgroupSize);
cmd.set_specialization_constant(1, upscale ? trailing_zeroes(caps.upscaling) : 0u);
cmd.set_specialization_constant(1, upscale ? Util::trailing_zeroes(caps.upscaling) : 0u);
Vulkan::QueryPoolHandle begin_ts, end_ts;
if (caps.timestamp >= 2)
@@ -1780,7 +1780,7 @@ void Renderer::submit_rasterization(Vulkan::CommandBuffer &cmd, Vulkan::Buffer &
if (caps.timestamp >= 2)
start_ts = cmd.write_timestamp(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
uint32_t scale_log2_bit = (upscaling ? trailing_zeroes(caps.upscaling) : 0u) << RASTERIZATION_UPSCALING_LOG2_BIT_OFFSET;
uint32_t scale_log2_bit = (upscaling ? Util::trailing_zeroes(caps.upscaling) : 0u) << RASTERIZATION_UPSCALING_LOG2_BIT_OFFSET;
for (size_t i = 0; i < stream.static_raster_state_cache.size(); i++)
{
@@ -1891,7 +1891,7 @@ void Renderer::submit_tile_binning_combined(Vulkan::CommandBuffer &cmd, bool ups
if (supports_subgroup_size_control(32, subgroup_size))
{
cmd.enable_subgroup_size_control(true);
cmd.set_subgroup_size_log2(true, 5, trailing_zeroes(subgroup_size));
cmd.set_subgroup_size_log2(true, 5, Util::trailing_zeroes(subgroup_size));
}
}
else
@@ -2092,7 +2092,7 @@ void Renderer::submit_depth_blend(Vulkan::CommandBuffer &cmd, Vulkan::Buffer &tm
cmd.set_specialization_constant(5, Limits::MaxPrimitives);
cmd.set_specialization_constant(6, upscaled ? caps.max_width : Limits::MaxWidth);
cmd.set_specialization_constant(7, uint32_t(force_write_mask || (!is_host_coherent && !upscaled)) |
((upscaled ? trailing_zeroes(caps.upscaling) : 0u) << 1u));
((upscaled ? Util::trailing_zeroes(caps.upscaling) : 0u) << 1u));
if (upscaled)
cmd.set_storage_buffer(0, 0, *upscaling_multisampled_rdram);
File diff suppressed because it is too large Load Diff
@@ -484,7 +484,7 @@ Vulkan::ImageHandle VideoInterface::vram_fetch_stage(const Registers &regs, unsi
async_cmd->set_specialization_constant_mask(7);
async_cmd->set_specialization_constant(0, uint32_t(rdram_size));
async_cmd->set_specialization_constant(1, regs.status & (VI_CONTROL_TYPE_MASK | VI_CONTROL_META_AA_BIT));
async_cmd->set_specialization_constant(2, trailing_zeroes(scaling_factor));
async_cmd->set_specialization_constant(2, Util::trailing_zeroes(scaling_factor));
async_cmd->push_constants(&push, 0, sizeof(push));
async_cmd->dispatch((extract_width + 15) / 16,
@@ -40,14 +40,18 @@ struct AlignedAllocation
static void *operator new(size_t size)
{
void *ret = ::Util::memalign_alloc(alignof(T), size);
#ifdef __EXCEPTIONS
if (!ret) throw std::bad_alloc();
#endif
return ret;
}
static void *operator new[](size_t size)
{
void *ret = ::Util::memalign_alloc(alignof(T), size);
#ifdef __EXCEPTIONS
if (!ret) throw std::bad_alloc();
#endif
return ret;
}
+23 -14
View File
@@ -29,13 +29,22 @@
namespace Util
{
#ifdef __GNUC__
#define leading_zeroes(x) ((x) == 0 ? 32 : __builtin_clz(x))
#define trailing_zeroes(x) ((x) == 0 ? 32 : __builtin_ctz(x))
#define trailing_ones(x) __builtin_ctz(~uint32_t(x))
#define leading_zeroes64(x) ((x) == 0 ? 64 : __builtin_clzll(x))
#define trailing_zeroes64(x) ((x) == 0 ? 64 : __builtin_ctzll(x))
#define trailing_ones64(x) __builtin_ctzll(~uint64_t(x))
#define popcount32(x) __builtin_popcount(x)
#define leading_zeroes_(x) ((x) == 0 ? 32 : __builtin_clz(x))
#define trailing_zeroes_(x) ((x) == 0 ? 32 : __builtin_ctz(x))
#define trailing_ones_(x) __builtin_ctz(~uint32_t(x))
#define leading_zeroes64_(x) ((x) == 0 ? 64 : __builtin_clzll(x))
#define trailing_zeroes64_(x) ((x) == 0 ? 64 : __builtin_ctzll(x))
#define trailing_ones64_(x) __builtin_ctzll(~uint64_t(x))
#define popcount32_(x) __builtin_popcount(x)
static inline uint32_t leading_zeroes(uint32_t x) { return leading_zeroes_(x); }
static inline uint32_t trailing_zeroes(uint32_t x) { return trailing_zeroes_(x); }
static inline uint32_t trailing_ones(uint32_t x) { return trailing_ones_(x); }
static inline uint32_t leading_zeroes64(uint64_t x) { return leading_zeroes64_(x); }
static inline uint32_t trailing_zeroes64(uint64_t x) { return trailing_zeroes64_(x); }
static inline uint32_t trailing_ones64(uint64_t x) { return trailing_ones64_(x); }
static inline uint32_t popcount32(uint32_t x) { return popcount32_(x); }
#elif defined(_MSC_VER)
namespace Internal
{
@@ -81,13 +90,13 @@ static inline uint32_t ctz64(uint64_t x)
}
}
#define popcount32(x) ::Util::Internal::popcount32(x)
#define leading_zeroes(x) ::Util::Internal::clz(x)
#define trailing_zeroes(x) ::Util::Internal::ctz(x)
#define trailing_ones(x) ::Util::Internal::ctz(~uint32_t(x))
#define leading_zeroes64(x) ::Util::Internal::clz64(x)
#define trailing_zeroes64(x) ::Util::Internal::ctz64(x)
#define trailing_ones64(x) ::Util::Internal::ctz64(~uint64_t(x))
static inline uint32_t leading_zeroes(uint32_t x) { return Internal::clz(x); }
static inline uint32_t trailing_zeroes(uint32_t x) { return Internal::ctz(x); }
static inline uint32_t trailing_ones(uint32_t x) { return Internal::ctz(~x); }
static inline uint32_t leading_zeroes64(uint64_t x) { return Internal::clz64(x); }
static inline uint32_t trailing_zeroes64(uint64_t x) { return Internal::ctz64(x); }
static inline uint32_t trailing_ones64(uint64_t x) { return Internal::ctz64(~x); }
static inline uint32_t popcount32(uint32_t x) { return Internal::popcount32(x); }
#else
#error "Implement me."
#endif
+2 -2
View File
@@ -107,7 +107,7 @@ int64_t get_current_time_nsecs()
return int64_t(double(li.QuadPart) * static_qpc_freq.inv_freq);
#else
struct timespec ts = {};
#ifdef ANDROID
#if defined(ANDROID) || defined(__FreeBSD__)
constexpr auto timebase = CLOCK_MONOTONIC;
#else
constexpr auto timebase = CLOCK_MONOTONIC_RAW;
@@ -128,4 +128,4 @@ double Timer::end()
auto nt = get_current_time_nsecs();
return double(nt - t) * 1e-9;
}
}
}
+220 -151
View File
@@ -767,7 +767,7 @@ void CommandBuffer::blit_image(const Image &dst, const Image &src,
void CommandBuffer::begin_context()
{
dirty = ~0u;
dirty_sets = ~0u;
dirty_sets_realloc = ~0u;
dirty_vbos = ~0u;
current_pipeline = {};
current_pipeline_layout = VK_NULL_HANDLE;
@@ -1291,9 +1291,9 @@ Pipeline CommandBuffer::build_graphics_pipeline(Device *device, const DeferredPi
// Depth state
VkPipelineDepthStencilStateCreateInfo ds = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
ds.stencilTestEnable = compile.compatible_render_pass->has_stencil(compile.subpass_index) && compile.static_state.state.stencil_test;
ds.depthTestEnable = compile.compatible_render_pass->has_depth(compile.subpass_index) && compile.static_state.state.depth_test;
ds.depthWriteEnable = compile.compatible_render_pass->has_depth(compile.subpass_index) && compile.static_state.state.depth_write;
ds.stencilTestEnable = compile.compatible_render_pass->has_stencil(compile.subpass_index) && compile.static_state.state.stencil_test != 0;
ds.depthTestEnable = compile.compatible_render_pass->has_depth(compile.subpass_index) && compile.static_state.state.depth_test != 0;
ds.depthWriteEnable = compile.compatible_render_pass->has_depth(compile.subpass_index) && compile.static_state.state.depth_write != 0;
if (ds.depthTestEnable)
ds.depthCompareOp = static_cast<VkCompareOp>(compile.static_state.state.depth_compare);
@@ -1391,7 +1391,7 @@ Pipeline CommandBuffer::build_graphics_pipeline(Device *device, const DeferredPi
VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_size_info_task;
VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_size_info_mesh;
for (unsigned i = 0; i < Util::ecast(ShaderStage::Count); i++)
for (int i = 0; i < Util::ecast(ShaderStage::Count); i++)
{
auto mask = compile.layout->get_resource_layout().spec_constant_mask[i] &
get_combined_spec_constant_mask(compile);
@@ -1414,7 +1414,7 @@ Pipeline CommandBuffer::build_graphics_pipeline(Device *device, const DeferredPi
}
}
for (unsigned i = 0; i < Util::ecast(ShaderStage::Count); i++)
for (int i = 0; i < Util::ecast(ShaderStage::Count); i++)
{
auto stage = static_cast<ShaderStage>(i);
if (compile.program->get_shader(stage))
@@ -2089,7 +2089,7 @@ void CommandBuffer::set_program_layout(const PipelineLayout *layout)
VK_ASSERT(layout);
if (!pipeline_state.layout)
{
dirty_sets = ~0u;
dirty_sets_realloc = ~0u;
set_dirty(COMMAND_BUFFER_DIRTY_PUSH_CONSTANTS_BIT);
}
else if (layout->get_hash() != pipeline_state.layout->get_hash())
@@ -2097,11 +2097,20 @@ void CommandBuffer::set_program_layout(const PipelineLayout *layout)
auto &new_layout = layout->get_resource_layout();
auto &old_layout = pipeline_state.layout->get_resource_layout();
uint32_t first_invalidated_set_index = VULKAN_NUM_DESCRIPTOR_SETS;
uint32_t new_push_set = layout->get_push_set_index();
uint32_t old_push_set = pipeline_state.layout->get_push_set_index();
if (new_push_set == old_push_set)
{
new_push_set = UINT32_MAX;
old_push_set = UINT32_MAX;
}
// If the push constant layout changes, all descriptor sets
// are invalidated.
if (new_layout.push_constant_layout_hash != old_layout.push_constant_layout_hash)
{
dirty_sets = ~0u;
first_invalidated_set_index = 0;
set_dirty(COMMAND_BUFFER_DIRTY_PUSH_CONSTANTS_BIT);
}
else
@@ -2109,13 +2118,28 @@ void CommandBuffer::set_program_layout(const PipelineLayout *layout)
// Find the first set whose descriptor set layout differs.
for (unsigned set = 0; set < VULKAN_NUM_DESCRIPTOR_SETS; set++)
{
if (layout->get_allocator(set) != pipeline_state.layout->get_allocator(set))
if (layout->get_allocator(set) != pipeline_state.layout->get_allocator(set) ||
set == new_push_set || set == old_push_set)
{
dirty_sets |= ~((1u << set) - 1);
first_invalidated_set_index = set;
break;
}
}
}
if (first_invalidated_set_index < VULKAN_NUM_DESCRIPTOR_SETS)
{
dirty_sets_rebind |= ~((1u << first_invalidated_set_index) - 1u);
for (unsigned set = first_invalidated_set_index; set < VULKAN_NUM_DESCRIPTOR_SETS; set++)
{
if (layout->get_allocator(set) != pipeline_state.layout->get_allocator(set) ||
set == new_push_set || set == old_push_set)
{
dirty_sets_realloc |= 1u << set;
}
}
}
}
pipeline_state.layout = layout;
@@ -2241,21 +2265,21 @@ void CommandBuffer::set_uniform_buffer(unsigned set, unsigned binding, const Buf
VK_ASSERT(buffer.get_create_info().usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
auto &b = bindings.bindings[set][binding];
if (buffer.get_cookie() == bindings.cookies[set][binding] && b.buffer.range == range)
if (buffer.get_cookie() == bindings.cookies[set][binding] && b.buffer.dynamic.range == range)
{
if (b.dynamic_offset != offset)
if (b.buffer.push.offset != offset)
{
dirty_sets_dynamic |= 1u << set;
b.dynamic_offset = offset;
dirty_sets_rebind |= 1u << set;
b.buffer.push.offset = offset;
}
}
else
{
b.buffer = { buffer.get_buffer(), 0, range };
b.dynamic_offset = offset;
b.buffer.dynamic = { buffer.get_buffer(), 0, range };
b.buffer.push = { buffer.get_buffer(), offset, range };
bindings.cookies[set][binding] = buffer.get_cookie();
bindings.secondary_cookies[set][binding] = 0;
dirty_sets |= 1u << set;
dirty_sets_realloc |= 1u << set;
}
}
@@ -2267,14 +2291,14 @@ void CommandBuffer::set_storage_buffer(unsigned set, unsigned binding, const Buf
VK_ASSERT(buffer.get_create_info().usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
auto &b = bindings.bindings[set][binding];
if (buffer.get_cookie() == bindings.cookies[set][binding] && b.buffer.offset == offset && b.buffer.range == range)
if (buffer.get_cookie() == bindings.cookies[set][binding] && b.buffer.dynamic.offset == offset && b.buffer.dynamic.range == range)
return;
b.buffer = { buffer.get_buffer(), offset, range };
b.dynamic_offset = 0;
b.buffer.dynamic = { buffer.get_buffer(), offset, range };
b.buffer.push = b.buffer.dynamic;
bindings.cookies[set][binding] = buffer.get_cookie();
bindings.secondary_cookies[set][binding] = 0;
dirty_sets |= 1u << set;
dirty_sets_realloc |= 1u << set;
}
void CommandBuffer::set_uniform_buffer(unsigned set, unsigned binding, const Buffer &buffer)
@@ -2297,7 +2321,7 @@ void CommandBuffer::set_sampler(unsigned set, unsigned binding, const Sampler &s
auto &b = bindings.bindings[set][binding];
b.image.fp.sampler = sampler.get_sampler();
b.image.integer.sampler = sampler.get_sampler();
dirty_sets |= 1u << set;
dirty_sets_realloc |= 1u << set;
bindings.secondary_cookies[set][binding] = sampler.get_cookie();
}
@@ -2311,7 +2335,7 @@ void CommandBuffer::set_buffer_view_common(unsigned set, unsigned binding, const
b.buffer_view = view.get_view();
bindings.cookies[set][binding] = view.get_cookie();
bindings.secondary_cookies[set][binding] = 0;
dirty_sets |= 1u << set;
dirty_sets_realloc |= 1u << set;
}
void CommandBuffer::set_buffer_view(unsigned set, unsigned binding, const BufferView &view)
@@ -2353,7 +2377,7 @@ void CommandBuffer::set_input_attachments(unsigned set, unsigned start_binding)
b.image.fp.imageView = view->get_float_view();
b.image.integer.imageView = view->get_integer_view();
bindings.cookies[set][start_binding + i] = view->get_cookie();
dirty_sets |= 1u << set;
dirty_sets_realloc |= 1u << set;
}
}
@@ -2374,14 +2398,14 @@ void CommandBuffer::set_texture(unsigned set, unsigned binding,
b.image.integer.imageLayout = layout;
b.image.integer.imageView = integer_view;
bindings.cookies[set][binding] = cookie;
dirty_sets |= 1u << set;
dirty_sets_realloc |= 1u << set;
}
void CommandBuffer::set_bindless(unsigned set, VkDescriptorSet desc_set)
{
VK_ASSERT(set < VULKAN_NUM_DESCRIPTOR_SETS);
bindless_sets[set] = desc_set;
dirty_sets |= 1u << set;
dirty_sets_realloc |= 1u << set;
}
void CommandBuffer::set_texture(unsigned set, unsigned binding, const ImageView &view)
@@ -2452,180 +2476,225 @@ void CommandBuffer::set_unorm_storage_texture(unsigned set, unsigned binding, co
view.get_image().get_layout(VK_IMAGE_LAYOUT_GENERAL), view.get_cookie() | COOKIE_BIT_UNORM);
}
void CommandBuffer::rebind_descriptor_set(uint32_t set)
void CommandBuffer::flush_descriptor_binds(const VkDescriptorSet *sets,
uint32_t &first_set, uint32_t &set_count,
uint32_t *dynamic_offsets, uint32_t &num_dynamic_offsets)
{
auto &layout = pipeline_state.layout->get_resource_layout();
if (layout.bindless_descriptor_set_mask & (1u << set))
{
VK_ASSERT(bindless_sets[set]);
table.vkCmdBindDescriptorSets(cmd, actual_render_pass ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE,
current_pipeline_layout, set, 1, &bindless_sets[set], 0, nullptr);
if (!set_count)
return;
}
auto &set_layout = layout.sets[set];
uint32_t num_dynamic_offsets = 0;
uint32_t dynamic_offsets[VULKAN_NUM_BINDINGS];
table.vkCmdBindDescriptorSets(
cmd, actual_render_pass ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE,
current_pipeline_layout, first_set, set_count, sets, num_dynamic_offsets, dynamic_offsets);
// UBOs
for_each_bit(set_layout.uniform_buffer_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
{
VK_ASSERT(num_dynamic_offsets < VULKAN_NUM_BINDINGS);
dynamic_offsets[num_dynamic_offsets++] = bindings.bindings[set][binding + i].dynamic_offset;
}
});
table.vkCmdBindDescriptorSets(cmd, actual_render_pass ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE,
current_pipeline_layout, set, 1, &allocated_sets[set], num_dynamic_offsets, dynamic_offsets);
set_count = 0;
num_dynamic_offsets = 0;
}
void CommandBuffer::flush_descriptor_set(uint32_t set)
void CommandBuffer::rebind_descriptor_set(uint32_t set, VkDescriptorSet *sets, uint32_t &first_set, uint32_t &set_count,
uint32_t *dynamic_offsets, uint32_t &num_dynamic_offsets)
{
if (set_count == 0)
first_set = set;
else if (first_set + set_count != set)
{
flush_descriptor_binds(sets, first_set, set_count, dynamic_offsets, num_dynamic_offsets);
first_set = set;
}
auto &layout = pipeline_state.layout->get_resource_layout();
if (layout.bindless_descriptor_set_mask & (1u << set))
{
VK_ASSERT(bindless_sets[set]);
table.vkCmdBindDescriptorSets(cmd, actual_render_pass ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE,
current_pipeline_layout, set, 1, &bindless_sets[set], 0, nullptr);
sets[set_count++] = bindless_sets[set];
return;
}
auto &set_layout = layout.sets[set];
uint32_t num_dynamic_offsets = 0;
uint32_t dynamic_offsets[VULKAN_NUM_BINDINGS];
Hasher h;
h.u32(set_layout.fp_mask);
// UBOs
for_each_bit(set_layout.uniform_buffer_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
{
h.u64(bindings.cookies[set][binding + i]);
h.u32(bindings.bindings[set][binding + i].buffer.range);
VK_ASSERT(bindings.bindings[set][binding + i].buffer.buffer != VK_NULL_HANDLE);
VK_ASSERT(num_dynamic_offsets < VULKAN_NUM_BINDINGS);
dynamic_offsets[num_dynamic_offsets++] = bindings.bindings[set][binding + i].dynamic_offset;
VK_ASSERT(num_dynamic_offsets < VULKAN_NUM_DYNAMIC_UBOS);
dynamic_offsets[num_dynamic_offsets++] = bindings.bindings[set][binding + i].buffer.push.offset;
}
});
sets[set_count++] = allocated_sets[set];
}
void CommandBuffer::validate_descriptor_binds(uint32_t set)
{
#ifdef VULKAN_DEBUG
auto &layout = pipeline_state.layout->get_resource_layout();
auto &set_layout = layout.sets[set];
for_each_bit(set_layout.uniform_buffer_mask,
[&](uint32_t binding)
{
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
VK_ASSERT(bindings.bindings[set][binding + i].buffer.dynamic.buffer != VK_NULL_HANDLE);
});
// SSBOs
for_each_bit(set_layout.storage_buffer_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
{
h.u64(bindings.cookies[set][binding + i]);
h.u32(bindings.bindings[set][binding + i].buffer.offset);
h.u32(bindings.bindings[set][binding + i].buffer.range);
VK_ASSERT(bindings.bindings[set][binding + i].buffer.buffer != VK_NULL_HANDLE);
}
});
for_each_bit(set_layout.storage_buffer_mask,
[&](uint32_t binding)
{
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
VK_ASSERT(bindings.bindings[set][binding + i].buffer.dynamic.buffer != VK_NULL_HANDLE);
});
// Texel buffers
for_each_bit(set_layout.sampled_texel_buffer_mask | set_layout.storage_texel_buffer_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
{
h.u64(bindings.cookies[set][binding + i]);
VK_ASSERT(bindings.bindings[set][binding + i].buffer_view != VK_NULL_HANDLE);
}
});
for_each_bit(set_layout.sampled_texel_buffer_mask | set_layout.storage_texel_buffer_mask,
[&](uint32_t binding)
{
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
VK_ASSERT(bindings.bindings[set][binding + i].buffer_view != VK_NULL_HANDLE);
});
// Sampled images
for_each_bit(set_layout.sampled_image_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
{
h.u64(bindings.cookies[set][binding + i]);
if ((set_layout.immutable_sampler_mask & (1u << (binding + i))) == 0)
{
h.u64(bindings.secondary_cookies[set][binding + i]);
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.sampler != VK_NULL_HANDLE);
}
h.u32(bindings.bindings[set][binding + i].image.fp.imageLayout);
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE);
}
});
for_each_bit(set_layout.sampled_image_mask,
[&](uint32_t binding)
{
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
{
if ((set_layout.immutable_sampler_mask & (1u << (binding + i))) == 0)
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.sampler != VK_NULL_HANDLE);
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE);
}
});
// Separate images
for_each_bit(set_layout.separate_image_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
{
h.u64(bindings.cookies[set][binding + i]);
h.u32(bindings.bindings[set][binding + i].image.fp.imageLayout);
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE);
}
});
for_each_bit(set_layout.separate_image_mask,
[&](uint32_t binding)
{
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE);
});
// Separate samplers
for_each_bit(set_layout.sampler_mask & ~set_layout.immutable_sampler_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
{
h.u64(bindings.secondary_cookies[set][binding + i]);
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.sampler != VK_NULL_HANDLE);
}
});
for_each_bit(set_layout.sampler_mask & ~set_layout.immutable_sampler_mask,
[&](uint32_t binding)
{
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.sampler != VK_NULL_HANDLE);
});
// Storage images
for_each_bit(set_layout.storage_image_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
{
h.u64(bindings.cookies[set][binding + i]);
h.u32(bindings.bindings[set][binding + i].image.fp.imageLayout);
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE);
}
});
for_each_bit(set_layout.storage_image_mask,
[&](uint32_t binding)
{
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE);
});
// Input attachments
for_each_bit(set_layout.input_attachment_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
{
h.u64(bindings.cookies[set][binding + i]);
h.u32(bindings.bindings[set][binding + i].image.fp.imageLayout);
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE);
}
});
for_each_bit(set_layout.input_attachment_mask,
[&](uint32_t binding)
{
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
VK_ASSERT(bindings.bindings[set][binding + i].image.fp.imageView != VK_NULL_HANDLE);
});
#else
(void)set;
#endif
}
Hash hash = h.get();
auto allocated = pipeline_state.layout->get_allocator(set)->find(thread_index, hash);
void CommandBuffer::push_descriptor_set(uint32_t set)
{
#ifdef VULKAN_DEBUG
validate_descriptor_binds(set);
#endif
// The descriptor set was not successfully cached, rebuild.
if (!allocated.second)
VkDescriptorUpdateTemplate update_template = pipeline_state.layout->get_update_template(set);
VK_ASSERT(update_template);
table.vkCmdPushDescriptorSetWithTemplateKHR(
cmd, update_template,
pipeline_state.layout->get_layout(), set, bindings.bindings[set]);
}
void CommandBuffer::flush_descriptor_set(uint32_t set, VkDescriptorSet *sets,
uint32_t &first_set, uint32_t &set_count,
uint32_t *dynamic_offsets, uint32_t &num_dynamic_offsets)
{
if (set_count == 0)
first_set = set;
else if (first_set + set_count != set)
{
auto update_template = pipeline_state.layout->get_update_template(set);
VK_ASSERT(update_template);
table.vkUpdateDescriptorSetWithTemplate(device->get_device(), allocated.first,
update_template, bindings.bindings[set]);
flush_descriptor_binds(sets, first_set, set_count, dynamic_offsets, num_dynamic_offsets);
first_set = set;
}
table.vkCmdBindDescriptorSets(cmd, actual_render_pass ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE,
current_pipeline_layout, set, 1, &allocated.first, num_dynamic_offsets, dynamic_offsets);
allocated_sets[set] = allocated.first;
auto &layout = pipeline_state.layout->get_resource_layout();
if (layout.bindless_descriptor_set_mask & (1u << set))
{
VK_ASSERT(bindless_sets[set]);
sets[set_count++] = bindless_sets[set];
return;
}
auto &set_layout = layout.sets[set];
#ifdef VULKAN_DEBUG
validate_descriptor_binds(set);
#endif
// UBOs
for_each_bit(set_layout.uniform_buffer_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
for (unsigned i = 0; i < array_size; i++)
dynamic_offsets[num_dynamic_offsets++] = bindings.bindings[set][binding + i].buffer.push.offset;
});
auto vk_set = pipeline_state.layout->get_allocator(set)->request_descriptor_set(thread_index, device->frame_context_index);
VkDescriptorUpdateTemplate update_template = pipeline_state.layout->get_update_template(set);
VK_ASSERT(update_template);
table.vkUpdateDescriptorSetWithTemplate(device->get_device(), vk_set, update_template, bindings.bindings[set]);
sets[set_count++] = vk_set;
allocated_sets[set] = vk_set;
}
void CommandBuffer::flush_descriptor_sets()
{
auto &layout = pipeline_state.layout->get_resource_layout();
uint32_t set_update = layout.descriptor_set_mask & dirty_sets;
for_each_bit(set_update, [&](uint32_t set) { flush_descriptor_set(set); });
dirty_sets &= ~set_update;
uint32_t first_set = 0;
uint32_t set_count = 0;
VkDescriptorSet sets[VULKAN_NUM_DESCRIPTOR_SETS];
uint32_t dynamic_offsets[VULKAN_NUM_DYNAMIC_UBOS];
uint32_t num_dynamic_offsets = 0;
// If we update a set, we also bind dynamically.
dirty_sets_dynamic &= ~set_update;
dirty_sets_rebind |= dirty_sets_realloc;
uint32_t set_update_mask = layout.descriptor_set_mask & dirty_sets_rebind;
// If we only rebound UBOs, we might get away with just rebinding descriptor sets, no hashing and lookup required.
uint32_t dynamic_set_update = layout.descriptor_set_mask & dirty_sets_dynamic;
for_each_bit(dynamic_set_update, [&](uint32_t set) { rebind_descriptor_set(set); });
dirty_sets_dynamic &= ~dynamic_set_update;
uint32_t push_set_index = pipeline_state.layout->get_push_set_index();
if (push_set_index != UINT32_MAX && (dirty_sets_rebind & (1u << push_set_index)) != 0)
{
push_descriptor_set(push_set_index);
set_update_mask &= ~(1u << push_set_index);
}
for_each_bit(set_update_mask, [&](uint32_t set) {
if ((dirty_sets_realloc & (1u << set)) != 0)
flush_descriptor_set(set, sets, first_set, set_count, dynamic_offsets, num_dynamic_offsets);
else
rebind_descriptor_set(set, sets, first_set, set_count, dynamic_offsets, num_dynamic_offsets);
});
dirty_sets_realloc = 0;
dirty_sets_rebind = 0;
flush_descriptor_binds(sets, first_set, set_count, dynamic_offsets, num_dynamic_offsets);
}
void CommandBuffer::draw(uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance)
@@ -2967,7 +3036,7 @@ void CommandBuffer::restore_state(const CommandBufferSavedState &state)
memcpy(bindings.bindings[i], state.bindings.bindings[i], sizeof(bindings.bindings[i]));
memcpy(bindings.cookies[i], state.bindings.cookies[i], sizeof(bindings.cookies[i]));
memcpy(bindings.secondary_cookies[i], state.bindings.secondary_cookies[i], sizeof(bindings.secondary_cookies[i]));
dirty_sets |= 1u << i;
dirty_sets_realloc |= 1u << i;
}
}
}
@@ -846,8 +846,8 @@ private:
VkRect2D scissor = {};
CommandBufferDirtyFlags dirty = ~0u;
uint32_t dirty_sets = 0;
uint32_t dirty_sets_dynamic = 0;
uint32_t dirty_sets_realloc = 0;
uint32_t dirty_sets_rebind = 0;
uint32_t dirty_vbos = 0;
uint32_t active_vbos = 0;
VkPipelineStageFlags2 uses_swapchain_in_stages = 0;
@@ -883,8 +883,20 @@ private:
bool flush_compute_pipeline(bool synchronous);
void flush_descriptor_sets();
void begin_graphics();
void flush_descriptor_set(uint32_t set);
void rebind_descriptor_set(uint32_t set);
void flush_descriptor_set(
uint32_t set, VkDescriptorSet *sets,
uint32_t &first_set, uint32_t &set_count,
uint32_t *dynamic_offsets, uint32_t &num_dynamic_offsets);
void push_descriptor_set(uint32_t set);
void rebind_descriptor_set(
uint32_t set, VkDescriptorSet *sets,
uint32_t &first_set, uint32_t &set_count,
uint32_t *dynamic_offsets, uint32_t &num_dynamic_offsets);
void flush_descriptor_binds(const VkDescriptorSet *sets,
uint32_t &first_set, uint32_t &set_count,
uint32_t *dynamic_offsets, uint32_t &num_dynamic_offsets);
void validate_descriptor_binds(uint32_t set);
void begin_compute();
void begin_context();
+56 -15
View File
@@ -203,10 +203,10 @@ PFN_vkGetInstanceProcAddr Context::get_instance_proc_addr()
return instance_proc_addr;
}
bool Context::init_loader(PFN_vkGetInstanceProcAddr addr)
bool Context::init_loader(PFN_vkGetInstanceProcAddr addr, bool force_reload)
{
std::lock_guard<std::mutex> holder(loader_init_lock);
if (loader_init_once && !addr)
if (loader_init_once && !force_reload && !addr)
return true;
if (!addr)
@@ -608,12 +608,6 @@ bool Context::create_instance(const char * const *instance_ext, uint32_t instanc
ext.supports_surface_capabilities2 = true;
}
if (ext.supports_surface_capabilities2 && has_extension(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME))
{
instance_exts.push_back(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME);
ext.supports_surface_maintenance1 = true;
}
if ((flags & CONTEXT_CREATION_ENABLE_ADVANCED_WSI_BIT) != 0 &&
has_surface_extension &&
has_extension(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME))
@@ -630,8 +624,6 @@ bool Context::create_instance(const char * const *instance_ext, uint32_t instanc
return layer_itr != end(queried_layers);
};
VkValidationFeaturesEXT validation_features = { VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT };
force_no_validation = Util::get_environment_bool("GRANITE_VULKAN_NO_VALIDATION", false);
if (!force_no_validation && has_layer("VK_LAYER_KHRONOS_validation"))
@@ -644,6 +636,10 @@ bool Context::create_instance(const char * const *instance_ext, uint32_t instanc
std::vector<VkExtensionProperties> layer_exts(layer_ext_count);
vkEnumerateInstanceExtensionProperties("VK_LAYER_KHRONOS_validation", &layer_ext_count, layer_exts.data());
#if 0
VkValidationFeaturesEXT validation_features = { VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT };
// Tons of false positives around timeline semaphores atm, so don't bother.
if (find_if(begin(layer_exts), end(layer_exts), [](const VkExtensionProperties &e) {
return strcmp(e.extensionName, VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME) == 0;
}) != end(layer_exts))
@@ -657,6 +653,7 @@ bool Context::create_instance(const char * const *instance_ext, uint32_t instanc
validation_features.pEnabledValidationFeatures = validation_sync_features;
info.pNext = &validation_features;
}
#endif
if (!ext.supports_debug_utils &&
find_if(begin(layer_exts), end(layer_exts), [](const VkExtensionProperties &e) {
@@ -669,6 +666,22 @@ bool Context::create_instance(const char * const *instance_ext, uint32_t instanc
}
#endif
if (ext.supports_surface_capabilities2 && has_extension(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME))
{
#ifdef VULKAN_DEBUG
// It seems like there are some bugs with EXT_swapchain_maint1 in VVL atm.
const bool support_maint1 = force_no_validation;
#else
constexpr bool support_maint1 = true;
#endif
if (support_maint1)
{
instance_exts.push_back(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME);
ext.supports_surface_maintenance1 = true;
}
}
info.enabledExtensionCount = instance_exts.size();
info.ppEnabledExtensionNames = instance_exts.empty() ? nullptr : instance_exts.data();
info.enabledLayerCount = instance_layers.size();
@@ -1302,7 +1315,14 @@ bool Context::create_device(VkPhysicalDevice gpu_, VkSurfaceKHR surface,
ADD_CHAIN(ext.storage_8bit_features, 8BIT_STORAGE_FEATURES_KHR);
enabled_extensions.push_back(VK_KHR_8BIT_STORAGE_EXTENSION_NAME);
}
}
if (ext.device_api_core_version >= VK_API_VERSION_1_3)
{
ADD_CHAIN(ext.vk13_features, VULKAN_1_3_FEATURES);
}
else
{
if (has_extension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME))
{
ADD_CHAIN(ext.subgroup_size_control_features, SUBGROUP_SIZE_CONTROL_FEATURES_EXT);
@@ -1310,9 +1330,6 @@ bool Context::create_device(VkPhysicalDevice gpu_, VkSurfaceKHR surface,
}
}
if (ext.device_api_core_version >= VK_API_VERSION_1_3)
ADD_CHAIN(ext.vk13_features, VULKAN_1_3_FEATURES);
if (has_extension(VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME))
{
enabled_extensions.push_back(VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME);
@@ -1362,6 +1379,12 @@ bool Context::create_device(VkPhysicalDevice gpu_, VkSurfaceKHR surface,
ADD_CHAIN(ext.device_generated_commands_compute_features, DEVICE_GENERATED_COMMANDS_COMPUTE_FEATURES_NV);
}
if (has_extension(VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME))
{
enabled_extensions.push_back(VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME);
ADD_CHAIN(ext.descriptor_pool_overallocation_features, DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV);
}
if (has_extension(VK_EXT_MESH_SHADER_EXTENSION_NAME))
{
enabled_extensions.push_back(VK_EXT_MESH_SHADER_EXTENSION_NAME);
@@ -1374,6 +1397,12 @@ bool Context::create_device(VkPhysicalDevice gpu_, VkSurfaceKHR surface,
ADD_CHAIN(ext.index_type_uint8_features, INDEX_TYPE_UINT8_FEATURES_EXT);
}
if (has_extension(VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME))
{
enabled_extensions.push_back(VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME);
ADD_CHAIN(ext.rgba10x6_formats_features, RGBA10X6_FORMATS_FEATURES_EXT);
}
if (has_extension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME))
{
ext.supports_external_memory_host = true;
@@ -1398,6 +1427,18 @@ bool Context::create_device(VkPhysicalDevice gpu_, VkSurfaceKHR surface,
ext.supports_push_descriptor = true;
}
if (has_extension(VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME))
{
enabled_extensions.push_back(VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME);
ADD_CHAIN(ext.image_compression_control_features, IMAGE_COMPRESSION_CONTROL_FEATURES_EXT);
}
if (has_extension(VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME))
{
enabled_extensions.push_back(VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME);
ADD_CHAIN(ext.image_compression_control_swapchain_features, IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT);
}
if (ext.device_api_core_version >= VK_API_VERSION_1_3)
{
ext.supports_store_op_none = true;
@@ -1581,14 +1622,14 @@ bool Context::create_device(VkPhysicalDevice gpu_, VkSurfaceKHR surface,
{
if (has_extension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME))
ADD_CHAIN(driver_properties, DRIVER_PROPERTIES);
if (has_extension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME))
ADD_CHAIN(size_control_props, SUBGROUP_SIZE_CONTROL_PROPERTIES);
ADD_CHAIN(id_properties, ID_PROPERTIES);
ADD_CHAIN(subgroup_properties, SUBGROUP_PROPERTIES);
}
if (ext.device_api_core_version >= VK_API_VERSION_1_3)
ADD_CHAIN(ext.vk13_props, VULKAN_1_3_PROPERTIES);
else if (has_extension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME))
ADD_CHAIN(size_control_props, SUBGROUP_SIZE_CONTROL_PROPERTIES);
if (ext.supports_external_memory_host)
ADD_CHAIN(ext.host_memory_properties, EXTERNAL_MEMORY_HOST_PROPERTIES_EXT);
+5 -1
View File
@@ -100,12 +100,16 @@ struct DeviceFeatures
VkPhysicalDeviceMeshShaderFeaturesEXT mesh_shader_features = {};
VkPhysicalDeviceMeshShaderPropertiesEXT mesh_shader_properties = {};
VkPhysicalDeviceIndexTypeUint8FeaturesEXT index_type_uint8_features = {};
VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT rgba10x6_formats_features = {};
VkPhysicalDeviceImageCompressionControlFeaturesEXT image_compression_control_features = {};
VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT image_compression_control_swapchain_features = {};
// Vendor
VkPhysicalDeviceComputeShaderDerivativesFeaturesNV compute_shader_derivative_features = {};
VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV device_generated_commands_features = {};
VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV device_generated_commands_compute_features = {};
VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV device_generated_commands_properties = {};
VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV descriptor_pool_overallocation_features = {};
// Fallback feature structs (Vulkan 1.1)
VkPhysicalDeviceHostQueryResetFeatures host_query_reset_features = {};
@@ -239,7 +243,7 @@ public:
Context();
Context(const Context &) = delete;
void operator=(const Context &) = delete;
static bool init_loader(PFN_vkGetInstanceProcAddr addr);
static bool init_loader(PFN_vkGetInstanceProcAddr addr, bool force_reload = false);
static PFN_vkGetInstanceProcAddr get_instance_proc_addr();
~Context();
@@ -40,9 +40,8 @@ DescriptorSetAllocator::DescriptorSetAllocator(Hash hash, Device *device_, const
if (!bindless)
{
unsigned count = device_->num_thread_indices;
for (unsigned i = 0; i < count; i++)
per_thread.emplace_back(new PerThread);
unsigned count = device_->num_thread_indices * device_->per_frame.size();
per_thread_and_frame.resize(count);
}
if (bindless && !device->get_device_features().vk12_features.descriptorIndexing)
@@ -176,11 +175,27 @@ DescriptorSetAllocator::DescriptorSetAllocator(Hash hash, Device *device_, const
#ifdef VULKAN_DEBUG
LOGI("Creating descriptor set layout.\n");
#endif
if (table.vkCreateDescriptorSetLayout(device->get_device(), &info, nullptr, &set_layout) != VK_SUCCESS)
if (table.vkCreateDescriptorSetLayout(device->get_device(), &info, nullptr, &set_layout_pool) != VK_SUCCESS)
LOGE("Failed to create descriptor set layout.");
#ifdef GRANITE_VULKAN_FOSSILIZE
device->register_descriptor_set_layout(set_layout, get_hash(), info);
if (set_layout_pool)
device->register_descriptor_set_layout(set_layout_pool, get_hash(), info);
#endif
if (!bindless && device->get_device_features().supports_push_descriptor)
{
info.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
for (auto &b : bindings)
if (b.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC)
b.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
if (table.vkCreateDescriptorSetLayout(device->get_device(), &info, nullptr, &set_layout_push) != VK_SUCCESS)
LOGE("Failed to create descriptor set layout.");
#ifdef GRANITE_VULKAN_FOSSILIZE
if (set_layout_push)
device->register_descriptor_set_layout(set_layout_push, get_hash(), info);
#endif
}
}
void DescriptorSetAllocator::reset_bindless_pool(VkDescriptorPool pool)
@@ -196,7 +211,7 @@ VkDescriptorSet DescriptorSetAllocator::allocate_bindless_set(VkDescriptorPool p
VkDescriptorSetAllocateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
info.descriptorPool = pool;
info.descriptorSetCount = 1;
info.pSetLayouts = &set_layout;
info.pSetLayouts = &set_layout_pool;
VkDescriptorSetVariableDescriptorCountAllocateInfoEXT count_info =
{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT };
@@ -225,12 +240,6 @@ VkDescriptorPool DescriptorSetAllocator::allocate_bindless_pool(unsigned num_set
info.poolSizeCount = 1;
VkDescriptorPoolSize size = pool_size[0];
if (num_descriptors > size.descriptorCount)
{
LOGE("Trying to allocate more than max bindless descriptors for descriptor layout.\n");
return VK_NULL_HANDLE;
}
size.descriptorCount = num_descriptors;
info.pPoolSizes = &size;
@@ -247,82 +256,98 @@ void DescriptorSetAllocator::begin_frame()
{
if (!bindless)
{
for (auto &thr : per_thread)
thr->should_begin = true;
// This can only be called in a situation where no command buffers are alive,
// so we don't need to consider any locks here.
if (device->per_frame.size() * device->num_thread_indices != per_thread_and_frame.size())
per_thread_and_frame.resize(device->per_frame.size() * device->num_thread_indices);
// It would be safe to set all offsets to 0 here, but that's a little wasteful.
for (uint32_t i = 0; i < device->num_thread_indices; i++)
per_thread_and_frame[i * device->per_frame.size() + device->frame_context_index].offset = 0;
}
}
std::pair<VkDescriptorSet, bool> DescriptorSetAllocator::find(unsigned thread_index, Hash hash)
VkDescriptorSet DescriptorSetAllocator::request_descriptor_set(unsigned thread_index, unsigned frame_index)
{
VK_ASSERT(!bindless);
auto &state = *per_thread[thread_index];
if (state.should_begin)
size_t flattened_index = thread_index * device->per_frame.size() + frame_index;
auto &state = per_thread_and_frame[flattened_index];
unsigned pool_index = state.offset / VULKAN_NUM_SETS_PER_POOL;
unsigned pool_offset = state.offset % VULKAN_NUM_SETS_PER_POOL;
if (pool_index >= state.pools.size())
{
state.set_nodes.begin_frame();
state.should_begin = false;
Pool *pool = state.object_pool.allocate();
VkDescriptorPoolCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
info.maxSets = VULKAN_NUM_SETS_PER_POOL;
if (!pool_size.empty())
{
info.poolSizeCount = pool_size.size();
info.pPoolSizes = pool_size.data();
}
bool overallocation =
device->get_device_features().descriptor_pool_overallocation_features.descriptorPoolOverallocation ==
VK_TRUE;
if (overallocation)
{
// No point in allocating new pools if we can keep using the existing one.
info.flags |= VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_POOLS_BIT_NV |
VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV;
}
bool need_alloc = !overallocation || state.pools.empty();
pool->pool = VK_NULL_HANDLE;
if (need_alloc && table.vkCreateDescriptorPool(device->get_device(), &info, nullptr, &pool->pool) != VK_SUCCESS)
{
LOGE("Failed to create descriptor pool.\n");
state.object_pool.free(pool);
return VK_NULL_HANDLE;
}
VkDescriptorSetLayout layouts[VULKAN_NUM_SETS_PER_POOL];
std::fill(std::begin(layouts), std::end(layouts), set_layout_pool);
VkDescriptorSetAllocateInfo alloc = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
alloc.descriptorPool = pool->pool != VK_NULL_HANDLE ? pool->pool : state.pools.front()->pool;
alloc.descriptorSetCount = VULKAN_NUM_SETS_PER_POOL;
alloc.pSetLayouts = layouts;
if (table.vkAllocateDescriptorSets(device->get_device(), &alloc, pool->sets) != VK_SUCCESS)
LOGE("Failed to allocate descriptor sets.\n");
state.pools.push_back(pool);
}
auto *node = state.set_nodes.request(hash);
if (node)
return { node->set, true };
node = state.set_nodes.request_vacant(hash);
if (node)
return { node->set, false };
VkDescriptorPool pool;
VkDescriptorPoolCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
info.maxSets = VULKAN_NUM_SETS_PER_POOL;
if (!pool_size.empty())
{
info.poolSizeCount = pool_size.size();
info.pPoolSizes = pool_size.data();
}
if (table.vkCreateDescriptorPool(device->get_device(), &info, nullptr, &pool) != VK_SUCCESS)
{
LOGE("Failed to create descriptor pool.\n");
return { VK_NULL_HANDLE, false };
}
VkDescriptorSet sets[VULKAN_NUM_SETS_PER_POOL];
VkDescriptorSetLayout layouts[VULKAN_NUM_SETS_PER_POOL];
std::fill(std::begin(layouts), std::end(layouts), set_layout);
VkDescriptorSetAllocateInfo alloc = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
alloc.descriptorPool = pool;
alloc.descriptorSetCount = VULKAN_NUM_SETS_PER_POOL;
alloc.pSetLayouts = layouts;
if (table.vkAllocateDescriptorSets(device->get_device(), &alloc, sets) != VK_SUCCESS)
LOGE("Failed to allocate descriptor sets.\n");
state.pools.push_back(pool);
for (auto set : sets)
state.set_nodes.make_vacant(set);
return { state.set_nodes.request_vacant(hash)->set, false };
VkDescriptorSet vk_set = state.pools[pool_index]->sets[pool_offset];
state.offset++;
return vk_set;
}
void DescriptorSetAllocator::clear()
{
for (auto &thr : per_thread)
for (auto &state : per_thread_and_frame)
{
thr->set_nodes.clear();
for (auto &pool : thr->pools)
for (auto *obj : state.pools)
{
table.vkResetDescriptorPool(device->get_device(), pool, 0);
table.vkDestroyDescriptorPool(device->get_device(), pool, nullptr);
table.vkDestroyDescriptorPool(device->get_device(), obj->pool, nullptr);
state.object_pool.free(obj);
}
thr->pools.clear();
state.pools.clear();
state.offset = 0;
state.object_pool = {};
}
}
DescriptorSetAllocator::~DescriptorSetAllocator()
{
if (set_layout != VK_NULL_HANDLE)
table.vkDestroyDescriptorSetLayout(device->get_device(), set_layout, nullptr);
table.vkDestroyDescriptorSetLayout(device->get_device(), set_layout_pool, nullptr);
table.vkDestroyDescriptorSetLayout(device->get_device(), set_layout_push, nullptr);
clear();
}
@@ -56,8 +56,8 @@ struct DescriptorSetLayout
// Avoid -Wclass-memaccess warnings since we hash DescriptorSetLayout.
static const unsigned VULKAN_NUM_SETS_PER_POOL = 16;
static const unsigned VULKAN_DESCRIPTOR_RING_SIZE = 8;
static const unsigned VULKAN_NUM_SETS_PER_POOL = 64;
static const unsigned VULKAN_DESCRIPTOR_RING_SIZE = 16;
class DescriptorSetAllocator;
class BindlessDescriptorPool;
@@ -121,11 +121,16 @@ public:
DescriptorSetAllocator(const DescriptorSetAllocator &) = delete;
void begin_frame();
std::pair<VkDescriptorSet, bool> find(unsigned thread_index, Util::Hash hash);
VkDescriptorSet request_descriptor_set(unsigned thread_index, unsigned frame_context);
VkDescriptorSetLayout get_layout() const
VkDescriptorSetLayout get_layout_for_pool() const
{
return set_layout;
return set_layout_pool;
}
VkDescriptorSetLayout get_layout_for_push() const
{
return set_layout_push;
}
void clear();
@@ -140,27 +145,25 @@ public:
void reset_bindless_pool(VkDescriptorPool pool);
private:
struct DescriptorSetNode : Util::TemporaryHashmapEnabled<DescriptorSetNode>, Util::IntrusiveListEnabled<DescriptorSetNode>
{
explicit DescriptorSetNode(VkDescriptorSet set_)
: set(set_)
{
}
VkDescriptorSet set;
};
Device *device;
const VolkDeviceTable &table;
VkDescriptorSetLayout set_layout = VK_NULL_HANDLE;
VkDescriptorSetLayout set_layout_pool = VK_NULL_HANDLE;
VkDescriptorSetLayout set_layout_push = VK_NULL_HANDLE;
struct PerThread
struct Pool
{
Util::TemporaryHashmap<DescriptorSetNode, VULKAN_DESCRIPTOR_RING_SIZE, true> set_nodes;
std::vector<VkDescriptorPool> pools;
bool should_begin = true;
VkDescriptorPool pool;
VkDescriptorSet sets[VULKAN_NUM_SETS_PER_POOL];
};
std::vector<std::unique_ptr<PerThread>> per_thread;
struct PerThreadAndFrame
{
std::vector<Pool *> pools;
Util::ObjectPool<Pool> object_pool;
uint32_t offset = 0;
};
std::vector<PerThreadAndFrame> per_thread_and_frame;
std::vector<VkDescriptorPoolSize> pool_size;
bool bindless = false;
};
+7 -1
View File
@@ -502,6 +502,8 @@ const PipelineLayout *Device::request_pipeline_layout(const CombinedResourceLayo
h.data(layout.spec_constant_mask, sizeof(layout.spec_constant_mask));
h.u32(layout.attribute_mask);
h.u32(layout.render_target_mask);
// Drivers with and without push descriptor support need to observe different hashes for Fossilize.
h.s32(int(ext.supports_push_descriptor));
for (unsigned set = 0; set < VULKAN_NUM_DESCRIPTOR_SETS; set++)
{
Util::for_each_bit(layout.sets[set].immutable_sampler_mask, [&](unsigned bit) {
@@ -874,7 +876,11 @@ void Device::init_workarounds()
workarounds.emulate_event_as_pipeline_barrier = true;
}
if (ext.driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY && gpu_props.driverVersion < VK_VERSION_MAJOR(535))
// For whatever ridiculous reason, pipeline cache control causes GPU hangs on Pascal cards in parallel-rdp.
// Use mesh shaders as the sentinel to check for that.
if (ext.driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
(gpu_props.driverVersion < VK_VERSION_MAJOR(535) ||
!ext.mesh_shader_features.meshShader))
{
LOGW("Disabling pipeline cache control.\n");
workarounds.broken_pipeline_cache_control = true;
@@ -25,6 +25,7 @@
namespace Vulkan
{
constexpr unsigned VULKAN_NUM_DESCRIPTOR_SETS = 4;
constexpr unsigned VULKAN_NUM_DYNAMIC_UBOS = 8; // Vulkan min-spec
constexpr unsigned VULKAN_NUM_BINDINGS = 32;
constexpr unsigned VULKAN_NUM_BINDINGS_BINDLESS_VARYING = 16 * 1024;
constexpr unsigned VULKAN_NUM_ATTACHMENTS = 8;
@@ -210,7 +210,7 @@ private:
uint32_t height = 0;
};
static const unsigned VULKAN_FRAMEBUFFER_RING_SIZE = 8;
static const unsigned VULKAN_FRAMEBUFFER_RING_SIZE = 16;
class FramebufferAllocator
{
public:
+134 -84
View File
@@ -65,16 +65,24 @@ PipelineLayout::PipelineLayout(Hash hash, Device *device_, const CombinedResourc
{
set_allocators[i] = device->request_descriptor_set_allocator(layout.sets[i], layout.stages_for_bindings[i],
immutable_samplers ? immutable_samplers->samplers[i] : nullptr);
layouts[i] = set_allocators[i]->get_layout();
layouts[i] = set_allocators[i]->get_layout_for_pool();
if (layout.descriptor_set_mask & (1u << i))
{
num_sets = i + 1;
// Assume the last set index in layout is the highest frequency update one, make that push descriptor if possible.
// Only one descriptor set can be push descriptor.
bool has_push_layout = set_allocators[i]->get_layout_for_push() != VK_NULL_HANDLE;
if (has_push_layout)
push_set_index = i;
}
}
if (num_sets > device->get_gpu_properties().limits.maxBoundDescriptorSets)
{
LOGE("Number of sets %u exceeds device limit of %u.\n",
num_sets, device->get_gpu_properties().limits.maxBoundDescriptorSets);
}
if (push_set_index != UINT32_MAX)
layouts[push_set_index] = set_allocators[push_set_index]->get_layout_for_push();
if (num_sets > VULKAN_NUM_DESCRIPTOR_SETS)
LOGE("Number of sets %u exceeds limit of %u.\n", num_sets, VULKAN_NUM_DESCRIPTOR_SETS);
VkPipelineLayoutCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
if (num_sets)
@@ -120,127 +128,169 @@ void PipelineLayout::create_update_templates()
for_each_bit(set_layout.uniform_buffer_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
VK_ASSERT(update_count < VULKAN_NUM_BINDINGS);
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
entry.dstBinding = binding;
entry.dstArrayElement = 0;
entry.descriptorCount = array_size;
entry.offset = offsetof(ResourceBinding, buffer) + sizeof(ResourceBinding) * binding;
entry.stride = sizeof(ResourceBinding);
// Work around a RenderDoc capture bug where descriptorCount > 1 is not handled correctly.
for (unsigned i = 0; i < array_size; i++)
{
auto &entry = update_entries[update_count++];
entry.descriptorType = desc_set == push_set_index ?
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
entry.dstBinding = binding;
entry.dstArrayElement = i;
entry.descriptorCount = 1;
if (desc_set == push_set_index)
entry.offset = offsetof(ResourceBinding, buffer.push) + sizeof(ResourceBinding) * (binding + i);
else
entry.offset = offsetof(ResourceBinding, buffer.dynamic) + sizeof(ResourceBinding) * (binding + i);
entry.stride = sizeof(ResourceBinding);
}
});
for_each_bit(set_layout.storage_buffer_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
VK_ASSERT(update_count < VULKAN_NUM_BINDINGS);
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
entry.dstBinding = binding;
entry.dstArrayElement = 0;
entry.descriptorCount = array_size;
entry.offset = offsetof(ResourceBinding, buffer) + sizeof(ResourceBinding) * binding;
entry.stride = sizeof(ResourceBinding);
for (unsigned i = 0; i < array_size; i++)
{
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
entry.dstBinding = binding;
entry.dstArrayElement = i;
entry.descriptorCount = 1;
entry.offset = offsetof(ResourceBinding, buffer.dynamic) + sizeof(ResourceBinding) * (binding + i);
entry.stride = sizeof(ResourceBinding);
}
});
for_each_bit(set_layout.sampled_texel_buffer_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
VK_ASSERT(update_count < VULKAN_NUM_BINDINGS);
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
entry.dstBinding = binding;
entry.dstArrayElement = 0;
entry.descriptorCount = array_size;
entry.offset = offsetof(ResourceBinding, buffer_view) + sizeof(ResourceBinding) * binding;
entry.stride = sizeof(ResourceBinding);
for (unsigned i = 0; i < array_size; i++)
{
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
entry.dstBinding = binding;
entry.dstArrayElement = i;
entry.descriptorCount = 1;
entry.offset = offsetof(ResourceBinding, buffer_view) + sizeof(ResourceBinding) * (binding + i);
entry.stride = sizeof(ResourceBinding);
}
});
for_each_bit(set_layout.storage_texel_buffer_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
VK_ASSERT(update_count < VULKAN_NUM_BINDINGS);
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
entry.dstBinding = binding;
entry.dstArrayElement = 0;
entry.descriptorCount = array_size;
entry.offset = offsetof(ResourceBinding, buffer_view) + sizeof(ResourceBinding) * binding;
entry.stride = sizeof(ResourceBinding);
for (unsigned i = 0; i < array_size; i++)
{
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
entry.dstBinding = binding;
entry.dstArrayElement = i;
entry.descriptorCount = 1;
entry.offset = offsetof(ResourceBinding, buffer_view) + sizeof(ResourceBinding) * (binding + i);
entry.stride = sizeof(ResourceBinding);
}
});
for_each_bit(set_layout.sampled_image_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
VK_ASSERT(update_count < VULKAN_NUM_BINDINGS);
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
entry.dstBinding = binding;
entry.dstArrayElement = 0;
entry.descriptorCount = array_size;
if (set_layout.fp_mask & (1u << binding))
entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * binding;
else
entry.offset = offsetof(ResourceBinding, image.integer) + sizeof(ResourceBinding) * binding;
entry.stride = sizeof(ResourceBinding);
for (unsigned i = 0; i < array_size; i++)
{
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
entry.dstBinding = binding;
entry.dstArrayElement = i;
entry.descriptorCount = 1;
if (set_layout.fp_mask & (1u << binding))
entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * (binding + i);
else
entry.offset = offsetof(ResourceBinding, image.integer) + sizeof(ResourceBinding) * (binding + i);
entry.stride = sizeof(ResourceBinding);
}
});
for_each_bit(set_layout.separate_image_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
VK_ASSERT(update_count < VULKAN_NUM_BINDINGS);
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
entry.dstBinding = binding;
entry.dstArrayElement = 0;
entry.descriptorCount = array_size;
if (set_layout.fp_mask & (1u << binding))
entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * binding;
else
entry.offset = offsetof(ResourceBinding, image.integer) + sizeof(ResourceBinding) * binding;
entry.stride = sizeof(ResourceBinding);
for (unsigned i = 0; i < array_size; i++)
{
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
entry.dstBinding = binding;
entry.dstArrayElement = i;
entry.descriptorCount = 1;
if (set_layout.fp_mask & (1u << binding))
entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * (binding + i);
else
entry.offset = offsetof(ResourceBinding, image.integer) + sizeof(ResourceBinding) * (binding + i);
entry.stride = sizeof(ResourceBinding);
}
});
for_each_bit(set_layout.sampler_mask & ~set_layout.immutable_sampler_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
VK_ASSERT(update_count < VULKAN_NUM_BINDINGS);
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
entry.dstBinding = binding;
entry.dstArrayElement = 0;
entry.descriptorCount = array_size;
entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * binding;
entry.stride = sizeof(ResourceBinding);
for (unsigned i = 0; i < array_size; i++)
{
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
entry.dstBinding = binding;
entry.dstArrayElement = i;
entry.descriptorCount = 1;
entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * (binding + i);
entry.stride = sizeof(ResourceBinding);
}
});
for_each_bit(set_layout.storage_image_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
VK_ASSERT(update_count < VULKAN_NUM_BINDINGS);
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
entry.dstBinding = binding;
entry.dstArrayElement = 0;
entry.descriptorCount = array_size;
if (set_layout.fp_mask & (1u << binding))
entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * binding;
else
entry.offset = offsetof(ResourceBinding, image.integer) + sizeof(ResourceBinding) * binding;
entry.stride = sizeof(ResourceBinding);
for (unsigned i = 0; i < array_size; i++)
{
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
entry.dstBinding = binding;
entry.dstArrayElement = i;
entry.descriptorCount = 1;
if (set_layout.fp_mask & (1u << binding))
entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * (binding + i);
else
entry.offset = offsetof(ResourceBinding, image.integer) + sizeof(ResourceBinding) * (binding + i);
entry.stride = sizeof(ResourceBinding);
}
});
for_each_bit(set_layout.input_attachment_mask, [&](uint32_t binding) {
unsigned array_size = set_layout.array_size[binding];
VK_ASSERT(update_count < VULKAN_NUM_BINDINGS);
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
entry.dstBinding = binding;
entry.dstArrayElement = 0;
entry.descriptorCount = array_size;
if (set_layout.fp_mask & (1u << binding))
entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * binding;
else
entry.offset = offsetof(ResourceBinding, image.integer) + sizeof(ResourceBinding) * binding;
entry.stride = sizeof(ResourceBinding);
for (unsigned i = 0; i < array_size; i++)
{
auto &entry = update_entries[update_count++];
entry.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
entry.dstBinding = binding;
entry.dstArrayElement = i;
entry.descriptorCount = 1;
if (set_layout.fp_mask & (1u << binding))
entry.offset = offsetof(ResourceBinding, image.fp) + sizeof(ResourceBinding) * (binding + i);
else
entry.offset = offsetof(ResourceBinding, image.integer) + sizeof(ResourceBinding) * (binding + i);
entry.stride = sizeof(ResourceBinding);
}
});
VkDescriptorUpdateTemplateCreateInfo info = {VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO };
VkDescriptorUpdateTemplateCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO };
info.pipelineLayout = pipe_layout;
info.descriptorSetLayout = set_allocators[desc_set]->get_layout();
info.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET;
if (desc_set == push_set_index)
{
info.descriptorSetLayout = set_allocators[desc_set]->get_layout_for_push();
info.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR;
}
else
{
info.descriptorSetLayout = set_allocators[desc_set]->get_layout_for_pool();
info.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET;
}
info.set = desc_set;
info.descriptorUpdateEntryCount = update_count;
info.pDescriptorUpdateEntries = update_entries;
+20 -11
View File
@@ -83,18 +83,21 @@ struct CombinedResourceLayout
Util::Hash push_constant_layout_hash = 0;
};
struct ResourceBinding
union ResourceBinding
{
union {
VkDescriptorBufferInfo buffer;
struct
{
VkDescriptorImageInfo fp;
VkDescriptorImageInfo integer;
} image;
VkBufferView buffer_view;
};
VkDeviceSize dynamic_offset;
struct
{
VkDescriptorBufferInfo dynamic;
VkDescriptorBufferInfo push;
} buffer;
struct
{
VkDescriptorImageInfo fp;
VkDescriptorImageInfo integer;
} image;
VkBufferView buffer_view;
};
struct ResourceBindings
@@ -138,12 +141,18 @@ public:
return update_template[set];
}
uint32_t get_push_set_index() const
{
return push_set_index;
}
private:
Device *device;
VkPipelineLayout pipe_layout = VK_NULL_HANDLE;
CombinedResourceLayout layout;
DescriptorSetAllocator *set_allocators[VULKAN_NUM_DESCRIPTOR_SETS] = {};
VkDescriptorUpdateTemplate update_template[VULKAN_NUM_DESCRIPTOR_SETS] = {};
uint32_t push_set_index = UINT32_MAX;
void create_update_templates();
};
@@ -35,11 +35,16 @@
#include "logging.hpp"
#include <utility>
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
// Workaround silly Xlib headers that define macros for these globally :(
#ifdef None
#undef None
#endif
#ifdef Bool
#undef Bool
#endif
#ifdef Status
#undef Status
#endif
#ifdef VULKAN_DEBUG
#define VK_ASSERT(x) \
+9
View File
@@ -222,6 +222,9 @@ bool WSI::init_surface_swapchain_dxgi(unsigned width, unsigned height)
case BackbufferFormat::HDR10:
format = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_HDR10_ST2084_EXT };
break;
default:
return false;
}
constexpr unsigned num_images = 3;
@@ -411,11 +414,13 @@ void WSI::nonblock_delete_swapchains()
{
if (!swap.fence || swap.fence->wait_timeout(0))
{
platform->destroy_swapchain_resources(swap.swapchain);
table->vkDestroySwapchainKHR(device->get_device(), swap.swapchain, nullptr);
}
else if (pending >= 2)
{
swap.fence->wait();
platform->destroy_swapchain_resources(swap.swapchain);
table->vkDestroySwapchainKHR(device->get_device(), swap.swapchain, nullptr);
}
else
@@ -448,6 +453,7 @@ void WSI::drain_swapchain(bool in_tear_down)
{
if (old_swap.fence)
old_swap.fence->wait();
platform->destroy_swapchain_resources(old_swap.swapchain);
table->vkDestroySwapchainKHR(context->get_device(), old_swap.swapchain, nullptr);
}
@@ -475,6 +481,7 @@ void WSI::tear_down_swapchain()
drain_swapchain(true);
platform->event_swapchain_destroyed();
platform->destroy_swapchain_resources(swapchain);
table->vkDestroySwapchainKHR(context->get_device(), swapchain, nullptr);
swapchain = VK_NULL_HANDLE;
has_acquired_swapchain_index = false;
@@ -1664,6 +1671,7 @@ WSI::SwapchainError WSI::init_swapchain(unsigned width, unsigned height)
platform->event_swapchain_destroyed();
auto res = table->vkCreateSwapchainKHR(context->get_device(), &info, nullptr, &swapchain);
platform->destroy_swapchain_resources(old_swapchain);
table->vkDestroySwapchainKHR(context->get_device(), old_swapchain, nullptr);
has_acquired_swapchain_index = false;
present_id = 0;
@@ -1749,6 +1757,7 @@ void WSIPlatform::event_swapchain_created(Device *, VkSwapchainKHR, unsigned, un
VkFormat, VkColorSpaceKHR,
VkSurfaceTransformFlagBitsKHR) {}
void WSIPlatform::event_swapchain_destroyed() {}
void WSIPlatform::destroy_swapchain_resources(VkSwapchainKHR) {}
void WSIPlatform::event_frame_tick(double, double) {}
void WSIPlatform::event_swapchain_index(Device *, unsigned) {}
void WSIPlatform::begin_drop_event() {}
+1
View File
@@ -118,6 +118,7 @@ public:
float aspect_ratio, size_t num_swapchain_images,
VkFormat format, VkColorSpaceKHR color_space,
VkSurfaceTransformFlagBitsKHR pre_rotate);
virtual void destroy_swapchain_resources(VkSwapchainKHR swapchain);
virtual void event_swapchain_destroyed();
virtual void event_frame_tick(double frame, double elapsed);
virtual void event_swapchain_index(Device *device, unsigned index);