Skip to content

Commit c7af98a

Browse files
Fixed HDR Vulkan bugs (#18658)
1 parent 9804687 commit c7af98a

1 file changed

Lines changed: 88 additions & 56 deletions

File tree

gfx/drivers/vulkan.c

Lines changed: 88 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@
7070
typedef struct VKALIGN(16)
7171
{
7272
math_matrix_4x4 mvp;
73-
struct
73+
struct
7474
{
7575
float width;
7676
float height;
7777
float pad0;
7878
float pad1;
7979
} not_used1;
80-
struct
80+
struct
8181
{
8282
float width;
8383
float height;
@@ -179,7 +179,7 @@ typedef struct vk
179179
struct vk_image *backbuffer;
180180
#ifdef VULKAN_HDR_SWAPCHAIN
181181
VkRenderPass readback_render_pass;
182-
struct vk_image main_buffer;
182+
struct vk_image offscreen_buffer;
183183
struct vk_image readback_image;
184184
#endif /* VULKAN_HDR_SWAPCHAIN */
185185

@@ -199,6 +199,7 @@ typedef struct vk
199199
math_matrix_4x4 mvp, mvp_no_rot, mvp_menu; /* float alignment */
200200
VkViewport vk_vp;
201201
VkRenderPass render_pass;
202+
VkRenderPass sdr_render_pass;
202203
VkRenderPass keep_render_pass;
203204
struct video_viewport vp;
204205
float translate_x;
@@ -2246,11 +2247,21 @@ static void vulkan_init_render_pass(
22462247
vkCreateRenderPass(vk->context->device,
22472248
&rp_info, NULL, &vk->render_pass);
22482249

2250+
attachment.format = vk->context->swapchain_format;
22492251
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
22502252
attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
22512253

22522254
vkCreateRenderPass(vk->context->device,
22532255
&rp_info, NULL, &vk->keep_render_pass);
2256+
2257+
attachment.format = VK_FORMAT_B8G8R8A8_UNORM;
2258+
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
2259+
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
2260+
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
2261+
attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2262+
2263+
vkCreateRenderPass(vk->context->device,
2264+
&rp_info, NULL, &vk->sdr_render_pass);
22542265
}
22552266

22562267

@@ -2596,7 +2607,7 @@ static void vulkan_init_pipelines(vk_t *vk)
25962607
pipe.pViewportState = &vp;
25972608
pipe.pDepthStencilState = &depth_stencil;
25982609
pipe.pDynamicState = &dynamic;
2599-
pipe.renderPass = vk->render_pass;
2610+
pipe.renderPass = vk->sdr_render_pass;
26002611
pipe.layout = vk->pipelines.layout;
26012612

26022613
module_info.codeSize = sizeof(alpha_blend_vert);
@@ -2657,6 +2668,7 @@ if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT)
26572668
/* HDR pipeline. */
26582669
blend_attachment.blendEnable = VK_TRUE;
26592670

2671+
26602672
/* HDR pipeline. */
26612673
module_info.codeSize = sizeof(hdr_frag);
26622674
module_info.pCode = hdr_frag;
@@ -2665,6 +2677,7 @@ if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT)
26652677
vkCreateShaderModule(vk->context->device,
26662678
&module_info, NULL, &shader_stages[1].module);
26672679

2680+
pipe.renderPass = vk->render_pass;
26682681
vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache,
26692682
1, &pipe, NULL, &vk->pipelines.hdr);
26702683

@@ -3012,6 +3025,8 @@ static void vulkan_deinit_framebuffers(vk_t *vk)
30123025
}
30133026

30143027
vkDestroyRenderPass(vk->context->device, vk->render_pass, NULL);
3028+
vkDestroyRenderPass(vk->context->device, vk->keep_render_pass, NULL);
3029+
vkDestroyRenderPass(vk->context->device, vk->sdr_render_pass, NULL);
30153030
}
30163031

30173032
#ifdef VULKAN_HDR_SWAPCHAIN
@@ -3042,7 +3057,7 @@ static void vulkan_set_hdr_max_nits(void* data, float max_nits)
30423057
static void vulkan_set_hdr_paper_white_nits(void* data, float paper_white_nits)
30433058
{
30443059
vk_t *vk = (vk_t*)data;
3045-
3060+
30463061
vk->hdr.ubo_values.paper_white_nits = paper_white_nits;
30473062

30483063
if(vk->filter_chain)
@@ -3125,7 +3140,7 @@ static void vulkan_set_hdr10(vk_t* vk, vulkan_filter_chain_t* filter_chain, bool
31253140
#endif /* VULKAN_HDR_SWAPCHAIN */
31263141

31273142
static bool vulkan_init_default_filter_chain(vk_t *vk)
3128-
{
3143+
{
31293144
struct vulkan_filter_chain_create_info info;
31303145

31313146
if (!vk->context)
@@ -3134,7 +3149,7 @@ static bool vulkan_init_default_filter_chain(vk_t *vk)
31343149
if (vk->filter_chain_default)
31353150
return true;
31363151

3137-
settings_t *settings = config_get_ptr();
3152+
settings_t *settings = config_get_ptr();
31383153

31393154
info.device = vk->context->device;
31403155
info.gpu = vk->context->gpu;
@@ -3152,7 +3167,7 @@ static bool vulkan_init_default_filter_chain(vk_t *vk)
31523167
info.swapchain.num_indices = vk->context->num_swapchain_images;
31533168
#ifdef VULKAN_HDR_SWAPCHAIN
31543169
info.hdr_enabled = settings->bools.video_hdr_enable;
3155-
#endif /* VULKAN_HDR_SWAPCHAIN */
3170+
#endif /* VULKAN_HDR_SWAPCHAIN */
31563171

31573172
vk->filter_chain_default = vulkan_filter_chain_create_default(
31583173
&info,
@@ -3202,11 +3217,11 @@ static bool vulkan_init_default_filter_chain(vk_t *vk)
32023217
vulkan_set_hdr10(vk, vk->filter_chain_default, true);
32033218
vk->flags |= VK_FLAG_SHOULD_RESIZE;
32043219
}
3205-
else if (rt_format == VK_FORMAT_R8G8B8A8_UNORM)
3220+
else if (rt_format == VK_FORMAT_B8G8R8A8_UNORM)
32063221
{
32073222
vulkan_set_hdr_inverse_tonemap(vk, vk->filter_chain_default, true);
32083223
vulkan_set_hdr10(vk, vk->filter_chain_default, true);
3209-
vulkan_filter_chain_set_subpixel_layout(vk->filter_chain_default, 0.0f);
3224+
vulkan_filter_chain_set_scanlines(vk->filter_chain_default, 0.0f);
32103225
settings->bools.video_hdr_scanlines = false;
32113226
vk->flags |= VK_FLAG_SHOULD_RESIZE;
32123227
}
@@ -3216,7 +3231,7 @@ static bool vulkan_init_default_filter_chain(vk_t *vk)
32163231
vulkan_set_hdr10(vk, vk->filter_chain_default, true);
32173232
}
32183233

3219-
}
3234+
}
32203235
#endif /* VULKAN_HDR_SWAPCHAIN */
32213236

32223237
return true;
@@ -3247,7 +3262,7 @@ static bool vulkan_init_filter_chain_preset(vk_t *vk, const char *shader_path)
32473262
info.swapchain.num_indices = vk->context->num_swapchain_images;
32483263
#ifdef VULKAN_HDR_SWAPCHAIN
32493264
info.hdr_enabled = settings->bools.video_hdr_enable;
3250-
#endif /* VULKAN_HDR_SWAPCHAIN */
3265+
#endif /* VULKAN_HDR_SWAPCHAIN */
32513266

32523267
vk->filter_chain = vulkan_filter_chain_create_from_preset(
32533268
&info, shader_path,
@@ -3296,7 +3311,7 @@ static bool vulkan_init_filter_chain_preset(vk_t *vk, const char *shader_path)
32963311
vulkan_set_hdr10(vk, vk->filter_chain, true);
32973312
vk->flags |= VK_FLAG_SHOULD_RESIZE;
32983313
}
3299-
else if (rt_format == VK_FORMAT_R8G8B8A8_UNORM)
3314+
else if (rt_format == VK_FORMAT_B8G8R8A8_UNORM)
33003315
{
33013316
vulkan_set_hdr_inverse_tonemap(vk, vk->filter_chain, true);
33023317
vulkan_set_hdr10(vk, vk->filter_chain, true);
@@ -3477,7 +3492,7 @@ static void vulkan_free(void *data)
34773492
if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT)
34783493
{
34793494
vulkan_destroy_buffer(vk->context->device, &vk->hdr.ubo);
3480-
vulkan_destroy_hdr_buffer(vk->context->device, &vk->main_buffer);
3495+
vulkan_destroy_hdr_buffer(vk->context->device, &vk->offscreen_buffer);
34813496
vulkan_destroy_hdr_buffer(vk->context->device, &vk->readback_image);
34823497
vulkan_deinit_hdr_readback_render_pass(vk);
34833498
video_driver_unset_hdr_support();
@@ -3814,7 +3829,7 @@ static void *vulkan_init(const video_info_t *video,
38143829
vk->hdr.ubo_values.mvp = vk->mvp_no_rot;
38153830
vk->hdr.ubo_values.max_nits = settings->floats.video_hdr_max_nits;
38163831
vk->hdr.ubo_values.paper_white_nits = settings->floats.video_hdr_paper_white_nits;
3817-
3832+
38183833
vk->hdr.ubo_values.expand_gamut = settings->bools.video_hdr_expand_gamut;
38193834

38203835
vk->hdr.ubo_values.inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */
@@ -4582,7 +4597,7 @@ static void vulkan_run_hdr_pipeline(VkPipeline pipeline, VkRenderPass render_pas
45824597
vk->hdr.ubo_values.mvp = vk->mvp_no_rot;
45834598
//vk->hdr.ubo_values.scanlines = false;
45844599
vk->hdr.ubo_values.inverse_tonemap = 1.0f;
4585-
vk->hdr.ubo_values.hdr10 = 1.0f;
4600+
vk->hdr.ubo_values.hdr10 = 1.0f;
45864601

45874602
rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
45884603
rp_info.pNext = NULL;
@@ -4630,7 +4645,7 @@ static void vulkan_run_hdr_pipeline(VkPipeline pipeline, VkRenderPass render_pas
46304645
0,
46314646
ubo->buffer,
46324647
0,
4633-
ubo->size);
4648+
ubo->size);
46344649

46354650
image_info.sampler = vk->samplers.nearest;
46364651
image_info.imageView = source_image->view;
@@ -4703,7 +4718,7 @@ static void vulkan_run_hdr_pipeline(VkPipeline pipeline, VkRenderPass render_pas
47034718
vkCmdEndRenderPass(vk->cmd);
47044719

47054720
vk->hdr.ubo_values.inverse_tonemap = prev_inverse_tonemap;
4706-
vk->hdr.ubo_values.hdr10 = prev_hdr10;
4721+
vk->hdr.ubo_values.hdr10 = prev_hdr10;
47074722
}
47084723

47094724
static bool vulkan_frame(void *data, const void *frame,
@@ -4769,8 +4784,10 @@ static bool vulkan_frame(void *data, const void *frame,
47694784
VkFormat back_buffer_format = (shader_preset && shader_preset->passes)
47704785
? vulkan_filter_chain_get_pass_rt_format(filter_chain, shader_preset->passes - 1)
47714786
: vk->context->swapchain_format;
4772-
bool use_main_buffer = vulkan_is_hdr10_format(back_buffer_format) &&
4773-
(filter_chain && !vulkan_filter_chain_emits_hdr10(filter_chain)); /* this is used when presets use scale_type in their last pass */
4787+
bool use_offscreen_buffer = vulkan_is_hdr10_format(back_buffer_format) &&
4788+
(shader_preset && shader_preset->passes) &&
4789+
(filter_chain && !vulkan_filter_chain_emits_hdr10(filter_chain)) &&
4790+
(vk->offscreen_buffer.image != VK_NULL_HANDLE); /* this is used when presets use scale_type in their last pass */
47744791
#endif /* VULKAN_HDR_SWAPCHAIN */
47754792

47764793
/* Bookkeeping on start of frame. */
@@ -4964,7 +4981,7 @@ static bool vulkan_frame(void *data, const void *frame,
49644981
#ifdef VULKAN_HDR_SWAPCHAIN
49654982
vulkan_filter_chain_set_enable_hdr(
49664983
(vulkan_filter_chain_t*)filter_chain, (vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) ? 1.0f : 0.0f);
4967-
#endif /* VULKAN_HDR_SWAPCHAIN */
4984+
#endif /* VULKAN_HDR_SWAPCHAIN */
49684985

49694986
/* Render offscreen filter chain passes. */
49704987
{
@@ -5064,8 +5081,8 @@ static bool vulkan_frame(void *data, const void *frame,
50645081
#endif
50655082

50665083
#ifdef VULKAN_HDR_SWAPCHAIN
5067-
if (use_main_buffer)
5068-
backbuffer = &vk->main_buffer;
5084+
if (use_offscreen_buffer)
5085+
backbuffer = &vk->offscreen_buffer;
50695086
#endif /* VULKAN_HDR_SWAPCHAIN */
50705087

50715088
/* Render to backbuffer. */
@@ -5097,48 +5114,61 @@ static bool vulkan_frame(void *data, const void *frame,
50975114

50985115
#ifdef VULKAN_HDR_SWAPCHAIN
50995116
bool end_pass = true;
5100-
bool end_main_pass = true;
5117+
bool end_main_pass = true;
51015118

51025119
/* Copy over back buffer to swap chain render targets */
5103-
if ((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) &&
5104-
use_main_buffer)
5105-
{
5106-
if(end_pass)
5107-
{
5108-
vkCmdEndRenderPass(vk->cmd);
5109-
end_pass = false;
5120+
if ((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) &&
5121+
use_offscreen_buffer)
5122+
{
5123+
if(end_pass)
5124+
{
5125+
vkCmdEndRenderPass(vk->cmd);
5126+
end_pass = false;
51105127
}
51115128

51125129
backbuffer = &vk->backbuffers[swapchain_index];
51135130
/* Prepare source buffer for reading */
5114-
VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, vk->main_buffer.image,
5131+
VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, vk->offscreen_buffer.image,
51155132
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
51165133
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
51175134
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
51185135
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
51195136

5120-
vulkan_run_hdr_pipeline(vk->pipelines.hdr, vk->render_pass, &vk->main_buffer, backbuffer, vk, &vk->hdr.ubo);
5121-
5122-
VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, vk->main_buffer.image,
5123-
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
5124-
0, VK_ACCESS_TRANSFER_WRITE_BIT,
5137+
vulkan_run_hdr_pipeline(vk->pipelines.hdr, vk->render_pass, &vk->offscreen_buffer, backbuffer, vk, &vk->hdr.ubo);
5138+
5139+
VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, vk->offscreen_buffer.image,
5140+
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
5141+
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
51255142
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
51265143
VK_PIPELINE_STAGE_TRANSFER_BIT);
51275144

51285145
end_main_pass = false;
51295146
}
51305147

5131-
if ((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) &&
5132-
(vk->flags & VK_FLAG_MENU_ENABLE))
5148+
if ((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) &&
5149+
((vk->flags & VK_FLAG_MENU_ENABLE) || (vk->flags & VK_FLAG_OVERLAY_ENABLE)) &&
5150+
(vk->offscreen_buffer.image != VK_NULL_HANDLE))
51335151
{
51345152
if(end_pass) vkCmdEndRenderPass(vk->cmd);
51355153

5136-
backbuffer = &vk->main_buffer;
5154+
backbuffer = &vk->offscreen_buffer;
5155+
5156+
rp_info.renderPass = vk->sdr_render_pass;
5157+
rp_info.framebuffer = backbuffer->framebuffer;
51375158

5138-
rp_info.framebuffer = backbuffer->framebuffer;
5159+
VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, vk->offscreen_buffer.image,
5160+
use_offscreen_buffer ?
5161+
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED,
5162+
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
5163+
use_offscreen_buffer ?
5164+
VK_ACCESS_TRANSFER_WRITE_BIT : 0,
5165+
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
5166+
use_offscreen_buffer ?
5167+
VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
5168+
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
51395169

51405170
/* Begin render pass and set up viewport */
5141-
vkCmdBeginRenderPass(vk->cmd, &rp_info, VK_SUBPASS_CONTENTS_INLINE);
5171+
vkCmdBeginRenderPass(vk->cmd, &rp_info, VK_SUBPASS_CONTENTS_INLINE);
51425172
}
51435173
#endif /* VULKAN_HDR_SWAPCHAIN */
51445174

@@ -5211,18 +5241,27 @@ static bool vulkan_frame(void *data, const void *frame,
52115241

52125242
#ifdef VULKAN_HDR_SWAPCHAIN
52135243
/* Copy over back buffer to swap chain render targets */
5214-
if ((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) &&
5215-
(vk->flags & VK_FLAG_MENU_ENABLE))
5244+
if ((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) &&
5245+
((vk->flags & VK_FLAG_MENU_ENABLE) || (vk->flags & VK_FLAG_OVERLAY_ENABLE)) &&
5246+
(vk->offscreen_buffer.image != VK_NULL_HANDLE))
52165247
{
52175248
backbuffer = &vk->backbuffers[swapchain_index];
5249+
5250+
VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, backbuffer->image,
5251+
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
5252+
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
5253+
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
5254+
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
5255+
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
5256+
52185257
/* Prepare source buffer for reading */
5219-
VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, vk->main_buffer.image,
5258+
VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, vk->offscreen_buffer.image,
52205259
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
52215260
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
52225261
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
52235262
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
52245263

5225-
vulkan_run_hdr_pipeline(vk->pipelines.hdr, vk->keep_render_pass, &vk->main_buffer, backbuffer, vk, &vk->hdr.ubo);
5264+
vulkan_run_hdr_pipeline(vk->pipelines.hdr, vk->keep_render_pass, &vk->offscreen_buffer, backbuffer, vk, &vk->hdr.ubo);
52265265
}
52275266
#endif /* VULKAN_HDR_SWAPCHAIN */
52285267
}
@@ -5245,13 +5284,6 @@ static bool vulkan_frame(void *data, const void *frame,
52455284
struct vk_image* readback_source = backbuffer;
52465285
if((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE))
52475286
{
5248-
if (vk->flags & VK_FLAG_MENU_ENABLE)
5249-
{
5250-
/* Read directly from sdr main buffer instead of tonemapping */
5251-
readback_source = &vk->main_buffer;
5252-
/* No need to transition layout, it's already read-only optimal */
5253-
}
5254-
else
52555287
{
52565288
/* Prepare backbuffer for reading */
52575289
backbuffer_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -5445,7 +5477,7 @@ static bool vulkan_frame(void *data, const void *frame,
54455477
#ifdef HAVE_THREADS
54465478
slock_unlock(vk->context->queue_lock);
54475479
#endif
5448-
vulkan_destroy_hdr_buffer(vk->context->device, &vk->main_buffer);
5480+
vulkan_destroy_hdr_buffer(vk->context->device, &vk->offscreen_buffer);
54495481
vulkan_destroy_hdr_buffer(vk->context->device, &vk->readback_image);
54505482
}
54515483
else
@@ -5464,8 +5496,8 @@ static bool vulkan_frame(void *data, const void *frame,
54645496
if (vk->context->flags & VK_CTX_FLAG_HDR_ENABLE)
54655497
{
54665498
/* Create intermediary buffer to render filter chain output to */
5467-
vulkan_init_render_target(&vk->main_buffer, video_width, video_height,
5468-
VK_FORMAT_B8G8R8A8_UNORM, vk->render_pass, vk->context);
5499+
vulkan_init_render_target(&vk->offscreen_buffer, video_width, video_height,
5500+
VK_FORMAT_B8G8R8A8_UNORM, vk->sdr_render_pass, vk->context);
54695501
/* Create image for readback target in bgra8 format */
54705502
vulkan_init_render_target(&vk->readback_image, video_width, video_height,
54715503
VK_FORMAT_B8G8R8A8_UNORM, vk->readback_render_pass, vk->context);

0 commit comments

Comments
 (0)