@@ -520,25 +520,110 @@ static void WriteRGBAFormattedVariant(
520520 TransferRGBAFormattedVariantColor (dstFormat, dataType, dstBuffer, idx, value);
521521}
522522
523+ // Worker thread procedure for the "ConvertImageBufferFormat" function
524+ static void ConvertImageBufferFormatWorker (
525+ const ImageView& srcImageView,
526+ const MutableImageView& dstImageView,
527+ const ImageOperationMemoryInfo& memoryInfo,
528+ const Extent3D& extent,
529+ std::size_t begin,
530+ std::size_t end)
531+ {
532+ VariantConstBuffer srcBuffer = srcImageView.data ;
533+ VariantBuffer dstBuffer = dstImageView.data ;
534+
535+ ApplyPaddingOffset (srcBuffer, dstBuffer, begin, memoryInfo, extent);
536+
537+ const std::uint32_t layerSize = extent.width * extent.height ;
538+
539+ /* Initialize default variant color (0, 0, 0, 1) */
540+ VariantColor colorValue{ UninitializeTag{} };
541+
542+ SetVariantMinMax (srcImageView.dataType , colorValue.r , true );
543+ SetVariantMinMax (srcImageView.dataType , colorValue.g , true );
544+ SetVariantMinMax (srcImageView.dataType , colorValue.b , true );
545+ SetVariantMinMax (srcImageView.dataType , colorValue.a , false );
546+
547+ for_subrange (i, begin, end)
548+ {
549+ /* Apply source and destination stride when passing an edge */
550+ AdvancePaddingOffsetAtEdge (srcBuffer, dstBuffer, i, begin, memoryInfo, extent.width , layerSize);
551+
552+ /* Read RGBA variant from source buffer */
553+ ReadRGBAFormattedVariant (srcImageView.format , srcImageView.dataType , srcBuffer, i, colorValue);
554+
555+ /* Write RGBA variant to destination buffer */
556+ WriteRGBAFormattedVariant (dstImageView.format , dstImageView.dataType , dstBuffer, i, colorValue);
557+ }
558+ }
559+
560+ static std::size_t ConvertImageBufferFormat (
561+ const ImageView& srcImageView,
562+ const MutableImageView& dstImageView,
563+ const Extent3D& extent,
564+ unsigned threadCount)
565+ {
566+ LLGL_ASSERT (srcImageView.dataType == dstImageView.dataType );
567+
568+ /* Validate destination buffer size */
569+ const std::size_t numPixels = extent.width * extent.height * extent.depth ;
570+
571+ ImageOperationMemoryInfo memoryInfo = {};
572+ GetImageOperationMemoryInfo (memoryInfo, srcImageView, dstImageView, extent);
573+
574+ LLGL_ASSERT (
575+ dstImageView.dataSize >= memoryInfo.dstImageSize ,
576+ " destination image buffer is too small to convert image format; expected %zu, but %zu was specified" ,
577+ memoryInfo.dstImageSize , dstImageView.dataSize
578+ );
579+
580+ /* Get variant buffer for source and destination images */
581+ DoConcurrentRange (
582+ std::bind (
583+ ConvertImageBufferFormatWorker,
584+ std::cref (srcImageView),
585+ std::cref (dstImageView),
586+ std::cref (memoryInfo),
587+ std::cref (extent),
588+ std::placeholders::_1,
589+ std::placeholders::_2
590+ ),
591+ numPixels,
592+ threadCount
593+ );
594+
595+ return memoryInfo.dstImageSize ;
596+ }
597+
598+ static float UnpackD24UNorm (std::uint32_t value)
599+ {
600+ return (static_cast <float >(value) / static_cast <float >(0x00FFFFFFu ));
601+ }
602+
523603static void ReadDepthStencilValue (
524604 ImageFormat srcFormat, DataType dataType, const VariantConstBuffer& srcBuffer, std::size_t idx, DepthStencilValue& value)
525605{
526606 if (srcFormat == ImageFormat::Depth && dataType == DataType::UInt16)
527607 {
528- /* Read D16UNorm format: Decompress 16-bit float */
529- value.depth = DecompressFloat16 (srcBuffer.uint16 [idx]);
608+ /* Read D16UNorm format: Decode 16-bit unsigned normalized depth */
609+ value.depth = static_cast < float > (srcBuffer.uint16 [idx]) / static_cast < float >( 0x0000FFFFu );
530610 }
531- else if (srcFormat == ImageFormat::DepthStencil && dataType == DataType::UInt32 )
611+ else if (srcFormat == ImageFormat::Depth && dataType == DataType::Float16 )
532612 {
533- /* Read D24UNormS8UInt format: Decompress 24-bit float and 8-bit unsigned integer */
534- value.depth = static_cast <float >(srcBuffer.uint32 [idx] & 0x00FFFFFFu ) / static_cast <float >(0x00FFFFFFu );
535- value.stencil = srcBuffer.uint32 [idx] >> 24 ;
613+ /* Read R16Float format: Decompress 16-bit float */
614+ value.depth = DecompressFloat16 (srcBuffer.uint16 [idx]);
536615 }
537616 else if (srcFormat == ImageFormat::Depth && dataType == DataType::Float32)
538617 {
539618 /* Read D32Float format: Copy 32-bit float */
540619 value.depth = srcBuffer.real32 [idx];
541620 }
621+ else if (srcFormat == ImageFormat::DepthStencil && dataType == DataType::UInt32)
622+ {
623+ /* Read D24UNormS8UInt format: Decode 24-bit unsigned normalized depth and 8-bit unsigned stencil */
624+ value.depth = UnpackD24UNorm (srcBuffer.uint32 [idx] & 0x00FFFFFF );
625+ value.stencil = (srcBuffer.uint32 [idx] >> 24 );
626+ }
542627 else if (srcFormat == ImageFormat::DepthStencil && dataType == DataType::Float32)
543628 {
544629 /* Read D32FloatS8X24UInt format: Copy 32-bit float and 8-bit unsigned integer */
@@ -557,25 +642,34 @@ static void ReadDepthStencilValue(
557642 }
558643}
559644
645+ static std::uint32_t PackD24UNorm (float value)
646+ {
647+ return static_cast <std::uint32_t >(value * static_cast <float >(0x00FFFFFFu ));
648+ }
649+
560650static void WriteDepthStencilValue (
561651 ImageFormat dstFormat, DataType dataType, VariantBuffer& dstBuffer, std::size_t idx, const DepthStencilValue& value)
562652{
563653 if (dstFormat == ImageFormat::Depth && dataType == DataType::UInt16)
564654 {
565- /* Write D16UNorm format: Compress 16-bit float */
566- dstBuffer.uint16 [idx] = CompressFloat16 (value.depth );
655+ /* Write D16UNorm format: Encode 16-bit unsigned normalized depth */
656+ dstBuffer.uint16 [idx] = static_cast <std:: uint16_t > (value.depth * static_cast < float >( 0x0000FFFFu ) );
567657 }
568- else if (dstFormat == ImageFormat::DepthStencil && dataType == DataType::UInt32 )
658+ else if (dstFormat == ImageFormat::Depth && dataType == DataType::Float16 )
569659 {
570- /* Write D24UNormS8UInt format: Decompress 24-bit float and 8-bit unsigned integer */
571- const std::uint32_t depth24 = static_cast <std::uint32_t >(value.depth * static_cast <float >(0x00FFFFFFu ));
572- dstBuffer.uint32 [idx] = ((value.stencil & 0x000000FFu )) << 24 | (depth24 & 0x00FFFFFFu );
660+ /* Write R16Float format: Compress 16-bit float */
661+ dstBuffer.uint16 [idx] = CompressFloat16 (value.depth );
573662 }
574663 else if (dstFormat == ImageFormat::Depth && dataType == DataType::Float32)
575664 {
576665 /* Write D32Float format: Copy 32-bit float */
577666 dstBuffer.real32 [idx] = value.depth ;
578667 }
668+ else if (dstFormat == ImageFormat::DepthStencil && dataType == DataType::UInt32)
669+ {
670+ /* Write D24UNormS8UInt format: Encode 24-bit unsigned normalized depth and 8-bit unsigned stencil */
671+ dstBuffer.uint32 [idx] = (value.stencil << 24 ) | (PackD24UNorm (value.depth ) & 0x00FFFFFF );
672+ }
579673 else if (dstFormat == ImageFormat::DepthStencil && dataType == DataType::Float32)
580674 {
581675 /* Read D32FloatS8X24UInt format: Copy 32-bit float and 8-bit unsigned integer */
@@ -594,12 +688,31 @@ static void WriteDepthStencilValue(
594688 }
595689}
596690
597- // Worker thread procedure for the "ConvertImageBufferFormat" function
598- static void ConvertImageBufferFormatWorker (
691+ static float UInt32AsFloat32 (std::uint32_t value)
692+ {
693+ return *reinterpret_cast <const float *>(&value);
694+ }
695+
696+ static std::uint32_t Float32AsUInt32 (float value)
697+ {
698+ return *reinterpret_cast <const std::uint32_t *>(&value);
699+ }
700+
701+ static void MergeDepthStencilValues (
702+ DepthStencilValue& dst, const DepthStencilValue& src, std::uint32_t srcDepthMask, std::uint32_t srcStencilMask)
703+ {
704+ dst.depth = UInt32AsFloat32 ((Float32AsUInt32 (dst.depth ) & ~srcDepthMask) | (Float32AsUInt32 (src.depth ) & srcDepthMask));
705+ dst.stencil = (dst.stencil & ~srcStencilMask) | (src.stencil & srcStencilMask);
706+ }
707+
708+ // Worker thread procedure for the "ConvertDepthStencilImageBufferFormat" function
709+ static void ConvertDepthStencilImageBufferFormatWorker (
599710 const ImageView& srcImageView,
600711 const MutableImageView& dstImageView,
601712 const ImageOperationMemoryInfo& memoryInfo,
602713 const Extent3D& extent,
714+ std::uint32_t depthMask,
715+ std::uint32_t stencilMask,
603716 std::size_t begin,
604717 std::size_t end)
605718{
@@ -610,54 +723,36 @@ static void ConvertImageBufferFormatWorker(
610723
611724 const std::uint32_t layerSize = extent.width * extent.height ;
612725
613- if (IsDepthOrStencilFormat (srcImageView.format ))
614- {
615- /* Initialize default depth-stencil value (0, 0) */
616- DepthStencilValue depthStencilValue{ 0 .0f , 0u };
726+ /* Initialize default depth-stencil value (0, 0) */
727+ DepthStencilValue depthStencilValueSrc{ 0 .0f , 0u };
728+ DepthStencilValue depthStencilValueDst{ 0 .0f , 0u };
617729
618- for_subrange (i, begin, end)
619- {
620- /* Apply source and destination stride when passing an edge */
621- AdvancePaddingOffsetAtEdge (srcBuffer, dstBuffer, i, begin, memoryInfo, extent.width , layerSize);
622-
623- /* Read depth-stencil value from source buffer */
624- ReadDepthStencilValue (srcImageView.format , srcImageView.dataType , srcBuffer, i, depthStencilValue);
625-
626- /* Write depth-stencil value to destination buffer */
627- WriteDepthStencilValue (dstImageView.format , dstImageView.dataType , dstBuffer, i, depthStencilValue);
628- }
629- }
630- else
730+ for_subrange (i, begin, end)
631731 {
632- /* Initialize default variant color (0, 0, 0, 1) */
633- VariantColor colorValue{ UninitializeTag{} } ;
732+ /* Apply source and destination stride when passing an edge */
733+ AdvancePaddingOffsetAtEdge (srcBuffer, dstBuffer, i, begin, memoryInfo, extent. width , layerSize) ;
634734
635- SetVariantMinMax (srcImageView.dataType , colorValue.r , true );
636- SetVariantMinMax (srcImageView.dataType , colorValue.g , true );
637- SetVariantMinMax (srcImageView.dataType , colorValue.b , true );
638- SetVariantMinMax (srcImageView.dataType , colorValue.a , false );
735+ /* Read depth-stencil value from source buffer */
736+ ReadDepthStencilValue (srcImageView.format , srcImageView.dataType , srcBuffer, i, depthStencilValueSrc);
737+ ReadDepthStencilValue (dstImageView.format , dstImageView.dataType , VariantConstBuffer{ dstBuffer.uint8 }, i, depthStencilValueDst);
639738
640- for_subrange (i, begin, end)
641- {
642- /* Apply source and destination stride when passing an edge */
643- AdvancePaddingOffsetAtEdge (srcBuffer, dstBuffer, i, begin, memoryInfo, extent.width , layerSize);
739+ /* Apply masking */
740+ MergeDepthStencilValues (depthStencilValueDst, depthStencilValueSrc, depthMask, stencilMask);
644741
645- /* Read RGBA variant from source buffer */
646- ReadRGBAFormattedVariant (srcImageView.format , srcImageView.dataType , srcBuffer, i, colorValue);
647-
648- /* Write RGBA variant to destination buffer */
649- WriteRGBAFormattedVariant (dstImageView.format , dstImageView.dataType , dstBuffer, i, colorValue);
650- }
742+ /* Write depth-stencil value to destination buffer */
743+ WriteDepthStencilValue (dstImageView.format , dstImageView.dataType , dstBuffer, i, depthStencilValueDst);
651744 }
652745}
653746
654- static std::size_t ConvertImageBufferFormat (
747+ static std::size_t ConvertDepthStencilImageBufferFormat (
655748 const ImageView& srcImageView,
656749 const MutableImageView& dstImageView,
657750 const Extent3D& extent,
751+ std::uint32_t depthMask,
752+ std::uint32_t stencilMask,
658753 unsigned threadCount)
659754{
660- LLGL_ASSERT (IsDepthOrStencilFormat (srcImageView.format ) || srcImageView. dataType == dstImageView. dataType );
755+ LLGL_ASSERT (IsDepthOrStencilFormat (srcImageView.format ));
661756
662757 /* Validate destination buffer size */
663758 const std::size_t numPixels = extent.width * extent.height * extent.depth ;
@@ -674,11 +769,13 @@ static std::size_t ConvertImageBufferFormat(
674769 /* Get variant buffer for source and destination images */
675770 DoConcurrentRange (
676771 std::bind (
677- ConvertImageBufferFormatWorker ,
772+ ConvertDepthStencilImageBufferFormatWorker ,
678773 std::cref (srcImageView),
679774 std::cref (dstImageView),
680775 std::cref (memoryInfo),
681776 std::cref (extent),
777+ depthMask,
778+ stencilMask,
682779 std::placeholders::_1,
683780 std::placeholders::_2
684781 ),
@@ -726,7 +823,9 @@ LLGL_EXPORT std::size_t ConvertImageBuffer(
726823 const MutableImageView& dstImageView,
727824 const Extent3D& extent,
728825 unsigned threadCount,
729- bool copyUnchangedImage)
826+ bool copyUnchangedImage,
827+ std::uint32_t depthMask,
828+ std::uint32_t stencilMask)
730829{
731830 /* Validate input parameters */
732831 ValidateSourceImageView (srcImageView);
@@ -736,7 +835,7 @@ LLGL_EXPORT std::size_t ConvertImageBuffer(
736835 if (IsDepthOrStencilFormat (srcImageView.format ))
737836 {
738837 /* Convert depth-stencil image format */
739- return ConvertImageBufferFormat (srcImageView, dstImageView, extent, threadCount);
838+ return ConvertDepthStencilImageBufferFormat (srcImageView, dstImageView, extent, depthMask, stencilMask , threadCount);
740839 }
741840 else if (srcImageView.dataType != dstImageView.dataType && srcImageView.format != dstImageView.format )
742841 {
0 commit comments