@@ -416,6 +416,54 @@ static uint16_t floatToUnorm16(float value) {
416416 return (uint16_t )((value * 65535.0f ) + 0.5f );
417417}
418418
419+ static void clampPixelRGBNonNegative (float pixel [static 4 ]) {
420+ if (!pixel ) return ;
421+ pixel [0 ] = fmaxf (pixel [0 ], 0.0f );
422+ pixel [1 ] = fmaxf (pixel [1 ], 0.0f );
423+ pixel [2 ] = fmaxf (pixel [2 ], 0.0f );
424+ }
425+
426+ static void normalizePixelRGB (float pixel [static 4 ]) {
427+ if (!pixel ) return ;
428+
429+ float lengthSquared = (pixel [0 ] * pixel [0 ]) + (pixel [1 ] * pixel [1 ]) + (pixel [2 ] * pixel [2 ]);
430+ if (lengthSquared > 1e-20f ) {
431+ float invLength = 1.0f / sqrtf (lengthSquared );
432+ pixel [0 ] *= invLength ;
433+ pixel [1 ] *= invLength ;
434+ pixel [2 ] *= invLength ;
435+ return ;
436+ }
437+
438+ pixel [0 ] = 0.0f ;
439+ pixel [1 ] = 0.0f ;
440+ pixel [2 ] = 0.0f ;
441+ }
442+
443+ static int prepareRGBA32FPixels (
444+ const RenderImageBuffer * source ,
445+ size_t pixelCount ,
446+ size_t byteCount ,
447+ float * converted
448+ ) {
449+ if (!source || !source -> pixels || !converted ) return 0 ;
450+
451+ if (source -> format == RENDER_IMAGE_BUFFER_FORMAT_RGBA32F ) {
452+ memcpy (converted , source -> pixels , byteCount );
453+ return 1 ;
454+ }
455+
456+ if (source -> format == RENDER_IMAGE_BUFFER_FORMAT_RGBA16F ) {
457+ const uint16_t * halfPixels = (const uint16_t * )source -> pixels ;
458+ for (size_t i = 0 ; i < pixelCount * 4u ; i ++ ) {
459+ converted [i ] = decodeHalfFloat (halfPixels [i ]);
460+ }
461+ return 1 ;
462+ }
463+
464+ return 0 ;
465+ }
466+
419467static int prepareRGBA32FBuffer (
420468 const RenderImageBuffer * source ,
421469 uint32_t width ,
@@ -438,14 +486,7 @@ static int prepareRGBA32FBuffer(
438486 float * converted = (float * )malloc (rgba32fByteCount );
439487 if (!converted ) return 0 ;
440488
441- if (source -> format == RENDER_IMAGE_BUFFER_FORMAT_RGBA32F ) {
442- memcpy (converted , source -> pixels , rgba32fByteCount );
443- } else if (source -> format == RENDER_IMAGE_BUFFER_FORMAT_RGBA16F ) {
444- const uint16_t * halfPixels = (const uint16_t * )source -> pixels ;
445- for (size_t i = 0 ; i < pixelCount * 4u ; i ++ ) {
446- converted [i ] = decodeHalfFloat (halfPixels [i ]);
447- }
448- } else {
489+ if (!prepareRGBA32FPixels (source , pixelCount , rgba32fByteCount , converted )) {
449490 free (converted );
450491 return 0 ;
451492 }
@@ -457,39 +498,41 @@ static int prepareRGBA32FBuffer(
457498 free (converted );
458499 return 0 ;
459500 }
501+ float pixel [4 ] = {
502+ converted [baseIndex + 0u ],
503+ converted [baseIndex + 1u ],
504+ converted [baseIndex + 2u ],
505+ converted [baseIndex + 3u ],
506+ };
460507
461- float * pixel = & converted [baseIndex ];
462- float sourceWeight = pixel [3 ];
463508 if (preserveSourceWeight ) {
464- pixel [3 ] = fmaxf (sourceWeight , 0.0f );
509+ pixel [3 ] = fmaxf (pixel [ 3 ] , 0.0f );
465510 if (pixel [3 ] <= 0.0f ) {
466511 pixel [0 ] = 0.0f ;
467512 pixel [1 ] = 0.0f ;
468513 pixel [2 ] = 0.0f ;
514+ converted [baseIndex + 0u ] = pixel [0 ];
515+ converted [baseIndex + 1u ] = pixel [1 ];
516+ converted [baseIndex + 2u ] = pixel [2 ];
517+ converted [baseIndex + 3u ] = pixel [3 ];
469518 continue ;
470519 }
471520 }
521+
472522 if (clampNonNegative ) {
473- pixel [0 ] = fmaxf (pixel [0 ], 0.0f );
474- pixel [1 ] = fmaxf (pixel [1 ], 0.0f );
475- pixel [2 ] = fmaxf (pixel [2 ], 0.0f );
523+ clampPixelRGBNonNegative (pixel );
476524 }
477525 if (normalizeVectors ) {
478- float lengthSquared = (pixel [0 ] * pixel [0 ]) + (pixel [1 ] * pixel [1 ]) + (pixel [2 ] * pixel [2 ]);
479- if (lengthSquared > 1e-20f ) {
480- float invLength = 1.0f / sqrtf (lengthSquared );
481- pixel [0 ] *= invLength ;
482- pixel [1 ] *= invLength ;
483- pixel [2 ] *= invLength ;
484- } else {
485- pixel [0 ] = 0.0f ;
486- pixel [1 ] = 0.0f ;
487- pixel [2 ] = 0.0f ;
488- }
526+ normalizePixelRGB (pixel );
489527 }
490528 if (!preserveSourceWeight ) {
491529 pixel [3 ] = 1.0f ;
492530 }
531+
532+ converted [baseIndex + 0u ] = pixel [0 ];
533+ converted [baseIndex + 1u ] = pixel [1 ];
534+ converted [baseIndex + 2u ] = pixel [2 ];
535+ converted [baseIndex + 3u ] = pixel [3 ];
493536 }
494537
495538 * outPixels = converted ;
@@ -639,6 +682,79 @@ static int prefilterDenoiseFeatureBuffer(
639682 return 0 ;
640683}
641684
685+ static int tryPrefilterDenoiseFeatureBufferInPlace (
686+ const char * outputLabel ,
687+ const char * featureLabel ,
688+ VKRT_OIDNAuxImage auxImage ,
689+ uint32_t width ,
690+ uint32_t height ,
691+ float * * inOutBuffer
692+ ) {
693+ if (!inOutBuffer || !* inOutBuffer ) return 0 ;
694+
695+ float * filtered = NULL ;
696+ if (!prefilterDenoiseFeatureBuffer (outputLabel , featureLabel , auxImage , * inOutBuffer , width , height , & filtered )) {
697+ return 0 ;
698+ }
699+
700+ free (* inOutBuffer );
701+ * inOutBuffer = filtered ;
702+ return 1 ;
703+ }
704+
705+ static void tryPrefilterDenoiseFeatureBuffers (
706+ const LinearRenderOutputRequest * request ,
707+ const char * outputLabel ,
708+ float * * albedo ,
709+ float * * normal ,
710+ int * outAlbedoPrefiltered ,
711+ int * outNormalPrefiltered
712+ ) {
713+ if (outAlbedoPrefiltered ) * outAlbedoPrefiltered = 0 ;
714+ if (outNormalPrefiltered ) * outNormalPrefiltered = 0 ;
715+ if (!request ) return ;
716+
717+ if (outAlbedoPrefiltered ) {
718+ * outAlbedoPrefiltered = tryPrefilterDenoiseFeatureBufferInPlace (
719+ outputLabel ,
720+ "albedo" ,
721+ VKRT_OIDN_AUX_IMAGE_ALBEDO ,
722+ request -> width ,
723+ request -> height ,
724+ albedo
725+ );
726+ }
727+ if (outNormalPrefiltered ) {
728+ * outNormalPrefiltered = tryPrefilterDenoiseFeatureBufferInPlace (
729+ outputLabel ,
730+ "normal" ,
731+ VKRT_OIDN_AUX_IMAGE_NORMAL ,
732+ request -> width ,
733+ request -> height ,
734+ normal
735+ );
736+ }
737+ }
738+
739+ static int reportDenoiseFailure (
740+ const LinearRenderOutputRequest * request ,
741+ const char * outputLabel ,
742+ const char * errorMessage
743+ ) {
744+ if (!request ) return 0 ;
745+
746+ if (!request -> allowRawFallback ) {
747+ LOG_ERROR ("OIDN denoising failed for '%s'" , outputLabel );
748+ } else {
749+ LOG_INFO ("OIDN denoising failed for '%s'; using raw render" , outputLabel );
750+ }
751+ if (errorMessage && errorMessage [0 ]) {
752+ LOG_INFO ("OIDN error detail: %s" , errorMessage );
753+ }
754+
755+ return request -> allowRawFallback ;
756+ }
757+
642758static int denoiseLinearRenderOutput (
643759 const LinearRenderOutputRequest * request ,
644760 const char * outputLabel ,
@@ -666,34 +782,14 @@ static int denoiseLinearRenderOutput(
666782 }
667783
668784 if (featureBuffersReady ) {
669- if (prefilterDenoiseFeatureBuffer (
670- outputLabel ,
671- "albedo" ,
672- VKRT_OIDN_AUX_IMAGE_ALBEDO ,
673- albedo ,
674- request -> width ,
675- request -> height ,
676- & prefilteredAlbedo
677- )) {
678- free (albedo );
679- albedo = prefilteredAlbedo ;
680- prefilteredAlbedo = NULL ;
681- albedoPrefiltered = 1 ;
682- }
683- if (prefilterDenoiseFeatureBuffer (
684- outputLabel ,
685- "normal" ,
686- VKRT_OIDN_AUX_IMAGE_NORMAL ,
687- normal ,
688- request -> width ,
689- request -> height ,
690- & prefilteredNormal
691- )) {
692- free (normal );
693- normal = prefilteredNormal ;
694- prefilteredNormal = NULL ;
695- normalPrefiltered = 1 ;
696- }
785+ tryPrefilterDenoiseFeatureBuffers (
786+ request ,
787+ outputLabel ,
788+ & albedo ,
789+ & normal ,
790+ & albedoPrefiltered ,
791+ & normalPrefiltered
792+ );
697793 }
698794
699795 const char * errorMessage = NULL ;
@@ -714,17 +810,7 @@ static int denoiseLinearRenderOutput(
714810 goto cleanup ;
715811 }
716812
717- if (!request -> allowRawFallback ) {
718- LOG_ERROR ("OIDN denoising failed for '%s'" , outputLabel );
719- } else {
720- LOG_INFO ("OIDN denoising failed for '%s'; using raw render" , outputLabel );
721- }
722- if (errorMessage && errorMessage [0 ]) {
723- LOG_INFO ("OIDN error detail: %s" , errorMessage );
724- }
725- if (request -> allowRawFallback ) {
726- succeeded = 1 ;
727- }
813+ succeeded = reportDenoiseFailure (request , outputLabel , errorMessage );
728814
729815cleanup :
730816 free (prefilteredNormal );
0 commit comments