Merge pull request #3220 from Themaister/master

Vulkan: Use manual memory management for cached/incoherent devices.
This commit is contained in:
Twinaphex 2016-07-15 19:18:41 +02:00 committed by GitHub
commit f816829d99
3 changed files with 42 additions and 19 deletions

View File

@ -157,6 +157,7 @@ void vulkan_copy_staging_to_dynamic(vk_t *vk, VkCommandBuffer cmd,
retro_assert(dynamic->type == VULKAN_TEXTURE_DYNAMIC);
retro_assert(staging->type == VULKAN_TEXTURE_STAGING);
vulkan_sync_texture_to_gpu(vk, staging);
vulkan_transition_texture(vk, staging);
/* We don't have to sync against previous TRANSFER,
@ -240,6 +241,30 @@ static void vulkan_track_dealloc(VkImage image)
}
#endif
void vulkan_sync_texture_to_gpu(vk_t *vk, const struct vk_texture *tex)
{
VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
if (!tex || !tex->need_manual_cache_management || tex->memory == VK_NULL_HANDLE)
return;
range.memory = tex->memory;
range.offset = 0;
range.size = VK_WHOLE_SIZE;
vkFlushMappedMemoryRanges(vk->context->device, 1, &range);
}
void vulkan_sync_texture_to_cpu(vk_t *vk, const struct vk_texture *tex)
{
VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
if (!tex || !tex->need_manual_cache_management || tex->memory == VK_NULL_HANDLE)
return;
range.memory = tex->memory;
range.offset = 0;
range.size = VK_WHOLE_SIZE;
vkInvalidateMappedMemoryRanges(vk->context->device, 1, &range);
}
struct vk_texture vulkan_create_texture(vk_t *vk,
struct vk_texture *old,
unsigned width, unsigned height,
@ -340,14 +365,18 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
break;
default:
/* Try to find a memory type which is cached, even if it means manual cache management. */
alloc.memoryTypeIndex = vulkan_find_memory_type_fallback(
&vk->context->memory_properties,
mem_reqs.memoryTypeBits,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
tex.need_manual_cache_management =
(vk->context->memory_properties.memoryTypes[alloc.memoryTypeIndex].propertyFlags &
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0;
break;
}
@ -472,6 +501,7 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
for (y = 0; y < tex.height; y++, dst += tex.stride, src += stride)
memcpy(dst, src, width * bpp);
vulkan_sync_texture_to_gpu(vk, &tex);
vkUnmapMemory(device, tex.memory);
}
else if (initial && type == VULKAN_TEXTURE_STATIC)

View File

@ -170,6 +170,7 @@ struct vk_texture
VkImageLayout layout;
enum vk_texture_type type;
bool default_smooth;
bool need_manual_cache_management;
};
struct vk_buffer
@ -406,6 +407,9 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
const void *initial, const VkComponentMapping *swizzle,
enum vk_texture_type type);
void vulkan_sync_texture_to_gpu(vk_t *vk, const struct vk_texture *tex);
void vulkan_sync_texture_to_cpu(vk_t *vk, const struct vk_texture *tex);
void vulkan_transition_texture(vk_t *vk, struct vk_texture *texture);
void vulkan_transfer_image_ownership(VkCommandBuffer cmd,

View File

@ -1448,22 +1448,6 @@ static void vulkan_readback(vk_t *vk)
VK_PIPELINE_STAGE_HOST_BIT);
}
static void vulkan_flush_caches(vk_t *vk)
{
VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT;
vkCmdPipelineBarrier(vk->cmd,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
false,
1, &barrier,
0, NULL, 0, NULL);
}
static bool vulkan_frame(void *data, const void *frame,
unsigned frame_width, unsigned frame_height,
uint64_t frame_count,
@ -1522,8 +1506,6 @@ static bool vulkan_frame(void *data, const void *frame,
memset(&vk->tracker, 0, sizeof(vk->tracker));
vulkan_flush_caches(vk);
waits_for_semaphores = vk->hw.enable && frame &&
!vk->hw.num_cmd && vk->hw.valid_semaphore;
@ -1591,6 +1573,8 @@ static bool vulkan_frame(void *data, const void *frame,
vulkan_copy_staging_to_dynamic(vk, vk->cmd,
&chain->texture_optimal, &chain->texture);
}
else
vulkan_sync_texture_to_gpu(vk, &chain->texture);
vk->last_valid_index = frame_index;
}
@ -2016,6 +2000,7 @@ static void vulkan_set_texture_frame(void *data,
for (y = 0; y < height; y++, dst += texture->stride, src += stride)
memcpy(dst, src, stride);
vulkan_sync_texture_to_gpu(vk, texture);
vkUnmapMemory(vk->context->device, texture->memory);
vk->menu.alpha = alpha;
@ -2164,6 +2149,8 @@ static bool vulkan_read_viewport(void *data, uint8_t *buffer)
vkMapMemory(vk->context->device, staging->memory,
staging->offset, staging->size, 0, (void**)&src);
vulkan_sync_texture_to_cpu(vk, staging);
vk->readback.scaler.in_stride = staging->stride;
vk->readback.scaler.out_stride = -(int)vk->vp.width * 3;
scaler_ctx_scale(&vk->readback.scaler, buffer, src);
@ -2187,6 +2174,8 @@ static bool vulkan_read_viewport(void *data, uint8_t *buffer)
vulkan_map_persistent_texture(
vk->context->device, staging);
vulkan_sync_texture_to_cpu(vk, staging);
{
unsigned x, y;
const uint8_t *src = (const uint8_t*)staging->mapped;