NVIDIA OptiX 8.1 nvidia_logo_transpbg.gif Up
optix_denoiser_tiling.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: Copyright (c) 2019 - 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: BSD-3-Clause
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
34
35#ifndef OPTIX_DENOISER_TILING_H
36#define OPTIX_DENOISER_TILING_H
37
38#include <optix.h>
39
40#include <algorithm>
41#include <vector>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
56{
57 // input tile image
59
60 // output tile image
62
63 // overlap offsets, parameters for #optixUtilDenoiserInvoke
64 unsigned int inputOffsetX;
65 unsigned int inputOffsetY;
66};
67
75inline OptixResult optixUtilGetPixelStride( const OptixImage2D& image, unsigned int& pixelStrideInBytes )
76{
77 pixelStrideInBytes = image.pixelStrideInBytes;
78 if( pixelStrideInBytes == 0 )
79 {
80 switch( image.format )
81 {
83 pixelStrideInBytes = 1 * sizeof( short );
84 break;
86 pixelStrideInBytes = 2 * sizeof( short );
87 break;
89 pixelStrideInBytes = 3 * sizeof( short );
90 break;
92 pixelStrideInBytes = 4 * sizeof( short );
93 break;
95 pixelStrideInBytes = 1 * sizeof( float );
96 break;
98 pixelStrideInBytes = 2 * sizeof( float );
99 break;
101 pixelStrideInBytes = 3 * sizeof( float );
102 break;
104 pixelStrideInBytes = 4 * sizeof( float );
105 break;
107 pixelStrideInBytes = 3 * sizeof( char );
108 break;
110 pixelStrideInBytes = 4 * sizeof( char );
111 break;
114 break;
115 }
116 }
117 return OPTIX_SUCCESS;
118}
119
130 const OptixImage2D& input,
131 const OptixImage2D& output,
132 unsigned int overlapWindowSizeInPixels,
133 unsigned int tileWidth,
134 unsigned int tileHeight,
135 std::vector<OptixUtilDenoiserImageTile>& tiles )
136{
137 if( tileWidth == 0 || tileHeight == 0 )
139
140 unsigned int inPixelStride, outPixelStride;
141 if( const OptixResult res = optixUtilGetPixelStride( input, inPixelStride ) )
142 return res;
143 if( const OptixResult res = optixUtilGetPixelStride( output, outPixelStride ) )
144 return res;
145
146 int inp_w = std::min( tileWidth + 2 * overlapWindowSizeInPixels, input.width );
147 int inp_h = std::min( tileHeight + 2 * overlapWindowSizeInPixels, input.height );
148 int inp_y = 0, copied_y = 0;
149
150 int upscaleX = output.width / input.width;
151 int upscaleY = output.height / input.height;
152
153 do
154 {
155 int inputOffsetY = inp_y == 0 ? 0 : std::max( (int)overlapWindowSizeInPixels, inp_h - ( (int)input.height - inp_y ) );
156 int copy_y = inp_y == 0 ? std::min( input.height, tileHeight + overlapWindowSizeInPixels ) :
157 std::min( tileHeight, input.height - copied_y );
158
159 int inp_x = 0, copied_x = 0;
160 do
161 {
162 int inputOffsetX = inp_x == 0 ? 0 : std::max( (int)overlapWindowSizeInPixels, inp_w - ( (int)input.width - inp_x ) );
163 int copy_x = inp_x == 0 ? std::min( input.width, tileWidth + overlapWindowSizeInPixels ) :
164 std::min( tileWidth, input.width - copied_x );
165
167 tile.input.data = input.data + (size_t)( inp_y - inputOffsetY ) * input.rowStrideInBytes
168 + (size_t)( inp_x - inputOffsetX ) * inPixelStride;
169 tile.input.width = inp_w;
170 tile.input.height = inp_h;
173 tile.input.format = input.format;
174
175 tile.output.data = output.data + (size_t)( upscaleY * inp_y ) * output.rowStrideInBytes
176 + (size_t)( upscaleX * inp_x ) * outPixelStride;
177 tile.output.width = upscaleX * copy_x;
178 tile.output.height = upscaleY * copy_y;
181 tile.output.format = output.format;
182
183 tile.inputOffsetX = inputOffsetX;
184 tile.inputOffsetY = inputOffsetY;
185
186 tiles.push_back( tile );
187
188 inp_x += inp_x == 0 ? tileWidth + overlapWindowSizeInPixels : tileWidth;
189 copied_x += copy_x;
190 } while( inp_x < static_cast<int>( input.width ) );
191
192 inp_y += inp_y == 0 ? tileHeight + overlapWindowSizeInPixels : tileHeight;
193 copied_y += copy_y;
194 } while( inp_y < static_cast<int>( input.height ) );
195
196 return OPTIX_SUCCESS;
197}
198
202
209
226 OptixDenoiser denoiser,
227 CUstream stream,
228 const OptixDenoiserParams* params,
229 CUdeviceptr denoiserState,
230 size_t denoiserStateSizeInBytes,
231 const OptixDenoiserGuideLayer* guideLayer,
232 const OptixDenoiserLayer* layers,
233 unsigned int numLayers,
234 CUdeviceptr scratch,
235 size_t scratchSizeInBytes,
236 unsigned int overlapWindowSizeInPixels,
237 unsigned int tileWidth,
238 unsigned int tileHeight )
239{
240 if( !guideLayer || !layers )
242
243 const unsigned int upscale = numLayers > 0 && layers[0].previousOutput.width == 2 * layers[0].input.width ? 2 : 1;
244
245 std::vector<std::vector<OptixUtilDenoiserImageTile>> tiles( numLayers );
246 std::vector<std::vector<OptixUtilDenoiserImageTile>> prevTiles( numLayers );
247 for( unsigned int l = 0; l < numLayers; l++ )
248 {
249 if( const OptixResult res = optixUtilDenoiserSplitImage( layers[l].input, layers[l].output,
250 overlapWindowSizeInPixels,
251 tileWidth, tileHeight, tiles[l] ) )
252 return res;
253
254 if( layers[l].previousOutput.data )
255 {
256 OptixImage2D dummyOutput = layers[l].previousOutput;
257 if( const OptixResult res = optixUtilDenoiserSplitImage( layers[l].previousOutput, dummyOutput,
258 upscale * overlapWindowSizeInPixels,
259 upscale * tileWidth, upscale * tileHeight, prevTiles[l] ) )
260 return res;
261 }
262 }
263
264 std::vector<OptixUtilDenoiserImageTile> albedoTiles;
265 if( guideLayer->albedo.data )
266 {
267 OptixImage2D dummyOutput = guideLayer->albedo;
268 if( const OptixResult res = optixUtilDenoiserSplitImage( guideLayer->albedo, dummyOutput,
269 overlapWindowSizeInPixels,
270 tileWidth, tileHeight, albedoTiles ) )
271 return res;
272 }
273
274 std::vector<OptixUtilDenoiserImageTile> normalTiles;
275 if( guideLayer->normal.data )
276 {
277 OptixImage2D dummyOutput = guideLayer->normal;
278 if( const OptixResult res = optixUtilDenoiserSplitImage( guideLayer->normal, dummyOutput,
279 overlapWindowSizeInPixels,
280 tileWidth, tileHeight, normalTiles ) )
281 return res;
282 }
283
284 std::vector<OptixUtilDenoiserImageTile> flowTiles;
285 if( guideLayer->flow.data )
286 {
287 OptixImage2D dummyOutput = guideLayer->flow;
288 if( const OptixResult res = optixUtilDenoiserSplitImage( guideLayer->flow, dummyOutput,
289 overlapWindowSizeInPixels,
290 tileWidth, tileHeight, flowTiles ) )
291 return res;
292 }
293
294 std::vector<OptixUtilDenoiserImageTile> flowTrustTiles;
295 if( guideLayer->flowTrustworthiness.data )
296 {
297 OptixImage2D dummyOutput = guideLayer->flowTrustworthiness;
298 if( const OptixResult res = optixUtilDenoiserSplitImage( guideLayer->flowTrustworthiness, dummyOutput,
299 overlapWindowSizeInPixels,
300 tileWidth, tileHeight, flowTrustTiles ) )
301 return res;
302 }
303
304 std::vector<OptixUtilDenoiserImageTile> internalGuideLayerTiles;
306 {
308 guideLayer->outputInternalGuideLayer,
309 upscale * overlapWindowSizeInPixels,
310 upscale * tileWidth, upscale * tileHeight, internalGuideLayerTiles ) )
311 return res;
312 }
313
314 for( size_t t = 0; t < tiles[0].size(); t++ )
315 {
316 std::vector<OptixDenoiserLayer> tlayers;
317 for( unsigned int l = 0; l < numLayers; l++ )
318 {
319 OptixDenoiserLayer layer = {};
320 layer.input = ( tiles[l] )[t].input;
321 layer.output = ( tiles[l] )[t].output;
322 if( layers[l].previousOutput.data )
323 layer.previousOutput = ( prevTiles[l] )[t].input;
324 layer.type = layers[l].type;
325 tlayers.push_back( layer );
326 }
327
329 if( guideLayer->albedo.data )
330 gl.albedo = albedoTiles[t].input;
331
332 if( guideLayer->normal.data )
333 gl.normal = normalTiles[t].input;
334
335 if( guideLayer->flow.data )
336 gl.flow = flowTiles[t].input;
337
338 if( guideLayer->flowTrustworthiness.data )
339 gl.flowTrustworthiness = flowTrustTiles[t].input;
340
341 if( guideLayer->previousOutputInternalGuideLayer.data )
342 gl.previousOutputInternalGuideLayer = internalGuideLayerTiles[t].input;
343
344 if( guideLayer->outputInternalGuideLayer.data )
345 gl.outputInternalGuideLayer = internalGuideLayerTiles[t].output;
346
347 if( const OptixResult res =
348 optixDenoiserInvoke( denoiser, stream, params, denoiserState, denoiserStateSizeInBytes,
349 &gl, &tlayers[0], numLayers,
350 ( tiles[0] )[t].inputOffsetX, ( tiles[0] )[t].inputOffsetY,
351 scratch, scratchSizeInBytes ) )
352 return res;
353 }
354 return OPTIX_SUCCESS;
355}
356 // end group optix_utilities
358
359#ifdef __cplusplus
360}
361#endif
362
363#endif // OPTIX_DENOISER_TILING_H
struct OptixDenoiser_t * OptixDenoiser
Opaque type representing a denoiser instance.
Definition: optix_types.h:62
unsigned long long CUdeviceptr
CUDA device pointer.
Definition: optix_types.h:43
OptixResult
Result codes returned from API functions.
Definition: optix_types.h:143
@ OPTIX_SUCCESS
Definition: optix_types.h:144
@ OPTIX_ERROR_INVALID_VALUE
Definition: optix_types.h:145
@ OPTIX_PIXEL_FORMAT_HALF4
four halfs, RGBA
Definition: optix_types.h:1572
@ OPTIX_PIXEL_FORMAT_FLOAT2
two floats, XY
Definition: optix_types.h:1574
@ OPTIX_PIXEL_FORMAT_FLOAT4
four floats, RGBA
Definition: optix_types.h:1576
@ OPTIX_PIXEL_FORMAT_UCHAR4
four unsigned chars, RGBA
Definition: optix_types.h:1578
@ OPTIX_PIXEL_FORMAT_HALF3
three halfs, RGB
Definition: optix_types.h:1571
@ OPTIX_PIXEL_FORMAT_FLOAT3
three floats, RGB
Definition: optix_types.h:1575
@ OPTIX_PIXEL_FORMAT_UCHAR3
three unsigned chars, RGB
Definition: optix_types.h:1577
@ OPTIX_PIXEL_FORMAT_HALF1
one half
Definition: optix_types.h:1569
@ OPTIX_PIXEL_FORMAT_INTERNAL_GUIDE_LAYER
internal format
Definition: optix_types.h:1579
@ OPTIX_PIXEL_FORMAT_FLOAT1
one float
Definition: optix_types.h:1573
@ OPTIX_PIXEL_FORMAT_HALF2
two halfs, XY
Definition: optix_types.h:1570
OptixResult optixUtilDenoiserInvokeTiled(OptixDenoiser denoiser, CUstream stream, const OptixDenoiserParams *params, CUdeviceptr denoiserState, size_t denoiserStateSizeInBytes, const OptixDenoiserGuideLayer *guideLayer, const OptixDenoiserLayer *layers, unsigned int numLayers, CUdeviceptr scratch, size_t scratchSizeInBytes, unsigned int overlapWindowSizeInPixels, unsigned int tileWidth, unsigned int tileHeight)
Run denoiser on input layers see optixDenoiserInvoke additional parameters:
Definition: optix_denoiser_tiling.h:225
OptixResult optixUtilDenoiserSplitImage(const OptixImage2D &input, const OptixImage2D &output, unsigned int overlapWindowSizeInPixels, unsigned int tileWidth, unsigned int tileHeight, std::vector<OptixUtilDenoiserImageTile> &tiles)
Split image into 2D tiles given horizontal and vertical tile size.
Definition: optix_denoiser_tiling.h:129
OptixResult optixUtilGetPixelStride(const OptixImage2D &image, unsigned int &pixelStrideInBytes)
Return pixel stride in bytes for the given pixel format if the pixelStrideInBytes member of the image...
Definition: optix_denoiser_tiling.h:75
OptiX public API header.
OPTIXAPI OptixResult optixDenoiserInvoke(OptixDenoiser denoiser, CUstream stream, const OptixDenoiserParams *params, CUdeviceptr denoiserState, size_t denoiserStateSizeInBytes, const OptixDenoiserGuideLayer *guideLayer, const OptixDenoiserLayer *layers, unsigned int numLayers, unsigned int inputOffsetX, unsigned int inputOffsetY, CUdeviceptr scratch, size_t scratchSizeInBytes)
Invokes denoiser on a set of input data and produces at least one output image. State memory must be ...
Guide layer for the denoiser.
Definition: optix_types.h:1663
OptixImage2D normal
Definition: optix_types.h:1670
OptixImage2D flowTrustworthiness
Definition: optix_types.h:1684
OptixImage2D flow
Definition: optix_types.h:1674
OptixImage2D previousOutputInternalGuideLayer
Definition: optix_types.h:1678
OptixImage2D albedo
Definition: optix_types.h:1665
OptixImage2D outputInternalGuideLayer
Definition: optix_types.h:1679
Input/Output layers for the denoiser.
Definition: optix_types.h:1707
OptixImage2D output
Definition: optix_types.h:1715
OptixImage2D input
Definition: optix_types.h:1709
OptixDenoiserAOVType type
Definition: optix_types.h:1718
OptixImage2D previousOutput
Definition: optix_types.h:1712
Various parameters used by the denoiser.
Definition: optix_types.h:1728
Image descriptor used by the denoiser.
Definition: optix_types.h:1586
unsigned int rowStrideInBytes
Stride between subsequent rows of the image (in bytes).
Definition: optix_types.h:1594
CUdeviceptr data
Pointer to the actual pixel data.
Definition: optix_types.h:1588
OptixPixelFormat format
Pixel format.
Definition: optix_types.h:1601
unsigned int width
Width of the image (in pixels)
Definition: optix_types.h:1590
unsigned int height
Height of the image (in pixels)
Definition: optix_types.h:1592
unsigned int pixelStrideInBytes
Stride between subsequent pixels of the image (in bytes). If set to 0, dense packing (no gaps) is ass...
Definition: optix_types.h:1599
Tile definition.
Definition: optix_denoiser_tiling.h:56
unsigned int inputOffsetY
Definition: optix_denoiser_tiling.h:65
OptixImage2D output
Definition: optix_denoiser_tiling.h:61
unsigned int inputOffsetX
Definition: optix_denoiser_tiling.h:64
OptixImage2D input
Definition: optix_denoiser_tiling.h:58