rendervulkan: Seamless full -> deferred composition switch
This commit is contained in:
parent
31eefd41a0
commit
5e99ecb46b
3 changed files with 58 additions and 56 deletions
|
@ -105,8 +105,6 @@ struct VulkanOutput_t
|
|||
VkFence acquireFence;
|
||||
|
||||
uint32_t nOutImage; // swapchain index in nested mode, or ping/pong between two RTs
|
||||
uint32_t nOutImagePartial;
|
||||
uint32_t nOutPresentImagePartial;
|
||||
std::vector<std::shared_ptr<CVulkanTexture>> outputImages;
|
||||
std::vector<std::shared_ptr<CVulkanTexture>> outputImagesPartialOverlay;
|
||||
|
||||
|
@ -2891,7 +2889,7 @@ std::shared_ptr<CVulkanTexture> vulkan_create_debug_white_texture()
|
|||
void vulkan_present_to_openvr( void )
|
||||
{
|
||||
//static auto texture = vulkan_create_debug_white_texture();
|
||||
auto texture = vulkan_get_last_output_image( false );
|
||||
auto texture = vulkan_get_last_output_image( false, false );
|
||||
|
||||
vr::VRVulkanTextureData_t data =
|
||||
{
|
||||
|
@ -3088,8 +3086,6 @@ bool vulkan_remake_output_images()
|
|||
g_device.waitIdle();
|
||||
|
||||
pOutput->nOutImage = 0;
|
||||
pOutput->nOutImagePartial = 0;
|
||||
pOutput->nOutPresentImagePartial = 2;
|
||||
|
||||
// Delete screenshot image to be remade if needed
|
||||
for (auto& pScreenshotImage : pOutput->pScreenshotImages)
|
||||
|
@ -3578,42 +3574,21 @@ bool vulkan_screenshot( const struct FrameInfo_t *frameInfo, std::shared_ptr<CVu
|
|||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::thread> partial_wait_thread;
|
||||
uint64_t partial_sequence = 0;
|
||||
std::unique_ptr<std::thread> defer_wait_thread;
|
||||
uint64_t defer_sequence = 0;
|
||||
|
||||
bool vulkan_composite( const struct FrameInfo_t *frameInfo, std::shared_ptr<CVulkanTexture> pPipewireTexture, bool partial )
|
||||
bool vulkan_composite( const struct FrameInfo_t *frameInfo, std::shared_ptr<CVulkanTexture> pPipewireTexture, bool partial, bool defer )
|
||||
{
|
||||
if ( partial_wait_thread )
|
||||
if ( defer_wait_thread )
|
||||
{
|
||||
partial_wait_thread->join();
|
||||
partial_wait_thread = nullptr;
|
||||
defer_wait_thread->join();
|
||||
defer_wait_thread = nullptr;
|
||||
|
||||
g_device.resetCmdBuffers(partial_sequence);
|
||||
partial_sequence = 0;
|
||||
g_device.resetCmdBuffers(defer_sequence);
|
||||
defer_sequence = 0;
|
||||
}
|
||||
|
||||
if ( partial )
|
||||
{
|
||||
if ( !g_bWasPartialComposite )
|
||||
{
|
||||
g_output.nOutPresentImagePartial = g_output.nOutImage;
|
||||
g_output.nOutImagePartial = g_output.nOutImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_output.nOutPresentImagePartial = g_output.nOutImagePartial;
|
||||
}
|
||||
g_output.nOutImagePartial = ( g_output.nOutImagePartial + 1 ) % 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_bWasPartialComposite)
|
||||
{
|
||||
g_output.nOutImage = ( g_output.nOutImagePartial + 1 ) % 3;
|
||||
}
|
||||
}
|
||||
|
||||
auto compositeImage = partial ? g_output.outputImagesPartialOverlay[ g_output.nOutImagePartial ] : g_output.outputImages[ g_output.nOutImage ];
|
||||
auto compositeImage = partial ? g_output.outputImagesPartialOverlay[ g_output.nOutImage ] : g_output.outputImages[ g_output.nOutImage ];
|
||||
|
||||
auto cmdBuffer = g_device.commandBuffer();
|
||||
|
||||
|
@ -3797,36 +3772,52 @@ bool vulkan_composite( const struct FrameInfo_t *frameInfo, std::shared_ptr<CVul
|
|||
|
||||
uint64_t sequence = g_device.submit(std::move(cmdBuffer));
|
||||
|
||||
if ( partial )
|
||||
if ( defer )
|
||||
{
|
||||
partial_wait_thread = std::make_unique<std::thread>([sequence]
|
||||
defer_wait_thread = std::make_unique<std::thread>([sequence]
|
||||
{
|
||||
g_device.wait(sequence, false);
|
||||
});
|
||||
defer_sequence = sequence;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_device.wait(sequence);
|
||||
}
|
||||
|
||||
if ( !BIsSDLSession() )
|
||||
{
|
||||
g_output.nOutImage = !g_output.nOutImage;
|
||||
}
|
||||
g_output.nOutImage = ( g_output.nOutImage + 1 ) % 3;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<CVulkanTexture> vulkan_get_last_output_image( bool partial )
|
||||
std::shared_ptr<CVulkanTexture> vulkan_get_last_output_image( bool partial, bool defer )
|
||||
{
|
||||
// Get previous image ( +2 )
|
||||
// 1 2 3
|
||||
// |
|
||||
// |
|
||||
uint32_t nRegularImage = ( g_output.nOutImage + 2 ) % 3;
|
||||
|
||||
// Get previous previous image ( +1 )
|
||||
// 1 2 3
|
||||
// |
|
||||
// |
|
||||
uint32_t nDeferredImage = ( g_output.nOutImage + 1 ) % 3;
|
||||
|
||||
uint32_t nOutImage = defer ? nDeferredImage : nRegularImage;
|
||||
|
||||
if ( partial )
|
||||
{
|
||||
uint32_t nOutImage = g_output.nOutPresentImagePartial;
|
||||
//vk_log.infof( "Partial overlay frame: %d", nOutImage );
|
||||
|
||||
//vk_log.infof( "Partial overlay frame: %d", nDeferredImage );
|
||||
return g_output.outputImagesPartialOverlay[ nOutImage ];
|
||||
}
|
||||
|
||||
return g_output.outputImages[ !g_output.nOutImage ];
|
||||
|
||||
return g_output.outputImages[ nOutImage ];
|
||||
}
|
||||
|
||||
bool vulkan_primary_dev_id(dev_t *id)
|
||||
|
|
|
@ -329,8 +329,8 @@ std::shared_ptr<CVulkanTexture> vulkan_create_texture_from_dmabuf( struct wlr_dm
|
|||
std::shared_ptr<CVulkanTexture> vulkan_create_texture_from_bits( uint32_t width, uint32_t height, uint32_t contentWidth, uint32_t contentHeight, uint32_t drmFormat, CVulkanTexture::createFlags texCreateFlags, void *bits );
|
||||
std::shared_ptr<CVulkanTexture> vulkan_create_texture_from_wlr_buffer( struct wlr_buffer *buf );
|
||||
|
||||
bool vulkan_composite( const struct FrameInfo_t *frameInfo, std::shared_ptr<CVulkanTexture> pScreenshotTexture, bool partial );
|
||||
std::shared_ptr<CVulkanTexture> vulkan_get_last_output_image( bool partial );
|
||||
bool vulkan_composite( const struct FrameInfo_t *frameInfo, std::shared_ptr<CVulkanTexture> pScreenshotTexture, bool partial, bool deferred );
|
||||
std::shared_ptr<CVulkanTexture> vulkan_get_last_output_image( bool partial, bool defer );
|
||||
std::shared_ptr<CVulkanTexture> vulkan_acquire_screenshot_texture(uint32_t width, uint32_t height, bool exportable, uint32_t drmFormat, EStreamColorspace colorspace = k_EStreamColorspace_Unknown);
|
||||
|
||||
void vulkan_present_to_window( void );
|
||||
|
|
|
@ -2435,6 +2435,7 @@ paint_all(bool async)
|
|||
bNeedsFullComposite |= !!(g_uCompositeDebug & CompositeDebugFlag::Heatmap);
|
||||
|
||||
static int g_nLastSingleOverlayZPos = 0;
|
||||
static bool g_bWasCompositing = false;
|
||||
|
||||
if ( !bNeedsFullComposite && !bWantsPartialComposite )
|
||||
{
|
||||
|
@ -2443,6 +2444,7 @@ paint_all(bool async)
|
|||
{
|
||||
bDoComposite = false;
|
||||
g_bWasPartialComposite = false;
|
||||
g_bWasCompositing = false;
|
||||
if ( frameInfo.layerCount == 2 )
|
||||
g_nLastSingleOverlayZPos = frameInfo.layers[1].zpos;
|
||||
}
|
||||
|
@ -2497,6 +2499,13 @@ paint_all(bool async)
|
|||
}
|
||||
}
|
||||
|
||||
// If we ever promoted from partial -> full, for the first frame
|
||||
// do NOT defer this partial composition.
|
||||
// We were already stalling for the full composition before, so it's not an issue
|
||||
// for latency, we just need to make sure we get 1 partial frame that isn't deferred
|
||||
// in time so we don't lose layers.
|
||||
bool bDefer = !bNeedsFullComposite && ( !g_bWasCompositing || g_bWasPartialComposite );
|
||||
|
||||
// If doing a partial composition then remove the baseplane
|
||||
// from our frameinfo to composite.
|
||||
if ( !bNeedsFullComposite )
|
||||
|
@ -2511,14 +2520,16 @@ paint_all(bool async)
|
|||
compositeFrameInfo.shaperLut[ nEOTF ] = nullptr;
|
||||
compositeFrameInfo.lut3D[ nEOTF ] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// If using composite debug markers, make sure we mark them as partial
|
||||
// so we know!
|
||||
if ( g_uCompositeDebug & CompositeDebugFlag::Markers )
|
||||
if ( bDefer && !!( g_uCompositeDebug & CompositeDebugFlag::Markers ) )
|
||||
g_uCompositeDebug |= CompositeDebugFlag::Markers_Partial;
|
||||
}
|
||||
|
||||
bool bResult = vulkan_composite( &compositeFrameInfo, pPipewireTexture, !bNeedsFullComposite );
|
||||
bool bResult = vulkan_composite( &compositeFrameInfo, pPipewireTexture, !bNeedsFullComposite, bDefer );
|
||||
|
||||
g_bWasCompositing = true;
|
||||
|
||||
g_uCompositeDebug &= ~CompositeDebugFlag::Markers_Partial;
|
||||
|
||||
|
@ -2559,7 +2570,7 @@ paint_all(bool async)
|
|||
baseLayer->opacity = 1.0;
|
||||
baseLayer->zpos = g_zposBase;
|
||||
|
||||
baseLayer->tex = vulkan_get_last_output_image( false );
|
||||
baseLayer->tex = vulkan_get_last_output_image( false, false );
|
||||
baseLayer->fbid = baseLayer->tex->fbid();
|
||||
baseLayer->applyColorMgmt = false;
|
||||
baseLayer->allowBlending = false;
|
||||
|
@ -2571,7 +2582,7 @@ paint_all(bool async)
|
|||
}
|
||||
else
|
||||
{
|
||||
if ( g_bWasPartialComposite )
|
||||
if ( g_bWasPartialComposite || !bDefer )
|
||||
{
|
||||
presentCompFrameInfo.applyOutputColorMgmt = true;
|
||||
presentCompFrameInfo.layerCount = 2;
|
||||
|
@ -2585,7 +2596,7 @@ paint_all(bool async)
|
|||
overlayLayer->opacity = 1.0;
|
||||
overlayLayer->zpos = g_zposOverlay;
|
||||
|
||||
overlayLayer->tex = vulkan_get_last_output_image( true );
|
||||
overlayLayer->tex = vulkan_get_last_output_image( true, bDefer );
|
||||
overlayLayer->fbid = overlayLayer->tex->fbid();
|
||||
overlayLayer->applyColorMgmt = true;
|
||||
overlayLayer->allowBlending = true;
|
||||
|
|
Loading…
Reference in a new issue