54 ID3D12Resource* backBuffer) {
56 const D3D12_RESOURCE_DESC desc = backBuffer->GetDesc();
57 if (desc.Format != DXGI_FORMAT_R8G8B8A8_UNORM)
58 return std::unexpected(
"画像に書けるのは RGBA8 のバックバッファだけ");
60 uint64_t totalBytes = 0;
61 device->GetCopyableFootprints(&desc, 0, 1, 0, &capture.
m_footprint,
nullptr,
nullptr, &totalBytes);
62 capture.
m_width =
static_cast<uint32_t
>(desc.Width);
68 device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&capture.
m_allocator))) ||
69 FAILED(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, capture.
m_allocator.Get(),
nullptr,
70 IID_PPV_ARGS(&capture.
m_list)))) {
71 return std::unexpected(
"画像の読み戻しを作れない");
74 capture.
m_readback->SetName(L
"Screenshot.readback");
75 if (FAILED(capture.
m_list->Close()))
76 return std::unexpected(
"画像のリストを閉じられない");
85 const D3D12_RESOURCE_BARRIER toCopy =
gpu::Transition(backBuffer, D3D12_RESOURCE_STATE_PRESENT,
86 D3D12_RESOURCE_STATE_COPY_SOURCE);
87 m_list->ResourceBarrier(1, &toCopy);
89 const D3D12_TEXTURE_COPY_LOCATION destination{.pResource =
m_readback.Get(),
90 .Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
93 const D3D12_TEXTURE_COPY_LOCATION source{
94 .pResource = backBuffer, .Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, .SubresourceIndex = 0};
95 m_list->CopyTextureRegion(&destination, 0, 0, 0, &source,
nullptr);
96 const D3D12_RESOURCE_BARRIER toPresent =
gpu::Transition(backBuffer, D3D12_RESOURCE_STATE_COPY_SOURCE,
97 D3D12_RESOURCE_STATE_PRESENT);
98 m_list->ResourceBarrier(1, &toPresent);
100 return SUCCEEDED(
m_list->Close()) ?
m_list.Get() :
nullptr;
104 void* mapped =
nullptr;
105 if (FAILED(
m_readback->Map(0,
nullptr, &mapped)))
106 return std::unexpected(
"画像の読み戻しを開けない");
108 const auto* source =
static_cast<const uint8_t*
>(mapped);
110 file.reserve(file.size() +
size_t{m_width} *
m_height * BYTES_PER_PIXEL);
112 for (uint32_t row = 0; row <
m_height; ++row) {
114 for (uint32_t column = 0; column <
m_width; ++column) {
115 const uint8_t* pixel = line +
size_t{column} * BYTES_PER_PIXEL;
116 file.insert(file.end(), {pixel[2], pixel[1], pixel[0], 255});
120 const D3D12_RANGE noWrite{};
124 std::error_code error;
125 if (path.has_parent_path())
126 fs::create_directories(path.parent_path(), error);
128 std::ofstream stream(path, std::ios::binary);
130 return std::unexpected(
"画像のファイルを開けない: " +
ToUtf8(path.wstring()));
132 stream.write(
reinterpret_cast<const char*
>(file.data()),
static_cast<std::streamsize
>(file.size()));
134 return std::unexpected(
"画像のファイルに書けない");