HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hgi.h
Go to the documentation of this file.
1 //
2 // Copyright 2019 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_IMAGING_HGI_HGI_H
8 #define PXR_IMAGING_HGI_HGI_H
9 
10 #include "pxr/pxr.h"
11 #include "pxr/base/tf/token.h"
12 #include "pxr/base/tf/type.h"
13 
14 #include "pxr/imaging/hgi/api.h"
16 #include "pxr/imaging/hgi/buffer.h"
27 #include "pxr/imaging/hgi/types.h"
29 
30 #include <atomic>
31 #include <memory>
32 
34 
35 class HgiCapabilities;
37 
38 using HgiUniquePtr = std::unique_ptr<class Hgi>;
39 
40 
41 /// \class Hgi
42 ///
43 /// Hydra Graphics Interface.
44 /// Hgi is used to communicate with one or more physical gpu devices.
45 ///
46 /// Hgi provides API to create/destroy resources that a gpu device owns.
47 /// The lifetime of resources is not managed by Hgi, so it is up to the caller
48 /// to destroy resources and ensure those resources are no longer used.
49 ///
50 /// Commands are recorded in 'HgiCmds' objects and submitted via Hgi.
51 ///
52 /// Thread-safety:
53 ///
54 /// Modern graphics APIs like Metal and Vulkan are designed with multi-threading
55 /// in mind. We want to try and take advantage of this where possible.
56 /// However we also wish to continue to support OpenGL for the time being.
57 ///
58 /// In an application where OpenGL is involved, when we say "main thread" we
59 /// mean the thread on which the gl-context is bound.
60 ///
61 /// Each Hgi backend should at minimum support the following:
62 ///
63 /// * Single threaded Hgi::SubmitCmds on main thread.
64 /// * Single threaded Hgi::Resource Create*** / Destroy*** on main thread.
65 /// * Multi threaded recording of commands in Hgi***Cmds objects.
66 /// * A Hgi***Cmds object should be creatable on the main thread, recorded
67 /// into with one secondary thread (only one thread may use a Cmds object) and
68 /// submitted via the main thread.
69 ///
70 /// Each Hgi backend is additionally encouraged to support:
71 ///
72 /// * Multi threaded support for resource creation and destruction.
73 ///
74 /// We currently do not rely on these additional multi-threading features in
75 /// Hydra / Storm where we still wish to run OpenGL. In Hydra we make sure to
76 /// use the main-thread for resource creation and command submission.
77 /// One day we may wish to switch this to be multi-threaded so new Hgi backends
78 /// are encouraged to support it.
79 ///
80 /// Pseudo code what should minimally be supported:
81 ///
82 /// vector<HgiGraphicsCmds> cmds
83 ///
84 /// for num_threads
85 /// cmds.push_back( Hgi->CreateGraphicsCmds() )
86 ///
87 /// parallel_for i to num_threads
88 /// cmds[i]->SetViewport()
89 /// cmds[i]->Draw()
90 ///
91 /// for i to num_threads
92 /// hgi->SubmitCmds( cmds[i] )
93 ///
94 class Hgi
95 {
96 public:
97  HGI_API
98  Hgi();
99 
100  HGI_API
101  virtual ~Hgi();
102 
103  /// Submit one HgiCmds objects.
104  /// Once the cmds object is submitted it cannot be re-used to record cmds.
105  /// A call to SubmitCmds would usually result in the hgi backend submitting
106  /// the cmd buffers of the cmds object(s) to the device queue.
107  /// Derived classes can override _SubmitCmds to customize submission.
108  /// Thread safety: This call is not thread-safe. Submission must happen on
109  /// the main thread so we can continue to support the OpenGL platform.
110  /// See notes above.
111  HGI_API
112  void SubmitCmds(
113  HgiCmds* cmds,
115 
116  /// *** DEPRECATED *** Please use: CreatePlatformDefaultHgi
117  HGI_API
118  static Hgi* GetPlatformDefaultHgi();
119 
120  /// Helper function to return a Hgi object for the current platform.
121  /// For example on Linux this may return HgiGL while on macOS HgiMetal.
122  /// Caller, usually the application, owns the lifetime of the Hgi object and
123  /// the object is destroyed when the caller drops the unique ptr.
124  /// Thread safety: Not thread safe.
125  HGI_API
127 
128  /// Helper function to return a Hgi object of choice supported by current
129  /// platform and build configuration.
130  /// For example, on macOS, this may allow HgiMetal only.
131  /// If the Hgi device specified is not available on the current platform,
132  /// this function will fail and return nullptr.
133  /// If an empty token is provided, the default Hgi type (see
134  /// CreatePlatformDefaultHgi) will be created.
135  /// Supported TfToken values are OpenGL, Metal, Vulkan, or an empty token;
136  /// if not using an empty token, the caller is expected to use a token from
137  /// HgiTokens.
138  /// Caller, usually the application, owns the lifetime of the Hgi object and
139  /// the object is destroyed when the caller drops the unique ptr.
140  /// Thread safety: Not thread safe.
141  HGI_API
142  static HgiUniquePtr CreateNamedHgi(const TfToken& hgiToken);
143 
144  /// Determine if Hgi instance can run on current hardware.
145  /// Thread safety: This call is thread safe.
146  HGI_API
147  virtual bool IsBackendSupported() const = 0;
148 
149  /// Constructs a temporary Hgi object and calls the object's
150  /// IsBackendSupported() function.
151  /// A token can optionally be provided to specify a specific Hgi backend to
152  /// create. Supported TfToken values are OpenGL, Metal, Vulkan, or an empty
153  /// token; if not using an empty token, the caller is expected to use a
154  /// token from HgiTokens.
155  /// An empty token will check support for creating the platform default Hgi.
156  /// An invalid token will result in this function returning false.
157  /// Thread safety: Not thread safe.
158  HGI_API
159  static bool IsSupported(const TfToken& hgiToken = TfToken());
160 
161  /// Returns a GraphicsCmds object (for temporary use) that is ready to
162  /// record draw commands. GraphicsCmds is a lightweight object that
163  /// should be re-acquired each frame (don't hold onto it after EndEncoding).
164  /// Thread safety: Each Hgi backend must ensure that a Cmds object can be
165  /// created on the main thread, recorded into (exclusively) by one secondary
166  /// thread and be submitted on the main thread. See notes above.
167  HGI_API
169  HgiGraphicsCmdsDesc const& desc) = 0;
170 
171  /// Returns a BlitCmds object (for temporary use) that is ready to execute
172  /// resource copy commands. BlitCmds is a lightweight object that
173  /// should be re-acquired each frame (don't hold onto it after EndEncoding).
174  /// Thread safety: Each Hgi backend must ensure that a Cmds object can be
175  /// created on the main thread, recorded into (exclusively) by one secondary
176  /// thread and be submitted on the main thread. See notes above.
177  HGI_API
178  virtual HgiBlitCmdsUniquePtr CreateBlitCmds() = 0;
179 
180  /// Returns a ComputeCmds object (for temporary use) that is ready to
181  /// record dispatch commands. ComputeCmds is a lightweight object that
182  /// should be re-acquired each frame (don't hold onto it after EndEncoding).
183  /// Thread safety: Each Hgi backend must ensure that a Cmds object can be
184  /// created on the main thread, recorded into (exclusively) by one secondary
185  /// thread and be submitted on the main thread. See notes above.
186  HGI_API
188  HgiComputeCmdsDesc const& desc) = 0;
189 
190  /// Create a texture in rendering backend.
191  /// Thread safety: Creation must happen on main thread. See notes above.
192  HGI_API
194 
195  /// Destroy a texture in rendering backend.
196  /// Thread safety: Destruction must happen on main thread. See notes above.
197  HGI_API
198  virtual void DestroyTexture(HgiTextureHandle* texHandle) = 0;
199 
200  /// Create a texture view in rendering backend.
201  /// A texture view aliases another texture's data.
202  /// It is the responsibility of the client to ensure that the sourceTexture
203  /// is not destroyed while the texture view is in use.
204  /// Thread safety: Creation must happen on main thread. See notes above.
205  HGI_API
207  HgiTextureViewDesc const & desc);
208 
209  /// Destroy a texture view in rendering backend.
210  /// This will destroy the view's texture, but not the sourceTexture that
211  /// was aliased by the view. The sourceTexture data remains unchanged.
212  /// Thread safety: Destruction must happen on main thread. See notes above.
213  HGI_API
214  virtual void DestroyTextureView(HgiTextureViewHandle* viewHandle) = 0;
215 
216  /// Create a sampler in rendering backend.
217  /// Thread safety: Creation must happen on main thread. See notes above.
218  HGI_API
219  virtual HgiSamplerHandle CreateSampler(HgiSamplerDesc const & desc) = 0;
220 
221  /// Destroy a sampler in rendering backend.
222  /// Thread safety: Destruction must happen on main thread. See notes above.
223  HGI_API
224  virtual void DestroySampler(HgiSamplerHandle* smpHandle) = 0;
225 
226  /// Create a buffer in rendering backend.
227  /// Thread safety: Creation must happen on main thread. See notes above.
228  HGI_API
230 
231  /// Destroy a buffer in rendering backend.
232  /// Thread safety: Destruction must happen on main thread. See notes above.
233  HGI_API
234  virtual void DestroyBuffer(HgiBufferHandle* bufHandle) = 0;
235 
236  /// Create a new shader function.
237  /// Thread safety: Creation must happen on main thread. See notes above.
238  HGI_API
240  HgiShaderFunctionDesc const& desc) = 0;
241 
242  /// Destroy a shader function.
243  /// Thread safety: Destruction must happen on main thread. See notes above.
244  HGI_API
245  virtual void DestroyShaderFunction(
246  HgiShaderFunctionHandle* shaderFunctionHandle) = 0;
247 
248  /// Create a new shader program.
249  /// Thread safety: Creation must happen on main thread. See notes above.
250  HGI_API
252  HgiShaderProgramDesc const& desc) = 0;
253 
254  /// Destroy a shader program.
255  /// Note that this does NOT automatically destroy the shader functions in
256  /// the program since shader functions may be used by more than one program.
257  /// Thread safety: Destruction must happen on main thread. See notes above.
258  HGI_API
259  virtual void DestroyShaderProgram(
260  HgiShaderProgramHandle* shaderProgramHandle) = 0;
261 
262  /// Create a new resource binding object.
263  /// Thread safety: Creation must happen on main thread. See notes above.
264  HGI_API
266  HgiResourceBindingsDesc const& desc);
267 
268  /// Destroy a resource binding object.
269  /// Thread safety: Destruction must happen on main thread. See notes above.
270  HGI_API
271  virtual void DestroyResourceBindings(
272  HgiResourceBindingsHandle* resHandle) = 0;
273 
274  /// Create a new graphics pipeline state object.
275  /// Thread safety: Creation must happen on main thread. See notes above.
276  HGI_API
278  HgiGraphicsPipelineDesc const& pipeDesc) = 0;
279 
280  /// Destroy a graphics pipeline state object.
281  /// Thread safety: Destruction must happen on main thread. See notes above.
282  HGI_API
283  virtual void DestroyGraphicsPipeline(
284  HgiGraphicsPipelineHandle* pipeHandle) = 0;
285 
286  /// Create a new compute pipeline state object.
287  /// Thread safety: Creation must happen on main thread. See notes above.
288  HGI_API
290  HgiComputePipelineDesc const& pipeDesc) = 0;
291 
292  /// Destroy a compute pipeline state object.
293  /// Thread safety: Destruction must happen on main thread. See notes above.
294  HGI_API
295  virtual void DestroyComputePipeline(HgiComputePipelineHandle* pipeHandle)=0;
296 
297  /// Return the name of the api (e.g. "OpenGL").
298  /// Thread safety: This call is thread safe.
299  HGI_API
300  virtual TfToken const& GetAPIName() const = 0;
301 
302  /// Returns the device-specific capabilities structure.
303  /// Thread safety: This call is thread safe.
304  HGI_API
305  virtual HgiCapabilities const* GetCapabilities() const = 0;
306 
307  /// Returns the device-specific indirect command buffer encoder
308  /// or nullptr if not supported.
309  /// Thread safety: This call is thread safe.
310  HGI_API
312 
313  /// Optionally called by client app at the start of a new rendering frame.
314  /// We can't rely on StartFrame for anything important, because it is up to
315  /// the external client to (optionally) call this and they may never do.
316  /// Hydra doesn't have a clearly defined start or end frame.
317  /// This can be helpful to insert GPU frame debug markers.
318  /// Thread safety: Not thread safe. Should be called on the main thread.
319  HGI_API
320  virtual void StartFrame() = 0;
321 
322  /// Optionally called at the end of a rendering frame.
323  /// Please read the comments in StartFrame.
324  /// Thread safety: Not thread safe. Should be called on the main thread.
325  HGI_API
326  virtual void EndFrame() = 0;
327 
328  /// Perform any necessary garbage collection, if applicable. This can be
329  /// used to flush pending deletes immediately after unloading assets, for
330  /// example. Note that as some clients may not call this, Hgi
331  /// implementations should find other opportunities to garbage collect as
332  /// well (e.g. EndFrame).
333  HGI_API
334  virtual void GarbageCollect() = 0;
335 
336 protected:
337  // Returns a unique id for handle creation.
338  // Thread safety: Thread-safe atomic increment.
339  HGI_API
340  uint64_t GetUniqueId();
341 
342  // Calls Submit on provided Cmds.
343  // Derived classes can override this function if they need customize the
344  // command submission. The default implementation calls cmds->_Submit().
345  HGI_API
346  virtual bool _SubmitCmds(
348 
349  HGI_API
350  virtual HgiTextureHandle _CreateTexture(HgiTextureDesc const & desc) = 0;
351 
352  HGI_API
354  HgiTextureViewDesc const & desc) = 0;
355 
356  HGI_API
357  virtual HgiBufferHandle _CreateBuffer(HgiBufferDesc const & desc) = 0;
358 
359  HGI_API
361  HgiResourceBindingsDesc const& desc) = 0;
362 
363 private:
364  Hgi & operator=(const Hgi&) = delete;
365  Hgi(const Hgi&) = delete;
366 
367  std::atomic<uint64_t> _uniqueIdCounter;
368 };
369 
370 
371 ///
372 /// Hgi factory for plugin system
373 ///
375 public:
376  virtual Hgi* New() const = 0;
377 };
378 
379 template <class T>
380 class HgiFactory : public HgiFactoryBase {
381 public:
382  Hgi* New() const {
383  return new T;
384  }
385 };
386 
387 
389 
390 #endif
virtual HGI_API bool _SubmitCmds(HgiCmds *cmds, HgiSubmitWaitType wait)
static HGI_API Hgi * GetPlatformDefaultHgi()
*** DEPRECATED *** Please use: CreatePlatformDefaultHgi
virtual HGI_API HgiShaderProgramHandle CreateShaderProgram(HgiShaderProgramDesc const &desc)=0
virtual HGI_API void DestroySampler(HgiSamplerHandle *smpHandle)=0
Hgi * New() const
Definition: hgi.h:382
virtual HGI_API HgiCapabilities const * GetCapabilities() const =0
virtual HGI_API HgiTextureHandle _CreateTexture(HgiTextureDesc const &desc)=0
virtual HGI_API void DestroyBuffer(HgiBufferHandle *bufHandle)=0
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
HGI_API HgiTextureHandle CreateTexture(HgiTextureDesc const &desc)
virtual HGI_API HgiResourceBindingsHandle _CreateResourceBindings(HgiResourceBindingsDesc const &desc)=0
HGI_API uint64_t GetUniqueId()
virtual HGI_API void DestroyGraphicsPipeline(HgiGraphicsPipelineHandle *pipeHandle)=0
HGI_API Hgi()
int HgiHandle< class HgiTexture > HgiTextureHandle
virtual HGI_API HgiGraphicsCmdsUniquePtr CreateGraphicsCmds(HgiGraphicsCmdsDesc const &desc)=0
virtual HGI_API HgiComputeCmdsUniquePtr CreateComputeCmds(HgiComputeCmdsDesc const &desc)=0
static HGI_API bool IsSupported(const TfToken &hgiToken=TfToken())
virtual HGI_API void DestroyShaderFunction(HgiShaderFunctionHandle *shaderFunctionHandle)=0
HGI_API void SubmitCmds(HgiCmds *cmds, HgiSubmitWaitType wait=HgiSubmitWaitTypeNoWait)
virtual HGI_API HgiShaderFunctionHandle CreateShaderFunction(HgiShaderFunctionDesc const &desc)=0
Base class of all factory types.
Definition: type.h:56
virtual HGI_API void DestroyTexture(HgiTextureHandle *texHandle)=0
virtual HGI_API void GarbageCollect()=0
HgiSubmitWaitType
Definition: enums.h:657
virtual HGI_API void EndFrame()=0
Definition: token.h:70
static HGI_API HgiUniquePtr CreateNamedHgi(const TfToken &hgiToken)
virtual HGI_API void DestroyResourceBindings(HgiResourceBindingsHandle *resHandle)=0
virtual HGI_API void DestroyShaderProgram(HgiShaderProgramHandle *shaderProgramHandle)=0
virtual Hgi * New() const =0
virtual HGI_API HgiBlitCmdsUniquePtr CreateBlitCmds()=0
virtual HGI_API bool IsBackendSupported() const =0
virtual HGI_API void StartFrame()=0
static HGI_API HgiUniquePtr CreatePlatformDefaultHgi()
virtual HGI_API void DestroyTextureView(HgiTextureViewHandle *viewHandle)=0
std::unique_ptr< class HgiGraphicsCmds > HgiGraphicsCmdsUniquePtr
Definition: effectsShader.h:28
std::unique_ptr< class HgiComputeCmds > HgiComputeCmdsUniquePtr
Definition: computeCmds.h:19
virtual HGI_API HgiBufferHandle _CreateBuffer(HgiBufferDesc const &desc)=0
virtual HGI_API HgiComputePipelineHandle CreateComputePipeline(HgiComputePipelineDesc const &pipeDesc)=0
*tasks wait()
virtual HGI_API HgiGraphicsPipelineHandle CreateGraphicsPipeline(HgiGraphicsPipelineDesc const &pipeDesc)=0
Definition: hgi.h:94
std::unique_ptr< class HgiBlitCmds > HgiBlitCmdsUniquePtr
Definition: blitCmds.h:28
HGI_API HgiBufferHandle CreateBuffer(HgiBufferDesc const &desc)
#define HGI_API
Definition: api.h:23
HGI_API HgiResourceBindingsHandle CreateResourceBindings(HgiResourceBindingsDesc const &desc)
HGI_API HgiTextureViewHandle CreateTextureView(HgiTextureViewDesc const &desc)
virtual HGI_API HgiIndirectCommandEncoder * GetIndirectCommandEncoder() const =0
virtual HGI_API HgiSamplerHandle CreateSampler(HgiSamplerDesc const &desc)=0
virtual HGI_API HgiTextureViewHandle _CreateTextureView(HgiTextureViewDesc const &desc)=0
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
virtual HGI_API ~Hgi()
virtual HGI_API void DestroyComputePipeline(HgiComputePipelineHandle *pipeHandle)=0
virtual HGI_API TfToken const & GetAPIName() const =0
Definition: cmds.h:28
std::unique_ptr< class Hgi > HgiUniquePtr
Definition: hgi.h:38