in skiko/src/awtMain/cpp/windows/InternalDirectXApi.cc [315:374]
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_graphicapi_InternalDirectXApi_waitForCompletion(
JNIEnv *env, jobject redrawer, jlong devicePtr, jlong texturePtr) {
DirectXOffscreenDevice *device = fromJavaPointer<DirectXOffscreenDevice *>(devicePtr);
DirectXOffScreenTexture *texture = fromJavaPointer<DirectXOffScreenTexture *>(texturePtr);
auto commandAllocator = device->commandAllocator;
auto commandList = device->commandList;
commandAllocator->Reset();
commandList->Reset(commandAllocator, nullptr);
D3D12_RESOURCE_BARRIER textureResourceBarrier;
textureResourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
textureResourceBarrier.Transition.pResource = texture->resource;
textureResourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
textureResourceBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
textureResourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES ;
textureResourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
commandList->ResourceBarrier(1, &textureResourceBarrier);
D3D12_TEXTURE_COPY_LOCATION src = {};
src.pResource = texture->resource;
src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
src.SubresourceIndex = 0;
D3D12_TEXTURE_COPY_LOCATION dst = {};
dst.pResource = texture->readbackBufferResource;
dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
dst.PlacedFootprint.Offset = 0;
dst.PlacedFootprint.Footprint.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
dst.PlacedFootprint.Footprint.Width = texture->width;
dst.PlacedFootprint.Footprint.Height = texture->height;
dst.PlacedFootprint.Footprint.Depth = 1;
dst.PlacedFootprint.Footprint.RowPitch = calculateRowPitch(texture->width);
D3D12_BOX srcBox = {0, 0, 0, static_cast<UINT>(texture->width), static_cast<UINT>(texture->height), 1};
commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, &srcBox);
commandList->Close();
ID3D12CommandList* commandLists[] = { commandList };
device->backendContext.fQueue->ExecuteCommandLists(_countof(commandLists), commandLists);
// Wait for the command list to finish executing; the readback buffer will be ready to read
auto fence = device->fence;
auto fenceEvent = device->fenceEvent;
auto& fenceValue = device->fenceValue;
fenceValue += 1;
device->backendContext.fQueue->Signal(fence, fenceValue);
if (fence->GetCompletedValue() < fenceValue) {
fence->SetEventOnCompletion(fenceValue, fenceEvent);
WaitForSingleObject(fenceEvent, INFINITE);
}
}