Blender V4.3
render_task_delegate.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include <epoxy/gl.h>
8
9#include "GPU_context.hh"
10
11#include <pxr/imaging/hd/renderBuffer.h>
12#include <pxr/imaging/hd/renderDelegate.h>
13#include <pxr/imaging/hdx/renderTask.h>
14
15#include "MEM_guardedalloc.h"
16
17#include "Eigen/Core"
18
19#include "engine.hh"
20
21namespace blender::render::hydra {
22
23RenderTaskDelegate::RenderTaskDelegate(pxr::HdRenderIndex *parent_index,
24 pxr::SdfPath const &delegate_id)
25 : pxr::HdSceneDelegate(parent_index, delegate_id)
26{
27 task_id_ = GetDelegateID().AppendElementString("task");
28 GetRenderIndex().InsertTask<pxr::HdxRenderTask>(this, task_id_);
29
30 task_params_.enableLighting = true;
31 task_params_.alphaThreshold = 0.1f;
32
33 CLOG_INFO(LOG_HYDRA_RENDER, 1, "%s", task_id_.GetText());
34}
35
36pxr::VtValue RenderTaskDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
37{
38 CLOG_INFO(LOG_HYDRA_RENDER, 3, "%s, %s", id.GetText(), key.GetText());
39
40 if (key == pxr::HdTokens->params) {
41 return pxr::VtValue(task_params_);
42 }
43 if (key == pxr::HdTokens->collection) {
44 return pxr::VtValue(pxr::HdRprimCollection(
45 pxr::HdTokens->geometry, pxr::HdReprSelector(pxr::HdReprTokens->smoothHull)));
46 }
47 return pxr::VtValue();
48}
49
50pxr::TfTokenVector RenderTaskDelegate::GetTaskRenderTags(pxr::SdfPath const &id)
51{
52 CLOG_INFO(LOG_HYDRA_RENDER, 3, "%s", id.GetText());
53
54 return {pxr::HdRenderTagTokens->geometry};
55}
56
57pxr::HdRenderBufferDescriptor RenderTaskDelegate::GetRenderBufferDescriptor(pxr::SdfPath const &id)
58{
59 CLOG_INFO(LOG_HYDRA_RENDER, 3, "%s", id.GetText());
60
61 return buffer_descriptors_[id];
62}
63
64pxr::HdTaskSharedPtr RenderTaskDelegate::task()
65{
66 return GetRenderIndex().GetTask(task_id_);
67}
68
69void RenderTaskDelegate::set_camera(pxr::SdfPath const &camera_id)
70{
71 if (task_params_.camera == camera_id) {
72 return;
73 }
74 task_params_.camera = camera_id;
75 GetRenderIndex().GetChangeTracker().MarkTaskDirty(task_id_, pxr::HdChangeTracker::DirtyParams);
76}
77
79{
80 return static_cast<pxr::HdxRenderTask *>(task().get())->IsConverged();
81}
82
83void RenderTaskDelegate::set_viewport(pxr::GfVec4d const &viewport)
84{
85 if (task_params_.viewport == viewport) {
86 return;
87 }
88 auto &render_index = GetRenderIndex();
89 task_params_.viewport = viewport;
90 render_index.GetChangeTracker().MarkTaskDirty(task_id_, pxr::HdChangeTracker::DirtyParams);
91
92 int w = viewport[2] - viewport[0];
93 int h = viewport[3] - viewport[1];
94 for (auto &it : buffer_descriptors_) {
95 it.second.dimensions = pxr::GfVec3i(w, h, 1);
96 render_index.GetChangeTracker().MarkBprimDirty(it.first,
97 pxr::HdRenderBuffer::DirtyDescription);
98 }
99}
100
101void RenderTaskDelegate::add_aov(pxr::TfToken const &aov_key)
102{
103 pxr::SdfPath buf_id = buffer_id(aov_key);
104 if (buffer_descriptors_.find(buf_id) != buffer_descriptors_.end()) {
105 return;
106 }
107 auto &render_index = GetRenderIndex();
108 pxr::HdAovDescriptor aov_desc = render_index.GetRenderDelegate()->GetDefaultAovDescriptor(
109 aov_key);
110
111 if (aov_desc.format == pxr::HdFormatInvalid) {
112 CLOG_ERROR(LOG_HYDRA_RENDER, "Invalid AOV: %s", aov_key.GetText());
113 return;
114 }
115 if (!ELEM(
116 pxr::HdGetComponentFormat(aov_desc.format), pxr::HdFormatFloat32, pxr::HdFormatFloat16))
117 {
119 "Unsupported data format %s for AOV %s",
120 pxr::TfEnum::GetName(aov_desc.format).c_str(),
121 aov_key.GetText());
122 return;
123 }
124
125 int w = task_params_.viewport[2] - task_params_.viewport[0];
126 int h = task_params_.viewport[3] - task_params_.viewport[1];
127 render_index.InsertBprim(pxr::HdPrimTypeTokens->renderBuffer, this, buf_id);
128 buffer_descriptors_[buf_id] = pxr::HdRenderBufferDescriptor(
129 pxr::GfVec3i(w, h, 1), aov_desc.format, aov_desc.multiSampled);
130
131 pxr::HdRenderPassAovBinding binding;
132 binding.aovName = aov_key;
133 binding.renderBufferId = buf_id;
134 binding.aovSettings = aov_desc.aovSettings;
135 binding.clearValue = aov_desc.clearValue;
136 task_params_.aovBindings.push_back(binding);
137 render_index.GetChangeTracker().MarkTaskDirty(task_id_, pxr::HdChangeTracker::DirtyParams);
138
139 CLOG_INFO(LOG_HYDRA_RENDER, 1, "%s", aov_key.GetText());
140}
141
142void RenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, void *data)
143{
144 pxr::HdRenderBuffer *buffer = static_cast<pxr::HdRenderBuffer *>(
145 GetRenderIndex().GetBprim(pxr::HdPrimTypeTokens->renderBuffer, buffer_id(aov_key)));
146 if (!buffer) {
147 return;
148 }
149
150 pxr::HdFormat format = buffer->GetFormat();
151 size_t len = buffer->GetWidth() * buffer->GetHeight() * pxr::HdGetComponentCount(format);
152 if (pxr::HdGetComponentFormat(format) == pxr::HdFormatFloat32) {
153 void *buf_data = buffer->Map();
154 memcpy(data, buf_data, len * sizeof(float));
155 buffer->Unmap();
156 }
157 else if (pxr::HdGetComponentFormat(format) == pxr::HdFormatFloat16) {
158 Eigen::half *buf_data = (Eigen::half *)buffer->Map();
159 float *fdata = (float *)data;
160 for (size_t i = 0; i < len; ++i) {
161 fdata[i] = buf_data[i];
162 }
163 buffer->Unmap();
164 }
165 else {
167 }
168}
169
170void RenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, GPUTexture *texture)
171{
172 pxr::HdRenderBuffer *buffer = (pxr::HdRenderBuffer *)GetRenderIndex().GetBprim(
173 pxr::HdPrimTypeTokens->renderBuffer, buffer_id(aov_key));
174 if (!buffer) {
175 return;
176 }
177 eGPUDataFormat format = buffer->GetFormat() == pxr::HdFormat::HdFormatFloat16Vec4 ?
180 void *buf_data = buffer->Map();
181 GPU_texture_update(texture, format, buf_data);
182 buffer->Unmap();
183}
184
186
188
189pxr::SdfPath RenderTaskDelegate::buffer_id(pxr::TfToken const &aov_key) const
190{
191 return GetDelegateID().AppendElementString("aov_" + aov_key.GetString());
192}
193
195{
196 unbind();
197 if (tex_color_) {
198 GPU_texture_free(tex_color_);
199 }
200 if (tex_depth_) {
201 GPU_texture_free(tex_depth_);
202 }
203}
204
205void GPURenderTaskDelegate::set_viewport(pxr::GfVec4d const &viewport)
206{
207 if (task_params_.viewport == viewport) {
208 return;
209 }
210 auto &render_index = GetRenderIndex();
211 task_params_.viewport = viewport;
212 render_index.GetChangeTracker().MarkTaskDirty(task_id_, pxr::HdChangeTracker::DirtyParams);
213
214 if (tex_color_) {
215 GPU_texture_free(tex_color_);
216 tex_color_ = nullptr;
217 add_aov(pxr::HdAovTokens->color);
218 }
219 if (tex_depth_) {
220 GPU_texture_free(tex_depth_);
221 tex_depth_ = nullptr;
222 add_aov(pxr::HdAovTokens->depth);
223 }
224}
225
226void GPURenderTaskDelegate::add_aov(pxr::TfToken const &aov_key)
227{
229 GPUTexture **tex;
230 if (aov_key == pxr::HdAovTokens->color) {
232 tex = &tex_color_;
233 }
234 else if (aov_key == pxr::HdAovTokens->depth) {
236 tex = &tex_depth_;
237 }
238 else {
239 CLOG_ERROR(LOG_HYDRA_RENDER, "Invalid AOV: %s", aov_key.GetText());
240 return;
241 }
242
243 if (*tex) {
244 return;
245 }
246
247 *tex = GPU_texture_create_2d(("tex_render_hydra_" + aov_key.GetString()).c_str(),
248 task_params_.viewport[2] - task_params_.viewport[0],
249 task_params_.viewport[3] - task_params_.viewport[1],
250 1,
251 format,
253 nullptr);
254
255 CLOG_INFO(LOG_HYDRA_RENDER, 1, "%s", aov_key.GetText());
256}
257
258void GPURenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, void *data)
259{
260 GPUTexture *tex = nullptr;
261 int c;
262 if (aov_key == pxr::HdAovTokens->color) {
263 tex = tex_color_;
264 c = 4;
265 }
266 else if (aov_key == pxr::HdAovTokens->depth) {
267 tex = tex_depth_;
268 c = 1;
269 }
270 if (!tex) {
271 return;
272 }
273
275 void *tex_data = GPU_texture_read(tex, GPU_DATA_FLOAT, 0);
276 memcpy(data, tex_data, sizeof(float) * w * h * c);
277 MEM_freeN(tex_data);
278}
279
280void GPURenderTaskDelegate::read_aov(pxr::TfToken const &aov_key, GPUTexture *texture)
281{
282 GPUTexture *tex = nullptr;
283 if (aov_key == pxr::HdAovTokens->color) {
284 tex = tex_color_;
285 }
286 else if (aov_key == pxr::HdAovTokens->depth) {
287 tex = tex_depth_;
288 }
289 if (!tex) {
290 return;
291 }
292
293 void *tex_data = GPU_texture_read(tex, GPU_DATA_FLOAT, 0);
294 GPU_texture_update(texture, GPU_DATA_FLOAT, tex_data);
295 MEM_freeN(tex_data);
296}
297
299{
300 if (!framebuffer_) {
301 framebuffer_ = GPU_framebuffer_create("fb_render_hydra");
302 }
304 &framebuffer_, {GPU_ATTACHMENT_TEXTURE(tex_depth_), GPU_ATTACHMENT_TEXTURE(tex_color_)});
305 GPU_framebuffer_bind(framebuffer_);
306
307 float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
308 GPU_framebuffer_clear_color_depth(framebuffer_, clear_color, 1.0f);
309
310 /* Workaround missing/buggy VAOs in hgiGL and hdSt. For OpenGL compatibility
311 * profile this is not a problem, but for core profile it is. */
312 if (VAO_ == 0 && GPU_backend_get_type() == GPU_BACKEND_OPENGL) {
313 glGenVertexArrays(1, &VAO_);
314 glBindVertexArray(VAO_);
315 }
316 CLOG_INFO(LOG_HYDRA_RENDER, 3, "bind");
317}
318
320{
321 if (VAO_) {
322 glDeleteVertexArrays(1, &VAO_);
323 VAO_ = 0;
324 }
325 if (framebuffer_) {
326 GPU_framebuffer_free(framebuffer_);
327 framebuffer_ = nullptr;
328 }
329 CLOG_INFO(LOG_HYDRA_RENDER, 3, "unbind");
330}
331
332GPUTexture *GPURenderTaskDelegate::aov_texture(pxr::TfToken const &aov_key)
333{
334 if (aov_key == pxr::HdAovTokens->color) {
335 return tex_color_;
336 }
337 if (aov_key == pxr::HdAovTokens->depth) {
338 return tex_depth_;
339 }
340 return nullptr;
341}
342
343} // namespace blender::render::hydra
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define ELEM(...)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
eGPUBackendType GPU_backend_get_type()
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
#define GPU_ATTACHMENT_TEXTURE(_texture)
void GPU_framebuffer_clear_color_depth(GPUFrameBuffer *fb, const float clear_col[4], float clear_depth)
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
#define GPU_framebuffer_ensure_config(_fb,...)
void GPU_framebuffer_free(GPUFrameBuffer *framebuffer)
int GPU_texture_height(const GPUTexture *texture)
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
int GPU_texture_width(const GPUTexture *texture)
void * GPU_texture_read(GPUTexture *texture, eGPUDataFormat data_format, int mip_level)
eGPUDataFormat
@ GPU_DATA_HALF_FLOAT
@ GPU_DATA_FLOAT
@ GPU_TEXTURE_USAGE_GENERAL
eGPUTextureFormat
@ GPU_DEPTH_COMPONENT32F
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
Read Guarded memory(de)allocation.
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
void add_aov(pxr::TfToken const &aov_key) override
void set_viewport(pxr::GfVec4d const &viewport) override
GPUTexture * aov_texture(pxr::TfToken const &aov_key)
void read_aov(pxr::TfToken const &aov_key, void *data) override
pxr::TfTokenVector GetTaskRenderTags(pxr::SdfPath const &id) override
RenderTaskDelegate(pxr::HdRenderIndex *parent_index, pxr::SdfPath const &delegate_id)
virtual void set_viewport(pxr::GfVec4d const &viewport)
pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override
virtual void add_aov(pxr::TfToken const &aov_key)
pxr::SdfPath buffer_id(pxr::TfToken const &aov_key) const
void set_camera(pxr::SdfPath const &camera_id)
virtual void read_aov(pxr::TfToken const &aov_key, void *data)
pxr::HdRenderBufferDescriptor GetRenderBufferDescriptor(pxr::SdfPath const &id) override
pxr::TfHashMap< pxr::SdfPath, pxr::HdRenderBufferDescriptor, pxr::SdfPath::Hash > buffer_descriptors_
additional_info("compositor_sum_float_shared") .push_constant(Type additional_info("compositor_sum_float_shared") .push_constant(Type GPU_RGBA32F
int len
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
format
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
struct CLG_LogRef * LOG_HYDRA_RENDER