13# include <optix_denoiser_tiling.h>
22OptiXDenoiser::~OptiXDenoiser()
27 if (optix_denoiser_ !=
nullptr) {
28 optixDenoiserDestroy(optix_denoiser_);
32uint OptiXDenoiser::get_device_type_mask()
const
37bool OptiXDenoiser::is_device_supported(
const DeviceInfo &device)
45bool OptiXDenoiser::denoise_buffer(
const DenoiseTask &task)
47 OptiXDevice *
const optix_device =
static_cast<OptiXDevice *
>(denoiser_device_);
49 const CUDAContextScope scope(optix_device);
54bool OptiXDenoiser::denoise_create_if_needed(DenoiseContext &context)
56 const bool recreate_denoiser = (optix_denoiser_ ==
nullptr) ||
57 (use_pass_albedo_ !=
context.use_pass_albedo) ||
58 (use_pass_normal_ !=
context.use_pass_normal) ||
59 (use_pass_motion_ !=
context.use_pass_motion);
60 if (!recreate_denoiser) {
65 if (optix_denoiser_) {
66 optixDenoiserDestroy(optix_denoiser_);
70 OptixDenoiserOptions denoiser_options = {};
71 denoiser_options.guideAlbedo =
context.use_pass_albedo;
72 denoiser_options.guideNormal =
context.use_pass_normal;
74 OptixDenoiserModelKind model = OPTIX_DENOISER_MODEL_KIND_AOV;
76 model = OPTIX_DENOISER_MODEL_KIND_TEMPORAL;
79 const OptixResult
result = optixDenoiserCreate(
80 static_cast<OptiXDevice *
>(denoiser_device_)->context,
85 if (
result != OPTIX_SUCCESS) {
86 set_error(
"Failed to create OptiX denoiser");
91 use_pass_albedo_ =
context.use_pass_albedo;
92 use_pass_normal_ =
context.use_pass_normal;
93 use_pass_motion_ =
context.use_pass_motion;
96 is_configured_ =
false;
101bool OptiXDenoiser::denoise_configure_if_needed(DenoiseContext &context)
107 if (is_configured_ && (configured_size_.x == tile_size.
x && configured_size_.y == tile_size.
y)) {
113 optixDenoiserComputeMemoryResources(optix_denoiser_, tile_size.
x, tile_size.
y, &sizes_));
115 const bool tiled = tile_size.
x <
context.buffer_params.width ||
116 tile_size.
y <
context.buffer_params.height;
119 state_.device = denoiser_device_;
120 state_.alloc_to_device(sizes_.stateSizeInBytes + sizes_.withOverlapScratchSizeInBytes);
123 const OptixResult
result = optixDenoiserSetup(
127 tile_size.
x + (tiled ? sizes_.overlapWindowSizeInPixels * 2 : 0),
128 tile_size.
y + (tiled ? sizes_.overlapWindowSizeInPixels * 2 : 0),
129 state_.device_pointer,
130 sizes_.stateSizeInBytes,
131 state_.device_pointer + sizes_.stateSizeInBytes,
132 sizes_.withOverlapScratchSizeInBytes);
133 if (
result != OPTIX_SUCCESS) {
134 set_error(
"Failed to set up OptiX denoiser");
138 cuda_device_assert(denoiser_device_, cuCtxSynchronize());
140 is_configured_ =
true;
141 configured_size_ = tile_size;
146bool OptiXDenoiser::denoise_run(
const DenoiseContext &context,
const DenoisePass &pass)
149 const int width = buffer_params.
width;
150 const int height = buffer_params.
height;
153 OptixImage2D color_layer = {0};
154 OptixImage2D albedo_layer = {0};
155 OptixImage2D normal_layer = {0};
156 OptixImage2D flow_layer = {0};
158 OptixImage2D output_layer = {0};
159 OptixImage2D prev_output_layer = {0};
163 const int pass_denoised = pass.denoised_offset;
166 color_layer.data =
context.render_buffers->buffer.device_pointer +
167 pass_denoised *
sizeof(
float);
168 color_layer.width = width;
169 color_layer.height = height;
170 color_layer.rowStrideInBytes = pass_stride_in_bytes *
context.buffer_params.stride;
171 color_layer.pixelStrideInBytes = pass_stride_in_bytes;
172 color_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3;
179 prev_output_layer.data =
context.prev_output.device_pointer +
181 prev_output_layer.width = width;
182 prev_output_layer.height = height;
183 prev_output_layer.rowStrideInBytes = pass_stride_in_bytes *
context.prev_output.stride;
184 prev_output_layer.pixelStrideInBytes = pass_stride_in_bytes;
185 prev_output_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3;
189 if (
context.num_input_passes > 1) {
192 const int64_t row_stride_in_bytes =
context.guiding_params.stride * pixel_stride_in_bytes;
195 albedo_layer.data = d_guiding_buffer +
context.guiding_params.pass_albedo *
sizeof(
float);
196 albedo_layer.width = width;
197 albedo_layer.height = height;
198 albedo_layer.rowStrideInBytes = row_stride_in_bytes;
199 albedo_layer.pixelStrideInBytes = pixel_stride_in_bytes;
200 albedo_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3;
204 normal_layer.data = d_guiding_buffer +
context.guiding_params.pass_normal *
sizeof(
float);
205 normal_layer.width = width;
206 normal_layer.height = height;
207 normal_layer.rowStrideInBytes = row_stride_in_bytes;
208 normal_layer.pixelStrideInBytes = pixel_stride_in_bytes;
209 normal_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3;
213 flow_layer.data = d_guiding_buffer +
context.guiding_params.pass_flow *
sizeof(
float);
214 flow_layer.width = width;
215 flow_layer.height = height;
216 flow_layer.rowStrideInBytes = row_stride_in_bytes;
217 flow_layer.pixelStrideInBytes = pixel_stride_in_bytes;
218 flow_layer.format = OPTIX_PIXEL_FORMAT_FLOAT2;
223 output_layer = color_layer;
225 OptixDenoiserGuideLayer guide_layers = {};
226 guide_layers.albedo = albedo_layer;
227 guide_layers.normal = normal_layer;
228 guide_layers.flow = flow_layer;
230 OptixDenoiserLayer image_layers = {};
231 image_layers.input = color_layer;
232 image_layers.previousOutput = prev_output_layer;
233 image_layers.output = output_layer;
236 OptixDenoiserParams
params = {};
238 optix_device_assert(denoiser_device_,
239 optixUtilDenoiserInvokeTiled(
241 static_cast<OptiXDeviceQueue *
>(denoiser_queue_.get())->stream(),
243 state_.device_pointer,
244 sizes_.stateSizeInBytes,
248 state_.device_pointer + sizes_.stateSizeInBytes,
249 sizes_.withOverlapScratchSizeInBytes,
250 sizes_.overlapWindowSizeInPixels,
252 configured_size_.y));
bool denoise_buffer(const BufferParams &buffer_params, RenderBuffers *render_buffers, const int num_samples, bool allow_inplace_modification) override
DenoiserTypeMask denoisers
#define CCL_NAMESPACE_END
int context(const bContext *C, const char *member, bContextDataResult *result)