make gets and sets async

pull/9/head
cosmonaut 2021-01-02 17:00:52 -08:00 committed by thatcosmonaut
parent e0ff380989
commit f8c99c4e18
4 changed files with 137 additions and 110 deletions

View File

@ -1092,9 +1092,25 @@ REFRESHAPI void REFRESH_SetFragmentSamplers(
/* Getters */ /* Getters */
/* Pulls image data from a 2D texture into client memory. Like any GetData, /* Synchronously copies data from a buffer to a pointer.
* this is generally asking for a massive CPU/GPU sync point, don't call this * You probably want to wait for a sync point to call this.
* unless there's absolutely no other way to use the image data! *
* buffer: The buffer to copy data from.
* data: The pointer to copy data to.
* dataLengthInBytes: The length of data to copy.
*/
REFRESHAPI void REFRESH_GetBufferData(
REFRESH_Device *device,
REFRESH_Buffer *buffer,
void *data,
uint32_t dataLengthInBytes
);
/* Asynchronously copies image data from a 2D texture into a buffer.
*
* NOTE:
* The buffer will not contain correct data until the command buffer
* is submitted and completed.
* *
* texture: The texture object being read. * texture: The texture object being read.
* x: The x offset of the subregion being read. * x: The x offset of the subregion being read.
@ -1102,23 +1118,23 @@ REFRESHAPI void REFRESH_SetFragmentSamplers(
* w: The width of the subregion being read. * w: The width of the subregion being read.
* h: The height of the subregion being read. * h: The height of the subregion being read.
* level: The mipmap level being read. * level: The mipmap level being read.
* data: The pointer being filled with the image data. * buffer: The buffer being filled with the image data.
*/ */
REFRESHAPI void REFRESH_GetTextureData2D( REFRESHAPI void REFRESH_CopyTextureData2D(
REFRESH_Device *device, REFRESH_Device *device,
REFRESH_CommandBuffer *commandBuffer,
REFRESH_Texture *texture, REFRESH_Texture *texture,
uint32_t x, uint32_t x,
uint32_t y, uint32_t y,
uint32_t w, uint32_t w,
uint32_t h, uint32_t h,
uint32_t level, uint32_t level,
void* data REFRESH_Buffer *buffer
); );
/* Pulls image data from a single face of a texture cube object into client /* Asynchronously copies image data from a single face of a texture cube
* memory. Like any GetData, this is generally asking for a massive CPU/GPU sync * object into a buffer. You must wait for the command buffer to be
* point, don't call this unless there's absolutely no other way to use the * submitted and completed before reading the buffer.
* image data!
* *
* texture: The texture object being read. * texture: The texture object being read.
* x: The x offset of the subregion being read. * x: The x offset of the subregion being read.
@ -1127,10 +1143,11 @@ REFRESHAPI void REFRESH_GetTextureData2D(
* h: The height of the subregion being read. * h: The height of the subregion being read.
* cubeMapFace: The face of the cube being read. * cubeMapFace: The face of the cube being read.
* level: The mipmap level being read. * level: The mipmap level being read.
* data: The pointer being filled with the image data. * buffer: The buffer being filled with the image data.
*/ */
REFRESHAPI void REFRESH_GetTextureDataCube( REFRESHAPI void REFRESH_CopyTextureDataCube(
REFRESH_Device *device, REFRESH_Device *device,
REFRESH_CommandBuffer *commandBuffer,
REFRESH_Texture *texture, REFRESH_Texture *texture,
uint32_t x, uint32_t x,
uint32_t y, uint32_t y,
@ -1138,7 +1155,7 @@ REFRESHAPI void REFRESH_GetTextureDataCube(
uint32_t h, uint32_t h,
REFRESH_CubeMapFace cubeMapFace, REFRESH_CubeMapFace cubeMapFace,
uint32_t level, uint32_t level,
void* data REFRESH_Buffer *buffer
); );
/* Disposal */ /* Disposal */

View File

@ -632,31 +632,49 @@ void REFRESH_SetFragmentSamplers(
); );
} }
void REFRESH_GetTextureData2D( void REFRESH_GetBufferData(
REFRESH_Device *device, REFRESH_Device *device,
REFRESH_Buffer *buffer,
void *data,
uint32_t dataLengthInBytes
) {
NULL_RETURN(device);
device->GetBufferData(
device->driverData,
buffer,
data,
dataLengthInBytes
);
}
void REFRESH_CopyTextureData2D(
REFRESH_Device *device,
REFRESH_CommandBuffer *commandBuffer,
REFRESH_Texture *texture, REFRESH_Texture *texture,
uint32_t x, uint32_t x,
uint32_t y, uint32_t y,
uint32_t w, uint32_t w,
uint32_t h, uint32_t h,
uint32_t level, uint32_t level,
void* data REFRESH_Buffer* buffer
) { ) {
NULL_RETURN(device); NULL_RETURN(device);
device->GetTextureData2D( device->CopyTextureData2D(
device->driverData, device->driverData,
commandBuffer,
texture, texture,
x, x,
y, y,
w, w,
h, h,
level, level,
data buffer
); );
} }
void REFRESH_GetTextureDataCube( void REFRESH_GetTextureDataCube(
REFRESH_Device *device, REFRESH_Device *device,
REFRESH_CommandBuffer *commandBuffer,
REFRESH_Texture *texture, REFRESH_Texture *texture,
uint32_t x, uint32_t x,
uint32_t y, uint32_t y,
@ -664,11 +682,12 @@ void REFRESH_GetTextureDataCube(
uint32_t h, uint32_t h,
REFRESH_CubeMapFace cubeMapFace, REFRESH_CubeMapFace cubeMapFace,
uint32_t level, uint32_t level,
void* data REFRESH_Buffer* buffer
) { ) {
NULL_RETURN(device); NULL_RETURN(device);
device->GetTextureDataCube( device->CopyTextureDataCube(
device->driverData, device->driverData,
commandBuffer,
texture, texture,
x, x,
y, y,
@ -676,7 +695,7 @@ void REFRESH_GetTextureDataCube(
h, h,
cubeMapFace, cubeMapFace,
level, level,
data buffer
); );
} }

View File

@ -402,19 +402,28 @@ struct REFRESH_Device
/* Getters */ /* Getters */
void(*GetTextureData2D)( void(*GetBufferData)(
REFRESH_Renderer *driverData, REFRESH_Renderer *driverData,
REFRESH_Buffer *buffer,
void *data,
uint32_t dataLengthInBytes
);
void(*CopyTextureData2D)(
REFRESH_Renderer *driverData,
REFRESH_CommandBuffer *commandBuffer,
REFRESH_Texture *texture, REFRESH_Texture *texture,
uint32_t x, uint32_t x,
uint32_t y, uint32_t y,
uint32_t w, uint32_t w,
uint32_t h, uint32_t h,
uint32_t level, uint32_t level,
void* data REFRESH_Buffer* buffer
); );
void(*GetTextureDataCube)( void(*CopyTextureDataCube)(
REFRESH_Renderer *driverData, REFRESH_Renderer *driverData,
REFRESH_CommandBuffer *commandBuffer,
REFRESH_Texture *texture, REFRESH_Texture *texture,
uint32_t x, uint32_t x,
uint32_t y, uint32_t y,
@ -422,7 +431,7 @@ struct REFRESH_Device
uint32_t h, uint32_t h,
REFRESH_CubeMapFace cubeMapFace, REFRESH_CubeMapFace cubeMapFace,
uint32_t level, uint32_t level,
void* data REFRESH_Buffer* buffer
); );
/* Disposal */ /* Disposal */
@ -595,8 +604,9 @@ struct REFRESH_Device
ASSIGN_DRIVER_FUNC(PushComputeShaderParams, name) \ ASSIGN_DRIVER_FUNC(PushComputeShaderParams, name) \
ASSIGN_DRIVER_FUNC(SetVertexSamplers, name) \ ASSIGN_DRIVER_FUNC(SetVertexSamplers, name) \
ASSIGN_DRIVER_FUNC(SetFragmentSamplers, name) \ ASSIGN_DRIVER_FUNC(SetFragmentSamplers, name) \
ASSIGN_DRIVER_FUNC(GetTextureData2D, name) \ ASSIGN_DRIVER_FUNC(GetBufferData, name) \
ASSIGN_DRIVER_FUNC(GetTextureDataCube, name) \ ASSIGN_DRIVER_FUNC(CopyTextureData2D, name) \
ASSIGN_DRIVER_FUNC(CopyTextureDataCube, name) \
ASSIGN_DRIVER_FUNC(AddDisposeTexture, name) \ ASSIGN_DRIVER_FUNC(AddDisposeTexture, name) \
ASSIGN_DRIVER_FUNC(AddDisposeSampler, name) \ ASSIGN_DRIVER_FUNC(AddDisposeSampler, name) \
ASSIGN_DRIVER_FUNC(AddDisposeVertexBuffer, name) \ ASSIGN_DRIVER_FUNC(AddDisposeVertexBuffer, name) \

View File

@ -1375,7 +1375,6 @@ typedef struct VulkanRenderer
static void VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer); static void VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
static void VULKAN_Submit(REFRESH_Renderer *driverData, REFRESH_CommandBuffer **pCommandBuffers, uint32_t commandBufferCount); static void VULKAN_Submit(REFRESH_Renderer *driverData, REFRESH_CommandBuffer **pCommandBuffers, uint32_t commandBufferCount);
static void VULKAN_INTERNAL_SubmitTransfer(REFRESH_Renderer *driverData);
/* Error Handling */ /* Error Handling */
@ -5872,8 +5871,6 @@ static void VULKAN_SetTextureData2D(
} }
renderer->pendingTransfer = 1; renderer->pendingTransfer = 1;
VULKAN_INTERNAL_SubmitTransfer(driverData);
} }
static void VULKAN_SetTextureData3D( static void VULKAN_SetTextureData3D(
@ -5980,8 +5977,6 @@ static void VULKAN_SetTextureData3D(
} }
renderer->pendingTransfer = 1; renderer->pendingTransfer = 1;
VULKAN_INTERNAL_SubmitTransfer(driverData);
} }
static void VULKAN_SetTextureDataCube( static void VULKAN_SetTextureDataCube(
@ -6087,8 +6082,6 @@ static void VULKAN_SetTextureDataCube(
} }
renderer->pendingTransfer = 1; renderer->pendingTransfer = 1;
VULKAN_INTERNAL_SubmitTransfer(driverData);
} }
static void VULKAN_SetTextureDataYUV( static void VULKAN_SetTextureDataYUV(
@ -6289,9 +6282,6 @@ static void VULKAN_SetTextureDataYUV(
} }
renderer->pendingTransfer = 1; renderer->pendingTransfer = 1;
/* Hard sync point */
VULKAN_INTERNAL_SubmitTransfer(driverData);
} }
static void VULKAN_SetBufferData( static void VULKAN_SetBufferData(
@ -6839,8 +6829,48 @@ static void VULKAN_SetFragmentSamplers(
); );
} }
static void VULKAN_INTERNAL_GetTextureData( static void VULKAN_GetBufferData(
REFRESH_Renderer *driverData, REFRESH_Renderer *driverData,
REFRESH_Buffer *buffer,
void *data,
uint32_t dataLengthInBytes
) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer;
uint8_t *dataPtr = (uint8_t*) data;
uint8_t *mapPointer;
VkResult vulkanResult;
vulkanResult = renderer->vkMapMemory(
renderer->logicalDevice,
vulkanBuffer->subBuffers[0]->allocation->memory,
vulkanBuffer->subBuffers[0]->offset,
vulkanBuffer->subBuffers[0]->size,
0,
(void**) &mapPointer
);
if (vulkanResult != VK_SUCCESS)
{
REFRESH_LogError("Failed to map buffer memory!");
return;
}
SDL_memcpy(
dataPtr,
mapPointer,
dataLengthInBytes
);
renderer->vkUnmapMemory(
renderer->logicalDevice,
vulkanBuffer->subBuffers[0]->allocation->memory
);
}
static void VULKAN_INTERNAL_CopyTextureData(
REFRESH_Renderer *driverData,
REFRESH_CommandBuffer *commandBuffer,
REFRESH_Texture *texture, REFRESH_Texture *texture,
int32_t x, int32_t x,
int32_t y, int32_t y,
@ -6848,27 +6878,22 @@ static void VULKAN_INTERNAL_GetTextureData(
int32_t h, int32_t h,
int32_t level, int32_t level,
int32_t layer, int32_t layer,
void* data REFRESH_Buffer *buffer
) { ) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanTexture *vulkanTexture = (VulkanTexture*) texture; VulkanTexture *vulkanTexture = (VulkanTexture*) texture;
VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer;
VkCommandBuffer commandBuffer = renderer->transferCommandBuffers[renderer->frameIndex];
VulkanResourceAccessType prevResourceAccess; VulkanResourceAccessType prevResourceAccess;
VkBufferImageCopy imageCopy; VkBufferImageCopy imageCopy;
uint8_t *dataPtr = (uint8_t*) data;
uint8_t *mapPointer;
VkResult vulkanResult;
uint32_t dataLength = BytesPerImage(w, h, vulkanTexture->colorFormat);
VULKAN_INTERNAL_MaybeExpandStagingBuffer(renderer, dataLength);
/* Cache this so we can restore it later */ /* Cache this so we can restore it later */
prevResourceAccess = vulkanTexture->resourceAccessType; prevResourceAccess = vulkanTexture->resourceAccessType;
VULKAN_INTERNAL_ImageMemoryBarrier( VULKAN_INTERNAL_ImageMemoryBarrier(
renderer, renderer,
commandBuffer, vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_READ, RESOURCE_ACCESS_TRANSFER_READ,
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
0, 0,
@ -6877,12 +6902,12 @@ static void VULKAN_INTERNAL_GetTextureData(
vulkanTexture->levelCount, vulkanTexture->levelCount,
0, 0,
vulkanTexture->image, vulkanTexture->image,
renderer->queueFamilyIndices.transferFamily, VK_QUEUE_FAMILY_IGNORED,
&vulkanTexture->queueFamilyIndex, NULL,
&vulkanTexture->resourceAccessType &vulkanTexture->resourceAccessType
); );
/* Save texture data to staging buffer */ /* Save texture data to buffer */
imageCopy.imageExtent.width = w; imageCopy.imageExtent.width = w;
imageCopy.imageExtent.height = h; imageCopy.imageExtent.height = h;
@ -6899,10 +6924,10 @@ static void VULKAN_INTERNAL_GetTextureData(
imageCopy.bufferOffset = 0; imageCopy.bufferOffset = 0;
renderer->vkCmdCopyImageToBuffer( renderer->vkCmdCopyImageToBuffer(
commandBuffer, vulkanCommandBuffer->commandBuffer,
vulkanTexture->image, vulkanTexture->image,
AccessMap[vulkanTexture->resourceAccessType].imageLayout, AccessMap[vulkanTexture->resourceAccessType].imageLayout,
renderer->textureStagingBuffer->subBuffers[0]->buffer, vulkanBuffer->subBuffers[vulkanBuffer->currentSubBufferIndex]->buffer,
1, 1,
&imageCopy &imageCopy
); );
@ -6911,7 +6936,7 @@ static void VULKAN_INTERNAL_GetTextureData(
VULKAN_INTERNAL_ImageMemoryBarrier( VULKAN_INTERNAL_ImageMemoryBarrier(
renderer, renderer,
commandBuffer, vulkanCommandBuffer->commandBuffer,
prevResourceAccess, prevResourceAccess,
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
0, 0,
@ -6920,57 +6945,28 @@ static void VULKAN_INTERNAL_GetTextureData(
vulkanTexture->levelCount, vulkanTexture->levelCount,
0, 0,
vulkanTexture->image, vulkanTexture->image,
renderer->queueFamilyIndices.graphicsFamily, VK_QUEUE_FAMILY_IGNORED,
&vulkanTexture->queueFamilyIndex, NULL,
&vulkanTexture->resourceAccessType &vulkanTexture->resourceAccessType
); );
renderer->pendingTransfer = 1; renderer->pendingTransfer = 1;
/* Hard sync point */
VULKAN_INTERNAL_SubmitTransfer(driverData);
/* Read from staging buffer */
vulkanResult = renderer->vkMapMemory(
renderer->logicalDevice,
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory,
renderer->textureStagingBuffer->subBuffers[0]->offset,
renderer->textureStagingBuffer->subBuffers[0]->size,
0,
(void**) &mapPointer
);
if (vulkanResult != VK_SUCCESS)
{
REFRESH_LogError("Failed to map buffer memory!");
return;
}
SDL_memcpy(
dataPtr,
mapPointer,
dataLength
);
renderer->vkUnmapMemory(
renderer->logicalDevice,
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory
);
} }
static void VULKAN_GetTextureData2D( static void VULKAN_CopyTextureData2D(
REFRESH_Renderer *driverData, REFRESH_Renderer *driverData,
REFRESH_CommandBuffer *commandBuffer,
REFRESH_Texture *texture, REFRESH_Texture *texture,
uint32_t x, uint32_t x,
uint32_t y, uint32_t y,
uint32_t w, uint32_t w,
uint32_t h, uint32_t h,
uint32_t level, uint32_t level,
void* data REFRESH_Buffer *buffer
) { ) {
VULKAN_INTERNAL_GetTextureData( VULKAN_INTERNAL_CopyTextureData(
driverData, driverData,
commandBuffer,
texture, texture,
x, x,
y, y,
@ -6978,12 +6974,13 @@ static void VULKAN_GetTextureData2D(
h, h,
level, level,
0, 0,
data buffer
); );
} }
static void VULKAN_GetTextureDataCube( static void VULKAN_CopyTextureDataCube(
REFRESH_Renderer *driverData, REFRESH_Renderer *driverData,
REFRESH_CommandBuffer *commandBuffer,
REFRESH_Texture *texture, REFRESH_Texture *texture,
uint32_t x, uint32_t x,
uint32_t y, uint32_t y,
@ -6991,10 +6988,11 @@ static void VULKAN_GetTextureDataCube(
uint32_t h, uint32_t h,
REFRESH_CubeMapFace cubeMapFace, REFRESH_CubeMapFace cubeMapFace,
uint32_t level, uint32_t level,
void* data REFRESH_Buffer *buffer
) { ) {
VULKAN_INTERNAL_GetTextureData( VULKAN_INTERNAL_CopyTextureData(
driverData, driverData,
commandBuffer,
texture, texture,
x, x,
y, y,
@ -7002,7 +7000,7 @@ static void VULKAN_GetTextureDataCube(
h, h,
level, level,
cubeMapFace, cubeMapFace,
data buffer
); );
} }
@ -8029,23 +8027,6 @@ static void VULKAN_INTERNAL_ResetCommandBuffer(
commandPool->inactiveCommandBufferCount += 1; commandPool->inactiveCommandBufferCount += 1;
} }
/* This function triggers a hard sync point */
static void VULKAN_INTERNAL_SubmitTransfer(
REFRESH_Renderer *driverData
) {
VulkanRenderer* renderer = (VulkanRenderer*)driverData;
VULKAN_Submit(driverData, NULL, 0);
renderer->vkWaitForFences(
renderer->logicalDevice,
1,
&renderer->inFlightFence,
VK_TRUE,
UINT64_MAX
);
}
static void VULKAN_Submit( static void VULKAN_Submit(
REFRESH_Renderer *driverData, REFRESH_Renderer *driverData,
REFRESH_CommandBuffer **pCommandBuffers, REFRESH_CommandBuffer **pCommandBuffers,