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
25 #include "pxr/imaging/garch/glApi.h"
26
27 #include "pxr/imaging/glf/contextCaps.h"
28 #include "pxr/imaging/glf/glContext.h"
29 #include "pxr/imaging/glf/testGLContext.h"
30
31 #include "pxr/imaging/hd/changeTracker.h"
32 #include "pxr/imaging/hd/driver.h"
33 #include "pxr/imaging/hd/engine.h"
34 #include "pxr/imaging/hd/tokens.h"
35
36 #include "pxr/imaging/hd/camera.h"
37 #include "pxr/imaging/hdSt/light.h"
38 #include "pxr/imaging/hdSt/renderDelegate.h"
39 #include "pxr/imaging/hdSt/renderPass.h"
40 #include "pxr/imaging/hdSt/renderPassState.h"
41
42 #include "pxr/imaging/hdx/unitTestDelegate.h"
43
44 #include "pxr/imaging/hgi/hgi.h"
45 #include "pxr/imaging/hgi/tokens.h"
46
47 #include "pxr/base/tf/errorMark.h"
48
49 #include <iostream>
50 #include <memory>
51
52 #define VERIFY_PERF_COUNT(token, count) \
53 TF_VERIFY(perfLog.GetCounter(token) == count, \
54 "expected %d found %.0f", \
55 count,\
56 perfLog.GetCounter(token));
57
58 PXR_NAMESPACE_USING_DIRECTIVE
59
60 class Hd_TestTask final : public HdTask
61 {
62 public:
Hd_TestTask(HdRenderPassSharedPtr const & renderPass,HdRenderPassStateSharedPtr const & renderPassState)63 Hd_TestTask(HdRenderPassSharedPtr const &renderPass,
64 HdRenderPassStateSharedPtr const &renderPassState)
65 : HdTask(SdfPath::EmptyPath())
66 , _renderPass(renderPass)
67 , _renderPassState(renderPassState)
68 {
69 }
70
Sync(HdSceneDelegate *,HdTaskContext *,HdDirtyBits *)71 virtual void Sync(HdSceneDelegate*,
72 HdTaskContext*,
73 HdDirtyBits*) override
74 {
75 _renderPass->Sync();
76 }
77
Prepare(HdTaskContext * ctx,HdRenderIndex * renderIndex)78 virtual void Prepare(HdTaskContext* ctx,
79 HdRenderIndex* renderIndex) override
80 {
81 _renderPassState->Prepare(renderIndex->GetResourceRegistry());
82 }
83
Execute(HdTaskContext * ctx)84 virtual void Execute(HdTaskContext* ctx) override
85 {
86 _renderPass->Execute(_renderPassState, GetRenderTags());
87 }
88
89 private:
90 HdRenderPassSharedPtr _renderPass;
91 HdRenderPassStateSharedPtr _renderPassState;
92 };
93
CameraAndLightTest()94 static void CameraAndLightTest()
95 {
96 // Hgi and HdDriver should be constructed before HdEngine to ensure they
97 // are destructed last. Hgi may be used during engine/delegate destruction.
98 HgiUniquePtr hgi = Hgi::CreatePlatformDefaultHgi();
99 HdDriver driver{HgiTokens->renderDriver, VtValue(hgi.get())};
100
101 HdStRenderDelegate renderDelegate;
102 std::unique_ptr<HdRenderIndex> index(
103 HdRenderIndex::New(&renderDelegate, {&driver}));
104 TF_VERIFY(index);
105 std::unique_ptr<Hdx_UnitTestDelegate> delegate(
106 new Hdx_UnitTestDelegate(index.get()));
107
108 HdChangeTracker& tracker = index->GetChangeTracker();
109 HdPerfLog& perfLog = HdPerfLog::GetInstance();
110 perfLog.Enable();
111 HdRprimCollection collection(HdTokens->geometry,
112 HdReprSelector(HdReprTokens->hull));
113 HdRenderPassStateSharedPtr renderPassState(new HdStRenderPassState());
114 HdRenderPassSharedPtr renderPass(
115 new HdSt_RenderPass(index.get(), collection));
116 HdEngine engine;
117
118 HdTaskSharedPtr drawTask = std::make_shared<Hd_TestTask>(renderPass,
119 renderPassState);
120 HdTaskSharedPtrVector tasks = { drawTask };
121
122 GfMatrix4d tx(1.0f);
123 tx.SetRow(3, GfVec4f(5, 0, 5, 1.0));
124 SdfPath cube("/geometry");
125 delegate->AddCube(cube, tx);
126
127 SdfPath camera("/camera_test");
128 SdfPath light("/light");
129
130 delegate->AddCamera(camera);
131 delegate->AddLight(light, GlfSimpleLight());
132 delegate->SetLight(light, HdLightTokens->shadowCollection,
133 VtValue(HdRprimCollection(HdTokens->geometry,
134 HdReprSelector(HdReprTokens->hull))));
135
136 engine.Execute(index.get(), &tasks);
137
138 VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 1);
139
140 // Update camera matrix
141 delegate->SetCamera(camera, GfMatrix4d(2), GfMatrix4d(2));
142 tracker.MarkSprimDirty(camera, HdCamera::DirtyViewMatrix);
143 tracker.MarkSprimDirty(camera, HdCamera::DirtyProjMatrix);
144
145 engine.Execute(index.get(), &tasks);
146
147 // batch should not be rebuilt
148 VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 1);
149
150 // Update shadow collection
151 delegate->SetLight(light, HdLightTokens->shadowCollection,
152 VtValue(HdRprimCollection(HdTokens->geometry,
153 HdReprSelector(HdReprTokens->refined))));
154 tracker.MarkSprimDirty(light, HdLight::DirtyCollection);
155
156 engine.Execute(index.get(), &tasks);
157
158 // batch rebuilt
159 VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 2);
160
161 // Update shadow collection again with the same data
162 delegate->SetLight(light, HdLightTokens->shadowCollection,
163 VtValue(HdRprimCollection(HdTokens->geometry,
164 HdReprSelector(HdReprTokens->refined))));
165 tracker.MarkSprimDirty(light, HdLight::DirtyCollection);
166
167 engine.Execute(index.get(), &tasks);
168
169 // batch should not be rebuilt
170 VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 2);
171 }
172
main()173 int main()
174 {
175 TfErrorMark mark;
176
177 // Test uses ContextCaps, so need to create a GL instance.
178 GlfTestGLContext::RegisterGLContextCallbacks();
179 GarchGLApiLoad();
180 GlfSharedGLContextScopeHolder sharedContext;
181 GlfContextCaps::InitInstance();
182
183 CameraAndLightTest();
184
185 TF_VERIFY(mark.IsClean());
186
187 if (mark.IsClean()) {
188 std::cout << "OK" << std::endl;
189 return EXIT_SUCCESS;
190 } else {
191 std::cout << "FAILED" << std::endl;
192 return EXIT_FAILURE;
193 }
194 }
195
196