Blender  V3.3
COM_WriteBufferOperation.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 Blender Foundation. */
3 
5 #include "COM_OpenCLDevice.h"
6 
7 namespace blender::compositor {
8 
10 {
11  this->add_input_socket(datatype);
12  memory_proxy_ = new MemoryProxy(datatype);
13  memory_proxy_->set_write_buffer_operation(this);
14  memory_proxy_->set_executor(nullptr);
16 }
18 {
19  if (memory_proxy_) {
20  delete memory_proxy_;
21  memory_proxy_ = nullptr;
22  }
23 }
24 
26  float x,
27  float y,
29 {
30  input_->read_sampled(output, x, y, sampler);
31 }
32 
34 {
35  input_ = this->get_input_operation(0);
36  memory_proxy_->allocate(this->get_width(), this->get_height());
37 }
38 
40 {
41  input_ = nullptr;
42  memory_proxy_->free();
43 }
44 
45 void WriteBufferOperation::execute_region(rcti *rect, unsigned int /*tile_number*/)
46 {
47  MemoryBuffer *memory_buffer = memory_proxy_->get_buffer();
48  float *buffer = memory_buffer->get_buffer();
49  const uint8_t num_channels = memory_buffer->get_num_channels();
50  if (input_->get_flags().complex) {
51  void *data = input_->initialize_tile_data(rect);
52  int x1 = rect->xmin;
53  int y1 = rect->ymin;
54  int x2 = rect->xmax;
55  int y2 = rect->ymax;
56  int x;
57  int y;
58  bool breaked = false;
59  for (y = y1; y < y2 && (!breaked); y++) {
60  int offset4 = (y * memory_buffer->get_width() + x1) * num_channels;
61  for (x = x1; x < x2; x++) {
62  input_->read(&(buffer[offset4]), x, y, data);
63  offset4 += num_channels;
64  }
65  if (is_braked()) {
66  breaked = true;
67  }
68  }
69  if (data) {
70  input_->deinitialize_tile_data(rect, data);
71  data = nullptr;
72  }
73  }
74  else {
75  int x1 = rect->xmin;
76  int y1 = rect->ymin;
77  int x2 = rect->xmax;
78  int y2 = rect->ymax;
79 
80  int x;
81  int y;
82  bool breaked = false;
83  for (y = y1; y < y2 && (!breaked); y++) {
84  int offset4 = (y * memory_buffer->get_width() + x1) * num_channels;
85  for (x = x1; x < x2; x++) {
86  input_->read_sampled(&(buffer[offset4]), x, y, PixelSampler::Nearest);
87  offset4 += num_channels;
88  }
89  if (is_braked()) {
90  breaked = true;
91  }
92  }
93  }
94 }
95 
97  rcti * /*rect*/,
98  unsigned int /*chunk_number*/,
99  MemoryBuffer **input_memory_buffers,
100  MemoryBuffer *output_buffer)
101 {
102  float *output_float_buffer = output_buffer->get_buffer();
103  cl_int error;
104  /*
105  * 1. create cl_mem from outputbuffer
106  * 2. call NodeOperation (input) executeOpenCLChunk(.....)
107  * 3. schedule read back from opencl to main device (outputbuffer)
108  * 4. schedule native callback
109  *
110  * NOTE: list of cl_mem will be filled by 2, and needs to be cleaned up by 4
111  */
112  /* STEP 1 */
113  const unsigned int output_buffer_width = output_buffer->get_width();
114  const unsigned int output_buffer_height = output_buffer->get_height();
115 
116  const cl_image_format *image_format = OpenCLDevice::determine_image_format(output_buffer);
117 
118  cl_mem cl_output_buffer = clCreateImage2D(device->get_context(),
119  CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
120  image_format,
121  output_buffer_width,
122  output_buffer_height,
123  0,
124  output_float_buffer,
125  &error);
126  if (error != CL_SUCCESS) {
127  printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
128  }
129 
130  /* STEP 2 */
131  std::list<cl_mem> *cl_mem_to_clean_up = new std::list<cl_mem>();
132  cl_mem_to_clean_up->push_back(cl_output_buffer);
133  std::list<cl_kernel> *cl_kernels_to_clean_up = new std::list<cl_kernel>();
134 
135  input_->execute_opencl(device,
136  output_buffer,
137  cl_output_buffer,
138  input_memory_buffers,
139  cl_mem_to_clean_up,
140  cl_kernels_to_clean_up);
141 
142  /* STEP 3 */
143 
144  size_t origin[3] = {0, 0, 0};
145  size_t region[3] = {output_buffer_width, output_buffer_height, 1};
146 
147  // clFlush(queue);
148  // clFinish(queue);
149 
150  error = clEnqueueBarrier(device->get_queue());
151  if (error != CL_SUCCESS) {
152  printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
153  }
154  error = clEnqueueReadImage(device->get_queue(),
155  cl_output_buffer,
156  CL_TRUE,
157  origin,
158  region,
159  0,
160  0,
161  output_float_buffer,
162  0,
163  nullptr,
164  nullptr);
165  if (error != CL_SUCCESS) {
166  printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
167  }
168 
169  this->get_memory_proxy()->get_buffer()->fill_from(*output_buffer);
170 
171  /* STEP 4 */
172  while (!cl_mem_to_clean_up->empty()) {
173  cl_mem mem = cl_mem_to_clean_up->front();
174  error = clReleaseMemObject(mem);
175  if (error != CL_SUCCESS) {
176  printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
177  }
178  cl_mem_to_clean_up->pop_front();
179  }
180 
181  while (!cl_kernels_to_clean_up->empty()) {
182  cl_kernel kernel = cl_kernels_to_clean_up->front();
183  error = clReleaseKernel(kernel);
184  if (error != CL_SUCCESS) {
185  printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
186  }
187  cl_kernels_to_clean_up->pop_front();
188  }
189  delete cl_kernels_to_clean_up;
190 }
191 
192 void WriteBufferOperation::determine_canvas(const rcti &preferred_area, rcti &r_area)
193 {
194  NodeOperation::determine_canvas(preferred_area, r_area);
195  /* make sure there is at least one pixel stored in case the input is a single value */
196  single_value_ = false;
197  if (BLI_rcti_size_x(&r_area) == 0) {
198  r_area.xmax += 1;
199  single_value_ = true;
200  }
201  if (BLI_rcti_size_y(&r_area) == 0) {
202  r_area.ymax += 1;
203  single_value_ = true;
204  }
205 }
206 
208 {
209  NodeOperation *input_operation = this->get_input_operation(0);
210  this->set_width(input_operation->get_width());
211  this->set_height(input_operation->get_height());
212 }
213 
214 } // namespace blender::compositor
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
a MemoryBuffer contains access to the data of a chunk
const int get_width() const
get the width of this MemoryBuffer
const int get_height() const
get the height of this MemoryBuffer
float * get_buffer()
get the data of this MemoryBuffer
void fill_from(const MemoryBuffer &src)
add the content from other_buffer to this MemoryBuffer
A MemoryProxy is a unique identifier for a memory buffer. A single MemoryProxy is used among all chun...
void free()
free the allocated memory
void set_executor(ExecutionGroup *executor)
set the ExecutionGroup that can be scheduled to calculate a certain chunk.
void allocate(unsigned int width, unsigned int height)
allocate memory of size width x height
void set_write_buffer_operation(WriteBufferOperation *operation)
set the WriteBufferOperation that is responsible for writing to this MemoryProxy
MemoryBuffer * get_buffer()
get the allocated memory
NodeOperation contains calculation logic.
const NodeOperationFlags get_flags() const
NodeOperation * get_input_operation(int index)
void set_width(unsigned int width)
void read(float result[4], int x, int y, void *chunk_data)
virtual void execute_opencl(OpenCLDevice *, MemoryBuffer *, cl_mem, MemoryBuffer **, std::list< cl_mem > *, std::list< cl_kernel > *)
custom handle to add new tasks to the OpenCL command queue in order to execute a chunk on an GPUDevic...
void set_height(unsigned int height)
virtual void deinitialize_tile_data(rcti *, void *)
void read_sampled(float result[4], float x, float y, PixelSampler sampler)
void add_input_socket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
virtual void * initialize_tile_data(rcti *)
virtual void determine_canvas(const rcti &preferred_area, rcti &r_area)
device representing an GPU OpenCL device. an instance of this class represents a single cl_device
static const cl_image_format * determine_image_format(MemoryBuffer *memory_buffer)
determine an image format
void execute_opencl_region(OpenCLDevice *device, rcti *rect, unsigned int chunk_number, MemoryBuffer **memory_buffers, MemoryBuffer *output_buffer) override
when a chunk is executed by an OpenCLDevice, this method is called
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void determine_canvas(const rcti &preferred_area, rcti &r_area) override
void execute_region(rcti *rect, unsigned int tile_number) override
when a chunk is executed by a CPUDevice, this method is called
SyclQueue void void size_t num_bytes SyclQueue void const char void *memory_device_pointer KernelContext int kernel
depth_tx sampler(1, ImageType::FLOAT_2D, "combined_tx") .sampler(2
DataType
possible data types for sockets
Definition: COM_defines.h:30
ccl_global float * buffer
ccl_global KernelShaderEvalInput ccl_global float * output
static void error(const char *str)
Definition: meshlaplacian.c:51
unsigned char uint8_t
Definition: stdint.h:78
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63