diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index f84c7f5d1a..b1a3b85c81 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -432,6 +432,7 @@ struct vk_texture vulkan_create_texture(vk_t *vk, 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 }; + uint32_t buffer_width; memset(&tex, 0, sizeof(tex)); @@ -445,9 +446,30 @@ struct vk_texture vulkan_create_texture(vk_t *vk, info.mipLevels = 1; info.samples = VK_SAMPLE_COUNT_1_BIT; - buffer_info.size = width * height * vulkan_format_to_bpp(format); + /* Align stride to 4 bytes to make sure we can use compute shader uploads without too many problems. */ + buffer_width = width * vulkan_format_to_bpp(format); + buffer_width = (buffer_width + 3u) & ~3u; + buffer_info.size = buffer_width * height; buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + /* Compatibility concern. Some Apple hardware does not support rgb565. + * Use compute shader uploads instead. + * If we attempt to use streamed texture, force staging path. + * If we're creating fallback dynamic texture, force RGBA8888. */ + if (format == VK_FORMAT_R5G6B5_UNORM_PACK16) + { + if (type == VULKAN_TEXTURE_STREAMED) + { + type = VULKAN_TEXTURE_STAGING; + } + else if (type == VULKAN_TEXTURE_DYNAMIC) + { + format = VK_FORMAT_R8G8B8A8_UNORM; + info.format = format; + info.usage |= VK_IMAGE_USAGE_STORAGE_BIT; + } + } + if (type == VULKAN_TEXTURE_STREAMED) { VkFormatProperties format_properties; @@ -483,7 +505,7 @@ struct vk_texture vulkan_create_texture(vk_t *vk, case VULKAN_TEXTURE_DYNAMIC: retro_assert(!initial && "Dynamic textures must not have initial data.\n"); 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_SRC_BIT; info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -497,7 +519,7 @@ struct vk_texture vulkan_create_texture(vk_t *vk, break; case VULKAN_TEXTURE_STAGING: - buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; info.initialLayout = VK_IMAGE_LAYOUT_GENERAL; info.tiling = VK_IMAGE_TILING_LINEAR; break; @@ -665,7 +687,7 @@ struct vk_texture vulkan_create_texture(vk_t *vk, { layout.offset = 0; layout.size = buffer_info.size; - layout.rowPitch = width * vulkan_format_to_bpp(format); + layout.rowPitch = buffer_width; } else memset(&layout, 0, sizeof(layout)); @@ -3073,11 +3095,6 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, return false; } - VkFormatProperties formatProperties; - vkGetPhysicalDeviceFormatProperties(vk->context.gpu, VK_FORMAT_R5G6B5_UNORM_PACK16, &formatProperties); - if (formatProperties.optimalTilingFeatures != 0) - vk->context.flags |= VK_CTX_FLAG_HAS_PACK16_FMTS; - #ifdef VULKAN_HDR_SWAPCHAIN if (settings->bools.video_hdr_enable) vk->context.flags |= VK_CTX_FLAG_HDR_ENABLE; @@ -3322,3 +3339,133 @@ void vulkan_set_uniform_buffer( vkUpdateDescriptorSets(device, 1, &write, 0, NULL); } + +void vulkan_copy_staging_to_dynamic(vk_t *vk, VkCommandBuffer cmd, + struct vk_texture *dynamic, struct vk_texture *staging) +{ + bool compute_upload = dynamic->format != staging->format; + + if (compute_upload) + { + const uint32_t ubo[3] = { dynamic->width, dynamic->height, staging->stride / 4 /* in terms of u32 words */ }; + VkWriteDescriptorSet write = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + VkDescriptorBufferInfo buffer_info; + VkDescriptorImageInfo image_info; + struct vk_buffer_range range; + VkDescriptorSet set; + + VULKAN_IMAGE_LAYOUT_TRANSITION( + cmd, + dynamic->image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_GENERAL, + 0, + VK_ACCESS_SHADER_WRITE_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + + /* staging->format is always RGB565 here. Can be expanded as needed. */ + retro_assert(staging->format == VK_FORMAT_R5G6B5_UNORM_PACK16); + + set = vulkan_descriptor_manager_alloc( + vk->context->device, + &vk->chain->descriptor_manager); + + if (!vulkan_buffer_chain_alloc(vk->context, &vk->chain->ubo, + sizeof(ubo), &range)) + return; + + memcpy(range.data, ubo, sizeof(ubo)); + vulkan_set_uniform_buffer(vk->context->device, + set, + 0, + range.buffer, + range.offset, + sizeof(ubo)); + + image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + image_info.imageView = dynamic->view; + image_info.sampler = VK_NULL_HANDLE; + + buffer_info.buffer = staging->buffer; + buffer_info.offset = 0; + buffer_info.range = VK_WHOLE_SIZE; + + write.descriptorCount = 1; + write.pTexelBufferView = NULL; + write.dstArrayElement = 0; + write.dstSet = set; + + write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + write.dstBinding = 3; + write.pImageInfo = &image_info; + write.pBufferInfo = NULL; + + vkUpdateDescriptorSets(vk->context->device, 1, &write, 0, NULL); + + write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + write.dstBinding = 4; + write.pImageInfo = NULL; + write.pBufferInfo = &buffer_info; + + vkUpdateDescriptorSets(vk->context->device, 1, &write, 0, NULL); + + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, vk->pipelines.rgb565_to_rgba8888); + vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, vk->pipelines.layout, 0, 1, &set, 0, NULL); + vkCmdDispatch(cmd, (dynamic->width + 15) / 16, (dynamic->height + 7) / 8, 1); + + VULKAN_IMAGE_LAYOUT_TRANSITION( + cmd, + dynamic->image, + VK_IMAGE_LAYOUT_GENERAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + } + else + { + VkBufferImageCopy region; + + VULKAN_IMAGE_LAYOUT_TRANSITION( + cmd, + dynamic->image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT); + region.bufferOffset = 0; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + region.imageOffset.x = 0; + region.imageOffset.y = 0; + region.imageOffset.z = 0; + region.imageExtent.width = dynamic->width; + region.imageExtent.height = dynamic->height; + region.imageExtent.depth = 1; + vkCmdCopyBufferToImage( + cmd, + staging->buffer, + dynamic->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + ®ion); + VULKAN_IMAGE_LAYOUT_TRANSITION( + cmd, + dynamic->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); + } + dynamic->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; +} diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index 65fdb66115..a6ad4abac3 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -119,7 +119,6 @@ enum vulkan_context_flags VK_CTX_FLAG_SWAPCHAIN_IS_SRGB = (1 << 2), VK_CTX_FLAG_SWAP_INTERVAL_EMULATION_LOCK = (1 << 3), VK_CTX_FLAG_HAS_ACQUIRED_SWAPCHAIN = (1 << 4), - VK_CTX_FLAG_HAS_PACK16_FMTS = (1 << 5) }; typedef struct vulkan_context @@ -423,6 +422,7 @@ typedef struct vk { VkPipeline alpha_blend; VkPipeline font; + VkPipeline rgb565_to_rgba8888; #ifdef VULKAN_HDR_SWAPCHAIN VkPipeline hdr; #endif /* VULKAN_HDR_SWAPCHAIN */ @@ -668,49 +668,8 @@ void vulkan_destroy_texture( /* Dynamic texture type should be set to : VULKAN_TEXTURE_DYNAMIC * Staging texture type should be set to : VULKAN_TEXTURE_STAGING */ -#define VULKAN_COPY_STAGING_TO_DYNAMIC(vk, cmd, dynamic, staging) \ -{ \ - VkBufferImageCopy region; \ - VULKAN_IMAGE_LAYOUT_TRANSITION( \ - cmd, \ - dynamic->image, \ - VK_IMAGE_LAYOUT_UNDEFINED, \ - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, \ - 0, \ - VK_ACCESS_TRANSFER_WRITE_BIT, \ - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, \ - VK_PIPELINE_STAGE_TRANSFER_BIT); \ - region.bufferOffset = 0; \ - region.bufferRowLength = 0; \ - region.bufferImageHeight = 0; \ - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; \ - region.imageSubresource.mipLevel = 0; \ - region.imageSubresource.baseArrayLayer = 0; \ - region.imageSubresource.layerCount = 1; \ - region.imageOffset.x = 0; \ - region.imageOffset.y = 0; \ - region.imageOffset.z = 0; \ - region.imageExtent.width = dynamic->width; \ - region.imageExtent.height = dynamic->height; \ - region.imageExtent.depth = 1; \ - vkCmdCopyBufferToImage( \ - cmd, \ - staging->buffer, \ - dynamic->image, \ - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, \ - 1, \ - ®ion); \ - VULKAN_IMAGE_LAYOUT_TRANSITION( \ - cmd, \ - dynamic->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); \ - dynamic->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; \ -} +void vulkan_copy_staging_to_dynamic(vk_t *vk, VkCommandBuffer cmd, + struct vk_texture *dynamic, struct vk_texture *staging); /* We don't have to sync against previous TRANSFER, * since we observed the completion by fences. diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 3e8beecf64..691196e7b9 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -261,12 +261,13 @@ static void vulkan_init_pipeline_layout( { VkPipelineLayoutCreateInfo layout_info; VkDescriptorSetLayoutCreateInfo set_layout_info; - VkDescriptorSetLayoutBinding bindings[3]; + VkDescriptorSetLayoutBinding bindings[5]; bindings[0].binding = 0; bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; bindings[0].descriptorCount = 1; - bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | + VK_SHADER_STAGE_COMPUTE_BIT; bindings[0].pImmutableSamplers = NULL; bindings[1].binding = 1; @@ -281,11 +282,23 @@ static void vulkan_init_pipeline_layout( bindings[2].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; bindings[2].pImmutableSamplers = NULL; + bindings[3].binding = 3; + bindings[3].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + bindings[3].descriptorCount = 1; + bindings[3].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + bindings[3].pImmutableSamplers = NULL; + + bindings[4].binding = 4; + bindings[4].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + bindings[4].descriptorCount = 1; + bindings[4].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + bindings[4].pImmutableSamplers = NULL; + set_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; set_layout_info.pNext = NULL; set_layout_info.flags = 0; - set_layout_info.bindingCount = 3; + set_layout_info.bindingCount = 5; set_layout_info.pBindings = bindings; vkCreateDescriptorSetLayout(vk->context->device, @@ -324,6 +337,10 @@ static void vulkan_init_pipelines(vk_t *vk) #include "vulkan_shaders/font.frag.inc" ; + static const uint32_t rgb565_to_rgba8888_comp[] = +#include "vulkan_shaders/rgb565_to_rgba8888.comp.inc" + ; + static const uint32_t pipeline_ribbon_vert[] = #include "vulkan_shaders/pipeline_ribbon.vert.inc" ; @@ -378,6 +395,8 @@ static void vulkan_init_pipelines(vk_t *vk) VkGraphicsPipelineCreateInfo pipe = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO }; + VkComputePipelineCreateInfo cpipe = { + VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; VkShaderModuleCreateInfo module_info = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO }; VkVertexInputAttributeDescription attributes[3] = {{0}}; @@ -642,6 +661,19 @@ static void vulkan_init_pipelines(vk_t *vk) vkDestroyShaderModule(vk->context->device, shader_stages[0].module, NULL); vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); } + + cpipe.layout = vk->pipelines.layout; + cpipe.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + cpipe.stage.pName = "main"; + cpipe.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; + + module_info.codeSize = sizeof(rgb565_to_rgba8888_comp); + module_info.pCode = rgb565_to_rgba8888_comp; + vkCreateShaderModule(vk->context->device, + &module_info, NULL, &cpipe.stage.module); + vkCreateComputePipelines(vk->context->device, vk->pipelines.cache, + 1, &cpipe, NULL, &vk->pipelines.rgb565_to_rgba8888); + vkDestroyShaderModule(vk->context->device, cpipe.stage.module, NULL); } static void vulkan_init_samplers(vk_t *vk) @@ -811,6 +843,8 @@ static void vulkan_deinit_pipelines(vk_t *vk) vk->pipelines.alpha_blend, NULL); vkDestroyPipeline(vk->context->device, vk->pipelines.font, NULL); + vkDestroyPipeline(vk->context->device, + vk->pipelines.rgb565_to_rgba8888, NULL); #ifdef VULKAN_HDR_SWAPCHAIN vkDestroyPipeline(vk->context->device, vk->pipelines.hdr, NULL); @@ -1476,11 +1510,7 @@ static void *vulkan_init(const video_info_t *video, vk->flags &= ~VK_FLAG_FULLSCREEN; vk->tex_w = RARCH_SCALE_BASE * video->input_scale; vk->tex_h = RARCH_SCALE_BASE * video->input_scale; - if (vk->context->flags & VK_CTX_FLAG_HAS_PACK16_FMTS) - vk->tex_fmt = video->rgb32 - ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R5G6B5_UNORM_PACK16; - else - vk->tex_fmt = VK_FORMAT_B8G8R8A8_UNORM; + vk->tex_fmt = video->rgb32 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R5G6B5_UNORM_PACK16; if (video->force_aspect) vk->flags |= VK_FLAG_KEEP_ASPECT; else @@ -1510,9 +1540,11 @@ static void *vulkan_init(const video_info_t *video, if (vk->context) { int i; - static const VkDescriptorPoolSize pool_sizes[2] = { + static const VkDescriptorPoolSize pool_sizes[4] = { { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS * 2 }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS }, }; vk->num_swapchain_images = vk->context->num_swapchain_images; @@ -1530,7 +1562,7 @@ static void *vulkan_init(const video_info_t *video, vk->swapchain[i].descriptor_manager = vulkan_create_descriptor_manager( vk->context->device, - pool_sizes, 2, vk->pipelines.set_layout); + pool_sizes, 4, vk->pipelines.set_layout); vk->swapchain[i].vbo = vulkan_buffer_chain_init( VULKAN_BUFFER_BLOCK_SIZE, 16, @@ -1618,9 +1650,11 @@ static void vulkan_check_swapchain(vk_t *vk) if (vk->context) { int i; - static const VkDescriptorPoolSize pool_sizes[2] = { + static const VkDescriptorPoolSize pool_sizes[4] = { { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS * 2 }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VULKAN_DESCRIPTOR_MANAGER_BLOCK_SETS }, }; vk->num_swapchain_images = vk->context->num_swapchain_images; @@ -1638,7 +1672,7 @@ static void vulkan_check_swapchain(vk_t *vk) vk->swapchain[i].descriptor_manager = vulkan_create_descriptor_manager( vk->context->device, - pool_sizes, 2, vk->pipelines.set_layout); + pool_sizes, 4, vk->pipelines.set_layout); vk->swapchain[i].vbo = vulkan_buffer_chain_init( VULKAN_BUFFER_BLOCK_SIZE, @@ -2314,36 +2348,11 @@ static bool vulkan_frame(void *data, const void *frame, vk, &chain->texture_optimal, frame_width, frame_height, - chain->texture_optimal.format, + chain->texture.format, /* Ensure we use the original format and not any remapped format. */ NULL, NULL, VULKAN_TEXTURE_DYNAMIC); } - if (!vk->video.rgb32 && !(vk->context->flags & VK_CTX_FLAG_HAS_PACK16_FMTS)) - { - uint16_t *rgb565_src = ((uint16_t*)frame) + (frame_height * pitch / 2/*bpp*/); - uint32_t *bgra8888_dst = ((uint32_t*)chain->texture.mapped) + (frame_height * chain->texture.stride / 4/*bpp*/); - uint16_t rgbpix; - uint32_t bgrapix; - unsigned x; - for (y = frame_height; y > 0; y--) - { - rgb565_src -= pitch / 2/*bpp*/; - bgra8888_dst -= chain->texture.stride / 4/*bpp*/; - for (x = frame_width; x > 0; ) - { - x--; - rgbpix = rgb565_src[x]; - bgrapix = 0xff00; - bgrapix |= (rgbpix & 0xf800) >> 8; - bgrapix <<= 8; - bgrapix |= (rgbpix & 0x07e0) >> 3; - bgrapix <<= 8; - bgrapix |= (rgbpix & 0x1f) << 3; - bgra8888_dst[x] = bgrapix; - } - } - } - else if (frame != chain->texture.mapped) + if (frame != chain->texture.mapped) { dst = (uint8_t*)chain->texture.mapped; if ( (chain->texture.stride == pitch ) @@ -2362,7 +2371,7 @@ static bool vulkan_frame(void *data, const void *frame, { struct vk_texture *dynamic = &chain->texture_optimal; struct vk_texture *staging = &chain->texture; - VULKAN_COPY_STAGING_TO_DYNAMIC(vk, vk->cmd, dynamic, staging); + vulkan_copy_staging_to_dynamic(vk, vk->cmd, dynamic, staging); } vk->last_valid_index = frame_index; @@ -2471,7 +2480,7 @@ static bool vulkan_frame(void *data, const void *frame, struct vk_texture *dynamic = optimal; struct vk_texture *staging = texture; VULKAN_SYNC_TEXTURE_TO_GPU_COND_PTR(vk, staging); - VULKAN_COPY_STAGING_TO_DYNAMIC(vk, vk->cmd, + vulkan_copy_staging_to_dynamic(vk, vk->cmd, dynamic, staging); vk->menu.dirty[vk->menu.last_index] = false; } @@ -3129,7 +3138,7 @@ static bool vulkan_get_current_sw_framebuffer(void *data, &chain->texture_optimal, framebuffer->width, framebuffer->height, - chain->texture_optimal.format, + chain->texture.format, /* Ensure we use the non-remapped format. */ NULL, NULL, VULKAN_TEXTURE_DYNAMIC); } } diff --git a/gfx/drivers/vulkan_shaders/Makefile b/gfx/drivers/vulkan_shaders/Makefile index 639b7d4846..5218b311dc 100644 --- a/gfx/drivers/vulkan_shaders/Makefile +++ b/gfx/drivers/vulkan_shaders/Makefile @@ -1,6 +1,7 @@ VERT_SHADERS := $(wildcard *.vert) FRAG_SHADERS := $(wildcard *.frag) -SPIRV := $(VERT_SHADERS:.vert=.vert.inc) $(FRAG_SHADERS:.frag=.frag.inc) +COMP_SHADERS := $(wildcard *.comp) +SPIRV := $(VERT_SHADERS:.vert=.vert.inc) $(FRAG_SHADERS:.frag=.frag.inc) $(COMP_SHADERS:.comp=.comp.inc) GLSLANG := glslc GLSLFLAGS := -mfmt=c @@ -13,6 +14,9 @@ all: $(SPIRV) %.frag.inc: %.frag $(GLSLANG) $(GLSLFLAGS) -o $@ $< +%.comp.inc: %.comp + $(GLSLANG) $(GLSLFLAGS) -o $@ $< + clean: rm -f $(SPIRV) diff --git a/gfx/drivers/vulkan_shaders/rgb565_to_rgba8888.comp b/gfx/drivers/vulkan_shaders/rgb565_to_rgba8888.comp new file mode 100644 index 0000000000..6e877c1d21 --- /dev/null +++ b/gfx/drivers/vulkan_shaders/rgb565_to_rgba8888.comp @@ -0,0 +1,40 @@ +#version 450 + +layout(local_size_x = 16, local_size_y = 8) in; + +layout(set = 0, binding = 3, rgba8) writeonly uniform image2D uImage; +layout(set = 0, binding = 4, std430) readonly buffer SSBO +{ + uint packed_pixels[]; +}; + +layout(set = 0, binding = 0, std140) uniform UBO +{ + uvec2 resolution; + uint word_stride; +}; + +vec3 rgb565_to_rgb888(uint word) +{ + return vec3((uvec3(word) >> uvec3(11, 5, 0)) & uvec3(31, 63, 31)) / vec3(31.0, 63.0, 31.0); +} + +void main() +{ + // We work on two horizonal pixels in parallel since we cannot rely on 16-bit storage. + uvec2 first_input_pixel = gl_GlobalInvocationID.xy; + uvec2 first_output_pixel = first_input_pixel * uvec2(2, 1); + + if (all(lessThan(first_output_pixel, resolution))) + { + uint word = packed_pixels[first_input_pixel.y * word_stride + first_input_pixel.x]; + uint lo_word = word & 0xffffu; + uint hi_word = word >> 16u; + vec3 lo = rgb565_to_rgb888(lo_word); + vec3 hi = rgb565_to_rgb888(hi_word); + + imageStore(uImage, ivec2(first_output_pixel), vec4(lo, 1.0)); + if (first_output_pixel.x + 1u < resolution.x) + imageStore(uImage, ivec2(first_output_pixel) + ivec2(1, 0), vec4(hi, 1.0)); + } +} diff --git a/gfx/drivers/vulkan_shaders/rgb565_to_rgba8888.comp.inc b/gfx/drivers/vulkan_shaders/rgb565_to_rgba8888.comp.inc new file mode 100644 index 0000000000..d5a1f6ae35 --- /dev/null +++ b/gfx/drivers/vulkan_shaders/rgb565_to_rgba8888.comp.inc @@ -0,0 +1,202 @@ +{0x07230203,0x00010000,0x000d000b,0x00000081, +0x00000000,0x00020011,0x00000001,0x0006000b, +0x00000001,0x4c534c47,0x6474732e,0x3035342e, +0x00000000,0x0003000e,0x00000000,0x00000001, +0x0006000f,0x00000005,0x00000004,0x6e69616d, +0x00000000,0x00000025,0x00060010,0x00000004, +0x00000011,0x00000010,0x00000008,0x00000001, +0x00030003,0x00000002,0x000001c2,0x000a0004, +0x475f4c47,0x4c474f4f,0x70635f45,0x74735f70, +0x5f656c79,0x656e696c,0x7269645f,0x69746365, +0x00006576,0x00080004,0x475f4c47,0x4c474f4f, +0x6e695f45,0x64756c63,0x69645f65,0x74636572, +0x00657669,0x00040005,0x00000004,0x6e69616d, +0x00000000,0x00080005,0x0000000c,0x35626772, +0x745f3536,0x67725f6f,0x38383862,0x3b317528, +0x00000000,0x00040005,0x0000000b,0x64726f77, +0x00000000,0x00070005,0x00000023,0x73726966, +0x6e695f74,0x5f747570,0x65786970,0x0000006c, +0x00080005,0x00000025,0x475f6c67,0x61626f6c, +0x766e496c,0x7461636f,0x496e6f69,0x00000044, +0x00070005,0x00000028,0x73726966,0x756f5f74, +0x74757074,0x7869705f,0x00006c65,0x00030005, +0x0000002f,0x004f4255,0x00060006,0x0000002f, +0x00000000,0x6f736572,0x6974756c,0x00006e6f, +0x00060006,0x0000002f,0x00000001,0x64726f77, +0x7274735f,0x00656469,0x00030005,0x00000031, +0x00000000,0x00040005,0x0000003d,0x64726f77, +0x00000000,0x00040005,0x0000003f,0x4f425353, +0x00000000,0x00070006,0x0000003f,0x00000000, +0x6b636170,0x705f6465,0x6c657869,0x00000073, +0x00030005,0x00000041,0x00000000,0x00040005, +0x0000004e,0x775f6f6c,0x0064726f,0x00040005, +0x00000052,0x775f6968,0x0064726f,0x00030005, +0x00000057,0x00006f6c,0x00040005,0x00000058, +0x61726170,0x0000006d,0x00030005,0x0000005b, +0x00006968,0x00040005,0x0000005c,0x61726170, +0x0000006d,0x00040005,0x00000061,0x616d4975, +0x00006567,0x00040047,0x00000025,0x0000000b, +0x0000001c,0x00050048,0x0000002f,0x00000000, +0x00000023,0x00000000,0x00050048,0x0000002f, +0x00000001,0x00000023,0x00000008,0x00030047, +0x0000002f,0x00000002,0x00040047,0x00000031, +0x00000022,0x00000000,0x00040047,0x00000031, +0x00000021,0x00000000,0x00040047,0x0000003e, +0x00000006,0x00000004,0x00040048,0x0000003f, +0x00000000,0x00000018,0x00050048,0x0000003f, +0x00000000,0x00000023,0x00000000,0x00030047, +0x0000003f,0x00000003,0x00040047,0x00000041, +0x00000022,0x00000000,0x00040047,0x00000041, +0x00000021,0x00000004,0x00040047,0x00000061, +0x00000022,0x00000000,0x00040047,0x00000061, +0x00000021,0x00000003,0x00030047,0x00000061, +0x00000019,0x00040047,0x00000080,0x0000000b, +0x00000019,0x00020013,0x00000002,0x00030021, +0x00000003,0x00000002,0x00040015,0x00000006, +0x00000020,0x00000000,0x00040020,0x00000007, +0x00000007,0x00000006,0x00030016,0x00000008, +0x00000020,0x00040017,0x00000009,0x00000008, +0x00000003,0x00040021,0x0000000a,0x00000009, +0x00000007,0x00040017,0x0000000f,0x00000006, +0x00000003,0x0004002b,0x00000006,0x00000011, +0x0000000b,0x0004002b,0x00000006,0x00000012, +0x00000005,0x0004002b,0x00000006,0x00000013, +0x00000000,0x0006002c,0x0000000f,0x00000014, +0x00000011,0x00000012,0x00000013,0x0004002b, +0x00000006,0x00000016,0x0000001f,0x0004002b, +0x00000006,0x00000017,0x0000003f,0x0006002c, +0x0000000f,0x00000018,0x00000016,0x00000017, +0x00000016,0x0004002b,0x00000008,0x0000001b, +0x41f80000,0x0004002b,0x00000008,0x0000001c, +0x427c0000,0x0006002c,0x00000009,0x0000001d, +0x0000001b,0x0000001c,0x0000001b,0x00040017, +0x00000021,0x00000006,0x00000002,0x00040020, +0x00000022,0x00000007,0x00000021,0x00040020, +0x00000024,0x00000001,0x0000000f,0x0004003b, +0x00000024,0x00000025,0x00000001,0x0004002b, +0x00000006,0x0000002a,0x00000002,0x0004002b, +0x00000006,0x0000002b,0x00000001,0x0005002c, +0x00000021,0x0000002c,0x0000002a,0x0000002b, +0x0004001e,0x0000002f,0x00000021,0x00000006, +0x00040020,0x00000030,0x00000002,0x0000002f, +0x0004003b,0x00000030,0x00000031,0x00000002, +0x00040015,0x00000032,0x00000020,0x00000001, +0x0004002b,0x00000032,0x00000033,0x00000000, +0x00040020,0x00000034,0x00000002,0x00000021, +0x00020014,0x00000037,0x00040017,0x00000038, +0x00000037,0x00000002,0x0003001d,0x0000003e, +0x00000006,0x0003001e,0x0000003f,0x0000003e, +0x00040020,0x00000040,0x00000002,0x0000003f, +0x0004003b,0x00000040,0x00000041,0x00000002, +0x0004002b,0x00000032,0x00000044,0x00000001, +0x00040020,0x00000045,0x00000002,0x00000006, +0x0004002b,0x00000006,0x00000050,0x0000ffff, +0x0004002b,0x00000006,0x00000054,0x00000010, +0x00040020,0x00000056,0x00000007,0x00000009, +0x00090019,0x0000005f,0x00000008,0x00000001, +0x00000000,0x00000000,0x00000000,0x00000002, +0x00000004,0x00040020,0x00000060,0x00000000, +0x0000005f,0x0004003b,0x00000060,0x00000061, +0x00000000,0x00040017,0x00000064,0x00000032, +0x00000002,0x0004002b,0x00000008,0x00000067, +0x3f800000,0x00040017,0x00000068,0x00000008, +0x00000004,0x0005002c,0x00000064,0x00000078, +0x00000044,0x00000033,0x0004002b,0x00000006, +0x0000007f,0x00000008,0x0006002c,0x0000000f, +0x00000080,0x00000054,0x0000007f,0x0000002b, +0x00050036,0x00000002,0x00000004,0x00000000, +0x00000003,0x000200f8,0x00000005,0x0004003b, +0x00000022,0x00000023,0x00000007,0x0004003b, +0x00000022,0x00000028,0x00000007,0x0004003b, +0x00000007,0x0000003d,0x00000007,0x0004003b, +0x00000007,0x0000004e,0x00000007,0x0004003b, +0x00000007,0x00000052,0x00000007,0x0004003b, +0x00000056,0x00000057,0x00000007,0x0004003b, +0x00000007,0x00000058,0x00000007,0x0004003b, +0x00000056,0x0000005b,0x00000007,0x0004003b, +0x00000007,0x0000005c,0x00000007,0x0004003d, +0x0000000f,0x00000026,0x00000025,0x0007004f, +0x00000021,0x00000027,0x00000026,0x00000026, +0x00000000,0x00000001,0x0003003e,0x00000023, +0x00000027,0x0004003d,0x00000021,0x00000029, +0x00000023,0x00050084,0x00000021,0x0000002d, +0x00000029,0x0000002c,0x0003003e,0x00000028, +0x0000002d,0x0004003d,0x00000021,0x0000002e, +0x00000028,0x00050041,0x00000034,0x00000035, +0x00000031,0x00000033,0x0004003d,0x00000021, +0x00000036,0x00000035,0x000500b0,0x00000038, +0x00000039,0x0000002e,0x00000036,0x0004009b, +0x00000037,0x0000003a,0x00000039,0x000300f7, +0x0000003c,0x00000000,0x000400fa,0x0000003a, +0x0000003b,0x0000003c,0x000200f8,0x0000003b, +0x00050041,0x00000007,0x00000042,0x00000023, +0x0000002b,0x0004003d,0x00000006,0x00000043, +0x00000042,0x00050041,0x00000045,0x00000046, +0x00000031,0x00000044,0x0004003d,0x00000006, +0x00000047,0x00000046,0x00050084,0x00000006, +0x00000048,0x00000043,0x00000047,0x00050041, +0x00000007,0x00000049,0x00000023,0x00000013, +0x0004003d,0x00000006,0x0000004a,0x00000049, +0x00050080,0x00000006,0x0000004b,0x00000048, +0x0000004a,0x00060041,0x00000045,0x0000004c, +0x00000041,0x00000033,0x0000004b,0x0004003d, +0x00000006,0x0000004d,0x0000004c,0x0003003e, +0x0000003d,0x0000004d,0x0004003d,0x00000006, +0x0000004f,0x0000003d,0x000500c7,0x00000006, +0x00000051,0x0000004f,0x00000050,0x0003003e, +0x0000004e,0x00000051,0x0004003d,0x00000006, +0x00000053,0x0000003d,0x000500c2,0x00000006, +0x00000055,0x00000053,0x00000054,0x0003003e, +0x00000052,0x00000055,0x0004003d,0x00000006, +0x00000059,0x0000004e,0x0003003e,0x00000058, +0x00000059,0x00050039,0x00000009,0x0000005a, +0x0000000c,0x00000058,0x0003003e,0x00000057, +0x0000005a,0x0004003d,0x00000006,0x0000005d, +0x00000052,0x0003003e,0x0000005c,0x0000005d, +0x00050039,0x00000009,0x0000005e,0x0000000c, +0x0000005c,0x0003003e,0x0000005b,0x0000005e, +0x0004003d,0x0000005f,0x00000062,0x00000061, +0x0004003d,0x00000021,0x00000063,0x00000028, +0x0004007c,0x00000064,0x00000065,0x00000063, +0x0004003d,0x00000009,0x00000066,0x00000057, +0x00050051,0x00000008,0x00000069,0x00000066, +0x00000000,0x00050051,0x00000008,0x0000006a, +0x00000066,0x00000001,0x00050051,0x00000008, +0x0000006b,0x00000066,0x00000002,0x00070050, +0x00000068,0x0000006c,0x00000069,0x0000006a, +0x0000006b,0x00000067,0x00040063,0x00000062, +0x00000065,0x0000006c,0x00050041,0x00000007, +0x0000006d,0x00000028,0x00000013,0x0004003d, +0x00000006,0x0000006e,0x0000006d,0x00050080, +0x00000006,0x0000006f,0x0000006e,0x0000002b, +0x00060041,0x00000045,0x00000070,0x00000031, +0x00000033,0x00000013,0x0004003d,0x00000006, +0x00000071,0x00000070,0x000500b0,0x00000037, +0x00000072,0x0000006f,0x00000071,0x000300f7, +0x00000074,0x00000000,0x000400fa,0x00000072, +0x00000073,0x00000074,0x000200f8,0x00000073, +0x0004003d,0x0000005f,0x00000075,0x00000061, +0x0004003d,0x00000021,0x00000076,0x00000028, +0x0004007c,0x00000064,0x00000077,0x00000076, +0x00050080,0x00000064,0x00000079,0x00000077, +0x00000078,0x0004003d,0x00000009,0x0000007a, +0x0000005b,0x00050051,0x00000008,0x0000007b, +0x0000007a,0x00000000,0x00050051,0x00000008, +0x0000007c,0x0000007a,0x00000001,0x00050051, +0x00000008,0x0000007d,0x0000007a,0x00000002, +0x00070050,0x00000068,0x0000007e,0x0000007b, +0x0000007c,0x0000007d,0x00000067,0x00040063, +0x00000075,0x00000079,0x0000007e,0x000200f9, +0x00000074,0x000200f8,0x00000074,0x000200f9, +0x0000003c,0x000200f8,0x0000003c,0x000100fd, +0x00010038,0x00050036,0x00000009,0x0000000c, +0x00000000,0x0000000a,0x00030037,0x00000007, +0x0000000b,0x000200f8,0x0000000d,0x0004003d, +0x00000006,0x0000000e,0x0000000b,0x00060050, +0x0000000f,0x00000010,0x0000000e,0x0000000e, +0x0000000e,0x000500c2,0x0000000f,0x00000015, +0x00000010,0x00000014,0x000500c7,0x0000000f, +0x00000019,0x00000015,0x00000018,0x00040070, +0x00000009,0x0000001a,0x00000019,0x00050088, +0x00000009,0x0000001e,0x0000001a,0x0000001d, +0x000200fe,0x0000001e,0x00010038} diff --git a/gfx/drivers_font/vulkan_raster_font.c b/gfx/drivers_font/vulkan_raster_font.c index de851985ae..9f47e94a70 100644 --- a/gfx/drivers_font/vulkan_raster_font.c +++ b/gfx/drivers_font/vulkan_raster_font.c @@ -312,7 +312,7 @@ static void vulkan_font_flush(vulkan_raster_t *font) dynamic_tex = &font->texture_optimal; staging_tex = &font->texture; - VULKAN_COPY_STAGING_TO_DYNAMIC(font->vk, staging, + vulkan_copy_staging_to_dynamic(font->vk, staging, dynamic_tex, staging_tex); vkEndCommandBuffer(staging);