modify readback API
continuous-integration/drone/push Build is failing Details

d3d11
cosmonaut 2024-03-05 17:30:20 -08:00
parent 6ebfabcecf
commit 52d4c934f3
5 changed files with 243 additions and 381 deletions

View File

@ -1193,46 +1193,6 @@ REFRESHAPI void Refresh_UploadToBuffer(
Refresh_WriteOptions writeOption
);
/* GPU-to-CPU copies occur on the GPU timeline.
*
* You may NOT assume that the data in the TransferBuffer is fully copied
* until the command buffer has finished execution.
*/
/*
* transferOption:
* SAFEDISCARD:
* If this TransferBuffer has been used in commands that have not completed,
* the issued commands will still be valid at the cost of increased memory usage.
* You may NOT assume that any of the previous data is retained.
* If the TransferBuffer was not in use, this option is equivalent to OVERWRITE.
* It is not recommended to use this option with large TransferBuffers.
*
* OVERWRITE:
* Overwrites the data regardless of whether a command has been issued.
* Use this option with great care, as it can cause data races to occur!
*/
/* Downloads data from a texture to a TransferBuffer. */
REFRESHAPI void Refresh_DownloadFromTexture(
Refresh_Device *device,
Refresh_CommandBuffer *commandBuffer,
Refresh_TextureRegion *textureRegion,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferImageCopy *copyParams,
Refresh_TransferOptions transferOption
);
/* Downloads data from a GpuBuffer object. */
REFRESHAPI void Refresh_DownloadFromBuffer(
Refresh_Device *device,
Refresh_CommandBuffer *commandBuffer,
Refresh_GpuBuffer *gpuBuffer,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferCopy *copyParams,
Refresh_TransferOptions transferOption
);
/* GPU-to-GPU copies occur on the GPU timeline,
* and you may assume the copy has finished in subsequent commands.
*/
@ -1401,6 +1361,49 @@ REFRESHAPI void Refresh_ReleaseFence(
Refresh_Fence *fence
);
/* Readback */
/* GPU-to-CPU copies occur immediately on the CPU timeline.
*
* If you modify data on the GPU and then call these functions without calling Wait or WaitForFences first,
* the data will be undefined!
*
* Readback forces a sync point and is generally a bad thing to do.
* Only use these functions if you have exhausted all other options.
*/
/*
* transferOption:
* SAFEDISCARD:
* If this TransferBuffer has been used in commands that have not completed,
* the issued commands will still be valid at the cost of increased memory usage.
* You may NOT assume that any of the previous data is retained.
* If the TransferBuffer was not in use, this option is equivalent to OVERWRITE.
* It is not recommended to use this option with large TransferBuffers.
*
* OVERWRITE:
* Overwrites the data regardless of whether a command has been issued.
* Use this option with great care, as it can cause data races to occur!
*/
/* Downloads data from a texture to a TransferBuffer. */
REFRESHAPI void Refresh_DownloadFromTexture(
Refresh_Device *device,
Refresh_TextureRegion *textureRegion,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferImageCopy *copyParams,
Refresh_TransferOptions transferOption
);
/* Downloads data from a GpuBuffer object. */
REFRESHAPI void Refresh_DownloadFromBuffer(
Refresh_Device *device,
Refresh_GpuBuffer *gpuBuffer,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferCopy *copyParams,
Refresh_TransferOptions transferOption
);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -824,44 +824,6 @@ void Refresh_UploadToBuffer(
);
}
void Refresh_DownloadFromTexture(
Refresh_Device *device,
Refresh_CommandBuffer *commandBuffer,
Refresh_TextureRegion *textureRegion,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferImageCopy *copyParams,
Refresh_TransferOptions transferOption
) {
NULL_RETURN(device);
device->DownloadFromTexture(
device->driverData,
commandBuffer,
textureRegion,
transferBuffer,
copyParams,
transferOption
);
}
void Refresh_DownloadFromBuffer(
Refresh_Device *device,
Refresh_CommandBuffer *commandBuffer,
Refresh_GpuBuffer *gpuBuffer,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferCopy *copyParams,
Refresh_TransferOptions transferOption
) {
NULL_RETURN(device);
device->DownloadFromBuffer(
device->driverData,
commandBuffer,
gpuBuffer,
transferBuffer,
copyParams,
transferOption
);
}
void Refresh_CopyTextureToTexture(
Refresh_Device *device,
Refresh_CommandBuffer *commandBuffer,
@ -1067,4 +1029,38 @@ void Refresh_ReleaseFence(
);
}
void Refresh_DownloadFromTexture(
Refresh_Device *device,
Refresh_TextureRegion *textureRegion,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferImageCopy *copyParams,
Refresh_TransferOptions transferOption
) {
NULL_RETURN(device);
device->DownloadFromTexture(
device->driverData,
textureRegion,
transferBuffer,
copyParams,
transferOption
);
}
void Refresh_DownloadFromBuffer(
Refresh_Device *device,
Refresh_GpuBuffer *gpuBuffer,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferCopy *copyParams,
Refresh_TransferOptions transferOption
) {
NULL_RETURN(device);
device->DownloadFromBuffer(
device->driverData,
gpuBuffer,
transferBuffer,
copyParams,
transferOption
);
}
/* vim: set noexpandtab shiftwidth=8 tabstop=8: */

View File

@ -506,24 +506,6 @@ struct Refresh_Device
Refresh_WriteOptions writeOption
);
void (*DownloadFromTexture)(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_TextureRegion *textureSlice,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferImageCopy *copyParams,
Refresh_TransferOptions transferOption
);
void (*DownloadFromBuffer)(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_GpuBuffer *gpuBuffer,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferCopy *copyParams,
Refresh_TransferOptions transferOption
);
void (*CopyTextureToTexture)(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
@ -619,6 +601,22 @@ struct Refresh_Device
Refresh_Fence *fence
);
void (*DownloadFromTexture)(
Refresh_Renderer *driverData,
Refresh_TextureRegion *textureSlice,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferImageCopy *copyParams,
Refresh_TransferOptions transferOption
);
void (*DownloadFromBuffer)(
Refresh_Renderer *driverData,
Refresh_GpuBuffer *gpuBuffer,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferCopy *copyParams,
Refresh_TransferOptions transferOption
);
/* Opaque pointer for the Driver */
Refresh_Renderer *driverData;
};

View File

@ -2069,14 +2069,12 @@ static void D3D11_UploadToBuffer(
static void D3D11_DownloadFromTexture(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_TextureRegion *textureRegion,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferImageCopy *copyParams,
Refresh_TransferOptions transferOption
) {
D3D11Renderer *renderer = (D3D11Renderer*) driverData;
D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer;
D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer;
D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer;
D3D11Texture *d3d11Texture = (D3D11Texture*) textureRegion->textureSlice.texture;
@ -2126,8 +2124,10 @@ static void D3D11_DownloadFromTexture(
);
ERROR_CHECK_RETURN("Staging texture creation failed",)
ID3D11DeviceContext1_CopySubresourceRegion1(
d3d11CommandBuffer->context,
/* Readback is only possible on CPU timeline in D3D11 */
SDL_LockMutex(renderer->contextLock);
ID3D11DeviceContext_CopySubresourceRegion(
renderer->immediateContext,
stagingTexture,
0,
0,
@ -2135,13 +2135,12 @@ static void D3D11_DownloadFromTexture(
0,
d3d11Texture->handle,
subresourceIndex,
&srcBox,
D3D11_COPY_NO_OVERWRITE
&srcBox
);
/* Read from the staging texture */
res = ID3D11DeviceContext1_Map(
d3d11CommandBuffer->context,
res = ID3D11DeviceContext_Map(
renderer->immediateContext,
stagingTexture,
subresourceIndex,
D3D11_MAP_READ,
@ -2170,24 +2169,24 @@ static void D3D11_DownloadFromTexture(
}
ID3D11DeviceContext1_Unmap(
d3d11CommandBuffer->context,
renderer->immediateContext,
stagingTexture,
0
);
SDL_UnlockMutex(renderer->contextLock);
/* Clean up the staging texture */
ID3D11Texture2D_Release(stagingTexture);
}
static void D3D11_DownloadFromBuffer(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_GpuBuffer *gpuBuffer,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferCopy *copyParams,
Refresh_TransferOptions transferOption
) {
D3D11Renderer *renderer = (D3D11Renderer*) driverData;
D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer*) commandBuffer;
D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer*) transferBuffer;
D3D11TransferBuffer *d3d11TransferBuffer = container->activeBuffer;
D3D11Buffer *d3d11Buffer = (D3D11Buffer*) gpuBuffer;
@ -2225,8 +2224,10 @@ static void D3D11_DownloadFromBuffer(
);
ERROR_CHECK_RETURN("Could not create staging buffer for readback", );
ID3D11DeviceContext1_CopySubresourceRegion1(
d3d11CommandBuffer->context,
/* Readback is only possible on CPU timeline in D3D11 */
SDL_LockMutex(renderer->contextLock);
ID3D11DeviceContext_CopySubresourceRegion(
renderer->immediateContext,
(ID3D11Resource*) stagingBuffer,
0,
0,
@ -2234,13 +2235,12 @@ static void D3D11_DownloadFromBuffer(
0,
(ID3D11Resource*) d3d11Buffer->handle,
0,
&srcBox,
D3D11_COPY_NO_OVERWRITE
&srcBox
);
/* Read from the staging buffer */
res = ID3D11DeviceContext1_Map(
d3d11CommandBuffer->context,
res = ID3D11DeviceContext_Map(
renderer->immediateContext,
stagingBuffer,
0,
D3D11_MAP_READ,
@ -2265,12 +2265,11 @@ static void D3D11_DownloadFromBuffer(
);
ID3D11DeviceContext1_Unmap(
d3d11CommandBuffer->context,
renderer->immediateContext,
stagingBuffer,
0
);
D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer);
SDL_UnlockMutex(renderer->contextLock);
/* Clean up the staging buffer */
ID3D11Buffer_Release(stagingBuffer);

View File

@ -8550,130 +8550,6 @@ static void VULKAN_UploadToBuffer(
VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer);
}
static void VULKAN_DownloadFromTexture(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_TextureRegion *textureRegion,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferImageCopy *copyParams,
Refresh_TransferOptions transferOption
) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanTextureSlice *vulkanTextureSlice;
VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer;
VkBufferImageCopy imageCopy;
vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice);
if (
transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD &&
SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0
) {
VULKAN_INTERNAL_DiscardActiveBuffer(
renderer,
transferBufferContainer
);
vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice);
}
VULKAN_INTERNAL_BufferMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_WRITE,
transferBufferContainer->activeBufferHandle->vulkanBuffer
);
VULKAN_INTERNAL_ImageMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_READ,
vulkanTextureSlice
);
imageCopy.imageExtent.width = textureRegion->w;
imageCopy.imageExtent.height = textureRegion->h;
imageCopy.imageExtent.depth = textureRegion->d;
imageCopy.imageOffset.x = textureRegion->x;
imageCopy.imageOffset.y = textureRegion->y;
imageCopy.imageOffset.z = textureRegion->z;
imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags;
imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer;
imageCopy.imageSubresource.layerCount = 1;
imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel;
imageCopy.bufferOffset = copyParams->bufferOffset;
imageCopy.bufferRowLength = copyParams->bufferStride;
imageCopy.bufferImageHeight = copyParams->bufferImageHeight;
renderer->vkCmdCopyImageToBuffer(
vulkanCommandBuffer->commandBuffer,
vulkanTextureSlice->parent->image,
AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout,
transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer,
1,
&imageCopy
);
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer);
VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice);
VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice);
}
static void VULKAN_DownloadFromBuffer(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_GpuBuffer *gpuBuffer,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferCopy *copyParams,
Refresh_TransferOptions transferOption
) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanBufferContainer *gpuBufferContainer = (VulkanBufferContainer*) gpuBuffer;
VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer;
VkBufferCopy bufferCopy;
if (
transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD &&
SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0
) {
VULKAN_INTERNAL_DiscardActiveBuffer(
renderer,
transferBufferContainer
);
}
VULKAN_INTERNAL_BufferMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_WRITE,
transferBufferContainer->activeBufferHandle->vulkanBuffer
);
VULKAN_INTERNAL_BufferMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_READ,
gpuBufferContainer->activeBufferHandle->vulkanBuffer
);
bufferCopy.srcOffset = copyParams->srcOffset;
bufferCopy.dstOffset = copyParams->dstOffset;
bufferCopy.size = copyParams->size;
renderer->vkCmdCopyBuffer(
vulkanCommandBuffer->commandBuffer,
gpuBufferContainer->activeBufferHandle->vulkanBuffer->buffer,
transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer,
1,
&bufferCopy
);
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer);
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer);
VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer);
}
static void VULKAN_CopyTextureToTexture(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
@ -8751,147 +8627,6 @@ static void VULKAN_CopyTextureToTexture(
VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, dstSlice);
}
static void VULKAN_CopyTextureToBuffer(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_TextureRegion *textureRegion,
Refresh_GpuBuffer *gpuBuffer,
Refresh_BufferImageCopy *copyParams,
Refresh_WriteOptions writeOption
) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanTextureSlice *vulkanTextureSlice;
VulkanBufferContainer *bufferContainer = (VulkanBufferContainer*) gpuBuffer;
VkBufferImageCopy imageCopy;
vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice);
if (
writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD &&
SDL_AtomicGet(&bufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0
) {
VULKAN_INTERNAL_DiscardActiveBuffer(
renderer,
bufferContainer
);
}
VULKAN_INTERNAL_ImageMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_READ,
vulkanTextureSlice
);
VULKAN_INTERNAL_BufferMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_WRITE,
bufferContainer->activeBufferHandle->vulkanBuffer
);
imageCopy.imageExtent.width = textureRegion->w;
imageCopy.imageExtent.height = textureRegion->h;
imageCopy.imageExtent.depth = textureRegion->d;
imageCopy.imageOffset.x = textureRegion->x;
imageCopy.imageOffset.y = textureRegion->y;
imageCopy.imageOffset.z = textureRegion->z;
imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags;
imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer;
imageCopy.imageSubresource.layerCount = 1;
imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel;
imageCopy.bufferOffset = copyParams->bufferOffset;
imageCopy.bufferRowLength = copyParams->bufferStride;
imageCopy.bufferImageHeight = copyParams->bufferImageHeight;
renderer->vkCmdCopyImageToBuffer(
vulkanCommandBuffer->commandBuffer,
vulkanTextureSlice->parent->image,
AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout,
bufferContainer->activeBufferHandle->vulkanBuffer->buffer,
1,
&imageCopy
);
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer);
VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice);
VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer);
VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice);
}
static void VULKAN_CopyBufferToTexture(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_GpuBuffer *gpuBuffer,
Refresh_TextureRegion *textureRegion,
Refresh_BufferImageCopy *copyParams,
Refresh_WriteOptions writeOption
) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanBufferContainer *bufferContainer = (VulkanBufferContainer*) gpuBuffer;
VulkanTextureContainer *textureContainer = (VulkanTextureContainer*) textureRegion->textureSlice.texture;
VulkanTextureSlice *vulkanTextureSlice;
VkBufferImageCopy imageCopy;
vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice);
if (
writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD &&
textureContainer->canBeDiscarded &&
SDL_AtomicGet(&vulkanTextureSlice->referenceCount) > 0
) {
VULKAN_INTERNAL_DiscardActiveTexture(
renderer,
textureContainer
);
vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice);
}
VULKAN_INTERNAL_BufferMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_READ,
bufferContainer->activeBufferHandle->vulkanBuffer
);
VULKAN_INTERNAL_ImageMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_WRITE,
vulkanTextureSlice
);
imageCopy.imageExtent.width = textureRegion->w;
imageCopy.imageExtent.height = textureRegion->h;
imageCopy.imageExtent.depth = textureRegion->d;
imageCopy.imageOffset.x = textureRegion->x;
imageCopy.imageOffset.y = textureRegion->y;
imageCopy.imageOffset.z = textureRegion->z;
imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags;
imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer;
imageCopy.imageSubresource.layerCount = 1;
imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel;
imageCopy.bufferOffset = copyParams->bufferOffset;
imageCopy.bufferRowLength = copyParams->bufferStride;
imageCopy.bufferImageHeight = copyParams->bufferImageHeight;
renderer->vkCmdCopyBufferToImage(
vulkanCommandBuffer->commandBuffer,
bufferContainer->activeBufferHandle->vulkanBuffer->buffer,
vulkanTextureSlice->parent->image,
AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout,
1,
&imageCopy
);
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer);
VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice);
VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer);
VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice);
}
static void VULKAN_CopyBufferToBuffer(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
@ -10461,6 +10196,137 @@ static void VULKAN_ReleaseFence(
VULKAN_INTERNAL_ReturnFenceToPool((VulkanRenderer*) driverData, (VkFence) fence);
}
/* Readback */
static void VULKAN_DownloadFromTexture(
Refresh_Renderer *driverData,
Refresh_TextureRegion *textureRegion,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferImageCopy *copyParams,
Refresh_TransferOptions transferOption
) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanTextureSlice *vulkanTextureSlice;
VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer;
VkBufferImageCopy imageCopy;
vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice);
Refresh_Fence *fence;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) VULKAN_AcquireCommandBuffer(driverData);
if (
transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD &&
SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0
) {
VULKAN_INTERNAL_DiscardActiveBuffer(
renderer,
transferBufferContainer
);
vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice);
}
VULKAN_INTERNAL_BufferMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_WRITE,
transferBufferContainer->activeBufferHandle->vulkanBuffer
);
VULKAN_INTERNAL_ImageMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_READ,
vulkanTextureSlice
);
imageCopy.imageExtent.width = textureRegion->w;
imageCopy.imageExtent.height = textureRegion->h;
imageCopy.imageExtent.depth = textureRegion->d;
imageCopy.imageOffset.x = textureRegion->x;
imageCopy.imageOffset.y = textureRegion->y;
imageCopy.imageOffset.z = textureRegion->z;
imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags;
imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer;
imageCopy.imageSubresource.layerCount = 1;
imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel;
imageCopy.bufferOffset = copyParams->bufferOffset;
imageCopy.bufferRowLength = copyParams->bufferStride;
imageCopy.bufferImageHeight = copyParams->bufferImageHeight;
renderer->vkCmdCopyImageToBuffer(
vulkanCommandBuffer->commandBuffer,
vulkanTextureSlice->parent->image,
AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout,
transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer,
1,
&imageCopy
);
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer);
VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice);
VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice);
fence = VULKAN_SubmitAndAcquireFence(driverData, (Refresh_CommandBuffer*) vulkanCommandBuffer);
VULKAN_WaitForFences(driverData, 1, 1, &fence);
}
static void VULKAN_DownloadFromBuffer(
Refresh_Renderer *driverData,
Refresh_GpuBuffer *gpuBuffer,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferCopy *copyParams,
Refresh_TransferOptions transferOption
) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanBufferContainer *gpuBufferContainer = (VulkanBufferContainer*) gpuBuffer;
VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer;
VkBufferCopy bufferCopy;
Refresh_Fence *fence;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) VULKAN_AcquireCommandBuffer(driverData);
if (
transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD &&
SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0
) {
VULKAN_INTERNAL_DiscardActiveBuffer(
renderer,
transferBufferContainer
);
}
VULKAN_INTERNAL_BufferMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_WRITE,
transferBufferContainer->activeBufferHandle->vulkanBuffer
);
VULKAN_INTERNAL_BufferMemoryBarrier(
renderer,
vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_READ,
gpuBufferContainer->activeBufferHandle->vulkanBuffer
);
bufferCopy.srcOffset = copyParams->srcOffset;
bufferCopy.dstOffset = copyParams->dstOffset;
bufferCopy.size = copyParams->size;
renderer->vkCmdCopyBuffer(
vulkanCommandBuffer->commandBuffer,
gpuBufferContainer->activeBufferHandle->vulkanBuffer->buffer,
transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer,
1,
&bufferCopy
);
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer);
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer);
VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer);
fence = VULKAN_SubmitAndAcquireFence(driverData, (Refresh_CommandBuffer*) vulkanCommandBuffer);
VULKAN_WaitForFences(driverData, 1, 1, &fence);
}
/* Device instantiation */
static inline uint8_t CheckDeviceExtensions(