1 //
2 // Copyright 2019 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/hdx/presentTask.h"
25 
26 #include "pxr/imaging/hd/aov.h"
27 #include "pxr/imaging/hd/tokens.h"
28 
29 #include "pxr/imaging/hgi/hgi.h"
30 #include "pxr/imaging/hgi/tokens.h"
31 
32 
33 PXR_NAMESPACE_OPEN_SCOPE
34 
35 bool
_IsIntegerFormat(HgiFormat format)36 _IsIntegerFormat(HgiFormat format)
37 {
38     return (format == HgiFormatUInt16 ||
39             format == HgiFormatUInt16Vec2 ||
40             format == HgiFormatUInt16Vec3 ||
41             format == HgiFormatUInt16Vec4 ||
42             format == HgiFormatInt32 ||
43             format == HgiFormatInt32Vec2 ||
44             format == HgiFormatInt32Vec3 ||
45             format == HgiFormatInt32Vec4);
46 }
47 
48 /*static*/
49 bool
IsFormatSupported(HgiFormat aovFormat)50 HdxPresentTask::IsFormatSupported(HgiFormat aovFormat)
51 {
52     // Integer formats are not supported (this requires the GL interop to
53     // support additional sampler types), nor are compressed formats.
54     return !_IsIntegerFormat(aovFormat) && !HgiIsCompressed(aovFormat);
55 }
56 
HdxPresentTask(HdSceneDelegate * delegate,SdfPath const & id)57 HdxPresentTask::HdxPresentTask(HdSceneDelegate* delegate, SdfPath const& id)
58     : HdxTask(id)
59 {
60 }
61 
62 HdxPresentTask::~HdxPresentTask() = default;
63 
64 void
_Sync(HdSceneDelegate * delegate,HdTaskContext * ctx,HdDirtyBits * dirtyBits)65 HdxPresentTask::_Sync(
66     HdSceneDelegate* delegate,
67     HdTaskContext* ctx,
68     HdDirtyBits* dirtyBits)
69 {
70     HD_TRACE_FUNCTION();
71     HF_MALLOC_TAG_FUNCTION();
72 
73     if ((*dirtyBits) & HdChangeTracker::DirtyParams) {
74         HdxPresentTaskParams params;
75 
76         if (_GetTaskParams(delegate, &params)) {
77             _params = params;
78         }
79     }
80     *dirtyBits = HdChangeTracker::Clean;
81 }
82 
83 void
Prepare(HdTaskContext * ctx,HdRenderIndex * renderIndex)84 HdxPresentTask::Prepare(HdTaskContext* ctx, HdRenderIndex *renderIndex)
85 {
86 }
87 
88 void
Execute(HdTaskContext * ctx)89 HdxPresentTask::Execute(HdTaskContext* ctx)
90 {
91     HD_TRACE_FUNCTION();
92     HF_MALLOC_TAG_FUNCTION();
93 
94     // The present task can be disabled in case an application does offscreen
95     // rendering or doesn't use Hgi interop (e.g. directly access AOV results).
96     // But we still need to call Hgi::EndFrame.
97 
98     if (_params.enabled && _HasTaskContextData(ctx, HdAovTokens->color)) {
99         // The color and depth aovs have the results we want to blit to the
100         // application. Depth is optional. When we are previewing a custom aov
101         // we may not have a depth buffer.
102 
103         HgiTextureHandle aovTexture;
104         _GetTaskContextData(ctx, HdAovTokens->color, &aovTexture);
105         if (aovTexture) {
106             HgiTextureDesc texDesc = aovTexture->GetDescriptor();
107             if (!IsFormatSupported(texDesc.format)) {
108                 // Warn, but don't bail.
109                 TF_WARN("Aov texture format %d may not be correctly supported "
110                         "for presentation via HgiInterop.", texDesc.format);
111             }
112         }
113 
114         HgiTextureHandle depthTexture;
115         if (_HasTaskContextData(ctx, HdAovTokens->depth)) {
116             _GetTaskContextData(ctx, HdAovTokens->depth, &depthTexture);
117         }
118 
119         // Use HgiInterop to composite the Hgi textures over the application's
120         // framebuffer contents.
121         // Eg. This allows us to render with HgiMetal and present the images
122         // into a opengl based application (such as usdview).
123         _interop.TransferToApp(
124             _hgi,
125             aovTexture, depthTexture,
126             _params.dstApi,
127             _params.dstFramebuffer, _params.dstRegion);
128     }
129 
130     // Wrap one HdEngine::Execute frame with Hgi StartFrame and EndFrame.
131     // StartFrame is currently called in the AovInputTask.
132     // This is important for Hgi garbage collection to run.
133     _GetHgi()->EndFrame();
134 }
135 
136 
137 // --------------------------------------------------------------------------- //
138 // VtValue Requirements
139 // --------------------------------------------------------------------------- //
140 
operator <<(std::ostream & out,const HdxPresentTaskParams & pv)141 std::ostream& operator<<(std::ostream& out, const HdxPresentTaskParams& pv)
142 {
143     out << "PresentTask Params: (...) "
144         << pv.dstApi;
145     return out;
146 }
147 
operator ==(const HdxPresentTaskParams & lhs,const HdxPresentTaskParams & rhs)148 bool operator==(const HdxPresentTaskParams& lhs,
149                 const HdxPresentTaskParams& rhs)
150 {
151     return lhs.dstApi == rhs.dstApi &&
152            lhs.dstFramebuffer == rhs.dstFramebuffer &&
153            lhs.dstRegion == rhs.dstRegion &&
154            lhs.enabled == rhs.enabled;
155 }
156 
operator !=(const HdxPresentTaskParams & lhs,const HdxPresentTaskParams & rhs)157 bool operator!=(const HdxPresentTaskParams& lhs,
158                 const HdxPresentTaskParams& rhs)
159 {
160     return !(lhs == rhs);
161 }
162 
163 PXR_NAMESPACE_CLOSE_SCOPE
164