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