@ -95,10 +95,16 @@ public:
std : : lock_guard lock { mutex } ;
const auto gpu_addr { tic . Address ( ) } ;
if ( ! gpu_addr ) {
return { } ;
return GetNullSurface ( SurfaceParams : : ExpectedTarget ( entry ) ) ;
}
const auto host_ptr { system . GPU ( ) . MemoryManager ( ) . GetPointer ( gpu_addr ) } ;
const auto cache_addr { ToCacheAddr ( host_ptr ) } ;
if ( ! cache_addr ) {
return GetNullSurface ( SurfaceParams : : ExpectedTarget ( entry ) ) ;
}
const auto params { SurfaceParams : : CreateForTexture ( format_lookup_table , tic , entry ) } ;
const auto [ surface , view ] = GetSurface ( gpu_addr , params , true , false ) ;
const auto [ surface , view ] = GetSurface ( gpu_addr , cache_addr, params, true , false ) ;
if ( guard_samplers ) {
sampled_textures . push_back ( surface ) ;
}
@ -110,10 +116,15 @@ public:
std : : lock_guard lock { mutex } ;
const auto gpu_addr { tic . Address ( ) } ;
if ( ! gpu_addr ) {
return { } ;
return GetNullSurface ( SurfaceParams : : ExpectedTarget ( entry ) ) ;
}
const auto host_ptr { system . GPU ( ) . MemoryManager ( ) . GetPointer ( gpu_addr ) } ;
const auto cache_addr { ToCacheAddr ( host_ptr ) } ;
if ( ! cache_addr ) {
return GetNullSurface ( SurfaceParams : : ExpectedTarget ( entry ) ) ;
}
const auto params { SurfaceParams : : CreateForImage ( format_lookup_table , tic , entry ) } ;
const auto [ surface , view ] = GetSurface ( gpu_addr , params , true , false ) ;
const auto [ surface , view ] = GetSurface ( gpu_addr , cache_addr, params, true , false ) ;
if ( guard_samplers ) {
sampled_textures . push_back ( surface ) ;
}
@ -143,11 +154,17 @@ public:
SetEmptyDepthBuffer ( ) ;
return { } ;
}
const auto host_ptr { system . GPU ( ) . MemoryManager ( ) . GetPointer ( gpu_addr ) } ;
const auto cache_addr { ToCacheAddr ( host_ptr ) } ;
if ( ! cache_addr ) {
SetEmptyDepthBuffer ( ) ;
return { } ;
}
const auto depth_params { SurfaceParams : : CreateForDepthBuffer (
system , regs . zeta_width , regs . zeta_height , regs . zeta . format ,
regs . zeta . memory_layout . block_width , regs . zeta . memory_layout . block_height ,
regs . zeta . memory_layout . block_depth , regs . zeta . memory_layout . type ) } ;
auto surface_view = GetSurface ( gpu_addr , depth_params , preserve_contents , true ) ;
auto surface_view = GetSurface ( gpu_addr , cache_addr, depth_params, preserve_contents , true ) ;
if ( depth_buffer . target )
depth_buffer . target - > MarkAsRenderTarget ( false , NO_RT ) ;
depth_buffer . target = surface_view . first ;
@ -180,8 +197,16 @@ public:
return { } ;
}
auto surface_view = GetSurface ( gpu_addr , SurfaceParams : : CreateForFramebuffer ( system , index ) ,
preserve_contents , true ) ;
const auto host_ptr { system . GPU ( ) . MemoryManager ( ) . GetPointer ( gpu_addr ) } ;
const auto cache_addr { ToCacheAddr ( host_ptr ) } ;
if ( ! cache_addr ) {
SetEmptyColorBuffer ( index ) ;
return { } ;
}
auto surface_view =
GetSurface ( gpu_addr , cache_addr , SurfaceParams : : CreateForFramebuffer ( system , index ) ,
preserve_contents , true ) ;
if ( render_targets [ index ] . target )
render_targets [ index ] . target - > MarkAsRenderTarget ( false , NO_RT ) ;
render_targets [ index ] . target = surface_view . first ;
@ -230,8 +255,14 @@ public:
const GPUVAddr src_gpu_addr = src_config . Address ( ) ;
const GPUVAddr dst_gpu_addr = dst_config . Address ( ) ;
DeduceBestBlit ( src_params , dst_params , src_gpu_addr , dst_gpu_addr ) ;
std : : pair < TSurface , TView > dst_surface = GetSurface ( dst_gpu_addr , dst_params , true , false ) ;
std : : pair < TSurface , TView > src_surface = GetSurface ( src_gpu_addr , src_params , true , false ) ;
const auto dst_host_ptr { system . GPU ( ) . MemoryManager ( ) . GetPointer ( dst_gpu_addr ) } ;
const auto dst_cache_addr { ToCacheAddr ( dst_host_ptr ) } ;
const auto src_host_ptr { system . GPU ( ) . MemoryManager ( ) . GetPointer ( src_gpu_addr ) } ;
const auto src_cache_addr { ToCacheAddr ( src_host_ptr ) } ;
std : : pair < TSurface , TView > dst_surface =
GetSurface ( dst_gpu_addr , dst_cache_addr , dst_params , true , false ) ;
std : : pair < TSurface , TView > src_surface =
GetSurface ( src_gpu_addr , src_cache_addr , src_params , true , false ) ;
ImageBlit ( src_surface . second , dst_surface . second , copy_config ) ;
dst_surface . first - > MarkAsModified ( true , Tick ( ) ) ;
}
@ -347,13 +378,6 @@ protected:
return new_surface ;
}
std : : pair < TSurface , TView > GetFermiSurface (
const Tegra : : Engines : : Fermi2D : : Regs : : Surface & config ) {
SurfaceParams params = SurfaceParams : : CreateForFermiCopySurface ( config ) ;
const GPUVAddr gpu_addr = config . Address ( ) ;
return GetSurface ( gpu_addr , params , true , false ) ;
}
Core : : System & system ;
private :
@ -614,22 +638,9 @@ private:
* left blank .
* @ param is_render Whether or not the surface is a render target .
* */
std : : pair < TSurface , TView > GetSurface ( const GPUVAddr gpu_addr , const SurfaceParams & params ,
bool preserve_contents , bool is_render ) {
const auto host_ptr { system . GPU ( ) . MemoryManager ( ) . GetPointer ( gpu_addr ) } ;
const auto cache_addr { ToCacheAddr ( host_ptr ) } ;
// Step 0: guarantee a valid surface
if ( ! cache_addr ) {
// Return a null surface if it's invalid
SurfaceParams new_params = params ;
new_params . width = 1 ;
new_params . height = 1 ;
new_params . depth = 1 ;
new_params . block_height = 0 ;
new_params . block_depth = 0 ;
return InitializeSurface ( gpu_addr , new_params , false ) ;
}
std : : pair < TSurface , TView > GetSurface ( const GPUVAddr gpu_addr , const CacheAddr cache_addr ,
const SurfaceParams & params , bool preserve_contents ,
bool is_render ) {
// Step 1
// Check Level 1 Cache for a fast structural match. If candidate surface
@ -793,6 +804,41 @@ private:
}
}
/**
* Gets a null surface based on a target texture .
* @ param target The target of the null surface .
*/
TView GetNullSurface ( SurfaceTarget target ) {
const u32 i_target = static_cast < u32 > ( target ) ;
if ( const auto it = invalid_cache . find ( i_target ) ; it ! = invalid_cache . end ( ) ) {
return it - > second - > GetMainView ( ) ;
}
SurfaceParams params { } ;
params . target = target ;
params . is_tiled = false ;
params . srgb_conversion = false ;
params . is_layered = false ;
params . block_width = 0 ;
params . block_height = 0 ;
params . block_depth = 0 ;
params . tile_width_spacing = 1 ;
params . width = 1 ;
params . height = 1 ;
params . depth = 1 ;
params . pitch = 4 ;
params . num_levels = 1 ;
params . emulated_levels = 1 ;
params . pixel_format = VideoCore : : Surface : : PixelFormat : : RGBA16F ;
params . type = VideoCore : : Surface : : SurfaceType : : ColorTexture ;
auto surface = CreateSurface ( 0ULL , params ) ;
invalid_memory . clear ( ) ;
invalid_memory . resize ( surface - > GetHostSizeInBytes ( ) , 0U ) ;
surface - > UploadTexture ( invalid_memory ) ;
surface - > MarkAsModified ( false , Tick ( ) ) ;
invalid_cache . emplace ( i_target , surface ) ;
return surface - > GetMainView ( ) ;
}
/**
* Gets the a source and destination starting address and parameters ,
* and tries to deduce if they are supposed to be depth textures . If so , their
@ -991,6 +1037,11 @@ private:
std : : vector < TSurface > sampled_textures ;
/// This cache stores null surfaces in order to be used as a placeholder
/// for invalid texture calls.
std : : unordered_map < u32 , TSurface > invalid_cache ;
std : : vector < u8 > invalid_memory ;
StagingCache staging_cache ;
std : : recursive_mutex mutex ;
} ;