@ -43,90 +43,66 @@ void DmaPusher::DispatchCalls() {
bool DmaPusher : : Step ( ) {
if ( ! ib_enable | | dma_pushbuffer . empty ( ) ) {
// pushbuffer empty and IB empty or nonexistent - nothing to do
return false ;
}
CommandList & command_list { dma_pushbuffer . front ( ) } ;
CommandList & command_list = dma_pushbuffer . front ( ) ;
ASSERT_OR_EXECUTE (
command_list . command_lists . size ( ) | | command_list . prefetch_command_list . size ( ) , {
// Somehow the command_list is empty, in order to avoid a crash
// We ignore it and assume its size is 0.
dma_pushbuffer . pop ( ) ;
dma_pushbuffer_subindex = 0 ;
return true ;
} ) ;
const size_t prefetch_size = command_list . prefetch_command_list . size ( ) ;
const size_t command_list_size = command_list . command_lists . size ( ) ;
if ( command_list . prefetch_command_list . size ( ) ) {
// Prefetched command list from nvdrv, used for things like synchronization
ProcessCommands ( VideoCommon : : FixSmallVectorADL ( command_list . prefetch_command_list ) ) ;
if ( prefetch_size = = 0 & & command_list_size = = 0 ) {
dma_pushbuffer . pop ( ) ;
} else {
const CommandListHeader command_list_header {
command_list . command_lists [ dma_pushbuffer_subindex + + ] } ;
if ( signal_sync ) {
std : : unique_lock lk ( sync_mutex ) ;
sync_cv . wait ( lk , [ this ] ( ) { return synced ; } ) ;
signal_sync = false ;
synced = false ;
}
dma_pushbuffer_subindex = 0 ;
return true ;
}
dma_state . dma_get = command_list_header . addr ;
if ( prefetch_size > 0 ) {
ProcessCommands ( command_list . prefetch_command_list ) ;
dma_pushbuffer . pop ( ) ;
return true ;
}
if ( command_list_header . size = = 0 ) {
return true ;
}
auto & current_command = command_list . command_lists [ dma_pushbuffer_subindex ] ;
const CommandListHeader & header = current_command ;
dma_state . dma_get = header . addr ;
// Push buffer non-empty, read a word
if ( dma_state . method > = MacroRegistersStart ) {
if ( subchannels [ dma_state . subchannel ] ) {
subchannels [ dma_state . subchannel ] - > current_dirty = memory_manager . IsMemoryDirty (
dma_state . dma_get , command_list_header . size * sizeof ( u32 ) ) ;
}
}
if ( signal_sync & & ! synced ) {
std : : unique_lock lk ( sync_mutex ) ;
sync_cv . wait ( lk , [ this ] ( ) { return synced ; } ) ;
signal_sync = false ;
synced = false ;
}
const auto safe_process = [ & ] {
Tegra : : Memory : : GpuGuestMemory < Tegra : : CommandHeader ,
Tegra : : Memory : : GuestMemoryFlags : : SafeRead >
headers ( memory_manager , dma_state . dma_get , command_list_header . size ,
& command_headers ) ;
ProcessCommands ( headers ) ;
} ;
if ( header . size > 0 & & dma_state . method > = MacroRegistersStart & & subchannels [ dma_state . subchannel ] ) {
subchannels [ dma_state . subchannel ] - > current_dirty = memory_manager . IsMemoryDirty ( dma_state . dma_get , header . size * sizeof ( u32 ) ) ;
}
const auto unsafe_process = [ & ] {
Tegra : : Memory : : GpuGuestMemory < Tegra : : CommandHeader ,
Tegra : : Memory : : GuestMemoryFlags : : UnsafeRead >
headers ( memory_manager , dma_state . dma_get , command_list_header . size ,
& command_headers ) ;
if ( header . size > 0 ) {
if ( Settings : : IsDMALevelDefault ( ) ? ( Settings : : IsGPULevelMedium ( ) | | Settings : : IsGPULevelHigh ( ) ) : Settings : : IsDMALevelSafe ( ) ) {
Tegra : : Memory : : GpuGuestMemory < Tegra : : CommandHeader , Tegra : : Memory : : GuestMemoryFlags : : SafeRead > headers ( memory_manager , dma_state . dma_get , header . size , & command_headers ) ;
ProcessCommands ( headers ) ;
} ;
const bool use_safe = Settings : : IsDMALevelDefault ( ) ? ( Settings : : IsGPULevelMedium ( ) | | Settings : : IsGPULevelHigh ( ) ) : Settings : : IsDMALevelSafe ( ) ;
if ( use_safe ) {
safe_process ( ) ;
} else {
unsafe_process ( ) ;
Tegra : : Memory : : GpuGuestMemory < Tegra : : CommandHeader , Tegra : : Memory : : GuestMemoryFlags : : UnsafeRead > headers ( memory_manager , dma_state . dma_get , header . size , & command_headers ) ;
ProcessCommands ( headers ) ;
}
}
if ( dma_pushbuffer_subindex > = command_list . command_lists . size ( ) ) {
// We've gone through the current list, remove it from the queue
dma_pushbuffer . pop ( ) ;
dma_pushbuffer_subindex = 0 ;
} else if ( command_list . command_lists [ dma_pushbuffer_subindex ] . sync & & Settings : : values . sync_memory_operations . GetValue ( ) ) {
signal_sync = true ;
}
if ( + + dma_pushbuffer_subindex > = command_list_size ) {
dma_pushbuffer . pop ( ) ;
dma_pushbuffer_subindex = 0 ;
} else {
signal_sync = command_list . command_lists [ dma_pushbuffer_subindex ] . sync & & Settings : : values . sync_memory_operations . GetValue ( ) ;
}
if ( signal_sync ) {
rasterizer - > SignalFence ( [ this ] ( ) {
if ( signal_sync ) {
rasterizer - > SignalFence ( [ this ] ( ) {
std : : scoped_lock lk ( sync_mutex ) ;
synced = true ;
sync_cv . notify_all ( ) ;
} ) ;
}
} ) ;
}
return true ;
}