KiCad PCB EDA Suite
Loading...
Searching...
No Matches
gpu_compute.cpp
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#include <rhi/gpu_compute.h>
21#include <rhi/rhi_device.h>
23
24
25GPU_COMPUTE::GPU_COMPUTE( std::unique_ptr<RHI_DEVICE> aDevice ) :
26 m_device( std::move( aDevice ) ),
27 m_limits( m_device->ComputeDeviceLimits() )
28{
29}
30
31
33
34
35std::shared_ptr<GPU_COMPUTE> GPU_COMPUTE::Get()
36{
37 static std::mutex mutex;
38 static std::weak_ptr<GPU_COMPUTE> instance;
39 static bool unavailable = false;
40 std::lock_guard<std::mutex> lock( mutex );
41 std::shared_ptr<GPU_COMPUTE> service = instance.lock();
42
43 if( service && !service->m_lost )
44 return service;
45
46 // Probing a missing GPU costs a device creation, so remember the failure
47 if( unavailable )
48 return nullptr;
49
50 std::unique_ptr<RHI_DEVICE> device = RhiCreatePlatformDevice( false );
51
52 if( !device || !device->SupportsCompute() )
53 {
54 unavailable = true;
55 return nullptr;
56 }
57
58 service.reset( new GPU_COMPUTE( std::move( device ) ) );
59 instance = service;
60 return service;
61}
62
63
65{
66 std::lock_guard<std::mutex> lock( m_mutex );
67 return m_device->ComputePipelineLimits( aPipeline );
68}
69
70
72{
73 if( !aBytes || aBytes > m_limits.maxStorageBufferRange )
74 return {};
75
76 std::lock_guard<std::mutex> lock( m_mutex );
77 return m_device->CreateBuffer( { .type = RHI_BUFFER_TYPE::STORAGE, .sizeBytes = aBytes } );
78}
79
80
82{
83 std::lock_guard<std::mutex> lock( m_mutex );
84 return m_device->CreateComputePipeline( aDesc );
85}
86
87
89{
91 return {};
92
93 std::lock_guard<std::mutex> lock( m_mutex );
94 return m_device->CreateBindGroupLayout( aDesc );
95}
96
97
99{
100 std::lock_guard<std::mutex> lock( m_mutex );
101 return m_device->CreateBindGroup( aDesc );
102}
103
104
105template <typename F>
106void GPU_COMPUTE::destroy( F aDestroy )
107{
108 std::lock_guard<std::mutex> lock( m_mutex );
109 aDestroy();
110
111 // Devices retire releases by frame count, and a compute device never ends frames on its own
112 for( uint32_t frame = 0; frame < RHI_FRAMES_IN_FLIGHT; ++frame )
113 m_device->EndFrame();
114}
115
116
118{
119 destroy(
120 [&]
121 {
122 m_device->DestroyBuffer( aBuffer );
123 } );
124}
125
126
128{
129 destroy(
130 [&]
131 {
132 m_device->DestroyComputePipeline( aPipeline );
133 } );
134}
135
136
138{
139 destroy(
140 [&]
141 {
142 m_device->DestroyBindGroupLayout( aLayout );
143 } );
144}
145
146
148{
149 destroy(
150 [&]
151 {
152 m_device->DestroyBindGroup( aGroup );
153 } );
154}
155
156
158{
159 std::lock_guard<std::mutex> lock( m_mutex );
160
161 if( m_lost )
163
164 const RHI_COMPUTE_RESULT result = m_device->ExecuteCompute( aJob );
166 return result;
167}
void DestroyBindGroupLayout(RHI_BindGroupLayoutHandle aLayout)
GPU_COMPUTE(const GPU_COMPUTE &)=delete
RHI_ComputePipelineHandle CreatePipeline(const RHI_COMPUTE_PIPELINE_DESC &aDesc)
RHI_COMPUTE_RESULT Submit(const RHI_COMPUTE_JOB &aJob)
Run the whole job and copy its readbacks before returning.
static std::shared_ptr< GPU_COMPUTE > Get()
Return nullptr if compute is unavailable; replace a lost instance on the next call.
void DestroyPipeline(RHI_ComputePipelineHandle aPipeline)
std::atomic< bool > m_lost
Definition gpu_compute.h:67
std::mutex m_mutex
Definition gpu_compute.h:64
RHI_COMPUTE_DEVICE_LIMITS m_limits
Definition gpu_compute.h:66
RHI_BindGroupLayoutHandle CreateBindGroupLayout(const RHI_BIND_GROUP_LAYOUT_DESC &aDesc)
std::unique_ptr< RHI_DEVICE > m_device
Definition gpu_compute.h:65
void DestroyBuffer(RHI_BufferHandle aBuffer)
RHI_COMPUTE_PIPELINE_LIMITS PipelineLimits(RHI_ComputePipelineHandle aPipeline)
void DestroyBindGroup(RHI_BindGroupHandle aGroup)
RHI_BindGroupHandle CreateBindGroup(const RHI_BIND_GROUP_DESC &aDesc)
RHI_BufferHandle CreateStorageBuffer(size_t aBytes)
void destroy(F aDestroy)
Destroy under the lock, then retire the release at once since no job can still be using it.
Plain owning command data, recordable on any thread without device access.
Definition rhi_compute.h:91
#define F(x, y, z)
Definition md5_hash.cpp:15
STL namespace.
bool RhiValidateComputeBindGroupLayout(const RHI_BIND_GROUP_LAYOUT_DESC &aLayout)
Validate a compute bind group layout.
RHI_COMPUTE_RESULT
Definition rhi_compute.h:79
constexpr uint64_t RHI_FRAMES_IN_FLIGHT
RHI_HANDLE< RHI_TAG_BUFFER > RHI_BufferHandle
Definition rhi_handle.h:83
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
std::unique_ptr< RHI_DEVICE > RhiCreatePlatformDevice(bool aEnableVulkanValidation)
Create the device of the one RHI backend this platform is built with, Metal on macOS and Vulkan elsew...
wxString result
Test unit parsing edge cases and error handling.