@ -205,19 +205,55 @@ bool PipelineCache::BindPipeline(const PipelineInfo& info, bool wait_built) {
return false ;
}
for ( u32 i = 0 ; i < NUM_RASTERIZER_SETS ; i + + ) {
if ( ! set_dirty [ i ] ) {
continue ;
}
bound_descriptor_sets [ i ] = descriptor_set_providers [ i ] . Acquire ( update_data [ i ] ) ;
set_dirty [ i ] = false ;
u32 new_descriptors_start = 0 ;
std : : span < vk : : DescriptorSet > new_descriptors_span { } ;
std : : span < u32 > new_offsets_span { } ;
// Ensure all the descriptor sets are set at least once at the beginning.
if ( scheduler . IsStateDirty ( StateFlags : : DescriptorSets ) ) {
set_dirty . set ( ) ;
}
if ( set_dirty . any ( ) ) {
for ( u32 i = 0 ; i < NUM_RASTERIZER_SETS ; i + + ) {
if ( ! set_dirty . test ( i ) ) {
continue ;
}
bound_descriptor_sets [ i ] = descriptor_set_providers [ i ] . Acquire ( update_data [ i ] ) ;
}
new_descriptors_span = bound_descriptor_sets ;
// Only send new offsets if the buffer descriptor-set changed.
if ( set_dirty . test ( 0 ) ) {
new_offsets_span = offsets ;
}
// Try to compact the number of updated descriptor-set slots to the ones that have actually
// changed
if ( ! set_dirty . all ( ) ) {
const u64 dirty_mask = set_dirty . to_ulong ( ) ;
new_descriptors_start = static_cast < u32 > ( std : : countr_zero ( dirty_mask ) ) ;
const u32 new_descriptors_end = 64u - static_cast < u32 > ( std : : countl_zero ( dirty_mask ) ) ;
const u32 new_descriptors_size = new_descriptors_end - new_descriptors_start ;
new_descriptors_span =
new_descriptors_span . subspan ( new_descriptors_start , new_descriptors_size ) ;
}
set_dirty . reset ( ) ;
}
boost : : container : : static_vector < vk : : DescriptorSet , NUM_RASTERIZER_SETS > new_descriptors (
new_descriptors_span . begin ( ) , new_descriptors_span . end ( ) ) ;
boost : : container : : static_vector < u32 , NUM_DYNAMIC_OFFSETS > new_offsets ( new_offsets_span . begin ( ) ,
new_offsets_span . end ( ) ) ;
const bool is_dirty = scheduler . IsStateDirty ( StateFlags : : Pipeline ) ;
const bool pipeline_dirty = ( current_pipeline ! = pipeline ) | | is_dirty ;
scheduler . Record ( [ this , is_dirty , pipeline_dirty , pipeline ,
current_dynamic = current_info . dynamic , dynamic = info . dynamic ,
descriptor_sets = bound_descriptor_sets , offsets = offsets ,
new_descriptors_start , descriptor_sets = std : : move ( new_descriptors ) ,
offsets = std : : move ( new_offsets ) ,
current_rasterization = current_info . rasterization ,
current_depth_stencil = current_info . depth_stencil ,
rasterization = info . rasterization ,
@ -318,13 +354,16 @@ bool PipelineCache::BindPipeline(const PipelineInfo& info, bool wait_built) {
}
cmdbuf . bindPipeline ( vk : : PipelineBindPoint : : eGraphics , pipeline - > Handle ( ) ) ;
}
cmdbuf . bindDescriptorSets ( vk : : PipelineBindPoint : : eGraphics , * pipeline_layout , 0 ,
descriptor_sets , offsets ) ;
if ( descriptor_sets . size ( ) ) {
cmdbuf . bindDescriptorSets ( vk : : PipelineBindPoint : : eGraphics , * pipeline_layout ,
new_descriptors_start , descriptor_sets , offsets ) ;
}
} ) ;
current_info = info ;
current_pipeline = pipeline ;
scheduler . MarkStateNonDirty ( StateFlags : : Pipeline ) ;
scheduler . MarkStateNonDirty ( StateFlags : : Pipeline | StateFlags : : DescriptorSets ) ;
return true ;
}
@ -497,7 +536,10 @@ void PipelineCache::BindTexelBuffer(u32 binding, vk::BufferView buffer_view) {
}
void PipelineCache : : SetBufferOffset ( u32 binding , size_t offset ) {
offsets [ binding ] = static_cast < u32 > ( offset ) ;
if ( offsets [ binding ] ! = static_cast < u32 > ( offset ) ) {
offsets [ binding ] = static_cast < u32 > ( offset ) ;
set_dirty [ 0 ] = true ;
}
}
bool PipelineCache : : IsCacheValid ( std : : span < const u8 > data ) const {