Skip to content

Commit 01c47b9

Browse files
oSoMoNmisyltoad
authored andcommitted
rendervulkan: define two separate texture pools for screenshots and video capture
Avoids running out of textures when requesting a screenshot while a screen capture is ongoing. Both pools can hold two textures to account for concurrent requests in different formats or at different resolutions.
1 parent 1d1495b commit 01c47b9

3 files changed

Lines changed: 53 additions & 32 deletions

File tree

src/rendervulkan.cpp

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3247,9 +3247,11 @@ bool vulkan_remake_swapchain( void )
32473247

32483248
g_device.vk.DestroySwapchainKHR( g_device.device(), pOutput->swapChain, nullptr );
32493249

3250-
// Delete screenshot image to be remade if needed
3251-
for (auto& pScreenshotImage : pOutput->pScreenshotImages)
3252-
pScreenshotImage = nullptr;
3250+
// Delete screenshot/capture textures to be remade if needed
3251+
for (auto& pScreenshotTexture : pOutput->pScreenshotTextures)
3252+
pScreenshotTexture = nullptr;
3253+
for (auto& pCaptureTexture : pOutput->pCaptureTextures)
3254+
pCaptureTexture = nullptr;
32533255

32543256
bool bRet = vulkan_make_swapchain( pOutput );
32553257
assert( bRet ); // Something has gone horribly wrong!
@@ -3343,9 +3345,11 @@ bool vulkan_remake_output_images()
33433345

33443346
pOutput->nOutImage = 0;
33453347

3346-
// Delete screenshot image to be remade if needed
3347-
for (auto& pScreenshotImage : pOutput->pScreenshotImages)
3348-
pScreenshotImage = nullptr;
3348+
// Delete screenshot/capture textures to be remade if needed
3349+
for (auto& pScreenshotTexture : pOutput->pScreenshotTextures)
3350+
pScreenshotTexture = nullptr;
3351+
for (auto& pCaptureTexture : pOutput->pCaptureTextures)
3352+
pCaptureTexture = nullptr;
33493353

33503354
bool bRet = vulkan_make_output_images( pOutput );
33513355
assert( bRet );
@@ -3593,51 +3597,66 @@ void vulkan_garbage_collect( void )
35933597
g_device.garbageCollect();
35943598
}
35953599

3596-
gamescope::Rc<CVulkanTexture> vulkan_acquire_screenshot_texture(uint32_t width, uint32_t height, bool exportable, uint32_t drmFormat, EStreamColorspace colorspace)
3600+
static gamescope::Rc<CVulkanTexture> acquire_pooled_texture( auto& pool, uint32_t width, uint32_t height, bool exportable, uint32_t drmFormat, EStreamColorspace colorspace )
35973601
{
3598-
for (auto& pScreenshotImage : g_output.pScreenshotImages)
3602+
for (auto& pTexture : pool)
35993603
{
3600-
// Evict a stale screenshot image, and reuse it
3601-
if (pScreenshotImage && pScreenshotImage->GetRefCount() == 0 &&
3602-
(width != pScreenshotImage->width() ||
3603-
height != pScreenshotImage->height() ||
3604-
drmFormat != pScreenshotImage->drmFormat()))
3604+
// Evict a stale texture and reuse the slot
3605+
if (pTexture && pTexture->GetRefCount() == 0 &&
3606+
(width != pTexture->width() ||
3607+
height != pTexture->height() ||
3608+
drmFormat != pTexture->drmFormat()))
36053609
{
3606-
pScreenshotImage = nullptr;
3610+
pTexture = nullptr;
36073611
}
36083612

3609-
if (pScreenshotImage == nullptr)
3613+
if (pTexture == nullptr)
36103614
{
3611-
pScreenshotImage = new CVulkanTexture();
3615+
pTexture = new CVulkanTexture();
36123616

3613-
CVulkanTexture::createFlags screenshotImageFlags;
3614-
screenshotImageFlags.bMappable = true;
3615-
screenshotImageFlags.bTransferDst = true;
3616-
screenshotImageFlags.bStorage = true;
3617+
CVulkanTexture::createFlags textureFlags;
3618+
textureFlags.bMappable = true;
3619+
textureFlags.bTransferDst = true;
3620+
textureFlags.bStorage = true;
36173621
if (exportable || drmFormat == DRM_FORMAT_NV12) {
3618-
screenshotImageFlags.bExportable = true;
3619-
screenshotImageFlags.bLinear = true; // TODO: support multi-planar DMA-BUF export via PipeWire
3622+
textureFlags.bExportable = true;
3623+
textureFlags.bLinear = true; // TODO: support multi-planar DMA-BUF export via PipeWire
36203624
}
36213625

3622-
bool bSuccess = pScreenshotImage->BInit( width, height, 1u, drmFormat, screenshotImageFlags );
3623-
pScreenshotImage->setStreamColorspace(colorspace);
3626+
bool bSuccess = pTexture->BInit( width, height, 1u, drmFormat, textureFlags );
3627+
pTexture->setStreamColorspace(colorspace);
36243628

36253629
assert( bSuccess );
36263630
}
36273631

3628-
if (pScreenshotImage->GetRefCount() != 0 ||
3629-
width != pScreenshotImage->width() ||
3630-
height != pScreenshotImage->height() ||
3631-
drmFormat != pScreenshotImage->drmFormat())
3632+
if (pTexture->GetRefCount() != 0 ||
3633+
width != pTexture->width() ||
3634+
height != pTexture->height() ||
3635+
drmFormat != pTexture->drmFormat())
36323636
continue;
36333637

3634-
return pScreenshotImage.get();
3638+
return pTexture.get();
36353639
}
36363640

3637-
vk_log.errorf("Unable to acquire screenshot texture. Out of textures.");
36383641
return nullptr;
36393642
}
36403643

3644+
gamescope::Rc<CVulkanTexture> vulkan_acquire_screenshot_texture(uint32_t width, uint32_t height, bool exportable, uint32_t drmFormat, EStreamColorspace colorspace)
3645+
{
3646+
auto texture = acquire_pooled_texture(g_output.pScreenshotTextures, width, height, exportable, drmFormat, colorspace);
3647+
if (!texture)
3648+
vk_log.errorf("Unable to acquire screenshot texture. Out of textures.");
3649+
return texture;
3650+
}
3651+
3652+
gamescope::Rc<CVulkanTexture> vulkan_acquire_capture_texture(uint32_t width, uint32_t height, bool exportable, uint32_t drmFormat, EStreamColorspace colorspace)
3653+
{
3654+
auto texture = acquire_pooled_texture(g_output.pCaptureTextures, width, height, exportable, drmFormat, colorspace);
3655+
if (!texture)
3656+
vk_log.errorf("Unable to acquire capture texture. Out of textures.");
3657+
return texture;
3658+
}
3659+
36413660
// Internal display's native brightness.
36423661
float g_flInternalDisplayBrightnessNits = 500.0f;
36433662

src/rendervulkan.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ std::optional<uint64_t> vulkan_composite( struct FrameInfo_t *frameInfo, gamesco
412412
void vulkan_wait( uint64_t ulSeqNo, bool bReset );
413413
gamescope::Rc<CVulkanTexture> vulkan_get_last_output_image( bool partial, bool defer );
414414
gamescope::Rc<CVulkanTexture> vulkan_acquire_screenshot_texture(uint32_t width, uint32_t height, bool exportable, uint32_t drmFormat, EStreamColorspace colorspace = k_EStreamColorspace_Unknown);
415+
gamescope::Rc<CVulkanTexture> vulkan_acquire_capture_texture(uint32_t width, uint32_t height, bool exportable, uint32_t drmFormat, EStreamColorspace colorspace = k_EStreamColorspace_Unknown);
415416

416417
void vulkan_present_to_window( void );
417418

@@ -537,7 +538,8 @@ struct VulkanOutput_t
537538
uint32_t uOutputFormat = DRM_FORMAT_INVALID;
538539
uint32_t uOutputFormatOverlay = DRM_FORMAT_INVALID;
539540

540-
std::array<gamescope::OwningRc<CVulkanTexture>, 2> pScreenshotImages;
541+
std::array<gamescope::OwningRc<CVulkanTexture>, 2> pScreenshotTextures;
542+
std::array<gamescope::OwningRc<CVulkanTexture>, 2> pCaptureTextures;
541543

542544
// NIS and FSR
543545
gamescope::OwningRc<CVulkanTexture> tmpOutput;

src/steamcompmgr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2405,7 +2405,7 @@ static void paint_pipewire()
24052405
}
24062406

24072407
gamescope::Rc<CVulkanTexture> pRGBTexture = s_pPipewireBuffer->texture->isYcbcr()
2408-
? vulkan_acquire_screenshot_texture( uWidth, uHeight, false, DRM_FORMAT_XRGB2101010 )
2408+
? vulkan_acquire_capture_texture( uWidth, uHeight, false, DRM_FORMAT_XRGB2101010 )
24092409
: gamescope::Rc<CVulkanTexture>{ s_pPipewireBuffer->texture };
24102410

24112411
gamescope::Rc<CVulkanTexture> pYUVTexture = s_pPipewireBuffer->texture->isYcbcr() ? s_pPipewireBuffer->texture : nullptr;

0 commit comments

Comments
 (0)