@ -143,6 +143,49 @@ Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry
}
}
}
}
/// @brief Determine if an attachment to be updated has to preserve contents
/// @param is_clear True when a clear is being executed
/// @param regs 3D registers
/// @return True when the contents have to be preserved
bool HasToPreserveColorContents ( bool is_clear , const Maxwell & regs ) {
if ( ! is_clear ) {
return true ;
}
// First we have to make sure all clear masks are enabled.
if ( ! regs . clear_buffers . R | | ! regs . clear_buffers . G | | ! regs . clear_buffers . B | |
! regs . clear_buffers . A ) {
return true ;
}
// If scissors are disabled, the whole screen is cleared
if ( ! regs . clear_flags . scissor ) {
return false ;
}
// Then we have to confirm scissor testing clears the whole image
const std : : size_t index = regs . clear_buffers . RT ;
const auto & scissor = regs . scissor_test [ 0 ] ;
return scissor . min_x > 0 | | scissor . min_y > 0 | | scissor . max_x < regs . rt [ index ] . width | |
scissor . max_y < regs . rt [ index ] . height ;
}
/// @brief Determine if an attachment to be updated has to preserve contents
/// @param is_clear True when a clear is being executed
/// @param regs 3D registers
/// @return True when the contents have to be preserved
bool HasToPreserveDepthContents ( bool is_clear , const Maxwell & regs ) {
// If we are not clearing, the contents have to be preserved
if ( ! is_clear ) {
return true ;
}
// For depth stencil clears we only have to confirm scissor test covers the whole image
if ( ! regs . clear_flags . scissor ) {
return false ;
}
// Make sure the clear cover the whole image
const auto & scissor = regs . scissor_test [ 0 ] ;
return scissor . min_x > 0 | | scissor . min_y > 0 | | scissor . max_x < regs . zeta_width | |
scissor . max_y < regs . zeta_height ;
}
} // Anonymous namespace
} // Anonymous namespace
class BufferBindings final {
class BufferBindings final {
@ -344,7 +387,7 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) {
buffer_cache . Unmap ( ) ;
buffer_cache . Unmap ( ) ;
const Texceptions texceptions = UpdateAttachments ( ) ;
const Texceptions texceptions = UpdateAttachments ( false ) ;
SetupImageTransitions ( texceptions , color_attachments , zeta_attachment ) ;
SetupImageTransitions ( texceptions , color_attachments , zeta_attachment ) ;
key . renderpass_params = GetRenderPassParams ( texceptions ) ;
key . renderpass_params = GetRenderPassParams ( texceptions ) ;
@ -400,7 +443,7 @@ void RasterizerVulkan::Clear() {
return ;
return ;
}
}
[[maybe_unused]] const auto texceptions = UpdateAttachments ( ) ;
[[maybe_unused]] const auto texceptions = UpdateAttachments ( true ) ;
DEBUG_ASSERT ( texceptions . none ( ) ) ;
DEBUG_ASSERT ( texceptions . none ( ) ) ;
SetupImageTransitions ( 0 , color_attachments , zeta_attachment ) ;
SetupImageTransitions ( 0 , color_attachments , zeta_attachment ) ;
@ -677,9 +720,12 @@ void RasterizerVulkan::FlushWork() {
draw_counter = 0 ;
draw_counter = 0 ;
}
}
RasterizerVulkan : : Texceptions RasterizerVulkan : : UpdateAttachments ( ) {
RasterizerVulkan : : Texceptions RasterizerVulkan : : UpdateAttachments ( bool is_clear ) {
MICROPROFILE_SCOPE ( Vulkan_RenderTargets ) ;
MICROPROFILE_SCOPE ( Vulkan_RenderTargets ) ;
auto & dirty = system . GPU ( ) . Maxwell3D ( ) . dirty . flags ;
auto & maxwell3d = system . GPU ( ) . Maxwell3D ( ) ;
auto & dirty = maxwell3d . dirty . flags ;
auto & regs = maxwell3d . regs ;
const bool update_rendertargets = dirty [ VideoCommon : : Dirty : : RenderTargets ] ;
const bool update_rendertargets = dirty [ VideoCommon : : Dirty : : RenderTargets ] ;
dirty [ VideoCommon : : Dirty : : RenderTargets ] = false ;
dirty [ VideoCommon : : Dirty : : RenderTargets ] = false ;
@ -688,7 +734,8 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() {
Texceptions texceptions ;
Texceptions texceptions ;
for ( std : : size_t rt = 0 ; rt < Maxwell : : NumRenderTargets ; + + rt ) {
for ( std : : size_t rt = 0 ; rt < Maxwell : : NumRenderTargets ; + + rt ) {
if ( update_rendertargets ) {
if ( update_rendertargets ) {
color_attachments [ rt ] = texture_cache . GetColorBufferSurface ( rt , true ) ;
const bool preserve_contents = HasToPreserveColorContents ( is_clear , regs ) ;
color_attachments [ rt ] = texture_cache . GetColorBufferSurface ( rt , preserve_contents ) ;
}
}
if ( color_attachments [ rt ] & & WalkAttachmentOverlaps ( * color_attachments [ rt ] ) ) {
if ( color_attachments [ rt ] & & WalkAttachmentOverlaps ( * color_attachments [ rt ] ) ) {
texceptions [ rt ] = true ;
texceptions [ rt ] = true ;
@ -696,7 +743,8 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() {
}
}
if ( update_rendertargets ) {
if ( update_rendertargets ) {
zeta_attachment = texture_cache . GetDepthBufferSurface ( true ) ;
const bool preserve_contents = HasToPreserveDepthContents ( is_clear , regs ) ;
zeta_attachment = texture_cache . GetDepthBufferSurface ( preserve_contents ) ;
}
}
if ( zeta_attachment & & WalkAttachmentOverlaps ( * zeta_attachment ) ) {
if ( zeta_attachment & & WalkAttachmentOverlaps ( * zeta_attachment ) ) {
texceptions [ ZETA_TEXCEPTION_INDEX ] = true ;
texceptions [ ZETA_TEXCEPTION_INDEX ] = true ;