Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/device/optix/device_impl.cpp
| Show First 20 Lines • Show All 560 Lines • ▼ Show 20 Lines | if (denoise_params.use_pass_albedo) { | ||||
| pass_denoising_albedo = buffer_params.get_pass_offset(PASS_DENOISING_ALBEDO); | pass_denoising_albedo = buffer_params.get_pass_offset(PASS_DENOISING_ALBEDO); | ||||
| if (denoise_params.use_pass_normal) { | if (denoise_params.use_pass_normal) { | ||||
| num_input_passes += 1; | num_input_passes += 1; | ||||
| use_pass_normal = true; | use_pass_normal = true; | ||||
| pass_denoising_normal = buffer_params.get_pass_offset(PASS_DENOISING_NORMAL); | pass_denoising_normal = buffer_params.get_pass_offset(PASS_DENOISING_NORMAL); | ||||
| } | } | ||||
| } | } | ||||
| if (denoise_params.temporally_stable) { | |||||
| prev_output.device_pointer = render_buffers->buffer.device_pointer; | |||||
| prev_output.offset = buffer_params.get_pass_offset(PASS_DENOISING_PREVIOUS); | |||||
| prev_output.stride = buffer_params.stride; | |||||
| prev_output.pass_stride = buffer_params.pass_stride; | |||||
| num_input_passes += 1; | |||||
| use_pass_flow = true; | |||||
| pass_motion = buffer_params.get_pass_offset(PASS_MOTION); | |||||
| } | |||||
| use_guiding_passes = (num_input_passes - 1) > 0; | use_guiding_passes = (num_input_passes - 1) > 0; | ||||
| if (use_guiding_passes) { | if (use_guiding_passes) { | ||||
| if (task.allow_inplace_modification) { | if (task.allow_inplace_modification) { | ||||
| guiding_params.device_pointer = render_buffers->buffer.device_pointer; | guiding_params.device_pointer = render_buffers->buffer.device_pointer; | ||||
| guiding_params.pass_albedo = pass_denoising_albedo; | guiding_params.pass_albedo = pass_denoising_albedo; | ||||
| guiding_params.pass_normal = pass_denoising_normal; | guiding_params.pass_normal = pass_denoising_normal; | ||||
| guiding_params.pass_flow = pass_motion; | |||||
| guiding_params.stride = buffer_params.stride; | guiding_params.stride = buffer_params.stride; | ||||
| guiding_params.pass_stride = buffer_params.pass_stride; | guiding_params.pass_stride = buffer_params.pass_stride; | ||||
| } | } | ||||
| else { | else { | ||||
| guiding_params.pass_stride = 0; | guiding_params.pass_stride = 0; | ||||
| if (use_pass_albedo) { | if (use_pass_albedo) { | ||||
| guiding_params.pass_albedo = guiding_params.pass_stride; | guiding_params.pass_albedo = guiding_params.pass_stride; | ||||
| guiding_params.pass_stride += 3; | guiding_params.pass_stride += 3; | ||||
| } | } | ||||
| if (use_pass_normal) { | if (use_pass_normal) { | ||||
| guiding_params.pass_normal = guiding_params.pass_stride; | guiding_params.pass_normal = guiding_params.pass_stride; | ||||
| guiding_params.pass_stride += 3; | guiding_params.pass_stride += 3; | ||||
| } | } | ||||
| if (use_pass_flow) { | |||||
| guiding_params.pass_flow = guiding_params.pass_stride; | |||||
| guiding_params.pass_stride += 2; | |||||
| } | |||||
| guiding_params.stride = buffer_params.width; | guiding_params.stride = buffer_params.width; | ||||
| guiding_buffer.alloc_to_device(buffer_params.width * buffer_params.height * | guiding_buffer.alloc_to_device(buffer_params.width * buffer_params.height * | ||||
| guiding_params.pass_stride); | guiding_params.pass_stride); | ||||
| guiding_params.device_pointer = guiding_buffer.device_pointer; | guiding_params.device_pointer = guiding_buffer.device_pointer; | ||||
| } | } | ||||
| } | } | ||||
| pass_sample_count = buffer_params.get_pass_offset(PASS_SAMPLE_COUNT); | pass_sample_count = buffer_params.get_pass_offset(PASS_SAMPLE_COUNT); | ||||
| } | } | ||||
| const DenoiseParams &denoise_params; | const DenoiseParams &denoise_params; | ||||
| RenderBuffers *render_buffers = nullptr; | RenderBuffers *render_buffers = nullptr; | ||||
| const BufferParams &buffer_params; | const BufferParams &buffer_params; | ||||
| /* Previous output. */ | |||||
| struct { | |||||
| device_ptr device_pointer = 0; | |||||
| int offset = PASS_UNUSED; | |||||
| int stride = -1; | |||||
| int pass_stride = -1; | |||||
| } prev_output; | |||||
| /* Device-side storage of the guiding passes. */ | /* Device-side storage of the guiding passes. */ | ||||
| device_only_memory<float> guiding_buffer; | device_only_memory<float> guiding_buffer; | ||||
| struct { | struct { | ||||
| device_ptr device_pointer = 0; | device_ptr device_pointer = 0; | ||||
| /* NOTE: Are only initialized when the corresponding guiding pass is enabled. */ | /* NOTE: Are only initialized when the corresponding guiding pass is enabled. */ | ||||
| int pass_albedo = PASS_UNUSED; | int pass_albedo = PASS_UNUSED; | ||||
| int pass_normal = PASS_UNUSED; | int pass_normal = PASS_UNUSED; | ||||
| int pass_flow = PASS_UNUSED; | |||||
| int stride = -1; | int stride = -1; | ||||
| int pass_stride = -1; | int pass_stride = -1; | ||||
| } guiding_params; | } guiding_params; | ||||
| /* Number of input passes. Including the color and extra auxiliary passes. */ | /* Number of input passes. Including the color and extra auxiliary passes. */ | ||||
| int num_input_passes = 0; | int num_input_passes = 0; | ||||
| bool use_guiding_passes = false; | bool use_guiding_passes = false; | ||||
| bool use_pass_albedo = false; | bool use_pass_albedo = false; | ||||
| bool use_pass_normal = false; | bool use_pass_normal = false; | ||||
| bool use_pass_flow = false; | |||||
| int num_samples = 0; | int num_samples = 0; | ||||
| int pass_sample_count = PASS_UNUSED; | int pass_sample_count = PASS_UNUSED; | ||||
| /* NOTE: Are only initialized when the corresponding guiding pass is enabled. */ | /* NOTE: Are only initialized when the corresponding guiding pass is enabled. */ | ||||
| int pass_denoising_albedo = PASS_UNUSED; | int pass_denoising_albedo = PASS_UNUSED; | ||||
| int pass_denoising_normal = PASS_UNUSED; | int pass_denoising_normal = PASS_UNUSED; | ||||
| int pass_motion = PASS_UNUSED; | |||||
| /* For passes which don't need albedo channel for denoising we replace the actual albedo with | /* For passes which don't need albedo channel for denoising we replace the actual albedo with | ||||
| * the (0.5, 0.5, 0.5). This flag indicates that the real albedo pass has been replaced with | * the (0.5, 0.5, 0.5). This flag indicates that the real albedo pass has been replaced with | ||||
| * the fake values and denoising of passes which do need albedo can no longer happen. */ | * the fake values and denoising of passes which do need albedo can no longer happen. */ | ||||
| bool albedo_replaced_with_fake = false; | bool albedo_replaced_with_fake = false; | ||||
| }; | }; | ||||
| class OptiXDevice::DenoisePass { | class OptiXDevice::DenoisePass { | ||||
| ▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | bool OptiXDevice::denoise_filter_guiding_preprocess(DenoiseContext &context) | ||||
| const BufferParams &buffer_params = context.buffer_params; | const BufferParams &buffer_params = context.buffer_params; | ||||
| const int work_size = buffer_params.width * buffer_params.height; | const int work_size = buffer_params.width * buffer_params.height; | ||||
| DeviceKernelArguments args(&context.guiding_params.device_pointer, | DeviceKernelArguments args(&context.guiding_params.device_pointer, | ||||
| &context.guiding_params.pass_stride, | &context.guiding_params.pass_stride, | ||||
| &context.guiding_params.pass_albedo, | &context.guiding_params.pass_albedo, | ||||
| &context.guiding_params.pass_normal, | &context.guiding_params.pass_normal, | ||||
| &context.guiding_params.pass_flow, | |||||
| &context.render_buffers->buffer.device_pointer, | &context.render_buffers->buffer.device_pointer, | ||||
| &buffer_params.offset, | &buffer_params.offset, | ||||
| &buffer_params.stride, | &buffer_params.stride, | ||||
| &buffer_params.pass_stride, | &buffer_params.pass_stride, | ||||
| &context.pass_sample_count, | &context.pass_sample_count, | ||||
| &context.pass_denoising_albedo, | &context.pass_denoising_albedo, | ||||
| &context.pass_denoising_normal, | &context.pass_denoising_normal, | ||||
| &context.pass_motion, | |||||
| &buffer_params.full_x, | &buffer_params.full_x, | ||||
| &buffer_params.full_y, | &buffer_params.full_y, | ||||
| &buffer_params.width, | &buffer_params.width, | ||||
| &buffer_params.height, | &buffer_params.height, | ||||
| &context.num_samples); | &context.num_samples); | ||||
| return denoiser_.queue.enqueue(DEVICE_KERNEL_FILTER_GUIDING_PREPROCESS, work_size, args); | return denoiser_.queue.enqueue(DEVICE_KERNEL_FILTER_GUIDING_PREPROCESS, work_size, args); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | bool OptiXDevice::denoise_ensure(DenoiseContext &context) | ||||
| return true; | return true; | ||||
| } | } | ||||
| bool OptiXDevice::denoise_create_if_needed(DenoiseContext &context) | bool OptiXDevice::denoise_create_if_needed(DenoiseContext &context) | ||||
| { | { | ||||
| const bool recreate_denoiser = (denoiser_.optix_denoiser == nullptr) || | const bool recreate_denoiser = (denoiser_.optix_denoiser == nullptr) || | ||||
| (denoiser_.use_pass_albedo != context.use_pass_albedo) || | (denoiser_.use_pass_albedo != context.use_pass_albedo) || | ||||
| (denoiser_.use_pass_normal != context.use_pass_normal); | (denoiser_.use_pass_normal != context.use_pass_normal) || | ||||
| (denoiser_.use_pass_flow != context.use_pass_flow); | |||||
| if (!recreate_denoiser) { | if (!recreate_denoiser) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| /* Destroy existing handle before creating new one. */ | /* Destroy existing handle before creating new one. */ | ||||
| if (denoiser_.optix_denoiser) { | if (denoiser_.optix_denoiser) { | ||||
| optixDenoiserDestroy(denoiser_.optix_denoiser); | optixDenoiserDestroy(denoiser_.optix_denoiser); | ||||
| } | } | ||||
| /* Create OptiX denoiser handle on demand when it is first used. */ | /* Create OptiX denoiser handle on demand when it is first used. */ | ||||
| OptixDenoiserOptions denoiser_options = {}; | OptixDenoiserOptions denoiser_options = {}; | ||||
| denoiser_options.guideAlbedo = context.use_pass_albedo; | denoiser_options.guideAlbedo = context.use_pass_albedo; | ||||
| denoiser_options.guideNormal = context.use_pass_normal; | denoiser_options.guideNormal = context.use_pass_normal; | ||||
| OptixDenoiserModelKind model = OPTIX_DENOISER_MODEL_KIND_HDR; | |||||
| if (context.use_pass_flow) { | |||||
| model = OPTIX_DENOISER_MODEL_KIND_TEMPORAL; | |||||
| } | |||||
| const OptixResult result = optixDenoiserCreate( | const OptixResult result = optixDenoiserCreate( | ||||
| this->context, OPTIX_DENOISER_MODEL_KIND_HDR, &denoiser_options, &denoiser_.optix_denoiser); | this->context, model, &denoiser_options, &denoiser_.optix_denoiser); | ||||
| if (result != OPTIX_SUCCESS) { | if (result != OPTIX_SUCCESS) { | ||||
| set_error("Failed to create OptiX denoiser"); | set_error("Failed to create OptiX denoiser"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* OptiX denoiser handle was created with the requested number of input passes. */ | /* OptiX denoiser handle was created with the requested number of input passes. */ | ||||
| denoiser_.use_pass_albedo = context.use_pass_albedo; | denoiser_.use_pass_albedo = context.use_pass_albedo; | ||||
| denoiser_.use_pass_normal = context.use_pass_normal; | denoiser_.use_pass_normal = context.use_pass_normal; | ||||
| denoiser_.use_pass_flow = context.use_pass_flow; | |||||
| /* OptiX denoiser has been created, but it needs configuration. */ | /* OptiX denoiser has been created, but it needs configuration. */ | ||||
| denoiser_.is_configured = false; | denoiser_.is_configured = false; | ||||
| return true; | return true; | ||||
| } | } | ||||
| bool OptiXDevice::denoise_configure_if_needed(DenoiseContext &context) | bool OptiXDevice::denoise_configure_if_needed(DenoiseContext &context) | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | bool OptiXDevice::denoise_run(DenoiseContext &context, const DenoisePass &pass) | ||||
| const BufferParams &buffer_params = context.buffer_params; | const BufferParams &buffer_params = context.buffer_params; | ||||
| const int width = buffer_params.width; | const int width = buffer_params.width; | ||||
| const int height = buffer_params.height; | const int height = buffer_params.height; | ||||
| /* Set up input and output layer information. */ | /* Set up input and output layer information. */ | ||||
| OptixImage2D color_layer = {0}; | OptixImage2D color_layer = {0}; | ||||
| OptixImage2D albedo_layer = {0}; | OptixImage2D albedo_layer = {0}; | ||||
| OptixImage2D normal_layer = {0}; | OptixImage2D normal_layer = {0}; | ||||
| OptixImage2D flow_layer = {0}; | |||||
| OptixImage2D output_layer = {0}; | OptixImage2D output_layer = {0}; | ||||
| OptixImage2D prev_output_layer = {0}; | |||||
| /* Color pass. */ | /* Color pass. */ | ||||
| { | { | ||||
| const int pass_denoised = pass.denoised_offset; | const int pass_denoised = pass.denoised_offset; | ||||
| const int64_t pass_stride_in_bytes = context.buffer_params.pass_stride * sizeof(float); | const int64_t pass_stride_in_bytes = context.buffer_params.pass_stride * sizeof(float); | ||||
| color_layer.data = context.render_buffers->buffer.device_pointer + | color_layer.data = context.render_buffers->buffer.device_pointer + | ||||
| pass_denoised * sizeof(float); | pass_denoised * sizeof(float); | ||||
| color_layer.width = width; | color_layer.width = width; | ||||
| color_layer.height = height; | color_layer.height = height; | ||||
| color_layer.rowStrideInBytes = pass_stride_in_bytes * context.buffer_params.stride; | color_layer.rowStrideInBytes = pass_stride_in_bytes * context.buffer_params.stride; | ||||
| color_layer.pixelStrideInBytes = pass_stride_in_bytes; | color_layer.pixelStrideInBytes = pass_stride_in_bytes; | ||||
| color_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3; | color_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3; | ||||
| } | } | ||||
| /* Previous output. */ | |||||
| if (context.prev_output.offset != PASS_UNUSED) { | |||||
| const int64_t pass_stride_in_bytes = context.prev_output.pass_stride * sizeof(float); | |||||
| prev_output_layer.data = context.prev_output.device_pointer + | |||||
| context.prev_output.offset * sizeof(float); | |||||
| prev_output_layer.width = width; | |||||
| prev_output_layer.height = height; | |||||
| prev_output_layer.rowStrideInBytes = pass_stride_in_bytes * context.prev_output.stride; | |||||
| prev_output_layer.pixelStrideInBytes = pass_stride_in_bytes; | |||||
| prev_output_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3; | |||||
| } | |||||
| /* Optional albedo and color passes. */ | /* Optional albedo and color passes. */ | ||||
| if (context.num_input_passes > 1) { | if (context.num_input_passes > 1) { | ||||
| const device_ptr d_guiding_buffer = context.guiding_params.device_pointer; | const device_ptr d_guiding_buffer = context.guiding_params.device_pointer; | ||||
| const int64_t pixel_stride_in_bytes = context.guiding_params.pass_stride * sizeof(float); | const int64_t pixel_stride_in_bytes = context.guiding_params.pass_stride * sizeof(float); | ||||
| const int64_t row_stride_in_bytes = context.guiding_params.stride * pixel_stride_in_bytes; | const int64_t row_stride_in_bytes = context.guiding_params.stride * pixel_stride_in_bytes; | ||||
| if (context.use_pass_albedo) { | if (context.use_pass_albedo) { | ||||
| albedo_layer.data = d_guiding_buffer + context.guiding_params.pass_albedo * sizeof(float); | albedo_layer.data = d_guiding_buffer + context.guiding_params.pass_albedo * sizeof(float); | ||||
| albedo_layer.width = width; | albedo_layer.width = width; | ||||
| albedo_layer.height = height; | albedo_layer.height = height; | ||||
| albedo_layer.rowStrideInBytes = row_stride_in_bytes; | albedo_layer.rowStrideInBytes = row_stride_in_bytes; | ||||
| albedo_layer.pixelStrideInBytes = pixel_stride_in_bytes; | albedo_layer.pixelStrideInBytes = pixel_stride_in_bytes; | ||||
| albedo_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3; | albedo_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3; | ||||
| } | } | ||||
| if (context.use_pass_normal) { | if (context.use_pass_normal) { | ||||
| normal_layer.data = d_guiding_buffer + context.guiding_params.pass_normal * sizeof(float); | normal_layer.data = d_guiding_buffer + context.guiding_params.pass_normal * sizeof(float); | ||||
| normal_layer.width = width; | normal_layer.width = width; | ||||
| normal_layer.height = height; | normal_layer.height = height; | ||||
| normal_layer.rowStrideInBytes = row_stride_in_bytes; | normal_layer.rowStrideInBytes = row_stride_in_bytes; | ||||
| normal_layer.pixelStrideInBytes = pixel_stride_in_bytes; | normal_layer.pixelStrideInBytes = pixel_stride_in_bytes; | ||||
| normal_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3; | normal_layer.format = OPTIX_PIXEL_FORMAT_FLOAT3; | ||||
| } | } | ||||
| if (context.use_pass_flow) { | |||||
| flow_layer.data = d_guiding_buffer + context.guiding_params.pass_flow * sizeof(float); | |||||
| flow_layer.width = width; | |||||
| flow_layer.height = height; | |||||
| flow_layer.rowStrideInBytes = row_stride_in_bytes; | |||||
| flow_layer.pixelStrideInBytes = pixel_stride_in_bytes; | |||||
| flow_layer.format = OPTIX_PIXEL_FORMAT_FLOAT2; | |||||
| } | |||||
| } | } | ||||
| /* Denoise in-place of the noisy input in the render buffers. */ | /* Denoise in-place of the noisy input in the render buffers. */ | ||||
| output_layer = color_layer; | output_layer = color_layer; | ||||
| /* Finally run denoising. */ | OptixDenoiserGuideLayer guide_layers = {}; | ||||
| OptixDenoiserParams params = {}; /* All parameters are disabled/zero. */ | guide_layers.albedo = albedo_layer; | ||||
| guide_layers.normal = normal_layer; | |||||
| guide_layers.flow = flow_layer; | |||||
| OptixDenoiserLayer image_layers = {}; | OptixDenoiserLayer image_layers = {}; | ||||
| image_layers.input = color_layer; | image_layers.input = color_layer; | ||||
| image_layers.previousOutput = prev_output_layer; | |||||
| image_layers.output = output_layer; | image_layers.output = output_layer; | ||||
| OptixDenoiserGuideLayer guide_layers = {}; | /* Finally run denoising. */ | ||||
| guide_layers.albedo = albedo_layer; | OptixDenoiserParams params = {}; /* All parameters are disabled/zero. */ | ||||
| guide_layers.normal = normal_layer; | |||||
| optix_assert(optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser, | optix_assert(optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser, | ||||
| denoiser_.queue.stream(), | denoiser_.queue.stream(), | ||||
| ¶ms, | ¶ms, | ||||
| denoiser_.state.device_pointer, | denoiser_.state.device_pointer, | ||||
| denoiser_.sizes.stateSizeInBytes, | denoiser_.sizes.stateSizeInBytes, | ||||
| &guide_layers, | &guide_layers, | ||||
| &image_layers, | &image_layers, | ||||
| ▲ Show 20 Lines • Show All 714 Lines • Show Last 20 Lines | |||||