1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #include "pxr/imaging/hd/renderPassState.h"
25 #include "pxr/imaging/plugin/hdEmbree/renderDelegate.h"
26 #include "pxr/imaging/plugin/hdEmbree/renderPass.h"
27
28 PXR_NAMESPACE_OPEN_SCOPE
29
HdEmbreeRenderPass(HdRenderIndex * index,HdRprimCollection const & collection,HdRenderThread * renderThread,HdEmbreeRenderer * renderer,std::atomic<int> * sceneVersion)30 HdEmbreeRenderPass::HdEmbreeRenderPass(HdRenderIndex *index,
31 HdRprimCollection const &collection,
32 HdRenderThread *renderThread,
33 HdEmbreeRenderer *renderer,
34 std::atomic<int> *sceneVersion)
35 : HdRenderPass(index, collection)
36 , _renderThread(renderThread)
37 , _renderer(renderer)
38 , _sceneVersion(sceneVersion)
39 , _lastSceneVersion(0)
40 , _lastSettingsVersion(0)
41 , _viewMatrix(1.0f) // == identity
42 , _projMatrix(1.0f) // == identity
43 , _aovBindings()
44 , _colorBuffer(SdfPath::EmptyPath())
45 , _depthBuffer(SdfPath::EmptyPath())
46 , _converged(false)
47 {
48 }
49
~HdEmbreeRenderPass()50 HdEmbreeRenderPass::~HdEmbreeRenderPass()
51 {
52 // Make sure the render thread's not running, in case it's writing
53 // to _colorBuffer/_depthBuffer.
54 _renderThread->StopRender();
55 }
56
57 bool
IsConverged() const58 HdEmbreeRenderPass::IsConverged() const
59 {
60 // If the aov binding array is empty, the render thread is rendering into
61 // _colorBuffer and _depthBuffer. _converged is set to their convergence
62 // state just before blit, so use that as our answer.
63 if (_aovBindings.size() == 0) {
64 return _converged;
65 }
66
67 // Otherwise, check the convergence of all attachments.
68 for (size_t i = 0; i < _aovBindings.size(); ++i) {
69 if (_aovBindings[i].renderBuffer &&
70 !_aovBindings[i].renderBuffer->IsConverged()) {
71 return false;
72 }
73 }
74 return true;
75 }
76
77 static
78 GfRect2i
_GetDataWindow(HdRenderPassStateSharedPtr const & renderPassState)79 _GetDataWindow(HdRenderPassStateSharedPtr const& renderPassState)
80 {
81 const CameraUtilFraming &framing = renderPassState->GetFraming();
82 if (framing.IsValid()) {
83 return framing.dataWindow;
84 } else {
85 // For applications that use the old viewport API instead of
86 // the new camera framing API.
87 const GfVec4f vp = renderPassState->GetViewport();
88 return GfRect2i(GfVec2i(0), int(vp[2]), int(vp[3]));
89 }
90 }
91
92 void
_Execute(HdRenderPassStateSharedPtr const & renderPassState,TfTokenVector const & renderTags)93 HdEmbreeRenderPass::_Execute(HdRenderPassStateSharedPtr const& renderPassState,
94 TfTokenVector const &renderTags)
95 {
96 // XXX: Add collection and renderTags support.
97 // XXX: Add clip planes support.
98
99 // Determine whether the scene has changed since the last time we rendered.
100 bool needStartRender = false;
101 int currentSceneVersion = _sceneVersion->load();
102 if (_lastSceneVersion != currentSceneVersion) {
103 needStartRender = true;
104 _lastSceneVersion = currentSceneVersion;
105 }
106
107 // Likewise the render settings.
108 HdRenderDelegate *renderDelegate = GetRenderIndex()->GetRenderDelegate();
109 int currentSettingsVersion = renderDelegate->GetRenderSettingsVersion();
110 if (_lastSettingsVersion != currentSettingsVersion) {
111 _renderThread->StopRender();
112 _lastSettingsVersion = currentSettingsVersion;
113
114 _renderer->SetSamplesToConvergence(
115 renderDelegate->GetRenderSetting<int>(
116 HdRenderSettingsTokens->convergedSamplesPerPixel, 1));
117
118 bool enableAmbientOcclusion =
119 renderDelegate->GetRenderSetting<bool>(
120 HdEmbreeRenderSettingsTokens->enableAmbientOcclusion, false);
121 if (enableAmbientOcclusion) {
122 _renderer->SetAmbientOcclusionSamples(
123 renderDelegate->GetRenderSetting<int>(
124 HdEmbreeRenderSettingsTokens->ambientOcclusionSamples, 0));
125 } else {
126 _renderer->SetAmbientOcclusionSamples(0);
127 }
128
129 _renderer->SetEnableSceneColors(
130 renderDelegate->GetRenderSetting<bool>(
131 HdEmbreeRenderSettingsTokens->enableSceneColors, true));
132
133 needStartRender = true;
134 }
135
136 // Determine whether we need to update the renderer camera.
137 const GfMatrix4d view = renderPassState->GetWorldToViewMatrix();
138 const GfMatrix4d proj = renderPassState->GetProjectionMatrix();
139 if (_viewMatrix != view || _projMatrix != proj) {
140 _viewMatrix = view;
141 _projMatrix = proj;
142
143 _renderThread->StopRender();
144 _renderer->SetCamera(_viewMatrix, _projMatrix);
145 needStartRender = true;
146 }
147
148 const GfRect2i dataWindow = _GetDataWindow(renderPassState);
149
150 if (_dataWindow != dataWindow) {
151 _dataWindow = dataWindow;
152
153 _renderThread->StopRender();
154 _renderer->SetDataWindow(dataWindow);
155
156 if (!renderPassState->GetFraming().IsValid()) {
157 // Support clients that do not use the new framing API
158 // and do not use AOVs.
159 //
160 // Note that we do not support the case of using the
161 // new camera framing API without using AOVs.
162 //
163 const GfVec3i dimensions(_dataWindow.GetWidth(),
164 _dataWindow.GetHeight(),
165 1);
166
167 _colorBuffer.Allocate(
168 dimensions,
169 HdFormatUNorm8Vec4,
170 /*multiSampled=*/true);
171
172 _depthBuffer.Allocate(
173 dimensions,
174 HdFormatFloat32,
175 /*multiSampled=*/false);
176 }
177
178 needStartRender = true;
179 }
180
181 // Determine whether we need to update the renderer AOV bindings.
182 //
183 // It's possible for the passed in bindings to be empty, but that's
184 // never a legal state for the renderer, so if that's the case we add
185 // a color and depth aov.
186 //
187 // If the renderer AOV bindings are empty, force a bindings update so that
188 // we always get a chance to add color/depth on the first time through.
189 HdRenderPassAovBindingVector aovBindings =
190 renderPassState->GetAovBindings();
191 if (_aovBindings != aovBindings || _renderer->GetAovBindings().empty()) {
192 _aovBindings = aovBindings;
193
194 _renderThread->StopRender();
195 if (aovBindings.empty()) {
196 HdRenderPassAovBinding colorAov;
197 colorAov.aovName = HdAovTokens->color;
198 colorAov.renderBuffer = &_colorBuffer;
199 colorAov.clearValue =
200 VtValue(GfVec4f(0.0707f, 0.0707f, 0.0707f, 1.0f));
201 aovBindings.push_back(colorAov);
202 HdRenderPassAovBinding depthAov;
203 depthAov.aovName = HdAovTokens->depth;
204 depthAov.renderBuffer = &_depthBuffer;
205 depthAov.clearValue = VtValue(1.0f);
206 aovBindings.push_back(depthAov);
207 }
208 _renderer->SetAovBindings(aovBindings);
209 // In general, the render thread clears aov bindings, but make sure
210 // they are cleared initially on this thread.
211 _renderer->Clear();
212 needStartRender = true;
213 }
214
215 TF_VERIFY(!_aovBindings.empty(), "No aov bindings to render into");
216
217 // Only start a new render if something in the scene has changed.
218 if (needStartRender) {
219 _converged = false;
220 _renderer->MarkAovBuffersUnconverged();
221 _renderThread->StartRender();
222 }
223 }
224
225 PXR_NAMESPACE_CLOSE_SCOPE
226