Fix T89671: Crash when using Denoise node on Full Frame mode

Tiled fallback doesn't support single element buffers.
Ensure tiles are initialized as full buffers.
This commit is contained in:
Manuel Castilla 2021-07-05 23:32:19 +02:00
parent 3d9ecf1cf2
commit cf17f7e0cc
Notes: blender-bot 2023-02-14 04:10:15 +01:00
Referenced by issue #89671, Enabling 'Full Frame Compositor' results in instant quit of blender 3/3-cycles Mac Versions
5 changed files with 32 additions and 1 deletions

View File

@ -23,6 +23,7 @@ namespace blender::compositor {
BufferOperation::BufferOperation(MemoryBuffer *buffer, DataType data_type)
{
buffer_ = buffer;
inflated_buffer_ = nullptr;
/* TODO: Implement a MemoryBuffer get_size() method returning a Size2d type. Shorten following
* code to: set_resolution(buffer.get_size()) */
unsigned int resolution[2];
@ -34,7 +35,19 @@ BufferOperation::BufferOperation(MemoryBuffer *buffer, DataType data_type)
void *BufferOperation::initializeTileData(rcti * /*rect*/)
{
return buffer_;
if (buffer_->is_a_single_elem() == false) {
return buffer_;
}
if (!inflated_buffer_) {
inflated_buffer_ = buffer_->inflate();
}
return inflated_buffer_;
}
void BufferOperation::deinitExecution()
{
delete inflated_buffer_;
}
void BufferOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)

View File

@ -25,11 +25,13 @@ namespace blender::compositor {
class BufferOperation : public NodeOperation {
private:
MemoryBuffer *buffer_;
MemoryBuffer *inflated_buffer_;
public:
BufferOperation(MemoryBuffer *buffer, DataType data_type);
void *initializeTileData(rcti *rect) override;
void deinitExecution() override;
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2]) override;
};

View File

@ -129,6 +129,18 @@ void MemoryBuffer::clear()
memset(m_buffer, 0, buffer_len() * m_num_channels * sizeof(float));
}
/**
* Converts a single elem buffer to a full size buffer (allocates memory for all
* elements in resolution).
*/
MemoryBuffer *MemoryBuffer::inflate() const
{
BLI_assert(is_a_single_elem());
MemoryBuffer *inflated = new MemoryBuffer(this->m_datatype, this->m_rect, false);
inflated->copy_from(this, this->m_rect);
return inflated;
}
float MemoryBuffer::get_max_value() const
{
float result = this->m_buffer[0];

View File

@ -247,6 +247,8 @@ class MemoryBuffer {
return this->m_buffer;
}
MemoryBuffer *inflate() const;
inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y)
{
const int w = getWidth();

View File

@ -328,6 +328,7 @@ Vector<NodeOperationOutput *> NodeOperation::replace_inputs_with_buffers(
BufferOperation *buffer_op = new BufferOperation(inputs_bufs[i], input_socket->getDataType());
orig_links[i] = input_socket->getLink();
input_socket->setLink(buffer_op->getOutputSocket());
buffer_op->initExecution();
}
return orig_links;
}
@ -340,6 +341,7 @@ void NodeOperation::remove_buffers_and_restore_original_inputs(
NodeOperation *buffer_op = get_input_operation(i);
BLI_assert(buffer_op != nullptr);
BLI_assert(typeid(*buffer_op) == typeid(BufferOperation));
buffer_op->deinitExecution();
NodeOperationInput *input_socket = getInputSocket(i);
input_socket->setLink(original_inputs_links[i]);
delete buffer_op;