NVIDIA OptiX 7.7 nvidia_logo_transpbg.gif Up
optix_denoiser_tiling.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 NVIDIA Corporation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of NVIDIA CORPORATION nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
32
33#ifndef OPTIX_DENOISER_TILING_H
34#define OPTIX_DENOISER_TILING_H
35
36#include <optix.h>
37
38#include <algorithm>
39#include <vector>
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
54{
55 // input tile image
57
58 // output tile image
60
61 // overlap offsets, parameters for #optixUtilDenoiserInvoke
62 unsigned int inputOffsetX;
63 unsigned int inputOffsetY;
64};
65
73inline OptixResult optixUtilGetPixelStride( const OptixImage2D& image, unsigned int& pixelStrideInBytes )
74{
75 pixelStrideInBytes = image.pixelStrideInBytes;
76 if( pixelStrideInBytes == 0 )
77 {
78 switch( image.format )
79 {
81 pixelStrideInBytes = 1 * sizeof( short );
82 break;
84 pixelStrideInBytes = 2 * sizeof( short );
85 break;
87 pixelStrideInBytes = 3 * sizeof( short );
88 break;
90 pixelStrideInBytes = 4 * sizeof( short );
91 break;
93 pixelStrideInBytes = 1 * sizeof( float );
94 break;
96 pixelStrideInBytes = 2 * sizeof( float );
97 break;
99 pixelStrideInBytes = 3 * sizeof( float );
100 break;
102 pixelStrideInBytes = 4 * sizeof( float );
103 break;
105 pixelStrideInBytes = 3 * sizeof( char );
106 break;
108 pixelStrideInBytes = 4 * sizeof( char );
109 break;
112 break;
113 }
114 }
115 return OPTIX_SUCCESS;
116}
117
128 const OptixImage2D& input,
129 const OptixImage2D& output,
130 unsigned int overlapWindowSizeInPixels,
131 unsigned int tileWidth,
132 unsigned int tileHeight,
133 std::vector<OptixUtilDenoiserImageTile>& tiles )
134{
135 if( tileWidth == 0 || tileHeight == 0 )
137
138 unsigned int inPixelStride, outPixelStride;
139 if( const OptixResult res = optixUtilGetPixelStride( input, inPixelStride ) )
140 return res;
141 if( const OptixResult res = optixUtilGetPixelStride( output, outPixelStride ) )
142 return res;
143
144 int inp_w = std::min( tileWidth + 2 * overlapWindowSizeInPixels, input.width );
145 int inp_h = std::min( tileHeight + 2 * overlapWindowSizeInPixels, input.height );
146 int inp_y = 0, copied_y = 0;
147
148 int upscaleX = output.width / input.width;
149 int upscaleY = output.height / input.height;
150
151 do
152 {
153 int inputOffsetY = inp_y == 0 ? 0 : std::max( (int)overlapWindowSizeInPixels, inp_h - ( (int)input.height - inp_y ) );
154 int copy_y = inp_y == 0 ? std::min( input.height, tileHeight + overlapWindowSizeInPixels ) :
155 std::min( tileHeight, input.height - copied_y );
156
157 int inp_x = 0, copied_x = 0;
158 do
159 {
160 int inputOffsetX = inp_x == 0 ? 0 : std::max( (int)overlapWindowSizeInPixels, inp_w - ( (int)input.width - inp_x ) );
161 int copy_x = inp_x == 0 ? std::min( input.width, tileWidth + overlapWindowSizeInPixels ) :
162 std::min( tileWidth, input.width - copied_x );
163
165 tile.input.data = input.data + (size_t)( inp_y - inputOffsetY ) * input.rowStrideInBytes
166 + (size_t)( inp_x - inputOffsetX ) * inPixelStride;
167 tile.input.width = inp_w;
168 tile.input.height = inp_h;
171 tile.input.format = input.format;
172
173 tile.output.data = output.data + (size_t)( upscaleY * inp_y ) * output.rowStrideInBytes
174 + (size_t)( upscaleX * inp_x ) * outPixelStride;
175 tile.output.width = upscaleX * copy_x;
176 tile.output.height = upscaleY * copy_y;
179 tile.output.format = output.format;
180
181 tile.inputOffsetX = inputOffsetX;
182 tile.inputOffsetY = inputOffsetY;
183
184 tiles.push_back( tile );
185
186 inp_x += inp_x == 0 ? tileWidth + overlapWindowSizeInPixels : tileWidth;
187 copied_x += copy_x;
188 } while( inp_x < static_cast<int>( input.width ) );
189
190 inp_y += inp_y == 0 ? tileHeight + overlapWindowSizeInPixels : tileHeight;
191 copied_y += copy_y;
192 } while( inp_y < static_cast<int>( input.height ) );
193
194 return OPTIX_SUCCESS;
195}
196
200
207
224 OptixDenoiser denoiser,
225 CUstream stream,
226 const OptixDenoiserParams* params,
227 CUdeviceptr denoiserState,
228 size_t denoiserStateSizeInBytes,
229 const OptixDenoiserGuideLayer* guideLayer,
230 const OptixDenoiserLayer* layers,
231 unsigned int numLayers,
232 CUdeviceptr scratch,
233 size_t scratchSizeInBytes,
234 unsigned int overlapWindowSizeInPixels,
235 unsigned int tileWidth,
236 unsigned int tileHeight )
237{
238 if( !guideLayer || !layers )
240
241 const unsigned int upscale = numLayers > 0 && layers[0].previousOutput.width == 2 * layers[0].input.width ? 2 : 1;
242
243 std::vector<std::vector<OptixUtilDenoiserImageTile>> tiles( numLayers );
244 std::vector<std::vector<OptixUtilDenoiserImageTile>> prevTiles( numLayers );
245 for( unsigned int l = 0; l < numLayers; l++ )
246 {
247 if( const OptixResult res = optixUtilDenoiserSplitImage( layers[l].input, layers[l].output,
248 overlapWindowSizeInPixels,
249 tileWidth, tileHeight, tiles[l] ) )
250 return res;
251
252 if( layers[l].previousOutput.data )
253 {
254 OptixImage2D dummyOutput = layers[l].previousOutput;
255 if( const OptixResult res = optixUtilDenoiserSplitImage( layers[l].previousOutput, dummyOutput,
256 upscale * overlapWindowSizeInPixels,
257 upscale * tileWidth, upscale * tileHeight, prevTiles[l] ) )
258 return res;
259 }
260 }
261
262 std::vector<OptixUtilDenoiserImageTile> albedoTiles;
263 if( guideLayer->albedo.data )
264 {
265 OptixImage2D dummyOutput = guideLayer->albedo;
266 if( const OptixResult res = optixUtilDenoiserSplitImage( guideLayer->albedo, dummyOutput,
267 overlapWindowSizeInPixels,
268 tileWidth, tileHeight, albedoTiles ) )
269 return res;
270 }
271
272 std::vector<OptixUtilDenoiserImageTile> normalTiles;
273 if( guideLayer->normal.data )
274 {
275 OptixImage2D dummyOutput = guideLayer->normal;
276 if( const OptixResult res = optixUtilDenoiserSplitImage( guideLayer->normal, dummyOutput,
277 overlapWindowSizeInPixels,
278 tileWidth, tileHeight, normalTiles ) )
279 return res;
280 }
281
282 std::vector<OptixUtilDenoiserImageTile> flowTiles;
283 if( guideLayer->flow.data )
284 {
285 OptixImage2D dummyOutput = guideLayer->flow;
286 if( const OptixResult res = optixUtilDenoiserSplitImage( guideLayer->flow, dummyOutput,
287 overlapWindowSizeInPixels,
288 tileWidth, tileHeight, flowTiles ) )
289 return res;
290 }
291
292 std::vector<OptixUtilDenoiserImageTile> flowTrustTiles;
293 if( guideLayer->flowTrustworthiness.data )
294 {
295 OptixImage2D dummyOutput = guideLayer->flowTrustworthiness;
296 if( const OptixResult res = optixUtilDenoiserSplitImage( guideLayer->flowTrustworthiness, dummyOutput,
297 overlapWindowSizeInPixels,
298 tileWidth, tileHeight, flowTrustTiles ) )
299 return res;
300 }
301
302 std::vector<OptixUtilDenoiserImageTile> internalGuideLayerTiles;
304 {
306 guideLayer->outputInternalGuideLayer,
307 upscale * overlapWindowSizeInPixels,
308 upscale * tileWidth, upscale * tileHeight, internalGuideLayerTiles ) )
309 return res;
310 }
311
312 for( size_t t = 0; t < tiles[0].size(); t++ )
313 {
314 std::vector<OptixDenoiserLayer> tlayers;
315 for( unsigned int l = 0; l < numLayers; l++ )
316 {
317 OptixDenoiserLayer layer = {};
318 layer.input = ( tiles[l] )[t].input;
319 layer.output = ( tiles[l] )[t].output;
320 if( layers[l].previousOutput.data )
321 layer.previousOutput = ( prevTiles[l] )[t].input;
322 layer.type = layers[l].type;
323 tlayers.push_back( layer );
324 }
325
327 if( guideLayer->albedo.data )
328 gl.albedo = albedoTiles[t].input;
329
330 if( guideLayer->normal.data )
331 gl.normal = normalTiles[t].input;
332
333 if( guideLayer->flow.data )
334 gl.flow = flowTiles[t].input;
335
336 if( guideLayer->flowTrustworthiness.data )
337 gl.flowTrustworthiness = flowTrustTiles[t].input;
338
339 if( guideLayer->previousOutputInternalGuideLayer.data )
340 gl.previousOutputInternalGuideLayer = internalGuideLayerTiles[t].input;
341
342 if( guideLayer->outputInternalGuideLayer.data )
343 gl.outputInternalGuideLayer = internalGuideLayerTiles[t].output;
344
345 if( const OptixResult res =
346 optixDenoiserInvoke( denoiser, stream, params, denoiserState, denoiserStateSizeInBytes,
347 &gl, &tlayers[0], numLayers,
348 ( tiles[0] )[t].inputOffsetX, ( tiles[0] )[t].inputOffsetY,
349 scratch, scratchSizeInBytes ) )
350 return res;
351 }
352 return OPTIX_SUCCESS;
353}
354 // end group optix_utilities
356
357#ifdef __cplusplus
358}
359#endif
360
361#endif // OPTIX_DENOISER_TILING_H
struct OptixDenoiser_t * OptixDenoiser
Opaque type representing a denoiser instance.
Definition: optix_types.h:71
unsigned long long CUdeviceptr
CUDA device pointer.
Definition: optix_types.h:52
OptixResult
Result codes returned from API functions.
Definition: optix_types.h:152
@ OPTIX_SUCCESS
Definition: optix_types.h:153
@ OPTIX_ERROR_INVALID_VALUE
Definition: optix_types.h:154
@ OPTIX_PIXEL_FORMAT_HALF4
four halfs, RGBA
Definition: optix_types.h:1559
@ OPTIX_PIXEL_FORMAT_FLOAT2
two floats, XY
Definition: optix_types.h:1561
@ OPTIX_PIXEL_FORMAT_FLOAT4
four floats, RGBA
Definition: optix_types.h:1563
@ OPTIX_PIXEL_FORMAT_UCHAR4
four unsigned chars, RGBA
Definition: optix_types.h:1565
@ OPTIX_PIXEL_FORMAT_HALF3
three halfs, RGB
Definition: optix_types.h:1558
@ OPTIX_PIXEL_FORMAT_FLOAT3
three floats, RGB
Definition: optix_types.h:1562
@ OPTIX_PIXEL_FORMAT_UCHAR3
three unsigned chars, RGB
Definition: optix_types.h:1564
@ OPTIX_PIXEL_FORMAT_HALF1
one half
Definition: optix_types.h:1556
@ OPTIX_PIXEL_FORMAT_INTERNAL_GUIDE_LAYER
internal format
Definition: optix_types.h:1566
@ OPTIX_PIXEL_FORMAT_FLOAT1
one float
Definition: optix_types.h:1560
@ OPTIX_PIXEL_FORMAT_HALF2
two halfs, XY
Definition: optix_types.h:1557
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:223
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:127
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:73
OptiX public API header.
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:1635
OptixImage2D normal
Definition: optix_types.h:1640
OptixImage2D flowTrustworthiness
Definition: optix_types.h:1653
OptixImage2D flow
Definition: optix_types.h:1643
OptixImage2D previousOutputInternalGuideLayer
Definition: optix_types.h:1647
OptixImage2D albedo
Definition: optix_types.h:1637
OptixImage2D outputInternalGuideLayer
Definition: optix_types.h:1648
Input/Output layers for the denoiser.
Definition: optix_types.h:1676
OptixImage2D output
Definition: optix_types.h:1684
OptixImage2D input
Definition: optix_types.h:1678
OptixDenoiserAOVType type
Definition: optix_types.h:1687
OptixImage2D previousOutput
Definition: optix_types.h:1681
Definition: optix_types.h:1708
Image descriptor used by the denoiser.
Definition: optix_types.h:1573
unsigned int rowStrideInBytes
Stride between subsequent rows of the image (in bytes).
Definition: optix_types.h:1581
CUdeviceptr data
Pointer to the actual pixel data.
Definition: optix_types.h:1575
OptixPixelFormat format
Pixel format.
Definition: optix_types.h:1588
unsigned int width
Width of the image (in pixels)
Definition: optix_types.h:1577
unsigned int height
Height of the image (in pixels)
Definition: optix_types.h:1579
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:1586
Tile definition.
Definition: optix_denoiser_tiling.h:54
unsigned int inputOffsetY
Definition: optix_denoiser_tiling.h:63
OptixImage2D output
Definition: optix_denoiser_tiling.h:59
unsigned int inputOffsetX
Definition: optix_denoiser_tiling.h:62
OptixImage2D input
Definition: optix_denoiser_tiling.h:56