blender/intern/cycles/device/device_task.cpp
2021-03-15 20:46:57 +01:00

183 lines
4.1 KiB
C++

/*
* Copyright 2011-2013 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <string.h>
#include "device/device_task.h"
#include "render/buffers.h"
#include "util/util_algorithm.h"
#include "util/util_time.h"
CCL_NAMESPACE_BEGIN
/* Device Task */
DeviceTask::DeviceTask(Type type_)
: type(type_),
x(0),
y(0),
w(0),
h(0),
rgba_byte(0),
rgba_half(0),
buffer(0),
sample(0),
num_samples(1),
shader_input(0),
shader_output(0),
shader_eval_type(0),
shader_filter(0),
shader_x(0),
shader_w(0),
buffers(nullptr),
tile_types(0),
denoising_from_render(false),
pass_stride(0),
frame_stride(0),
target_pass_stride(0),
pass_denoising_data(0),
pass_denoising_clean(0),
need_finish_queue(false),
integrator_branched(false)
{
last_update_time = time_dt();
}
int DeviceTask::get_subtask_count(int num, int max_size) const
{
if (max_size != 0) {
int max_size_num;
if (type == SHADER) {
max_size_num = (shader_w + max_size - 1) / max_size;
}
else {
max_size = max(1, max_size / w);
max_size_num = (h + max_size - 1) / max_size;
}
num = max(max_size_num, num);
}
if (type == SHADER) {
num = min(shader_w, num);
}
else if (type == RENDER) {
}
else {
num = min(h, num);
}
return num;
}
void DeviceTask::split(list<DeviceTask> &tasks, int num, int max_size) const
{
num = get_subtask_count(num, max_size);
if (type == SHADER) {
for (int i = 0; i < num; i++) {
int tx = shader_x + (shader_w / num) * i;
int tw = (i == num - 1) ? shader_w - i * (shader_w / num) : shader_w / num;
DeviceTask task = *this;
task.shader_x = tx;
task.shader_w = tw;
tasks.push_back(task);
}
}
else if (type == RENDER) {
for (int i = 0; i < num; i++)
tasks.push_back(*this);
}
else {
for (int i = 0; i < num; i++) {
int ty = y + (h / num) * i;
int th = (i == num - 1) ? h - i * (h / num) : h / num;
DeviceTask task = *this;
task.y = ty;
task.h = th;
tasks.push_back(task);
}
}
}
void DeviceTask::update_progress(RenderTile *rtile, int pixel_samples)
{
if (type == FILM_CONVERT)
return;
if (update_progress_sample) {
if (pixel_samples == -1) {
pixel_samples = shader_w;
}
update_progress_sample(pixel_samples, rtile ? rtile->sample : 0);
}
if (update_tile_sample) {
double current_time = time_dt();
if (current_time - last_update_time >= 1.0) {
update_tile_sample(*rtile);
last_update_time = current_time;
}
}
}
/* Adaptive Sampling */
AdaptiveSampling::AdaptiveSampling() : use(true), adaptive_step(0), min_samples(0)
{
}
/* Render samples in steps that align with the adaptive filtering. */
int AdaptiveSampling::align_samples(int sample, int num_samples) const
{
int end_sample = sample + num_samples;
/* Round down end sample to the nearest sample that needs filtering. */
end_sample &= ~(adaptive_step - 1);
if (end_sample <= sample) {
/* In order to reach the next sample that needs filtering, we'd need
* to increase num_samples. We don't do that in this function, so
* just keep it as is and don't filter this time around. */
return num_samples;
}
return end_sample - sample;
}
bool AdaptiveSampling::need_filter(int sample) const
{
if (sample > min_samples) {
return (sample & (adaptive_step - 1)) == (adaptive_step - 1);
}
else {
return false;
}
}
CCL_NAMESPACE_END