[Vulkan] Use compute shaders to upload RGB565. (#14953)

A compatible path that is still fast. No reason to bother checking for
compat here really.
This commit is contained in:
Hans-Kristian Arntzen 2023-02-05 19:23:48 +01:00 committed by GitHub
parent 568ffac8f6
commit a77ada403e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 458 additions and 97 deletions

View File

@ -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,
&region);
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;
}

View File

@ -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, \
&region); \
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.

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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));
}
}

View File

@ -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}

View File

@ -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);