Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/d3d12/d3d12_surface.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_context.h"
25
#include "d3d12_format.h"
26
#include "d3d12_resource.h"
27
#include "d3d12_screen.h"
28
#include "d3d12_surface.h"
29
30
#include "util/format/u_format.h"
31
#include "util/u_inlines.h"
32
#include "util/u_memory.h"
33
34
static D3D12_DSV_DIMENSION
35
view_dsv_dimension(enum pipe_texture_target target, unsigned samples)
36
{
37
switch (target) {
38
case PIPE_TEXTURE_1D: return D3D12_DSV_DIMENSION_TEXTURE1D;
39
case PIPE_TEXTURE_1D_ARRAY: return D3D12_DSV_DIMENSION_TEXTURE1DARRAY;
40
41
case PIPE_TEXTURE_2D:
42
case PIPE_TEXTURE_RECT:
43
return samples > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMS :
44
D3D12_DSV_DIMENSION_TEXTURE2D;
45
46
case PIPE_TEXTURE_2D_ARRAY:
47
case PIPE_TEXTURE_CUBE:
48
return samples > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY :
49
D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
50
51
default:
52
unreachable("unexpected target");
53
}
54
}
55
56
static D3D12_RTV_DIMENSION
57
view_rtv_dimension(enum pipe_texture_target target, unsigned samples)
58
{
59
switch (target) {
60
case PIPE_BUFFER: return D3D12_RTV_DIMENSION_BUFFER;
61
case PIPE_TEXTURE_1D: return D3D12_RTV_DIMENSION_TEXTURE1D;
62
case PIPE_TEXTURE_1D_ARRAY: return D3D12_RTV_DIMENSION_TEXTURE1DARRAY;
63
64
case PIPE_TEXTURE_2D:
65
case PIPE_TEXTURE_RECT:
66
return samples > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMS :
67
D3D12_RTV_DIMENSION_TEXTURE2D;
68
69
case PIPE_TEXTURE_2D_ARRAY:
70
case PIPE_TEXTURE_CUBE:
71
return samples > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY :
72
D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
73
74
case PIPE_TEXTURE_3D: return D3D12_RTV_DIMENSION_TEXTURE3D;
75
76
default:
77
unreachable("unexpected target");
78
}
79
}
80
81
static void
82
initialize_dsv(struct pipe_context *pctx,
83
struct pipe_resource *pres,
84
const struct pipe_surface *tpl,
85
struct d3d12_descriptor_handle *handle,
86
DXGI_FORMAT dxgi_format)
87
{
88
struct d3d12_resource *res = d3d12_resource(pres);
89
struct d3d12_screen *screen = d3d12_screen(pctx->screen);
90
91
D3D12_DEPTH_STENCIL_VIEW_DESC desc;
92
desc.Format = dxgi_format;
93
desc.Flags = D3D12_DSV_FLAG_NONE;
94
95
desc.ViewDimension = view_dsv_dimension(pres->target, pres->nr_samples);
96
switch (desc.ViewDimension) {
97
case D3D12_DSV_DIMENSION_TEXTURE1D:
98
if (tpl->u.tex.first_layer > 0)
99
debug_printf("D3D12: can't create 1D DSV from layer %d\n",
100
tpl->u.tex.first_layer);
101
102
desc.Texture1D.MipSlice = tpl->u.tex.level;
103
break;
104
105
case D3D12_DSV_DIMENSION_TEXTURE1DARRAY:
106
desc.Texture1DArray.MipSlice = tpl->u.tex.level;
107
desc.Texture1DArray.FirstArraySlice = tpl->u.tex.first_layer;
108
desc.Texture1DArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;
109
break;
110
111
case D3D12_DSV_DIMENSION_TEXTURE2DMS:
112
if (tpl->u.tex.first_layer > 0)
113
debug_printf("D3D12: can't create 2DMS DSV from layer %d\n",
114
tpl->u.tex.first_layer);
115
116
break;
117
118
case D3D12_DSV_DIMENSION_TEXTURE2D:
119
if (tpl->u.tex.first_layer > 0)
120
debug_printf("D3D12: can't create 2D DSV from layer %d\n",
121
tpl->u.tex.first_layer);
122
123
desc.Texture2D.MipSlice = tpl->u.tex.level;
124
break;
125
126
case D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY:
127
desc.Texture2DMSArray.FirstArraySlice = tpl->u.tex.first_layer;
128
desc.Texture2DMSArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;
129
break;
130
131
case D3D12_DSV_DIMENSION_TEXTURE2DARRAY:
132
desc.Texture2DArray.MipSlice = tpl->u.tex.level;
133
desc.Texture2DArray.FirstArraySlice = tpl->u.tex.first_layer;
134
desc.Texture2DArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;
135
break;
136
137
default:
138
unreachable("Unhandled DSV dimension");
139
}
140
141
mtx_lock(&screen->descriptor_pool_mutex);
142
d3d12_descriptor_pool_alloc_handle(screen->dsv_pool, handle);
143
mtx_unlock(&screen->descriptor_pool_mutex);
144
145
screen->dev->CreateDepthStencilView(d3d12_resource_resource(res), &desc,
146
handle->cpu_handle);
147
}
148
149
static void
150
initialize_rtv(struct pipe_context *pctx,
151
struct pipe_resource *pres,
152
const struct pipe_surface *tpl,
153
struct d3d12_descriptor_handle *handle,
154
DXGI_FORMAT dxgi_format)
155
{
156
struct d3d12_resource *res = d3d12_resource(pres);
157
struct d3d12_screen *screen = d3d12_screen(pctx->screen);
158
159
D3D12_RENDER_TARGET_VIEW_DESC desc;
160
desc.Format = dxgi_format;
161
162
desc.ViewDimension = view_rtv_dimension(pres->target, pres->nr_samples);
163
switch (desc.ViewDimension) {
164
case D3D12_RTV_DIMENSION_BUFFER:
165
desc.Buffer.FirstElement = 0;
166
desc.Buffer.NumElements = pres->width0 / util_format_get_blocksize(tpl->format);
167
break;
168
169
case D3D12_RTV_DIMENSION_TEXTURE1D:
170
if (tpl->u.tex.first_layer > 0)
171
debug_printf("D3D12: can't create 1D RTV from layer %d\n",
172
tpl->u.tex.first_layer);
173
174
desc.Texture1D.MipSlice = tpl->u.tex.level;
175
break;
176
177
case D3D12_RTV_DIMENSION_TEXTURE1DARRAY:
178
desc.Texture1DArray.MipSlice = tpl->u.tex.level;
179
desc.Texture1DArray.FirstArraySlice = tpl->u.tex.first_layer;
180
desc.Texture1DArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;
181
break;
182
183
case D3D12_RTV_DIMENSION_TEXTURE2DMS:
184
if (tpl->u.tex.first_layer > 0)
185
debug_printf("D3D12: can't create 2DMS RTV from layer %d\n",
186
tpl->u.tex.first_layer);
187
break;
188
189
case D3D12_RTV_DIMENSION_TEXTURE2D:
190
if (tpl->u.tex.first_layer > 0)
191
debug_printf("D3D12: can't create 2D RTV from layer %d\n",
192
tpl->u.tex.first_layer);
193
194
desc.Texture2D.MipSlice = tpl->u.tex.level;
195
desc.Texture2D.PlaneSlice = 0;
196
break;
197
198
case D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY:
199
desc.Texture2DMSArray.FirstArraySlice = tpl->u.tex.first_layer;
200
desc.Texture2DMSArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;
201
break;
202
203
case D3D12_RTV_DIMENSION_TEXTURE2DARRAY:
204
desc.Texture2DArray.MipSlice = tpl->u.tex.level;
205
desc.Texture2DArray.FirstArraySlice = tpl->u.tex.first_layer;
206
desc.Texture2DArray.ArraySize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;
207
desc.Texture2DArray.PlaneSlice = 0;
208
break;
209
210
case D3D12_RTV_DIMENSION_TEXTURE3D:
211
desc.Texture3D.MipSlice = tpl->u.tex.level;
212
desc.Texture3D.FirstWSlice = tpl->u.tex.first_layer;
213
desc.Texture3D.WSize = tpl->u.tex.last_layer - tpl->u.tex.first_layer + 1;
214
break;
215
216
default:
217
unreachable("Unhandled RTV dimension");
218
}
219
220
mtx_lock(&screen->descriptor_pool_mutex);
221
d3d12_descriptor_pool_alloc_handle(screen->rtv_pool, handle);
222
mtx_unlock(&screen->descriptor_pool_mutex);
223
224
screen->dev->CreateRenderTargetView(d3d12_resource_resource(res), &desc,
225
handle->cpu_handle);
226
}
227
228
static struct pipe_surface *
229
d3d12_create_surface(struct pipe_context *pctx,
230
struct pipe_resource *pres,
231
const struct pipe_surface *tpl)
232
{
233
bool is_depth_or_stencil = util_format_is_depth_or_stencil(tpl->format);
234
unsigned bind = is_depth_or_stencil ? PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET;
235
236
/* Don't bother if we don't support the requested format as RT or DS */
237
if (!pctx->screen->is_format_supported(pctx->screen, tpl->format, PIPE_TEXTURE_2D,
238
tpl->nr_samples, tpl->nr_samples,bind))
239
return NULL;
240
241
struct d3d12_surface *surface = CALLOC_STRUCT(d3d12_surface);
242
if (!surface)
243
return NULL;
244
245
pipe_resource_reference(&surface->base.texture, pres);
246
pipe_reference_init(&surface->base.reference, 1);
247
surface->base.context = pctx;
248
surface->base.format = tpl->format;
249
surface->base.width = u_minify(pres->width0, tpl->u.tex.level);
250
surface->base.height = u_minify(pres->height0, tpl->u.tex.level);
251
surface->base.u.tex.level = tpl->u.tex.level;
252
surface->base.u.tex.first_layer = tpl->u.tex.first_layer;
253
surface->base.u.tex.last_layer = tpl->u.tex.last_layer;
254
255
DXGI_FORMAT dxgi_format = d3d12_get_resource_rt_format(tpl->format);
256
if (is_depth_or_stencil)
257
initialize_dsv(pctx, pres, tpl, &surface->desc_handle, dxgi_format);
258
else
259
initialize_rtv(pctx, pres, tpl, &surface->desc_handle, dxgi_format);
260
261
return &surface->base;
262
}
263
264
static void
265
d3d12_surface_destroy(struct pipe_context *pctx,
266
struct pipe_surface *psurf)
267
{
268
struct d3d12_surface *surface = (struct d3d12_surface*) psurf;
269
struct d3d12_screen *screen = d3d12_screen(pctx->screen);
270
271
mtx_lock(&screen->descriptor_pool_mutex);
272
d3d12_descriptor_handle_free(&surface->desc_handle);
273
if (d3d12_descriptor_handle_is_allocated(&surface->uint_rtv_handle))
274
d3d12_descriptor_handle_free(&surface->uint_rtv_handle);
275
mtx_unlock(&screen->descriptor_pool_mutex);
276
277
pipe_resource_reference(&psurf->texture, NULL);
278
pipe_resource_reference(&surface->rgba_texture, NULL);
279
FREE(surface);
280
}
281
282
static void
283
blit_surface(struct d3d12_surface *surface, bool pre)
284
{
285
struct pipe_blit_info info = {};
286
287
info.src.resource = pre ? surface->base.texture : surface->rgba_texture;
288
info.dst.resource = pre ? surface->rgba_texture : surface->base.texture;
289
info.src.format = pre ? surface->base.texture->format : PIPE_FORMAT_R8G8B8A8_UNORM;
290
info.dst.format = pre ? PIPE_FORMAT_R8G8B8A8_UNORM : surface->base.texture->format;
291
info.src.level = info.dst.level = 0;
292
info.src.box.x = info.dst.box.x = 0;
293
info.src.box.y = info.dst.box.y = 0;
294
info.src.box.z = info.dst.box.z = 0;
295
info.src.box.width = info.dst.box.width = surface->base.width;
296
info.src.box.height = info.dst.box.height = surface->base.height;
297
info.src.box.depth = info.dst.box.depth = 0;
298
info.mask = PIPE_MASK_RGBA;
299
300
d3d12_blit(surface->base.context, &info);
301
}
302
303
enum d3d12_surface_conversion_mode
304
d3d12_surface_update_pre_draw(struct d3d12_surface *surface,
305
DXGI_FORMAT format)
306
{
307
struct d3d12_screen *screen = d3d12_screen(surface->base.context->screen);
308
struct d3d12_resource *res = d3d12_resource(surface->base.texture);
309
DXGI_FORMAT dxgi_format = d3d12_get_resource_rt_format(surface->base.format);
310
enum d3d12_surface_conversion_mode mode;
311
312
if (dxgi_format == format)
313
return D3D12_SURFACE_CONVERSION_NONE;
314
315
if (dxgi_format == DXGI_FORMAT_B8G8R8A8_UNORM ||
316
dxgi_format == DXGI_FORMAT_B8G8R8X8_UNORM)
317
mode = D3D12_SURFACE_CONVERSION_BGRA_UINT;
318
else
319
mode = D3D12_SURFACE_CONVERSION_RGBA_UINT;
320
321
if (mode == D3D12_SURFACE_CONVERSION_BGRA_UINT) {
322
if (!surface->rgba_texture) {
323
struct pipe_resource templ = {{0}};
324
struct pipe_resource *src = surface->base.texture;
325
326
templ.format = PIPE_FORMAT_R8G8B8A8_UNORM;
327
templ.width0 = src->width0;
328
templ.height0 = src->height0;
329
templ.depth0 = src->depth0;
330
templ.array_size = src->array_size;
331
templ.nr_samples = src->nr_samples;
332
templ.nr_storage_samples = src->nr_storage_samples;
333
templ.usage = PIPE_USAGE_DEFAULT | PIPE_USAGE_STAGING;
334
templ.bind = src->bind;
335
templ.target = src->target;
336
337
surface->rgba_texture = screen->base.resource_create(&screen->base, &templ);
338
}
339
340
blit_surface(surface, true);
341
res = d3d12_resource(surface->rgba_texture);
342
}
343
344
if (!d3d12_descriptor_handle_is_allocated(&surface->uint_rtv_handle)) {
345
initialize_rtv(surface->base.context, &res->base, &surface->base,
346
&surface->uint_rtv_handle, DXGI_FORMAT_R8G8B8A8_UINT);
347
}
348
349
return mode;
350
}
351
352
void
353
d3d12_surface_update_post_draw(struct d3d12_surface *surface,
354
enum d3d12_surface_conversion_mode mode)
355
{
356
if (mode == D3D12_SURFACE_CONVERSION_BGRA_UINT)
357
blit_surface(surface, false);
358
}
359
360
D3D12_CPU_DESCRIPTOR_HANDLE
361
d3d12_surface_get_handle(struct d3d12_surface *surface,
362
enum d3d12_surface_conversion_mode mode)
363
{
364
if (mode != D3D12_SURFACE_CONVERSION_NONE)
365
return surface->uint_rtv_handle.cpu_handle;
366
return surface->desc_handle.cpu_handle;
367
}
368
369
void
370
d3d12_context_surface_init(struct pipe_context *context)
371
{
372
context->create_surface = d3d12_create_surface;
373
context->surface_destroy = d3d12_surface_destroy;
374
}
375
376