SetTextureData2D

submit_rewrite
cosmonaut 2020-12-18 17:03:26 -08:00
parent faf536377f
commit 0b3bf3181b
1 changed files with 248 additions and 3 deletions

View File

@ -71,6 +71,7 @@ static uint32_t deviceExtensionCount = SDL_arraysize(deviceExtensionNames);
#define STARTING_ALLOCATION_SIZE 64000000 /* 64MB */
#define MAX_ALLOCATION_SIZE 256000000 /* 256MB */
#define TEXTURE_STAGING_SIZE 8000000 /* 8MB */
#define IDENTITY_SWIZZLE \
{ \
@ -572,6 +573,16 @@ static const VulkanResourceAccessInfo AccessMap[RESOURCE_ACCESS_TYPES_COUNT] =
}
};
typedef struct VulkanBuffer /* cast from FNA3D_Buffer */
{
VulkanMemoryAllocation *allocation;
VkBuffer buffer;
VkDeviceSize offset;
VkDeviceSize size;
VulkanResourceAccessType resourceAccessType;
int8_t bound;
} VulkanBuffer;
/* Renderer Structure */
typedef struct QueueFamilyIndices
@ -642,6 +653,8 @@ typedef struct VulkanRenderer
SDL_mutex *allocatorLock;
SDL_mutex *commandLock;
VulkanBuffer *textureStagingBuffer;
#define VULKAN_INSTANCE_FUNCTION(ext, ret, func, params) \
vkfntype_##func func;
#define VULKAN_DEVICE_FUNCTION(ext, ret, func, params) \
@ -1237,6 +1250,77 @@ static uint8_t VULKAN_INTERNAL_FindAvailableMemory(
/* Memory Barriers */
static void VULKAN_INTERNAL_BufferMemoryBarrier(
VulkanRenderer *renderer,
VulkanResourceAccessType nextResourceAccessType,
VulkanBuffer *buffer
) {
VkPipelineStageFlags srcStages = 0;
VkPipelineStageFlags dstStages = 0;
VkBufferMemoryBarrier memoryBarrier;
VulkanResourceAccessType prevAccess, nextAccess;
const VulkanResourceAccessInfo *prevAccessInfo, *nextAccessInfo;
if (buffer->resourceAccessType == nextResourceAccessType)
{
return;
}
memoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
memoryBarrier.pNext = NULL;
memoryBarrier.srcAccessMask = 0;
memoryBarrier.dstAccessMask = 0;
memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
memoryBarrier.buffer = buffer->buffer;
memoryBarrier.offset = 0;
memoryBarrier.size = buffer->size;
prevAccess = buffer->resourceAccessType;
prevAccessInfo = &AccessMap[prevAccess];
srcStages |= prevAccessInfo->stageMask;
if (prevAccess > RESOURCE_ACCESS_END_OF_READ)
{
memoryBarrier.srcAccessMask |= prevAccessInfo->accessMask;
}
nextAccess = nextResourceAccessType;
nextAccessInfo = &AccessMap[nextAccess];
dstStages |= nextAccessInfo->stageMask;
if (memoryBarrier.srcAccessMask != 0)
{
memoryBarrier.dstAccessMask |= nextAccessInfo->accessMask;
}
if (srcStages == 0)
{
srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
}
if (dstStages == 0)
{
dstStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
}
RECORD_CMD(renderer->vkCmdPipelineBarrier(
renderer->currentCommandBuffer,
srcStages,
dstStages,
0,
0,
NULL,
1,
&memoryBarrier,
0,
NULL
));
buffer->resourceAccessType = nextResourceAccessType;
}
static void VULKAN_INTERNAL_ImageMemoryBarrier(
VulkanRenderer *renderer,
VulkanResourceAccessType nextAccess,
@ -1326,6 +1410,90 @@ static void VULKAN_INTERNAL_ImageMemoryBarrier(
*resourceAccessType = nextAccess;
}
/* Data Buffer */
/* buffer should be an alloc'd but uninitialized VulkanTexture */
static uint8_t VULKAN_INTERNAL_CreateBuffer(
VulkanRenderer *renderer,
VkDeviceSize size,
VulkanResourceAccessType resourceAccessType,
VkBufferUsageFlags usage,
VulkanBuffer *buffer
) {
VkResult vulkanResult;
VkBufferCreateInfo bufferCreateInfo;
uint8_t findMemoryResult;
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferCreateInfo.pNext = NULL;
bufferCreateInfo.flags = 0;
bufferCreateInfo.size = size;
bufferCreateInfo.usage = usage;
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufferCreateInfo.queueFamilyIndexCount = 1;
bufferCreateInfo.pQueueFamilyIndices = &renderer->queueFamilyIndices.graphicsFamily;
vulkanResult = renderer->vkCreateBuffer(
renderer->logicalDevice,
&bufferCreateInfo,
NULL,
&buffer->buffer
);
if (vulkanResult != VK_SUCCESS)
{
LogVulkanResult("vkCreateBuffer", vulkanResult);
REFRESH_LogError("Failed to create VkBuffer");
return 0;
}
findMemoryResult = VULKAN_INTERNAL_FindAvailableMemory(
renderer,
buffer->buffer,
VK_NULL_HANDLE,
&buffer->allocation,
&buffer->offset,
&buffer->size
);
/* We're out of available memory */
if (findMemoryResult == 2)
{
REFRESH_LogWarn("Out of buffer memory!");
return 2;
}
else if (findMemoryResult == 0)
{
REFRESH_LogError("Failed to find buffer memory!");
return 0;
}
vulkanResult = renderer->vkBindBufferMemory(
renderer->logicalDevice,
buffer->buffer,
buffer->allocation->memory,
buffer->offset
);
if (vulkanResult != VK_SUCCESS)
{
REFRESH_LogError("Failed to bind buffer memory!");
return 0;
}
buffer->resourceAccessType = resourceAccessType;
buffer->bound = -1;
VULKAN_INTERNAL_BufferMemoryBarrier(
renderer,
buffer->resourceAccessType,
buffer
);
return 1;
}
/* Command Buffers */
static void VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer)
@ -2766,7 +2934,69 @@ static void VULKAN_SetTextureData2D(
void *data,
uint32_t dataLengthInBytes
) {
SDL_assert(0);
VkResult vulkanResult;
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanTexture *vulkanTexture = (VulkanTexture*) texture;
VkBufferImageCopy imageCopy;
uint8_t *mapPointer;
vulkanResult = renderer->vkMapMemory(
renderer->logicalDevice,
renderer->textureStagingBuffer->allocation->memory,
renderer->textureStagingBuffer->offset,
renderer->textureStagingBuffer->size,
0,
(void**) &mapPointer
);
if (vulkanResult != VK_SUCCESS)
{
REFRESH_LogError("Failed to map buffer memory!");
return;
}
SDL_memcpy(mapPointer, data, dataLengthInBytes);
renderer->vkUnmapMemory(
renderer->logicalDevice,
renderer->textureStagingBuffer->allocation->memory
);
VULKAN_INTERNAL_ImageMemoryBarrier(
renderer,
RESOURCE_ACCESS_TRANSFER_WRITE,
VK_IMAGE_ASPECT_COLOR_BIT,
0,
vulkanTexture->layerCount,
0,
vulkanTexture->levelCount,
0,
vulkanTexture->image,
&vulkanTexture->resourceAccessType
);
imageCopy.imageExtent.width = w;
imageCopy.imageExtent.height = h;
imageCopy.imageExtent.depth = 1;
imageCopy.imageOffset.x = x;
imageCopy.imageOffset.y = y;
imageCopy.imageOffset.z = 0;
imageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageCopy.imageSubresource.baseArrayLayer = 0;
imageCopy.imageSubresource.layerCount = 1;
imageCopy.imageSubresource.mipLevel = level;
imageCopy.bufferOffset = 0;
imageCopy.bufferRowLength = 0;
imageCopy.bufferImageHeight = 0;
RECORD_CMD(renderer->vkCmdCopyBufferToImage(
renderer->currentCommandBuffer,
renderer->textureStagingBuffer->buffer,
vulkanTexture->image,
AccessMap[vulkanTexture->resourceAccessType].imageLayout,
1,
&imageCopy
));
}
static void VULKAN_SetTextureData3D(
@ -4286,6 +4516,21 @@ static REFRESH_Device* VULKAN_CreateDevice(
renderer->memoryAllocator->subAllocators[i].sortedFreeRegionCapacity = 4;
}
/* Staging Buffer */
renderer->textureStagingBuffer = (VulkanBuffer*) SDL_malloc(sizeof(VulkanBuffer));
if (!VULKAN_INTERNAL_CreateBuffer(
renderer,
TEXTURE_STAGING_SIZE,
RESOURCE_ACCESS_MEMORY_TRANSFER_READ_WRITE,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
renderer->textureStagingBuffer
)) {
REFRESH_LogError("Failed to create texture staging buffer!");
return NULL;
}
/* Threading */
renderer->allocatorLock = SDL_CreateMutex();