Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/d3d12/d3d12_bufmgr.cpp
4570 views
1
/*
2
* Copyright © Microsoft Corporation
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
* IN THE SOFTWARE.
22
*/
23
24
#include "d3d12_bufmgr.h"
25
#include "d3d12_format.h"
26
#include "d3d12_screen.h"
27
28
#include "D3D12ResourceState.h"
29
30
#include "pipebuffer/pb_buffer.h"
31
#include "pipebuffer/pb_bufmgr.h"
32
33
#include "util/format/u_format.h"
34
#include "util/u_memory.h"
35
36
#include <directx/d3d12.h>
37
#include <dxguids/dxguids.h>
38
39
struct d3d12_bufmgr {
40
struct pb_manager base;
41
42
ID3D12Device *dev;
43
};
44
45
extern const struct pb_vtbl d3d12_buffer_vtbl;
46
47
static inline struct d3d12_bufmgr *
48
d3d12_bufmgr(struct pb_manager *mgr)
49
{
50
assert(mgr);
51
52
return (struct d3d12_bufmgr *)mgr;
53
}
54
55
static struct TransitionableResourceState *
56
create_trans_state(ID3D12Resource *res, enum pipe_format format)
57
{
58
D3D12_RESOURCE_DESC desc = res->GetDesc();
59
60
// Calculate the total number of subresources
61
unsigned arraySize = desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ?
62
1 : desc.DepthOrArraySize;
63
unsigned total_subresources = desc.MipLevels *
64
arraySize *
65
d3d12_non_opaque_plane_count(desc.Format);
66
total_subresources *= util_format_has_stencil(util_format_description(format)) ?
67
2 : 1;
68
69
return new TransitionableResourceState(res,
70
total_subresources,
71
SupportsSimultaneousAccess(desc));
72
}
73
74
struct d3d12_bo *
75
d3d12_bo_wrap_res(ID3D12Resource *res, enum pipe_format format)
76
{
77
struct d3d12_bo *bo;
78
79
bo = CALLOC_STRUCT(d3d12_bo);
80
if (!bo)
81
return NULL;
82
83
bo->refcount = 1;
84
bo->res = res;
85
bo->trans_state = create_trans_state(res, format);
86
87
return bo;
88
}
89
90
struct d3d12_bo *
91
d3d12_bo_new(ID3D12Device *dev, uint64_t size, const pb_desc *pb_desc)
92
{
93
ID3D12Resource *res;
94
95
D3D12_RESOURCE_DESC res_desc;
96
res_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
97
res_desc.Format = DXGI_FORMAT_UNKNOWN;
98
res_desc.Alignment = pb_desc->alignment;
99
res_desc.Width = size;
100
res_desc.Height = 1;
101
res_desc.DepthOrArraySize = 1;
102
res_desc.MipLevels = 1;
103
res_desc.SampleDesc.Count = 1;
104
res_desc.SampleDesc.Quality = 0;
105
res_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
106
res_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
107
108
D3D12_HEAP_TYPE heap_type = D3D12_HEAP_TYPE_DEFAULT;
109
if (pb_desc->usage & PB_USAGE_CPU_READ)
110
heap_type = D3D12_HEAP_TYPE_READBACK;
111
else if (pb_desc->usage & PB_USAGE_CPU_WRITE)
112
heap_type = D3D12_HEAP_TYPE_UPLOAD;
113
114
D3D12_HEAP_PROPERTIES heap_pris = dev->GetCustomHeapProperties(0, heap_type);
115
HRESULT hres = dev->CreateCommittedResource(&heap_pris,
116
D3D12_HEAP_FLAG_NONE,
117
&res_desc,
118
D3D12_RESOURCE_STATE_COMMON,
119
NULL,
120
IID_PPV_ARGS(&res));
121
122
if (FAILED(hres))
123
return NULL;
124
125
return d3d12_bo_wrap_res(res, PIPE_FORMAT_NONE);
126
}
127
128
struct d3d12_bo *
129
d3d12_bo_wrap_buffer(struct pb_buffer *buf)
130
{
131
struct d3d12_bo *bo;
132
133
bo = CALLOC_STRUCT(d3d12_bo);
134
if (!bo)
135
return NULL;
136
137
bo->refcount = 1;
138
bo->buffer = buf;
139
bo->trans_state = NULL; /* State from base BO will be used */
140
141
return bo;
142
}
143
144
void
145
d3d12_bo_unreference(struct d3d12_bo *bo)
146
{
147
if (bo == NULL)
148
return;
149
150
assert(p_atomic_read(&bo->refcount) > 0);
151
152
if (p_atomic_dec_zero(&bo->refcount)) {
153
if (bo->buffer) {
154
pb_reference(&bo->buffer, NULL);
155
} else {
156
delete bo->trans_state;
157
bo->res->Release();
158
}
159
FREE(bo);
160
}
161
}
162
163
void *
164
d3d12_bo_map(struct d3d12_bo *bo, D3D12_RANGE *range)
165
{
166
struct d3d12_bo *base_bo;
167
D3D12_RANGE offset_range = {0, 0};
168
uint64_t offset;
169
void *ptr;
170
171
base_bo = d3d12_bo_get_base(bo, &offset);
172
173
if (!range || offset == 0) {
174
/* Nothing to do */
175
} else if (range->Begin >= range->End) {
176
offset_range.Begin = offset;
177
offset_range.End = offset + d3d12_bo_get_size(bo);
178
range = &offset_range;
179
} else {
180
offset_range.Begin = range->Begin + offset;
181
offset_range.End = range->End + offset;
182
range = &offset_range;
183
}
184
185
if (FAILED(base_bo->res->Map(0, range, &ptr)))
186
return NULL;
187
188
return (uint8_t *)ptr + (range ? range->Begin : 0);
189
}
190
191
void
192
d3d12_bo_unmap(struct d3d12_bo *bo, D3D12_RANGE *range)
193
{
194
struct d3d12_bo *base_bo;
195
D3D12_RANGE offset_range = {0, 0};
196
uint64_t offset;
197
198
base_bo = d3d12_bo_get_base(bo, &offset);
199
200
if (!range || bo == base_bo)
201
{
202
/* Nothing to do */
203
} else if (range->Begin >= range->End) {
204
offset_range.Begin = offset;
205
offset_range.End = offset + base_bo->res->GetDesc().Width;
206
range = &offset_range;
207
} else {
208
offset_range.Begin = range->Begin + offset;
209
offset_range.End = range->End + offset;
210
range = &offset_range;
211
}
212
213
base_bo->res->Unmap(0, range);
214
}
215
216
static void
217
d3d12_buffer_destroy(void *winsys, struct pb_buffer *pbuf)
218
{
219
struct d3d12_buffer *buf = d3d12_buffer(pbuf);
220
221
d3d12_bo_unmap(buf->bo, &buf->range);
222
d3d12_bo_unreference(buf->bo);
223
FREE(buf);
224
}
225
226
static void *
227
d3d12_buffer_map(struct pb_buffer *pbuf,
228
enum pb_usage_flags flags,
229
void *flush_ctx)
230
{
231
return d3d12_buffer(pbuf)->map;
232
}
233
234
static void
235
d3d12_buffer_unmap(struct pb_buffer *pbuf)
236
{
237
}
238
239
static void
240
d3d12_buffer_get_base_buffer(struct pb_buffer *buf,
241
struct pb_buffer **base_buf,
242
pb_size *offset)
243
{
244
*base_buf = buf;
245
*offset = 0;
246
}
247
248
static enum pipe_error
249
d3d12_buffer_validate(struct pb_buffer *pbuf,
250
struct pb_validate *vl,
251
enum pb_usage_flags flags )
252
{
253
/* Always pinned */
254
return PIPE_OK;
255
}
256
257
static void
258
d3d12_buffer_fence(struct pb_buffer *pbuf,
259
struct pipe_fence_handle *fence )
260
{
261
}
262
263
const struct pb_vtbl d3d12_buffer_vtbl = {
264
d3d12_buffer_destroy,
265
d3d12_buffer_map,
266
d3d12_buffer_unmap,
267
d3d12_buffer_validate,
268
d3d12_buffer_fence,
269
d3d12_buffer_get_base_buffer
270
};
271
272
static struct pb_buffer *
273
d3d12_bufmgr_create_buffer(struct pb_manager *pmgr,
274
pb_size size,
275
const struct pb_desc *pb_desc)
276
{
277
struct d3d12_bufmgr *mgr = d3d12_bufmgr(pmgr);
278
struct d3d12_buffer *buf;
279
280
buf = CALLOC_STRUCT(d3d12_buffer);
281
if (!buf)
282
return NULL;
283
284
// Align the buffer to D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT
285
// in case it is to be used as a CBV.
286
size = align64(size, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
287
288
pipe_reference_init(&buf->base.reference, 1);
289
buf->base.alignment_log2 = util_logbase2(pb_desc->alignment);
290
buf->base.usage = pb_desc->usage;
291
buf->base.vtbl = &d3d12_buffer_vtbl;
292
buf->base.size = size;
293
buf->range.Begin = 0;
294
buf->range.End = size;
295
296
buf->bo = d3d12_bo_new(mgr->dev, size, pb_desc);
297
if (!buf->bo) {
298
FREE(buf);
299
return NULL;
300
}
301
302
if (pb_desc->usage & PB_USAGE_CPU_READ_WRITE) {
303
buf->map = d3d12_bo_map(buf->bo, &buf->range);
304
if (!buf->map) {
305
d3d12_bo_unreference(buf->bo);
306
FREE(buf);
307
return NULL;
308
}
309
}
310
311
return &buf->base;
312
}
313
314
static void
315
d3d12_bufmgr_flush(struct pb_manager *mgr)
316
{
317
/* No-op */
318
}
319
320
static void
321
d3d12_bufmgr_destroy(struct pb_manager *_mgr)
322
{
323
struct d3d12_bufmgr *mgr = d3d12_bufmgr(_mgr);
324
FREE(mgr);
325
}
326
327
struct pb_manager *
328
d3d12_bufmgr_create(struct d3d12_screen *screen)
329
{
330
struct d3d12_bufmgr *mgr;
331
332
mgr = CALLOC_STRUCT(d3d12_bufmgr);
333
if (!mgr)
334
return NULL;
335
336
mgr->base.destroy = d3d12_bufmgr_destroy;
337
mgr->base.create_buffer = d3d12_bufmgr_create_buffer;
338
mgr->base.flush = d3d12_bufmgr_flush;
339
340
mgr->dev = screen->dev;
341
342
return &mgr->base;
343
}
344
345