Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/util/d3d11_texture.cpp
7342 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#include "d3d11_texture.h"
5
#include "d3d11_device.h"
6
#include "d3d_common.h"
7
8
#include "common/assert.h"
9
#include "common/error.h"
10
#include "common/log.h"
11
#include "common/string_util.h"
12
13
#include "fmt/format.h"
14
15
#include <array>
16
17
LOG_CHANNEL(GPUDevice);
18
19
std::unique_ptr<GPUTexture> D3D11Device::CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples,
20
GPUTexture::Type type, GPUTextureFormat format,
21
GPUTexture::Flags flags, const void* data /* = nullptr */,
22
u32 data_stride /* = 0 */, Error* error /* = nullptr */)
23
{
24
return D3D11Texture::Create(m_device.Get(), width, height, layers, levels, samples, type, format, flags, data,
25
data_stride, error);
26
}
27
28
bool D3D11Device::SupportsTextureFormat(GPUTextureFormat format) const
29
{
30
const DXGI_FORMAT dfmt = D3DCommon::GetFormatMapping(format).resource_format;
31
if (dfmt == DXGI_FORMAT_UNKNOWN)
32
return false;
33
34
UINT support = 0;
35
const UINT required = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
36
return (SUCCEEDED(m_device->CheckFormatSupport(dfmt, &support)) && ((support & required) == required));
37
}
38
39
D3D11Sampler::D3D11Sampler(ComPtr<ID3D11SamplerState> ss) : m_ss(std::move(ss))
40
{
41
}
42
43
D3D11Sampler::~D3D11Sampler() = default;
44
45
#ifdef ENABLE_GPU_OBJECT_NAMES
46
47
void D3D11Sampler::SetDebugName(std::string_view name)
48
{
49
SetD3DDebugObjectName(m_ss.Get(), name);
50
}
51
52
#endif
53
54
std::unique_ptr<GPUSampler> D3D11Device::CreateSampler(const GPUSampler::Config& config, Error* error)
55
{
56
static constexpr std::array<D3D11_TEXTURE_ADDRESS_MODE, static_cast<u8>(GPUSampler::AddressMode::MaxCount)> ta = {{
57
D3D11_TEXTURE_ADDRESS_WRAP, // Repeat
58
D3D11_TEXTURE_ADDRESS_CLAMP, // ClampToEdge
59
D3D11_TEXTURE_ADDRESS_BORDER, // ClampToBorder
60
D3D11_TEXTURE_ADDRESS_MIRROR, // MirrorRepeat
61
}};
62
static constexpr u8 filter_count = static_cast<u8>(GPUSampler::Filter::MaxCount);
63
static constexpr D3D11_FILTER filters[filter_count][filter_count][filter_count] = {
64
{
65
{D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT},
66
{D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT, D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT},
67
},
68
{
69
{D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR, D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR},
70
{D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, D3D11_FILTER_MIN_MAG_MIP_LINEAR},
71
}};
72
73
D3D11_SAMPLER_DESC desc = {};
74
desc.AddressU = ta[static_cast<u8>(config.address_u.GetValue())];
75
desc.AddressV = ta[static_cast<u8>(config.address_v.GetValue())];
76
desc.AddressW = ta[static_cast<u8>(config.address_w.GetValue())];
77
std::memcpy(desc.BorderColor, RGBA8ToFloat(config.border_color).data(), sizeof(desc.BorderColor));
78
desc.MinLOD = static_cast<float>(config.min_lod);
79
desc.MaxLOD = static_cast<float>(config.max_lod);
80
81
if (config.anisotropy > 1)
82
{
83
desc.Filter = D3D11_FILTER_ANISOTROPIC;
84
desc.MaxAnisotropy = config.anisotropy;
85
}
86
else
87
{
88
desc.Filter = filters[static_cast<u8>(config.mip_filter.GetValue())][static_cast<u8>(config.min_filter.GetValue())]
89
[static_cast<u8>(config.mag_filter.GetValue())];
90
desc.MaxAnisotropy = 1;
91
}
92
93
ComPtr<ID3D11SamplerState> ss;
94
const HRESULT hr = m_device->CreateSamplerState(&desc, ss.GetAddressOf());
95
if (FAILED(hr)) [[unlikely]]
96
{
97
Error::SetHResult(error, "CreateSamplerState() failed: ", hr);
98
return {};
99
}
100
101
return std::unique_ptr<GPUSampler>(new D3D11Sampler(std::move(ss)));
102
}
103
104
D3D11Texture::D3D11Texture(u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type,
105
GPUTextureFormat format, Flags flags, ComPtr<ID3D11Texture2D> texture,
106
ComPtr<ID3D11ShaderResourceView> srv, ComPtr<ID3D11View> rtv_dsv,
107
ComPtr<ID3D11UnorderedAccessView> uav)
108
: GPUTexture(static_cast<u16>(width), static_cast<u16>(height), static_cast<u8>(layers), static_cast<u8>(levels),
109
static_cast<u8>(samples), type, format, flags),
110
m_texture(std::move(texture)), m_srv(std::move(srv)), m_rtv_dsv(std::move(rtv_dsv)), m_uav(std::move(uav))
111
{
112
}
113
114
D3D11Texture::~D3D11Texture()
115
{
116
D3D11Device::GetInstance().UnbindTexture(this);
117
}
118
119
D3D11_TEXTURE2D_DESC D3D11Texture::GetDesc() const
120
{
121
D3D11_TEXTURE2D_DESC desc;
122
m_texture->GetDesc(&desc);
123
return desc;
124
}
125
126
void D3D11Texture::CommitClear(ID3D11DeviceContext1* context)
127
{
128
if (m_state == GPUTexture::State::Dirty)
129
return;
130
131
if (IsDepthStencil())
132
{
133
if (m_state == GPUTexture::State::Invalidated)
134
context->DiscardView(GetD3DDSV());
135
else
136
context->ClearDepthStencilView(GetD3DDSV(), D3D11_CLEAR_DEPTH, GetClearDepth(), 0);
137
}
138
else if (IsRenderTarget())
139
{
140
if (m_state == GPUTexture::State::Invalidated)
141
context->DiscardView(GetD3DRTV());
142
else
143
context->ClearRenderTargetView(GetD3DRTV(), GetUNormClearColor().data());
144
}
145
146
m_state = GPUTexture::State::Dirty;
147
}
148
149
bool D3D11Texture::Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer /*= 0*/,
150
u32 level /*= 0*/)
151
{
152
if (HasFlag(Flags::AllowMap))
153
{
154
void* map;
155
u32 map_pitch;
156
if (!Map(&map, &map_pitch, x, y, width, height, layer, level))
157
return false;
158
159
CopyTextureDataForUpload(width, height, m_format, map, map_pitch, data, pitch);
160
Unmap();
161
return true;
162
}
163
164
const u32 bs = GetBlockSize();
165
const D3D11_BOX box = {Common::AlignDownPow2(x, bs), Common::AlignDownPow2(y, bs), 0U,
166
Common::AlignUpPow2(x + width, bs), Common::AlignUpPow2(y + height, bs), 1U};
167
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
168
169
ID3D11DeviceContext1* context = D3D11Device::GetD3DContext();
170
CommitClear(context);
171
172
GPUDevice::GetStatistics().buffer_streamed += CalcUploadSize(height, pitch);
173
GPUDevice::GetStatistics().num_uploads++;
174
175
context->UpdateSubresource(m_texture.Get(), srnum, &box, data, pitch, 0);
176
m_state = GPUTexture::State::Dirty;
177
return true;
178
}
179
180
bool D3D11Texture::Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer /*= 0*/,
181
u32 level /*= 0*/)
182
{
183
if (!HasFlag(Flags::AllowMap) || (x + width) > GetMipWidth(level) || (y + height) > GetMipHeight(level) ||
184
layer > m_layers || level > m_levels)
185
{
186
return false;
187
}
188
189
const bool discard = (width == m_width && height == m_height);
190
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
191
192
ID3D11DeviceContext1* context = D3D11Device::GetD3DContext();
193
CommitClear(context);
194
195
D3D11_MAPPED_SUBRESOURCE sr;
196
HRESULT hr = context->Map(m_texture.Get(), srnum, discard ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_READ_WRITE, 0, &sr);
197
if (FAILED(hr)) [[unlikely]]
198
{
199
ERROR_LOG("Map pixels texture failed: {:08X}", static_cast<unsigned>(hr));
200
return false;
201
}
202
203
GPUDevice::GetStatistics().buffer_streamed += CalcUploadSize(height, sr.RowPitch);
204
GPUDevice::GetStatistics().num_uploads++;
205
206
if (IsCompressedFormat(m_format))
207
{
208
*map = static_cast<u8*>(sr.pData) + ((y / GetBlockSize()) * sr.RowPitch) + ((x / GetBlockSize()) * GetPixelSize());
209
}
210
else
211
{
212
*map = static_cast<u8*>(sr.pData) + (y * sr.RowPitch) + (x * GetPixelSize());
213
}
214
*map_stride = sr.RowPitch;
215
m_mapped_subresource = srnum;
216
m_state = GPUTexture::State::Dirty;
217
return true;
218
}
219
220
void D3D11Texture::Unmap()
221
{
222
D3D11Device::GetD3DContext()->Unmap(m_texture.Get(), m_mapped_subresource);
223
m_mapped_subresource = 0;
224
}
225
226
void D3D11Texture::GenerateMipmaps()
227
{
228
DebugAssert(HasFlag(Flags::AllowGenerateMipmaps));
229
D3D11Device::GetD3DContext()->GenerateMips(m_srv.Get());
230
}
231
232
#ifdef ENABLE_GPU_OBJECT_NAMES
233
234
void D3D11Texture::SetDebugName(std::string_view name)
235
{
236
SetD3DDebugObjectName(m_texture.Get(), name);
237
}
238
239
#endif
240
241
DXGI_FORMAT D3D11Texture::GetDXGIFormat() const
242
{
243
return D3DCommon::GetFormatMapping(m_format).resource_format;
244
}
245
246
std::unique_ptr<D3D11Texture> D3D11Texture::Create(ID3D11Device* device, u32 width, u32 height, u32 layers, u32 levels,
247
u32 samples, Type type, GPUTextureFormat format, Flags flags,
248
const void* initial_data, u32 initial_data_stride, Error* error)
249
{
250
if (!ValidateConfig(width, height, layers, levels, samples, type, format, flags, error))
251
return nullptr;
252
253
u32 bind_flags = 0;
254
D3D11_USAGE usage = D3D11_USAGE_DEFAULT;
255
u32 cpu_access = 0;
256
u32 misc = 0;
257
switch (type)
258
{
259
case Type::Texture:
260
bind_flags = D3D11_BIND_SHADER_RESOURCE;
261
break;
262
263
case Type::RenderTarget:
264
bind_flags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
265
break;
266
267
case Type::DepthStencil:
268
bind_flags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
269
break;
270
271
DefaultCaseIsUnreachable();
272
}
273
274
if ((flags & Flags::AllowBindAsImage) != Flags::None)
275
{
276
DebugAssert(levels == 1);
277
bind_flags |= D3D11_BIND_UNORDERED_ACCESS;
278
}
279
280
if ((flags & Flags::AllowGenerateMipmaps) != Flags::None)
281
{
282
// Needs RT annoyingly.
283
bind_flags |= D3D11_BIND_RENDER_TARGET;
284
misc = D3D11_RESOURCE_MISC_GENERATE_MIPS;
285
}
286
287
if ((flags & Flags::AllowMap) != Flags::None)
288
{
289
DebugAssert(type == Type::Texture);
290
usage = D3D11_USAGE_DYNAMIC;
291
cpu_access = D3D11_CPU_ACCESS_WRITE;
292
}
293
294
const D3DCommon::DXGIFormatMapping& fm = D3DCommon::GetFormatMapping(format);
295
296
CD3D11_TEXTURE2D_DESC desc(fm.resource_format, width, height, layers, levels, bind_flags, usage, cpu_access, samples,
297
0, misc);
298
299
D3D11_SUBRESOURCE_DATA srd;
300
srd.pSysMem = initial_data;
301
srd.SysMemPitch = initial_data_stride;
302
srd.SysMemSlicePitch = initial_data_stride * height;
303
304
ComPtr<ID3D11Texture2D> texture;
305
const HRESULT tex_hr = device->CreateTexture2D(&desc, initial_data ? &srd : nullptr, texture.GetAddressOf());
306
if (FAILED(tex_hr))
307
{
308
Error::SetHResult(error, "CreateTexture2D() failed: ", tex_hr);
309
return nullptr;
310
}
311
312
if (initial_data)
313
{
314
GPUDevice::GetStatistics().buffer_streamed += CalcUploadSize(format, height, initial_data_stride);
315
GPUDevice::GetStatistics().num_uploads++;
316
}
317
318
ComPtr<ID3D11ShaderResourceView> srv;
319
if (bind_flags & D3D11_BIND_SHADER_RESOURCE)
320
{
321
const D3D11_SRV_DIMENSION srv_dimension =
322
(desc.SampleDesc.Count > 1) ?
323
D3D11_SRV_DIMENSION_TEXTURE2DMS :
324
(desc.ArraySize > 1 ? D3D11_SRV_DIMENSION_TEXTURE2DARRAY : D3D11_SRV_DIMENSION_TEXTURE2D);
325
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(srv_dimension, fm.srv_format, 0, desc.MipLevels, 0, desc.ArraySize);
326
const HRESULT hr = device->CreateShaderResourceView(texture.Get(), &srv_desc, srv.GetAddressOf());
327
if (FAILED(hr)) [[unlikely]]
328
{
329
Error::SetHResult(error, "CreateShaderResourceView() failed: ", hr);
330
return nullptr;
331
}
332
}
333
334
ComPtr<ID3D11View> rtv_dsv;
335
if (bind_flags & D3D11_BIND_RENDER_TARGET)
336
{
337
const D3D11_RTV_DIMENSION rtv_dimension =
338
(desc.SampleDesc.Count > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
339
const CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(rtv_dimension, fm.rtv_format, 0, 0, desc.ArraySize);
340
ComPtr<ID3D11RenderTargetView> rtv;
341
const HRESULT hr = device->CreateRenderTargetView(texture.Get(), &rtv_desc, rtv.GetAddressOf());
342
if (FAILED(hr)) [[unlikely]]
343
{
344
Error::SetHResult(error, "CreateRenderTargetView() failed: ", hr);
345
return nullptr;
346
}
347
348
rtv_dsv = std::move(rtv);
349
}
350
else if (bind_flags & D3D11_BIND_DEPTH_STENCIL)
351
{
352
const D3D11_DSV_DIMENSION dsv_dimension =
353
(desc.SampleDesc.Count > 1) ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
354
const CD3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc(dsv_dimension, fm.dsv_format, 0, 0, desc.ArraySize);
355
ComPtr<ID3D11DepthStencilView> dsv;
356
const HRESULT hr = device->CreateDepthStencilView(texture.Get(), &dsv_desc, dsv.GetAddressOf());
357
if (FAILED(hr)) [[unlikely]]
358
{
359
Error::SetHResult(error, "CreateDepthStencilView() failed: ", hr);
360
return nullptr;
361
}
362
363
rtv_dsv = std::move(dsv);
364
}
365
366
ComPtr<ID3D11UnorderedAccessView> uav;
367
if (bind_flags & D3D11_BIND_UNORDERED_ACCESS)
368
{
369
const D3D11_UAV_DIMENSION uav_dimension =
370
(desc.ArraySize > 1 ? D3D11_UAV_DIMENSION_TEXTURE2DARRAY : D3D11_UAV_DIMENSION_TEXTURE2D);
371
const CD3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc(uav_dimension, fm.srv_format, 0, 0, desc.ArraySize);
372
const HRESULT hr = device->CreateUnorderedAccessView(texture.Get(), &uav_desc, uav.GetAddressOf());
373
if (FAILED(hr)) [[unlikely]]
374
{
375
Error::SetHResult(error, "CreateUnorderedAccessView() failed: ", hr);
376
return nullptr;
377
}
378
}
379
380
return std::unique_ptr<D3D11Texture>(new D3D11Texture(width, height, layers, levels, samples, type, format, flags,
381
std::move(texture), std::move(srv), std::move(rtv_dsv),
382
std::move(uav)));
383
}
384
385
D3D11TextureBuffer::D3D11TextureBuffer(Format format, u32 size_in_elements) : GPUTextureBuffer(format, size_in_elements)
386
{
387
}
388
389
D3D11TextureBuffer::~D3D11TextureBuffer() = default;
390
391
bool D3D11TextureBuffer::CreateBuffer(Error* error)
392
{
393
const u32 size_in_bytes = GetSizeInBytes();
394
if (!m_buffer.Create(D3D11_BIND_SHADER_RESOURCE, size_in_bytes, size_in_bytes, error))
395
return false;
396
397
static constexpr std::array<DXGI_FORMAT, static_cast<u32>(Format::MaxCount)> dxgi_formats = {{
398
DXGI_FORMAT_R16_UINT,
399
}};
400
401
CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(m_buffer.GetD3DBuffer(), dxgi_formats[static_cast<u32>(m_format)], 0,
402
m_size_in_elements);
403
const HRESULT hr =
404
D3D11Device::GetD3DDevice()->CreateShaderResourceView(m_buffer.GetD3DBuffer(), &srv_desc, m_srv.GetAddressOf());
405
if (FAILED(hr)) [[unlikely]]
406
{
407
Error::SetHResult(error, "CreateShaderResourceView() failed: ", hr);
408
return false;
409
}
410
411
return true;
412
}
413
414
void* D3D11TextureBuffer::Map(u32 required_elements)
415
{
416
const u32 esize = GetElementSize(m_format);
417
const auto res = m_buffer.Map(D3D11Device::GetD3DContext(), esize, esize * required_elements);
418
m_current_position = res.index_aligned;
419
return res.pointer;
420
}
421
422
void D3D11TextureBuffer::Unmap(u32 used_elements)
423
{
424
const u32 size = used_elements * GetElementSize(m_format);
425
GPUDevice::GetStatistics().buffer_streamed += size;
426
GPUDevice::GetStatistics().num_uploads++;
427
m_buffer.Unmap(D3D11Device::GetD3DContext(), size);
428
}
429
430
#ifdef ENABLE_GPU_OBJECT_NAMES
431
432
void D3D11TextureBuffer::SetDebugName(std::string_view name)
433
{
434
SetD3DDebugObjectName(m_buffer.GetD3DBuffer(), name);
435
}
436
437
#endif
438
439
std::unique_ptr<GPUTextureBuffer> D3D11Device::CreateTextureBuffer(GPUTextureBuffer::Format format,
440
u32 size_in_elements, Error* error /* = nullptr */)
441
{
442
std::unique_ptr<D3D11TextureBuffer> tb = std::make_unique<D3D11TextureBuffer>(format, size_in_elements);
443
if (!tb->CreateBuffer(error))
444
tb.reset();
445
446
return tb;
447
}
448
449
D3D11DownloadTexture::D3D11DownloadTexture(Microsoft::WRL::ComPtr<ID3D11Texture2D> tex, u32 width, u32 height,
450
GPUTextureFormat format)
451
: GPUDownloadTexture(width, height, format, false), m_texture(std::move(tex))
452
{
453
}
454
455
D3D11DownloadTexture::~D3D11DownloadTexture()
456
{
457
if (IsMapped())
458
D3D11DownloadTexture::Unmap();
459
}
460
461
std::unique_ptr<D3D11DownloadTexture> D3D11DownloadTexture::Create(u32 width, u32 height, GPUTextureFormat format,
462
Error* error)
463
{
464
D3D11_TEXTURE2D_DESC desc = {};
465
desc.Width = width;
466
desc.Height = height;
467
desc.Format = D3DCommon::GetFormatMapping(format).srv_format;
468
desc.MipLevels = 1;
469
desc.ArraySize = 1;
470
desc.SampleDesc.Count = 1;
471
desc.SampleDesc.Quality = 0;
472
desc.Usage = D3D11_USAGE_STAGING;
473
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
474
475
Microsoft::WRL::ComPtr<ID3D11Texture2D> tex;
476
HRESULT hr = D3D11Device::GetD3DDevice()->CreateTexture2D(&desc, nullptr, tex.GetAddressOf());
477
if (FAILED(hr))
478
{
479
Error::SetHResult(error, "CreateTexture2D() failed: ", hr);
480
return {};
481
}
482
483
return std::unique_ptr<D3D11DownloadTexture>(new D3D11DownloadTexture(std::move(tex), width, height, format));
484
}
485
486
void D3D11DownloadTexture::CopyFromTexture(u32 dst_x, u32 dst_y, GPUTexture* src, u32 src_x, u32 src_y, u32 width,
487
u32 height, u32 src_layer, u32 src_level, bool use_transfer_pitch)
488
{
489
D3D11Texture* src11 = static_cast<D3D11Texture*>(src);
490
491
DebugAssert(src11->GetFormat() == m_format);
492
DebugAssert(src_level < src11->GetLevels());
493
DebugAssert((src_x + width) <= src11->GetMipWidth(src_level) && (src_y + height) <= src11->GetMipHeight(src_level));
494
DebugAssert((dst_x + width) <= m_width && (dst_y + height) <= m_height);
495
DebugAssert((dst_x == 0 && dst_y == 0) || !use_transfer_pitch);
496
497
ID3D11DeviceContext1* const ctx = D3D11Device::GetD3DContext();
498
src11->CommitClear(ctx);
499
500
D3D11Device::GetStatistics().num_downloads++;
501
502
if (IsMapped())
503
Unmap();
504
505
// depth textures need to copy the whole thing..
506
const u32 subresource = D3D11CalcSubresource(src_level, src_layer, src11->GetLevels());
507
if (GPUTexture::IsDepthFormat(src11->GetFormat()))
508
{
509
ctx->CopySubresourceRegion(m_texture.Get(), 0, 0, 0, 0, src11->GetD3DTexture(), subresource, nullptr);
510
}
511
else
512
{
513
const CD3D11_BOX sbox(src_x, src_y, 0, src_x + width, src_y + height, 1);
514
ctx->CopySubresourceRegion(m_texture.Get(), 0, dst_x, dst_y, 0, src11->GetD3DTexture(), subresource, &sbox);
515
}
516
517
m_needs_flush = true;
518
}
519
520
bool D3D11DownloadTexture::Map(u32 x, u32 y, u32 width, u32 height)
521
{
522
if (IsMapped())
523
return true;
524
525
D3D11_MAPPED_SUBRESOURCE sr;
526
HRESULT hr = D3D11Device::GetD3DContext()->Map(m_texture.Get(), 0, D3D11_MAP_READ, 0, &sr);
527
if (FAILED(hr))
528
{
529
ERROR_LOG("Map() failed: {:08X}", hr);
530
return false;
531
}
532
533
m_map_pointer = static_cast<u8*>(sr.pData);
534
m_current_pitch = sr.RowPitch;
535
return true;
536
}
537
538
void D3D11DownloadTexture::Unmap()
539
{
540
if (!IsMapped())
541
return;
542
543
D3D11Device::GetD3DContext()->Unmap(m_texture.Get(), 0);
544
m_map_pointer = nullptr;
545
}
546
547
void D3D11DownloadTexture::Flush()
548
{
549
if (!m_needs_flush)
550
return;
551
552
if (IsMapped())
553
Unmap();
554
555
// Handled when mapped.
556
}
557
558
#ifdef ENABLE_GPU_OBJECT_NAMES
559
560
void D3D11DownloadTexture::SetDebugName(std::string_view name)
561
{
562
if (name.empty())
563
return;
564
565
SetD3DDebugObjectName(m_texture.Get(), name);
566
}
567
568
#endif
569
570
std::unique_ptr<GPUDownloadTexture> D3D11Device::CreateDownloadTexture(u32 width, u32 height, GPUTextureFormat format,
571
Error* error /* = nullptr */)
572
{
573
return D3D11DownloadTexture::Create(width, height, format, error);
574
}
575
576
std::unique_ptr<GPUDownloadTexture> D3D11Device::CreateDownloadTexture(u32 width, u32 height, GPUTextureFormat format,
577
void* memory, size_t memory_size,
578
u32 memory_stride, Error* error /* = nullptr */)
579
{
580
Error::SetStringView(error, "D3D11 cannot import memory for download textures");
581
return {};
582
}
583
584