Skip to content

Commit 4bee7f8

Browse files
extended the screenshot extension to be able to convert image formats before attempting to save file
1 parent a4426a6 commit 4bee7f8

File tree

1 file changed

+61
-9
lines changed

1 file changed

+61
-9
lines changed

include/nbl/ext/ScreenShot/ScreenShot.h

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ namespace nbl
3232
- depth buffer is placed under video::EFAP_DEPTH_ATTACHMENT attachment
3333
*/
3434

35-
nbl::video::IFrameBuffer* createDefaultFBOForScreenshoting(core::smart_refctd_ptr<IrrlichtDevice> device)
35+
nbl::video::IFrameBuffer* createDefaultFBOForScreenshoting(core::smart_refctd_ptr<IrrlichtDevice> device, asset::E_FORMAT colorFormat=asset::EF_R8G8B8A8_SRGB)
3636
{
3737
auto driver = device->getVideoDriver();
3838

3939
auto createAttachement = [&](bool colorBuffer)
4040
{
4141
asset::ICPUImage::SCreationParams imgInfo;
42-
imgInfo.format = colorBuffer ? asset::EF_R8G8B8A8_SRGB : asset::EF_D24_UNORM_S8_UINT;
42+
imgInfo.format = colorBuffer ? colorFormat:asset::EF_D24_UNORM_S8_UINT;
4343
imgInfo.type = asset::ICPUImage::ET_2D;
4444
imgInfo.extent.width = driver->getScreenSize().Width;
4545
imgInfo.extent.height = driver->getScreenSize().Height;
@@ -69,7 +69,7 @@ namespace nbl
6969

7070
asset::ICPUImageView::SCreationParams imgViewInfo;
7171
imgViewInfo.image = std::move(image);
72-
imgViewInfo.format = colorBuffer ? asset::EF_R8G8B8A8_SRGB : asset::EF_D24_UNORM_S8_UINT;
72+
imgViewInfo.format = colorBuffer ? colorFormat:asset::EF_D24_UNORM_S8_UINT;
7373
imgViewInfo.viewType = asset::IImageView<asset::ICPUImage>::ET_2D;
7474
imgViewInfo.flags = static_cast<asset::ICPUImageView::E_CREATE_FLAGS>(0u);
7575
imgViewInfo.subresourceRange.baseArrayLayer = 0u;
@@ -117,7 +117,7 @@ namespace nbl
117117
/*
118118
Create a ScreenShot with gpu image usage and save it to a file.
119119
*/
120-
bool createScreenShot(video::IVideoDriver* driver, asset::IAssetManager* assetManager, const video::IGPUImageView* gpuImageView, const std::string& outFileName)
120+
bool createScreenShot(video::IVideoDriver* driver, asset::IAssetManager* assetManager, const video::IGPUImageView* gpuImageView, const std::string& outFileName, asset::E_FORMAT convertToFormat=asset::EF_UNKNOWN)
121121
{
122122
auto fetchedImageViewParmas = gpuImageView->getCreationParameters();
123123
auto gpuImage = fetchedImageViewParmas.image;
@@ -153,11 +153,65 @@ namespace nbl
153153
auto texelBuffer = core::make_smart_refctd_ptr<asset::CCustomAllocatorCPUBuffer<core::null_allocator<uint8_t>>>(memoryRequirements.vulkanReqs.size, destinationBoundMemory->getMappedPointer(), core::adopt_memory);
154154

155155
image->setBufferAndRegions(std::move(texelBuffer), regions);
156-
auto newCreationParams = image->getCreationParameters();
156+
157+
while (mapPointerGetterFence->waitCPU(1000ull, mapPointerGetterFence->canDeferredFlush()) == video::EDFR_TIMEOUT_EXPIRED) {}
158+
159+
core::smart_refctd_ptr<asset::ICPUImage> convertedImage;
160+
if (convertToFormat != asset::EF_UNKNOWN)
161+
{
162+
auto referenceImageParams = image->getCreationParameters();
163+
auto referenceBuffer = image->getBuffer();
164+
auto referenceRegions = image->getRegions();
165+
auto referenceRegion = referenceRegions.begin();
166+
const auto newTexelOrBlockByteSize = asset::getTexelOrBlockBytesize(convertToFormat);
167+
168+
auto newImageParams = referenceImageParams;
169+
auto newCpuBuffer = core::make_smart_refctd_ptr<asset::ICPUBuffer>(referenceBuffer->getSize() * newTexelOrBlockByteSize);
170+
auto newRegions = core::make_refctd_dynamic_array<core::smart_refctd_dynamic_array<asset::ICPUImage::SBufferCopy>>(referenceRegions.size());
171+
172+
for (auto newRegion = newRegions->begin(); newRegion != newRegions->end(); ++newRegion)
173+
{
174+
*newRegion = *(referenceRegion++);
175+
newRegion->bufferOffset = newRegion->bufferOffset * newTexelOrBlockByteSize;
176+
}
177+
178+
newImageParams.format = convertToFormat;
179+
convertedImage = asset::ICPUImage::create(std::move(newImageParams));
180+
convertedImage->setBufferAndRegions(std::move(newCpuBuffer), newRegions);
181+
182+
//asset::CConvertFormatImageFilter TODO: use this one instead with a nice dither @Anastazluk, we could also get rid of a lot of code here, since there's a bunch of constraints
183+
asset::CSwizzleAndConvertImageFilter<> convertFilter;
184+
asset::CSwizzleAndConvertImageFilter<>::state_type state;
185+
186+
state.swizzle = {};
187+
state.inImage = image.get();
188+
state.outImage = convertedImage.get();
189+
state.inOffset = { 0, 0, 0 };
190+
state.inBaseLayer = 0;
191+
state.outOffset = { 0, 0, 0 };
192+
state.outBaseLayer = 0;
193+
//state.dither = ;
194+
195+
for (auto itr = 0; itr < convertedImage->getCreationParameters().mipLevels; ++itr)
196+
{
197+
auto regionWithMipMap = convertedImage->getRegions(itr).begin();
198+
199+
state.extent = regionWithMipMap->getExtent();
200+
state.layerCount = regionWithMipMap->imageSubresource.layerCount;
201+
state.inMipLevel = regionWithMipMap->imageSubresource.mipLevel;
202+
state.outMipLevel = regionWithMipMap->imageSubresource.mipLevel;
203+
204+
const bool ok = convertFilter.execute(&state);
205+
assert(ok);
206+
}
207+
}
208+
else
209+
convertedImage = image;
210+
auto newCreationParams = convertedImage->getCreationParameters();
157211

158212
asset::ICPUImageView::SCreationParams viewParams;
159213
viewParams.flags = static_cast<asset::ICPUImageView::E_CREATE_FLAGS>(0u);
160-
viewParams.image = image;
214+
viewParams.image = convertedImage;
161215
viewParams.format = newCreationParams.format;
162216
viewParams.viewType = asset::ICPUImageView::ET_2D;
163217
viewParams.subresourceRange.baseArrayLayer = 0u;
@@ -172,10 +226,8 @@ namespace nbl
172226
asset::IAssetWriter::SAssetWriteParams wparams(asset);
173227
return assetManager->writeAsset(outFileName, wparams);
174228
};
175-
176-
while (mapPointerGetterFence->waitCPU(1000ull, mapPointerGetterFence->canDeferredFlush()) == video::EDFR_TIMEOUT_EXPIRED) {}
177229

178-
bool status = tryToWrite(image.get());
230+
bool status = tryToWrite(convertedImage.get());
179231
if (!status)
180232
status = tryToWrite(imageView.get());
181233

0 commit comments

Comments
 (0)