mirror of
https://github.com/blender/blender
synced 2026-10-25 03:07:01 +03:00
The render buffer is sliced horizontally to distribute work over
multiple devices. After recent changes this was no longer working well with
scaling for progressive render and denoising upscale.
In particular, when there is not enough work some slices did not properly
become empty but were clamped to height 1 as part of the scaling, which
caused mismatches.
Now the buffer is sliced at full resolution, and then the resulting Y
coordinates are scaled down, rather than slicing at each resolution. Empty
slices are handled better by early outs in a few functions.
Issue introduced in 02171cc356.
Co-authored-by: Leon Zandman <leon@wirwar.com>
Pull Request: https://projects.blender.org/blender/blender/pulls/162588
115 lines
4.3 KiB
C++
115 lines
4.3 KiB
C++
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 */
|
|
|
|
#include "device/queue.h"
|
|
|
|
#include "integrator/pass_accessor_gpu.h"
|
|
|
|
#include "session/buffers.h"
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
PassAccessorGPU::PassAccessorGPU(DeviceQueue *queue,
|
|
const PassAccessInfo &pass_access_info,
|
|
const float exposure,
|
|
const int num_samples)
|
|
: PassAccessor(pass_access_info, exposure, num_samples), queue_(queue)
|
|
{
|
|
}
|
|
|
|
/* --------------------------------------------------------------------
|
|
* Kernel execution.
|
|
*/
|
|
|
|
void PassAccessorGPU::run_film_convert_kernels(DeviceKernel kernel,
|
|
const RenderBuffers *render_buffers,
|
|
const BufferParams &buffer_params,
|
|
const Destination &destination) const
|
|
{
|
|
KernelFilmConvert kfilm_convert;
|
|
init_kernel_film_convert(&kfilm_convert, buffer_params, destination);
|
|
|
|
const int work_size = buffer_params.window_width * buffer_params.window_height;
|
|
if (!work_size) {
|
|
return;
|
|
}
|
|
|
|
const int destination_stride = destination.stride != 0 ? destination.stride :
|
|
buffer_params.window_width;
|
|
|
|
const int offset = buffer_params.window_x * buffer_params.pass_stride +
|
|
buffer_params.window_y * buffer_params.stride * buffer_params.pass_stride;
|
|
|
|
queue_->init_execution();
|
|
if (destination.d_pixels) {
|
|
DCHECK_EQ(destination.stride, 0) << "Custom stride for float destination is not implemented.";
|
|
|
|
const DeviceKernelArguments args(&kfilm_convert,
|
|
&destination.d_pixels,
|
|
&render_buffers->buffer.device_pointer,
|
|
&work_size,
|
|
&buffer_params.window_width,
|
|
&offset,
|
|
&buffer_params.stride,
|
|
&destination.pixel_offset,
|
|
&destination.offset,
|
|
&destination_stride);
|
|
|
|
queue_->enqueue(kernel, work_size, args);
|
|
}
|
|
if (destination.d_pixels_half_rgba) {
|
|
const DeviceKernel kernel_half_float = static_cast<DeviceKernel>(kernel + 1);
|
|
|
|
const DeviceKernelArguments args(&kfilm_convert,
|
|
&destination.d_pixels_half_rgba,
|
|
&render_buffers->buffer.device_pointer,
|
|
&work_size,
|
|
&buffer_params.window_width,
|
|
&offset,
|
|
&buffer_params.stride,
|
|
&destination.offset,
|
|
&destination_stride);
|
|
|
|
queue_->enqueue(kernel_half_float, work_size, args);
|
|
}
|
|
|
|
queue_->synchronize();
|
|
}
|
|
|
|
/* --------------------------------------------------------------------
|
|
* Pass accessors.
|
|
*/
|
|
|
|
#define DEFINE_PASS_ACCESSOR(pass, kernel_pass) \
|
|
void PassAccessorGPU::get_pass_##pass(const RenderBuffers *render_buffers, \
|
|
const BufferParams &buffer_params, \
|
|
const Destination &destination) const \
|
|
{ \
|
|
run_film_convert_kernels( \
|
|
DEVICE_KERNEL_FILM_CONVERT_##kernel_pass, render_buffers, buffer_params, destination); \
|
|
}
|
|
|
|
/* Float (scalar) passes. */
|
|
DEFINE_PASS_ACCESSOR(depth, DEPTH);
|
|
DEFINE_PASS_ACCESSOR(mist, MIST);
|
|
DEFINE_PASS_ACCESSOR(volume_majorant, VOLUME_MAJORANT);
|
|
DEFINE_PASS_ACCESSOR(sample_count, SAMPLE_COUNT);
|
|
DEFINE_PASS_ACCESSOR(float, FLOAT);
|
|
|
|
/* Float3 passes. */
|
|
DEFINE_PASS_ACCESSOR(light_path, LIGHT_PATH);
|
|
DEFINE_PASS_ACCESSOR(rgbe, RGBE);
|
|
DEFINE_PASS_ACCESSOR(float3, FLOAT3);
|
|
|
|
/* Float4 passes. */
|
|
DEFINE_PASS_ACCESSOR(motion, MOTION);
|
|
DEFINE_PASS_ACCESSOR(cryptomatte, CRYPTOMATTE);
|
|
DEFINE_PASS_ACCESSOR(shadow_catcher, SHADOW_CATCHER);
|
|
DEFINE_PASS_ACCESSOR(shadow_catcher_matte_with_shadow, SHADOW_CATCHER_MATTE_WITH_SHADOW);
|
|
DEFINE_PASS_ACCESSOR(combined, COMBINED);
|
|
DEFINE_PASS_ACCESSOR(float4, FLOAT4);
|
|
|
|
#undef DEFINE_PASS_ACCESSOR
|
|
|
|
CCL_NAMESPACE_END
|