Код: Выделить всё
// Get the device and command queue
// pDevice,
ID3D12Device* pDevice = nullptr;
HRESULT hr = pSwapChain->GetDevice(__uuidof(ID3D12Device), (void**)&pDevice);
if (FAILED(hr)) {
std::cout CreateCommittedResource(
&heapProps,
D3D12_HEAP_FLAG_NONE,
&readbackBufferDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
__uuidof(ID3D12Resource),
(void**)&pReadbackBuffer
);
if (FAILED(hr)) {
std::cout Release();
pCommandQueue->Release();
return;
}
// Create command allocator and command list
ID3D12CommandAllocator* pCommandAllocator = nullptr;
hr = pDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&pCommandAllocator);
if (FAILED(hr)) {
std::cout Release();
pDevice->Release();
pCommandQueue->Release();
return;
}
ID3D12GraphicsCommandList* pCommandList = nullptr;
hr = pDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, pCommandAllocator, nullptr, __uuidof(ID3D12GraphicsCommandList), (void**)&pCommandList);
if (FAILED(hr)) {
std::cout Release();
pBackBuffer->Release();
pDevice->Release();
pCommandQueue->Release();
return;
}
// Transition the back buffer to the copy source state
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = pBackBuffer;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
pCommandList->ResourceBarrier(1, &barrier);
// Copy the back buffer to the readback buffer
D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
srcLocation.pResource = pBackBuffer;
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
srcLocation.SubresourceIndex = 0;
D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
dstLocation.pResource = pReadbackBuffer;
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
pDevice->GetCopyableFootprints(&desc, 0, 1, 0, &dstLocation.PlacedFootprint, nullptr, nullptr, nullptr);
pCommandList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, nullptr);
// Transition the back buffer back to the present state
std::swap(barrier.Transition.StateBefore, barrier.Transition.StateAfter);
pCommandList->ResourceBarrier(1, &barrier);
// Close and execute the command list
// SOME GAMES ARE THROWING E_INVALIDARG (0x80070057) HERE
hr = pCommandList->Close();
if (FAILED(hr)) {
std::cout Release();
pDevice->Release();
pCommandQueue->Release();
return;
}
ID3D12CommandList* ppCommandLists[] = { pCommandList };
pCommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
// Wait for the GPU to finish executing the commands
ID3D12Fence* pFence = nullptr;
hr = pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void**)&pFence);
if (FAILED(hr)) {
std::cout Release();
pReadbackBuffer->Release();
pBackBuffer->Release();
pDevice->Release();
pCommandQueue->Release();
return;
}
HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
pCommandQueue->Signal(pFence, 1);
pFence->SetEventOnCompletion(1, hEvent);
if (hEvent != NULL) {
WaitForSingleObject(hEvent, INFINITE);
CloseHandle(hEvent);
}
pFence->Release();
// Map the readback buffer
void* pData;
hr = pReadbackBuffer->Map(0, nullptr, &pData);
if (FAILED(hr)) {
std::cout Release();
pReadbackBuffer->Release();
pBackBuffer->Release();
pDevice->Release();
pCommandQueue->Release();
return;
}
// Save the image using stbi_write_jpg
stbi_write_jpg(fullPath, desc.Width, desc.Height, 4, pData, dstLocation.PlacedFootprint.Footprint.RowPitch);
// Unmap and release resources
pReadbackBuffer->Unmap(0, nullptr);
pCommandList->Release();
pCommandAllocator->Release();
pReadbackBuffer->Release();
pBackBuffer->Release();
pDevice->Release();
pCommandQueue->Release();
DEBUG_COUT
Подробнее здесь: [url]https://stackoverflow.com/questions/78497444/trying-to-save-a-d3d12-texture-into-a-image-file[/url]
Мобильная версия