KiCad PCB EDA Suite
Loading...
Searching...
No Matches
rhi_device.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22#include <chrono>
23#include <optional>
24#include <utility>
25#include <rhi/rhi_types.h>
26#include <rhi/rhi_handle.h>
28#include <rhi/rhi_buffer.h>
29#include <rhi/rhi_compute.h>
30#include <rhi/rhi_texture.h>
31#include <rhi/rhi_shader.h>
32#include <rhi/rhi_pipeline.h>
33#include <rhi/rhi_render_pass.h>
34#include <rhi/rhi_command.h>
35#include <rhi/rhi_surface.h>
36
38#undef ERROR
39
51
52
60
66{
67public:
68 virtual ~RHI_DEVICE() = default;
69
71 virtual bool SupportsCompute() const { return false; }
72 virtual RHI_COMPUTE_DEVICE_LIMITS ComputeDeviceLimits() const { return {}; }
76
79
81 virtual const char* GetName() const = 0;
82
83 virtual RHI_BACKEND GetBackend() const = 0;
84
89 virtual uint32_t MaxTextureSize() const { return 16384; }
90
91 virtual bool IsInitialized() const = 0;
92
97 {
99 return handle && RealizeBuffer( handle, desc ) ? handle : RHI_BufferHandle{};
100 }
101
108
113 virtual bool RealizeBuffer( RHI_BufferHandle handle, const RHI_BUFFER_DESC& desc ) = 0;
114
119 virtual void DestroyBuffer( RHI_BufferHandle handle ) = 0;
120
124 virtual void UpdateBuffer( RHI_BufferHandle handle, const void* data,
125 size_t sizeBytes, size_t offset = 0 ) = 0;
126
131 {
133 return handle && RealizeTexture( handle, desc ) ? handle : RHI_TextureHandle{};
134 }
135
140
145 virtual bool RealizeTexture( RHI_TextureHandle handle, const RHI_TEXTURE_DESC& desc ) = 0;
146
148 virtual void DestroyTexture( RHI_TextureHandle handle ) = 0;
149
153 virtual void UploadTexture( RHI_TextureHandle handle, const void* data, size_t sizeBytes ) = 0;
154
159 virtual void BeginUploadBatch() {}
160 virtual void EndUploadBatch() {}
161
164
165 virtual void DestroyShader( RHI_ShaderHandle handle ) = 0;
166
169
170 virtual void DestroyPipeline( RHI_PipelineHandle handle ) = 0;
171
174
175 virtual void DestroyRenderPass( RHI_RenderPassHandle handle ) = 0;
176
179
180 virtual void DestroyFramebuffer( RHI_FramebufferHandle handle ) = 0;
181
187 RHI_FramebufferHandle handle, uint32_t attachmentIndex = 0 ) const = 0;
188
191 const RHI_BIND_GROUP_LAYOUT_DESC& desc ) = 0;
192
194
197
198 virtual void DestroyBindGroup( RHI_BindGroupHandle handle ) = 0;
199
201 virtual void BindGroup( uint32_t groupIndex, RHI_BindGroupHandle group ) = 0;
202
207 virtual bool BeginRenderPass( const RHI_RENDER_PASS_BEGIN_DESC& desc ) = 0;
208
210 virtual bool EndRenderPass() = 0;
211
213 virtual void SetViewport( const RHI_VIEWPORT& viewport ) = 0;
214
216 virtual void SetScissor( const RHI_SCISSOR_RECT& scissor ) = 0;
217
219 virtual void BindPipeline( RHI_PipelineHandle pipeline ) = 0;
220
224 virtual void SetPushConstants( const void* data, size_t sizeBytes ) = 0;
225
227 virtual void BindVertexBuffer( uint32_t slot, RHI_BufferHandle buffer ) = 0;
228
230 virtual void BindIndexBuffer( RHI_BufferHandle buffer ) = 0;
231
233 virtual void Draw( uint32_t vertexCount, uint32_t firstVertex = 0 ) = 0;
234
236 virtual void DrawInstanced( uint32_t vertexCount, uint32_t instanceCount,
237 uint32_t firstVertex = 0, int32_t vertexOffset = 0,
238 uint32_t firstInstance = 0 ) = 0;
239
241 virtual void DrawIndexedInstanced( uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex = 0,
242 int32_t vertexOffset = 0, uint32_t firstInstance = 0 ) = 0;
243
246
248 virtual void DestroySurface( RHI_SurfaceHandle handle ) = 0;
249
252
254 virtual bool ResizeSwapchain( RHI_SwapchainHandle handle, uint32_t width,
255 uint32_t height, float dpiScale ) = 0;
256
257 virtual void DestroySwapchain( RHI_SwapchainHandle handle ) = 0;
258
260 void Release( RHI_BufferHandle& aHandle ) { DestroyBuffer( std::exchange( aHandle, {} ) ); }
261 void Release( RHI_TextureHandle& aHandle ) { DestroyTexture( std::exchange( aHandle, {} ) ); }
262 void Release( RHI_ShaderHandle& aHandle ) { DestroyShader( std::exchange( aHandle, {} ) ); }
263 void Release( RHI_PipelineHandle& aHandle ) { DestroyPipeline( std::exchange( aHandle, {} ) ); }
264 void Release( RHI_BindGroupLayoutHandle& aHandle ) { DestroyBindGroupLayout( std::exchange( aHandle, {} ) ); }
265 void Release( RHI_RenderPassHandle& aHandle ) { DestroyRenderPass( std::exchange( aHandle, {} ) ); }
266 void Release( RHI_FramebufferHandle& aHandle ) { DestroyFramebuffer( std::exchange( aHandle, {} ) ); }
267 void Release( RHI_BindGroupHandle& aHandle ) { DestroyBindGroup( std::exchange( aHandle, {} ) ); }
268 void Release( RHI_SurfaceHandle& aHandle ) { DestroySurface( std::exchange( aHandle, {} ) ); }
269 void Release( RHI_SwapchainHandle& aHandle ) { DestroySwapchain( std::exchange( aHandle, {} ) ); }
270
279 const RHI_SCISSOR_RECT* aSourceRect = nullptr ) = 0;
280
286 uint32_t attachmentIndex,
287 void* buffer, size_t bufferSize ) = 0;
288
298 uint32_t aSourceX = 0, uint32_t aSourceY = 0 )
299 {
300 return false;
301 }
302
309 virtual bool WaitForPresentSlot( RHI_SwapchainHandle aSwapchain, std::chrono::milliseconds aTimeout,
310 int aAllowed )
311 {
312 return false;
313 }
314
320
325 virtual bool PresentWaitsForDisplay( RHI_SwapchainHandle aSwapchain ) const { return true; }
326
331 virtual bool PresentReplacesQueued( RHI_SwapchainHandle aSwapchain ) const { return false; }
332
337 virtual std::optional<std::chrono::steady_clock::time_point>
339 {
340 return std::nullopt;
341 }
342
343
348 virtual void EndFrame()
349 {
352 }
353
355 size_t PendingDeferredReleases() const { return m_deferredReleaseQueue.PendingCount(); }
356
357protected:
358 virtual void ExecuteDeferredReleases() = 0;
359
364 template <typename Tag>
366 RHI_HANDLE<Tag> aHandle )
367 {
368 if( aPool.MarkPendingDestroy( aHandle ) )
369 m_deferredReleaseQueue.Enqueue( aType, aHandle.value, m_frameCounter );
370 }
371
372 uint64_t m_frameCounter = 0;
374};
Plain owning command data, recordable on any thread without device access.
Definition rhi_compute.h:91
Holds destroyed GPU resource handles until no in-flight command buffer can still reference them.
Creates, uses and destroys GPU resources through one graphics API backend.
Definition rhi_device.h:66
virtual RHI_BufferHandle ReserveBufferHandle()=0
Reserve a handle without creating the GPU buffer, so the UI thread can hand out handles while Realize...
virtual bool PresentWaitsForDisplay(RHI_SwapchainHandle aSwapchain) const
False when presents show at once instead of at the next vertical blank, so frames drawn faster than t...
Definition rhi_device.h:325
virtual void DestroyPipeline(RHI_PipelineHandle handle)=0
virtual RHI_FRAME_OP_RESULT Present(RHI_SwapchainHandle handle, RHI_FramebufferHandle aSrcFBO={}, const RHI_SCISSOR_RECT *aSourceRect=nullptr)=0
When aSrcFBO is valid its first color attachment is copied to the swapchain first.
virtual bool CopyFramebufferDepth(RHI_FramebufferHandle aSource, RHI_FramebufferHandle aDestination, uint32_t aSourceX=0, uint32_t aSourceY=0)
Fill all of aDestination with source depth from (aSourceX, aSourceY) on, ordered after passes already...
Definition rhi_device.h:297
virtual uint32_t MaxTextureSize() const
Largest texture width or height in texels.
Definition rhi_device.h:89
virtual void DestroyComputePipeline(RHI_ComputePipelineHandle)
Definition rhi_device.h:74
virtual ~RHI_DEVICE()=default
virtual RHI_SurfaceHandle CreateSurface(const RHI_SURFACE_DESC &desc)=0
Returns a null handle if the native window handle is invalid.
virtual bool ResizeSwapchain(RHI_SwapchainHandle handle, uint32_t width, uint32_t height, float dpiScale)=0
Call when the window size or DPI scale changes.
virtual RHI_ComputePipelineHandle CreateComputePipeline(const RHI_COMPUTE_PIPELINE_DESC &)
Definition rhi_device.h:73
void Release(RHI_FramebufferHandle &aHandle)
Definition rhi_device.h:266
virtual RHI_BACKEND GetBackend() const =0
RHI_DEFERRED_RELEASE_QUEUE m_deferredReleaseQueue
Definition rhi_device.h:373
virtual void EndUploadBatch()
Definition rhi_device.h:160
virtual void EndFrame()
Retire deferred releases that are due.
Definition rhi_device.h:348
void deferDestroy(RHI_HANDLE_POOL< Tag > &aPool, RHI_DEFERRED_RESOURCE_TYPE aType, RHI_HANDLE< Tag > aHandle)
Only the destroy that wins the pending-destroy claim enqueues, so racing destroys of one handle canno...
Definition rhi_device.h:365
virtual bool BeginRenderPass(const RHI_RENDER_PASS_BEGIN_DESC &desc)=0
Draws and dynamic state changes must come between this and EndRenderPass().
virtual void DestroyFramebuffer(RHI_FramebufferHandle handle)=0
virtual void DestroyShader(RHI_ShaderHandle handle)=0
virtual void DrawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex=0, int32_t vertexOffset=0, uint32_t firstInstance=0)=0
Reads 16-bit indices from the bound index buffer.
virtual void UploadTexture(RHI_TextureHandle handle, const void *data, size_t sizeBytes)=0
Data is tightly packed rows in the texture's format, exactly width * height * bpp bytes.
virtual bool ReadbackFramebufferPixels(RHI_FramebufferHandle handle, uint32_t attachmentIndex, void *buffer, size_t bufferSize)=0
buffer must hold at least width * height * bpp bytes.
virtual bool EndRenderPass()=0
Returns false if no render pass is active.
virtual void DestroySurface(RHI_SurfaceHandle handle)=0
Destroy the surface's swapchain first.
virtual RHI_TextureHandle GetFramebufferColorTexture(RHI_FramebufferHandle handle, uint32_t attachmentIndex=0) const =0
The texture lets a later pass sample the framebuffer.
virtual void DestroyBindGroup(RHI_BindGroupHandle handle)=0
virtual bool PresentReplacesQueued(RHI_SwapchainHandle aSwapchain) const
True when a present replaces one still queued for the next vertical blank, as in Vulkan MAILBOX mode,...
Definition rhi_device.h:331
virtual void UpdateBuffer(RHI_BufferHandle handle, const void *data, size_t sizeBytes, size_t offset=0)=0
The buffer need not be mappable.
virtual void DestroyTexture(RHI_TextureHandle handle)=0
Render thread only.
void Release(RHI_PipelineHandle &aHandle)
Definition rhi_device.h:263
void Release(RHI_BufferHandle &aHandle)
Destroy the resource, if there is one, and clear the handle.
Definition rhi_device.h:260
virtual bool WaitForPresentSlot(RHI_SwapchainHandle aSwapchain, std::chrono::milliseconds aTimeout, int aAllowed)
Wait until fewer than aAllowed presents are queued for the display or the timeout passes,...
Definition rhi_device.h:309
virtual void BindGroup(uint32_t groupIndex, RHI_BindGroupHandle group)=0
Only valid inside a render pass with a bound pipeline.
virtual RHI_COMPUTE_DEVICE_LIMITS ComputeDeviceLimits() const
Definition rhi_device.h:72
virtual void DestroyBuffer(RHI_BufferHandle handle)=0
The handle's generation is retired, so later use of the stale handle is detected.
RHI_BufferHandle CreateBuffer(const RHI_BUFFER_DESC &desc)
Reserve and realize in one call, so render thread only.
Definition rhi_device.h:96
virtual void SetScissor(const RHI_SCISSOR_RECT &scissor)=0
Only valid inside a render pass.
virtual RHI_PipelineHandle CreatePipeline(const RHI_PIPELINE_DESC &desc)=0
Returns a null handle on failure.
virtual const char * GetName() const =0
Backend and GPU name for display, such as "Vulkan (GeForce RTX 3080)".
virtual RHI_COMPUTE_RESULT ExecuteCompute(const RHI_COMPUTE_JOB &)
Submit, wait for completion, and copy all readbacks before returning.
Definition rhi_device.h:78
virtual RHI_SURFACE_EXTENT_POLL_RESULT PollSurfaceExtent(RHI_SwapchainHandle aSwapchain)
Retry a fixed surface extent that lagged behind the requested window size.
Definition rhi_device.h:316
virtual void BindVertexBuffer(uint32_t slot, RHI_BufferHandle buffer)=0
Only valid inside a render pass.
virtual void DestroySwapchain(RHI_SwapchainHandle handle)=0
void Release(RHI_BindGroupHandle &aHandle)
Definition rhi_device.h:267
virtual RHI_ShaderHandle CreateShader(const RHI_SHADER_DESC &desc)=0
Returns a null handle on failure.
void Release(RHI_BindGroupLayoutHandle &aHandle)
Definition rhi_device.h:264
virtual RHI_COMPUTE_PIPELINE_LIMITS ComputePipelineLimits(RHI_ComputePipelineHandle) const
Definition rhi_device.h:75
virtual void DrawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex=0, int32_t vertexOffset=0, uint32_t firstInstance=0)=0
Non-indexed, so vertexOffset is ignored.
size_t PendingDeferredReleases() const
Releases still waiting on later frames, which only EndFrame() retires.
Definition rhi_device.h:355
virtual void ExecuteDeferredReleases()=0
virtual RHI_TextureHandle ReserveTextureHandle()=0
Thread-safe handle reservation, realized later by RealizeTexture().
virtual RHI_SwapchainHandle CreateSwapchain(const RHI_SWAPCHAIN_DESC &desc)=0
Returns a null handle on failure.
void Release(RHI_RenderPassHandle &aHandle)
Definition rhi_device.h:265
void Release(RHI_TextureHandle &aHandle)
Definition rhi_device.h:261
virtual void BindPipeline(RHI_PipelineHandle pipeline)=0
Only valid inside a render pass.
virtual void BeginUploadBatch()
UpdateBuffer() and UploadTexture() calls between these share one submission instead of syncing with t...
Definition rhi_device.h:159
virtual bool RealizeTexture(RHI_TextureHandle handle, const RHI_TEXTURE_DESC &desc)=0
Create the GPU texture for a reserved handle.
virtual bool SupportsCompute() const
Compute defaults keep backends without compute support usable for graphics.
Definition rhi_device.h:71
virtual void Draw(uint32_t vertexCount, uint32_t firstVertex=0)=0
Draws are only valid inside a render pass with a bound pipeline.
RHI_TextureHandle CreateTexture(const RHI_TEXTURE_DESC &desc)
Reserve and realize in one call, so render thread only.
Definition rhi_device.h:130
virtual RHI_BindGroupLayoutHandle CreateBindGroupLayout(const RHI_BIND_GROUP_LAYOUT_DESC &desc)=0
Returns a null handle on failure.
uint64_t m_frameCounter
Definition rhi_device.h:372
virtual void SetViewport(const RHI_VIEWPORT &viewport)=0
Only valid inside a render pass.
virtual RHI_FramebufferHandle CreateFramebuffer(const RHI_FRAMEBUFFER_DESC &desc)=0
Returns a null handle on failure.
virtual RHI_BindGroupHandle CreateBindGroup(const RHI_BIND_GROUP_DESC &desc)=0
Returns a null handle on failure.
void Release(RHI_SurfaceHandle &aHandle)
Definition rhi_device.h:268
virtual RHI_RenderPassHandle CreateRenderPass(const RHI_RENDER_PASS_DESC &desc)=0
Returns a null handle on failure.
virtual void SetPushConstants(const void *data, size_t sizeBytes)=0
Size must not exceed RHI_MAX_PUSH_CONSTANT_BYTES.
virtual void DestroyRenderPass(RHI_RenderPassHandle handle)=0
void Release(RHI_SwapchainHandle &aHandle)
Definition rhi_device.h:269
virtual std::optional< std::chrono::steady_clock::time_point > LastDisplayRefresh(RHI_SwapchainHandle aSwapchain) const
The vertical blank at which the display last showed a frame, or nothing if the backend cannot tell.
Definition rhi_device.h:338
virtual bool RealizeBuffer(RHI_BufferHandle handle, const RHI_BUFFER_DESC &desc)=0
Create the GPU buffer for a reserved handle.
virtual void DestroyBindGroupLayout(RHI_BindGroupLayoutHandle handle)=0
virtual void BindIndexBuffer(RHI_BufferHandle buffer)=0
Indices are 16 bits on every backend.
virtual bool IsInitialized() const =0
void Release(RHI_ShaderHandle &aHandle)
Definition rhi_device.h:262
Thread-safe pool that allocates and recycles generation-tracked handles for device implementations.
Definition rhi_handle.h:101
bool MarkPendingDestroy(RHI_HANDLE< Tag > handle)
Make a handle invalid while keeping its slot out of the free list until Release().
Definition rhi_handle.h:138
#define OK
RHI_COMPUTE_RESULT
Definition rhi_compute.h:79
RHI_DEFERRED_RESOURCE_TYPE
RHI_SURFACE_EXTENT_POLL_RESULT
Definition rhi_device.h:54
RHI_FRAME_OP_RESULT
Windows headers define ERROR as a macro.
Definition rhi_device.h:44
RHI_HANDLE< RHI_TAG_FRAMEBUFFER > RHI_FramebufferHandle
Definition rhi_handle.h:93
RHI_HANDLE< RHI_TAG_TEXTURE > RHI_TextureHandle
Definition rhi_handle.h:84
RHI_HANDLE< RHI_TAG_BUFFER > RHI_BufferHandle
Definition rhi_handle.h:83
RHI_HANDLE< RHI_TAG_PIPELINE > RHI_PipelineHandle
Definition rhi_handle.h:86
RHI_HANDLE< RHI_TAG_BIND_GROUP > RHI_BindGroupHandle
Definition rhi_handle.h:90
RHI_HANDLE< RHI_TAG_COMPUTE_PIPELINE > RHI_ComputePipelineHandle
Definition rhi_handle.h:87
RHI_HANDLE< RHI_TAG_BIND_GROUP_LAYOUT > RHI_BindGroupLayoutHandle
Definition rhi_handle.h:89
RHI_HANDLE< RHI_TAG_SURFACE > RHI_SurfaceHandle
Definition rhi_handle.h:91
RHI_HANDLE< RHI_TAG_SHADER > RHI_ShaderHandle
Definition rhi_handle.h:85
RHI_HANDLE< RHI_TAG_RENDER_PASS > RHI_RenderPassHandle
Definition rhi_handle.h:88
RHI_HANDLE< RHI_TAG_SWAPCHAIN > RHI_SwapchainHandle
Definition rhi_handle.h:92
RHI_BACKEND
Identifies which graphics backend a device implements.
Definition rhi_types.h:28
Opaque GPU resource handle, typed by a tag struct so handles of different kinds cannot be mixed.
Definition rhi_handle.h:34
uint32_t value
Definition rhi_handle.h:35
Everything here is fixed at creation except the states listed in dynamicStates.
Same pixel space as RHI_VIEWPORT.
Definition rhi_command.h:39
The bytecode is SPIR-V on Vulkan and MSL source text on Metal.
Definition rhi_shader.h:35
Descriptor for creating a surface from a native window.
Definition rhi_surface.h:71
Descriptor for creating a swapchain.
Definition rhi_surface.h:79
Top-left origin, in device pixels.
Definition rhi_command.h:28