mirror of
https://github.com/libretro/RetroArch
synced 2025-01-31 06:32:48 +00:00
Cleanup vulkan_create_texture
This commit is contained in:
parent
16ed4ce2d6
commit
9684bde88a
@ -492,56 +492,100 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
struct vk_texture tex;
|
struct vk_texture tex;
|
||||||
|
VkMemoryAllocateInfo alloc;
|
||||||
VkMemoryRequirements mem_reqs;
|
VkMemoryRequirements mem_reqs;
|
||||||
VkSubresourceLayout layout;
|
VkSubresourceLayout layout;
|
||||||
|
VkImageCreateInfo info;
|
||||||
|
VkSubmitInfo submit_info;
|
||||||
|
VkBufferCreateInfo buffer_info;
|
||||||
|
VkImageSubresource subresource;
|
||||||
VkDevice device = vk->context->device;
|
VkDevice device = vk->context->device;
|
||||||
VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
|
|
||||||
VkBufferCreateInfo buffer_info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
|
||||||
VkImageViewCreateInfo view = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
|
||||||
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
|
|
||||||
VkImageSubresource subresource = { VK_IMAGE_ASPECT_COLOR_BIT };
|
|
||||||
VkCommandBufferAllocateInfo cmd_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
|
|
||||||
VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
|
||||||
VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
|
||||||
|
|
||||||
memset(&tex, 0, sizeof(tex));
|
mem_reqs.size = 0;
|
||||||
|
mem_reqs.alignment = 0;
|
||||||
|
mem_reqs.memoryTypeBits = 0;
|
||||||
|
|
||||||
|
alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
|
alloc.pNext = NULL;
|
||||||
|
alloc.allocationSize = 0;
|
||||||
|
alloc.memoryTypeIndex = 0;
|
||||||
|
|
||||||
|
tex.type = VULKAN_TEXTURE_STREAMED;
|
||||||
|
tex.default_smooth = false;
|
||||||
|
tex.need_manual_cache_management = false;
|
||||||
|
tex.mipmap = false;
|
||||||
|
tex.memory_type = 0;
|
||||||
|
tex.width = 0;
|
||||||
|
tex.height = 0;
|
||||||
|
tex.offset = 0;
|
||||||
|
tex.stride = 0;
|
||||||
|
tex.size = 0;
|
||||||
|
tex.mapped = NULL;
|
||||||
|
tex.image = VK_NULL_HANDLE;
|
||||||
|
tex.view = VK_NULL_HANDLE;
|
||||||
|
tex.memory = VK_NULL_HANDLE;
|
||||||
|
tex.buffer = VK_NULL_HANDLE;
|
||||||
|
tex.format = VK_FORMAT_UNDEFINED;
|
||||||
|
tex.memory_size = 0;
|
||||||
|
tex.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
|
info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
|
info.pNext = NULL;
|
||||||
|
info.flags = 0;
|
||||||
info.imageType = VK_IMAGE_TYPE_2D;
|
info.imageType = VK_IMAGE_TYPE_2D;
|
||||||
info.format = format;
|
info.format = format;
|
||||||
info.extent.width = width;
|
info.extent.width = width;
|
||||||
info.extent.height = height;
|
info.extent.height = height;
|
||||||
info.extent.depth = 1;
|
info.extent.depth = 1;
|
||||||
info.arrayLayers = 1;
|
|
||||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
|
|
||||||
buffer_info.size = width * height * vulkan_format_to_bpp(format);
|
|
||||||
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
|
|
||||||
/* For simplicity, always build mipmaps for
|
|
||||||
* static textures, samplers can be used to enable it dynamically.
|
|
||||||
*/
|
|
||||||
if (type == VULKAN_TEXTURE_STATIC)
|
|
||||||
{
|
|
||||||
info.mipLevels = vulkan_num_miplevels(width, height);
|
|
||||||
tex.mipmap = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
info.mipLevels = 1;
|
info.mipLevels = 1;
|
||||||
|
info.arrayLayers = 1;
|
||||||
info.samples = VK_SAMPLE_COUNT_1_BIT;
|
info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
info.usage = 0;
|
||||||
|
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
info.queueFamilyIndexCount = 0;
|
||||||
|
info.pQueueFamilyIndices = NULL;
|
||||||
|
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
|
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
buffer_info.pNext = NULL;
|
||||||
|
buffer_info.flags = 0;
|
||||||
|
buffer_info.size = width * height *
|
||||||
|
vulkan_format_to_bpp(format);
|
||||||
|
buffer_info.usage = 0;
|
||||||
|
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
buffer_info.queueFamilyIndexCount = 0;
|
||||||
|
buffer_info.pQueueFamilyIndices = NULL;
|
||||||
|
|
||||||
|
subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
subresource.mipLevel = 0;
|
||||||
|
subresource.arrayLayer = 0;
|
||||||
|
|
||||||
|
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
submit_info.pNext = NULL;
|
||||||
|
submit_info.waitSemaphoreCount = 0;
|
||||||
|
submit_info.pWaitSemaphores = NULL;
|
||||||
|
submit_info.pWaitDstStageMask = NULL;
|
||||||
|
submit_info.commandBufferCount = 0;
|
||||||
|
submit_info.pCommandBuffers = NULL;
|
||||||
|
submit_info.signalSemaphoreCount = 0;
|
||||||
|
submit_info.pSignalSemaphores = NULL;
|
||||||
|
|
||||||
if (type == VULKAN_TEXTURE_STREAMED)
|
if (type == VULKAN_TEXTURE_STREAMED)
|
||||||
{
|
{
|
||||||
VkFormatProperties format_properties;
|
VkFormatProperties format_properties;
|
||||||
const VkFormatFeatureFlags required = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
|
const VkFormatFeatureFlags required =
|
||||||
|
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
|
||||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
|
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
|
||||||
|
|
||||||
vkGetPhysicalDeviceFormatProperties(
|
vkGetPhysicalDeviceFormatProperties(
|
||||||
vk->context->gpu, format, &format_properties);
|
vk->context->gpu, format, &format_properties);
|
||||||
|
|
||||||
if ((format_properties.linearTilingFeatures & required) != required)
|
if ((format_properties.linearTilingFeatures
|
||||||
|
& required) != required)
|
||||||
{
|
{
|
||||||
RARCH_LOG("[Vulkan]: GPU does not support using linear images as textures. Falling back to copy path.\n");
|
RARCH_LOG("[Vulkan]: GPU does not support using"
|
||||||
|
"linear images as textures. Falling back to copy path.\n");
|
||||||
type = VULKAN_TEXTURE_STAGING;
|
type = VULKAN_TEXTURE_STAGING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -549,21 +593,42 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case VULKAN_TEXTURE_STATIC:
|
case VULKAN_TEXTURE_STATIC:
|
||||||
retro_assert(initial && "Static textures must have initial data.\n");
|
/* For simplicity, always build mipmaps for
|
||||||
|
* static textures, samplers can be used to
|
||||||
|
* enable it dynamically.
|
||||||
|
*/
|
||||||
|
info.mipLevels = vulkan_num_miplevels(width, height);
|
||||||
|
tex.mipmap = true;
|
||||||
|
|
||||||
|
retro_assert(initial &&
|
||||||
|
"Static textures must have initial data.\n");
|
||||||
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
|
vkCreateImage(device, &info, NULL, &tex.image);
|
||||||
|
#if 0
|
||||||
|
vulkan_track_alloc(tex.image);
|
||||||
|
#endif
|
||||||
|
vkGetImageMemoryRequirements(device, tex.image, &mem_reqs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VULKAN_TEXTURE_DYNAMIC:
|
case VULKAN_TEXTURE_DYNAMIC:
|
||||||
retro_assert(!initial && "Dynamic textures must not have initial data.\n");
|
retro_assert(!initial &&
|
||||||
|
"Dynamic textures must not have initial data.\n");
|
||||||
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
|
vkCreateImage(device, &info, NULL, &tex.image);
|
||||||
|
#if 0
|
||||||
|
vulkan_track_alloc(tex.image);
|
||||||
|
#endif
|
||||||
|
vkGetImageMemoryRequirements(device, tex.image, &mem_reqs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VULKAN_TEXTURE_STREAMED:
|
case VULKAN_TEXTURE_STREAMED:
|
||||||
@ -571,36 +636,37 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
info.tiling = VK_IMAGE_TILING_LINEAR;
|
info.tiling = VK_IMAGE_TILING_LINEAR;
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
|
info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
|
||||||
|
|
||||||
|
vkCreateImage(device, &info, NULL, &tex.image);
|
||||||
|
#if 0
|
||||||
|
vulkan_track_alloc(tex.image);
|
||||||
|
#endif
|
||||||
|
vkGetImageMemoryRequirements(device, tex.image, &mem_reqs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VULKAN_TEXTURE_STAGING:
|
case VULKAN_TEXTURE_STAGING:
|
||||||
buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
|
info.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
info.tiling = VK_IMAGE_TILING_LINEAR;
|
info.tiling = VK_IMAGE_TILING_LINEAR;
|
||||||
|
|
||||||
|
/* Linear staging textures are not guaranteed to be supported,
|
||||||
|
* use buffers instead. */
|
||||||
|
vkCreateBuffer(device, &buffer_info, NULL, &tex.buffer);
|
||||||
|
vkGetBufferMemoryRequirements(device, tex.buffer, &mem_reqs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VULKAN_TEXTURE_READBACK:
|
case VULKAN_TEXTURE_READBACK:
|
||||||
buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
|
info.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
info.tiling = VK_IMAGE_TILING_LINEAR;
|
info.tiling = VK_IMAGE_TILING_LINEAR;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type != VULKAN_TEXTURE_STAGING && type != VULKAN_TEXTURE_READBACK)
|
|
||||||
{
|
|
||||||
vkCreateImage(device, &info, NULL, &tex.image);
|
|
||||||
#if 0
|
|
||||||
vulkan_track_alloc(tex.image);
|
|
||||||
#endif
|
|
||||||
vkGetImageMemoryRequirements(device, tex.image, &mem_reqs);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Linear staging textures are not guaranteed to be supported,
|
/* Linear staging textures are not guaranteed to be supported,
|
||||||
* use buffers instead. */
|
* use buffers instead. */
|
||||||
vkCreateBuffer(device, &buffer_info, NULL, &tex.buffer);
|
vkCreateBuffer(device, &buffer_info, NULL, &tex.buffer);
|
||||||
vkGetBufferMemoryRequirements(device, tex.buffer, &mem_reqs);
|
vkGetBufferMemoryRequirements(device, tex.buffer, &mem_reqs);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc.allocationSize = mem_reqs.size;
|
alloc.allocationSize = mem_reqs.size;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
@ -614,7 +680,8 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Try to find a memory type which is cached, even if it means manual cache management. */
|
/* Try to find a memory type which is cached,
|
||||||
|
* even if it means manual cache management. */
|
||||||
alloc.memoryTypeIndex = vulkan_find_memory_type_fallback(
|
alloc.memoryTypeIndex = vulkan_find_memory_type_fallback(
|
||||||
&vk->context->memory_properties,
|
&vk->context->memory_properties,
|
||||||
mem_reqs.memoryTypeBits,
|
mem_reqs.memoryTypeBits,
|
||||||
@ -624,22 +691,26 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
|
|
||||||
tex.need_manual_cache_management =
|
tex.need_manual_cache_management =
|
||||||
(vk->context->memory_properties.memoryTypes[alloc.memoryTypeIndex].propertyFlags &
|
(vk->context->memory_properties.
|
||||||
|
memoryTypes[alloc.memoryTypeIndex].propertyFlags &
|
||||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0;
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the texture is STREAMED and it's not DEVICE_LOCAL, we expect to hit a slower path,
|
/* If the texture is STREAMED and it's not DEVICE_LOCAL,
|
||||||
|
* we expect to hit a slower path,
|
||||||
* so fallback to copy path. */
|
* so fallback to copy path. */
|
||||||
if (type == VULKAN_TEXTURE_STREAMED &&
|
if (type == VULKAN_TEXTURE_STREAMED &&
|
||||||
(vk->context->memory_properties.memoryTypes[alloc.memoryTypeIndex].propertyFlags &
|
(vk->context->memory_properties.
|
||||||
|
memoryTypes[alloc.memoryTypeIndex].propertyFlags &
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0)
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0)
|
||||||
{
|
{
|
||||||
/* Recreate texture but for STAGING this time ... */
|
/* Recreate texture but for STAGING this time ... */
|
||||||
RARCH_LOG("[Vulkan]: GPU supports linear images as textures, but not DEVICE_LOCAL. Falling back to copy path.\n");
|
RARCH_LOG("[Vulkan]: GPU supports linear images as textures"
|
||||||
|
", but not DEVICE_LOCAL. Falling back to copy path.\n");
|
||||||
type = VULKAN_TEXTURE_STAGING;
|
type = VULKAN_TEXTURE_STAGING;
|
||||||
vkDestroyImage(device, tex.image, NULL);
|
vkDestroyImage(device, tex.image, NULL);
|
||||||
tex.image = (VkImage)NULL;
|
tex.image = (VkImage)VK_NULL_HANDLE;
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
|
info.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
|
||||||
buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||||
@ -658,20 +729,22 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We're not reusing the objects themselves. */
|
/* We're not reusing the objects themselves. */
|
||||||
if (old && old->view != VK_NULL_HANDLE)
|
if (old)
|
||||||
|
{
|
||||||
|
if (old->view != VK_NULL_HANDLE)
|
||||||
vkDestroyImageView(vk->context->device, old->view, NULL);
|
vkDestroyImageView(vk->context->device, old->view, NULL);
|
||||||
if (old && old->image != VK_NULL_HANDLE)
|
if (old->image != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
vkDestroyImage(vk->context->device, old->image, NULL);
|
vkDestroyImage(vk->context->device, old->image, NULL);
|
||||||
#ifdef VULKAN_DEBUG_TEXTURE_ALLOC
|
#ifdef VULKAN_DEBUG_TEXTURE_ALLOC
|
||||||
vulkan_track_dealloc(old->image);
|
vulkan_track_dealloc(old->image);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (old && old->buffer != VK_NULL_HANDLE)
|
if (old->buffer != VK_NULL_HANDLE)
|
||||||
vkDestroyBuffer(vk->context->device, old->buffer, NULL);
|
vkDestroyBuffer(vk->context->device, old->buffer, NULL);
|
||||||
|
|
||||||
/* We can pilfer the old memory and move it over to the new texture. */
|
/* We can pilfer the old memory and move it over to the new texture. */
|
||||||
if (old &&
|
if (
|
||||||
old->memory_size >= mem_reqs.size &&
|
old->memory_size >= mem_reqs.size &&
|
||||||
old->memory_type == alloc.memoryTypeIndex)
|
old->memory_type == alloc.memoryTypeIndex)
|
||||||
{
|
{
|
||||||
@ -684,6 +757,11 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
|
|
||||||
old->memory = VK_NULL_HANDLE;
|
old->memory = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (old->memory != VK_NULL_HANDLE)
|
||||||
|
vkFreeMemory(device, old->memory, NULL);
|
||||||
|
memset(old, 0, sizeof(*old));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vkAllocateMemory(device, &alloc, NULL, &tex.memory);
|
vkAllocateMemory(device, &alloc, NULL, &tex.memory);
|
||||||
@ -691,13 +769,6 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
tex.memory_type = alloc.memoryTypeIndex;
|
tex.memory_type = alloc.memoryTypeIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old)
|
|
||||||
{
|
|
||||||
if (old->memory != VK_NULL_HANDLE)
|
|
||||||
vkFreeMemory(device, old->memory, NULL);
|
|
||||||
memset(old, 0, sizeof(*old));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tex.image)
|
if (tex.image)
|
||||||
vkBindImageMemory(device, tex.image, tex.memory, 0);
|
vkBindImageMemory(device, tex.image, tex.memory, 0);
|
||||||
if (tex.buffer)
|
if (tex.buffer)
|
||||||
@ -705,20 +776,24 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
|
|
||||||
if (type != VULKAN_TEXTURE_STAGING && type != VULKAN_TEXTURE_READBACK)
|
if (type != VULKAN_TEXTURE_STAGING && type != VULKAN_TEXTURE_READBACK)
|
||||||
{
|
{
|
||||||
|
VkImageViewCreateInfo view;
|
||||||
|
view.sType =
|
||||||
|
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
view.pNext = NULL;
|
||||||
|
view.flags = 0;
|
||||||
view.image = tex.image;
|
view.image = tex.image;
|
||||||
view.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
view.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
view.format = format;
|
view.format = format;
|
||||||
if (swizzle)
|
|
||||||
view.components = *swizzle;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
view.components.r = VK_COMPONENT_SWIZZLE_R;
|
view.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||||
view.components.g = VK_COMPONENT_SWIZZLE_G;
|
view.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||||
view.components.b = VK_COMPONENT_SWIZZLE_B;
|
view.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||||
view.components.a = VK_COMPONENT_SWIZZLE_A;
|
view.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||||
}
|
if (swizzle)
|
||||||
|
view.components = *swizzle;
|
||||||
view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
view.subresourceRange.baseMipLevel = 0;
|
||||||
view.subresourceRange.levelCount = info.mipLevels;
|
view.subresourceRange.levelCount = info.mipLevels;
|
||||||
|
view.subresourceRange.baseArrayLayer = 0;
|
||||||
view.subresourceRange.layerCount = 1;
|
view.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
vkCreateImageView(device, &view, NULL, &tex.view);
|
vkCreateImageView(device, &view, NULL, &tex.view);
|
||||||
@ -726,16 +801,20 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
else
|
else
|
||||||
tex.view = VK_NULL_HANDLE;
|
tex.view = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
layout.offset = 0;
|
||||||
|
layout.size = 0;
|
||||||
|
layout.rowPitch = 0;
|
||||||
|
layout.arrayPitch = 0;
|
||||||
|
layout.depthPitch = 0;
|
||||||
|
|
||||||
if (tex.image && info.tiling == VK_IMAGE_TILING_LINEAR)
|
if (tex.image && info.tiling == VK_IMAGE_TILING_LINEAR)
|
||||||
vkGetImageSubresourceLayout(device, tex.image, &subresource, &layout);
|
vkGetImageSubresourceLayout(device, tex.image, &subresource, &layout);
|
||||||
else if (tex.buffer)
|
else if (tex.buffer)
|
||||||
{
|
{
|
||||||
layout.offset = 0;
|
|
||||||
layout.size = buffer_info.size;
|
layout.size = buffer_info.size;
|
||||||
layout.rowPitch = width * vulkan_format_to_bpp(format);
|
layout.rowPitch = width *
|
||||||
|
vulkan_format_to_bpp(format);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
memset(&layout, 0, sizeof(layout));
|
|
||||||
|
|
||||||
tex.stride = layout.rowPitch;
|
tex.stride = layout.rowPitch;
|
||||||
tex.offset = layout.offset;
|
tex.offset = layout.offset;
|
||||||
@ -747,7 +826,12 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
tex.format = format;
|
tex.format = format;
|
||||||
tex.type = type;
|
tex.type = type;
|
||||||
|
|
||||||
if (initial && (type == VULKAN_TEXTURE_STREAMED || type == VULKAN_TEXTURE_STAGING))
|
if (initial)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case VULKAN_TEXTURE_STREAMED:
|
||||||
|
case VULKAN_TEXTURE_STAGING:
|
||||||
{
|
{
|
||||||
unsigned y;
|
unsigned y;
|
||||||
uint8_t *dst = NULL;
|
uint8_t *dst = NULL;
|
||||||
@ -766,32 +850,51 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
vulkan_sync_texture_to_gpu(vk, &tex);
|
vulkan_sync_texture_to_gpu(vk, &tex);
|
||||||
vkUnmapMemory(device, tex.memory);
|
vkUnmapMemory(device, tex.memory);
|
||||||
}
|
}
|
||||||
else if (initial && type == VULKAN_TEXTURE_STATIC)
|
break;
|
||||||
|
case VULKAN_TEXTURE_STATIC:
|
||||||
{
|
{
|
||||||
VkBufferImageCopy region;
|
VkBufferImageCopy region;
|
||||||
VkCommandBuffer staging;
|
VkCommandBuffer staging;
|
||||||
struct vk_texture tmp = vulkan_create_texture(vk, NULL,
|
VkCommandBufferAllocateInfo cmd_info;
|
||||||
width, height, format, initial, NULL, VULKAN_TEXTURE_STAGING);
|
VkCommandBufferBeginInfo begin_info;
|
||||||
|
struct vk_texture tmp =
|
||||||
|
vulkan_create_texture(vk, NULL,
|
||||||
|
width, height, format, initial,
|
||||||
|
NULL, VULKAN_TEXTURE_STAGING);
|
||||||
|
|
||||||
|
cmd_info.sType =
|
||||||
|
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
|
cmd_info.pNext = NULL;
|
||||||
cmd_info.commandPool = vk->staging_pool;
|
cmd_info.commandPool = vk->staging_pool;
|
||||||
cmd_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
cmd_info.level =
|
||||||
|
VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
cmd_info.commandBufferCount = 1;
|
cmd_info.commandBufferCount = 1;
|
||||||
|
|
||||||
vkAllocateCommandBuffers(vk->context->device, &cmd_info, &staging);
|
vkAllocateCommandBuffers(vk->context->device,
|
||||||
|
&cmd_info, &staging);
|
||||||
|
|
||||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
begin_info.sType =
|
||||||
|
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
begin_info.pNext = NULL;
|
||||||
|
begin_info.flags =
|
||||||
|
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
|
begin_info.pInheritanceInfo = NULL;
|
||||||
|
|
||||||
vkBeginCommandBuffer(staging, &begin_info);
|
vkBeginCommandBuffer(staging, &begin_info);
|
||||||
|
|
||||||
/* If doing mipmapping on upload, keep in general so we can easily do transfers to
|
/* If doing mipmapping on upload, keep in general
|
||||||
|
* so we can easily do transfers to
|
||||||
* and transfers from the images without having to
|
* and transfers from the images without having to
|
||||||
* mess around with lots of extra transitions at per-level granularity.
|
* mess around with lots of extra transitions at
|
||||||
|
* per-level granularity.
|
||||||
*/
|
*/
|
||||||
vulkan_image_layout_transition(vk,
|
vulkan_image_layout_transition(vk,
|
||||||
staging,
|
staging,
|
||||||
tex.image,
|
tex.image,
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
tex.mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
tex.mipmap
|
||||||
|
? VK_IMAGE_LAYOUT_GENERAL
|
||||||
|
: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
@ -806,7 +909,9 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
vkCmdCopyBufferToImage(staging,
|
vkCmdCopyBufferToImage(staging,
|
||||||
tmp.buffer,
|
tmp.buffer,
|
||||||
tex.image,
|
tex.image,
|
||||||
tex.mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
tex.mipmap
|
||||||
|
? VK_IMAGE_LAYOUT_GENERAL
|
||||||
|
: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
1, ®ion);
|
1, ®ion);
|
||||||
|
|
||||||
if (tex.mipmap)
|
if (tex.mipmap)
|
||||||
@ -848,26 +953,19 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
tex.image, VK_IMAGE_LAYOUT_GENERAL,
|
tex.image, VK_IMAGE_LAYOUT_GENERAL,
|
||||||
1, &blit_region, VK_FILTER_LINEAR);
|
1, &blit_region, VK_FILTER_LINEAR);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Complete our texture. */
|
/* Complete our texture. */
|
||||||
vulkan_image_layout_transition(vk, staging, tex.image,
|
vulkan_image_layout_transition(vk, staging, tex.image,
|
||||||
VK_IMAGE_LAYOUT_GENERAL,
|
tex.mipmap
|
||||||
|
? VK_IMAGE_LAYOUT_GENERAL
|
||||||
|
: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
|
||||||
|
,
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
VK_ACCESS_SHADER_READ_BIT,
|
VK_ACCESS_SHADER_READ_BIT,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vulkan_image_layout_transition(vk, staging, tex.image,
|
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
|
||||||
VK_ACCESS_SHADER_READ_BIT,
|
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
vkEndCommandBuffer(staging);
|
vkEndCommandBuffer(staging);
|
||||||
submit_info.commandBufferCount = 1;
|
submit_info.commandBufferCount = 1;
|
||||||
@ -893,6 +991,11 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
vk->context->device, &tmp);
|
vk->context->device, &tmp);
|
||||||
tex.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
tex.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -915,7 +1018,24 @@ void vulkan_destroy_texture(
|
|||||||
if (tex->image)
|
if (tex->image)
|
||||||
vulkan_track_dealloc(tex->image);
|
vulkan_track_dealloc(tex->image);
|
||||||
#endif
|
#endif
|
||||||
memset(tex, 0, sizeof(*tex));
|
tex->type = VULKAN_TEXTURE_STREAMED;
|
||||||
|
tex->default_smooth = false;
|
||||||
|
tex->need_manual_cache_management = false;
|
||||||
|
tex->mipmap = false;
|
||||||
|
tex->memory_type = 0;
|
||||||
|
tex->width = 0;
|
||||||
|
tex->height = 0;
|
||||||
|
tex->offset = 0;
|
||||||
|
tex->stride = 0;
|
||||||
|
tex->size = 0;
|
||||||
|
tex->mapped = NULL;
|
||||||
|
tex->image = VK_NULL_HANDLE;
|
||||||
|
tex->view = VK_NULL_HANDLE;
|
||||||
|
tex->memory = VK_NULL_HANDLE;
|
||||||
|
tex->buffer = VK_NULL_HANDLE;
|
||||||
|
tex->format = VK_FORMAT_UNDEFINED;
|
||||||
|
tex->memory_size = 0;
|
||||||
|
tex->layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vulkan_write_quad_descriptors(
|
static void vulkan_write_quad_descriptors(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user