vulkan: enable selecting a compatible representation of format

When using **integer** images inside shaders, it turns out
that conversion doesn't automatically happen, but we need to
explicitly use the imageviews to get the image exposed as
a suitable representation for the shader.

Finally enables bitexact image representations.
pull/391/head
Lynne 3 months ago
parent 76e8afa8a6
commit 4b128de44a
No known key found for this signature in database
GPG Key ID: A2FEA5F03F034464
  1. 4
      libavfilter/vf_nlmeans_vulkan.c
  2. 14
      libavfilter/vulkan_filter.c
  3. 98
      libavutil/vulkan.c
  4. 2
      libavutil/vulkan.h

@ -854,7 +854,7 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
ws_buf = NULL; ws_buf = NULL;
/* Input frame prep */ /* Input frame prep */
RET(ff_vk_create_imageviews(vkctx, exec, in_views, in)); RET(ff_vk_create_imageviews(vkctx, exec, in_views, in, FF_VK_REP_FLOAT));
ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar, ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar,
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
@ -863,7 +863,7 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
VK_QUEUE_FAMILY_IGNORED); VK_QUEUE_FAMILY_IGNORED);
/* Output frame prep */ /* Output frame prep */
RET(ff_vk_create_imageviews(vkctx, exec, out_views, out)); RET(ff_vk_create_imageviews(vkctx, exec, out_views, out, FF_VK_REP_FLOAT));
ff_vk_frame_barrier(vkctx, exec, out, img_bar, &nb_img_bar, ff_vk_frame_barrier(vkctx, exec, out, img_bar, &nb_img_bar,
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,

@ -257,7 +257,7 @@ int ff_vk_filter_process_simple(FFVulkanContext *vkctx, FFVkExecPool *e,
RET(ff_vk_exec_add_dep_frame(vkctx, exec, out_f, RET(ff_vk_exec_add_dep_frame(vkctx, exec, out_f,
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
RET(ff_vk_create_imageviews(vkctx, exec, out_views, out_f)); RET(ff_vk_create_imageviews(vkctx, exec, out_views, out_f, FF_VK_REP_FLOAT));
ff_vk_shader_update_img_array(vkctx, exec, shd, out_f, out_views, 0, !!in_f, ff_vk_shader_update_img_array(vkctx, exec, shd, out_f, out_views, 0, !!in_f,
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
VK_NULL_HANDLE); VK_NULL_HANDLE);
@ -265,7 +265,7 @@ int ff_vk_filter_process_simple(FFVulkanContext *vkctx, FFVkExecPool *e,
RET(ff_vk_exec_add_dep_frame(vkctx, exec, in_f, RET(ff_vk_exec_add_dep_frame(vkctx, exec, in_f,
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
RET(ff_vk_create_imageviews(vkctx, exec, in_views, in_f)); RET(ff_vk_create_imageviews(vkctx, exec, in_views, in_f, FF_VK_REP_FLOAT));
ff_vk_shader_update_img_array(vkctx, exec, shd, in_f, in_views, 0, 0, ff_vk_shader_update_img_array(vkctx, exec, shd, in_f, in_views, 0, 0,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
sampler); sampler);
@ -336,9 +336,9 @@ int ff_vk_filter_process_2pass(FFVulkanContext *vkctx, FFVkExecPool *e,
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
RET(ff_vk_create_imageviews(vkctx, exec, in_views, in)); RET(ff_vk_create_imageviews(vkctx, exec, in_views, in, FF_VK_REP_FLOAT));
RET(ff_vk_create_imageviews(vkctx, exec, tmp_views, tmp)); RET(ff_vk_create_imageviews(vkctx, exec, tmp_views, tmp, FF_VK_REP_FLOAT));
RET(ff_vk_create_imageviews(vkctx, exec, out_views, out)); RET(ff_vk_create_imageviews(vkctx, exec, out_views, out, FF_VK_REP_FLOAT));
ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar, ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar,
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
@ -418,12 +418,12 @@ int ff_vk_filter_process_Nin(FFVulkanContext *vkctx, FFVkExecPool *e,
RET(ff_vk_exec_add_dep_frame(vkctx, exec, out, RET(ff_vk_exec_add_dep_frame(vkctx, exec, out,
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
RET(ff_vk_create_imageviews(vkctx, exec, out_views, out)); RET(ff_vk_create_imageviews(vkctx, exec, out_views, out, FF_VK_REP_FLOAT));
for (int i = 0; i < nb_in; i++) { for (int i = 0; i < nb_in; i++) {
RET(ff_vk_exec_add_dep_frame(vkctx, exec, in[i], RET(ff_vk_exec_add_dep_frame(vkctx, exec, in[i],
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT)); VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
RET(ff_vk_create_imageviews(vkctx, exec, in_views[i], in[i])); RET(ff_vk_create_imageviews(vkctx, exec, in_views[i], in[i], FF_VK_REP_FLOAT));
} }
/* Update descriptor sets */ /* Update descriptor sets */

@ -1457,9 +1457,96 @@ static void destroy_imageviews(void *opaque, uint8_t *data)
av_free(iv); av_free(iv);
} }
static VkFormat map_fmt_to_rep(VkFormat fmt, enum FFVkShaderRepFormat rep_fmt)
{
#define REPS_FMT(fmt) \
[FF_VK_REP_NATIVE] = fmt ## _UINT, \
[FF_VK_REP_FLOAT] = fmt ## _UNORM, \
[FF_VK_REP_INT] = fmt ## _SINT, \
[FF_VK_REP_UINT] = fmt ## _UINT,
#define REPS_FMT_PACK(fmt, num) \
[FF_VK_REP_NATIVE] = fmt ## _UINT_PACK ## num, \
[FF_VK_REP_FLOAT] = fmt ## _UNORM_PACK ## num, \
[FF_VK_REP_INT] = fmt ## _SINT_PACK ## num, \
[FF_VK_REP_UINT] = fmt ## _UINT_PACK ## num,
const VkFormat fmts_map[][4] = {
{ REPS_FMT_PACK(VK_FORMAT_A2B10G10R10, 32) },
{ REPS_FMT_PACK(VK_FORMAT_A2R10G10B10, 32) },
{
VK_FORMAT_B5G6R5_UNORM_PACK16,
VK_FORMAT_B5G6R5_UNORM_PACK16,
VK_FORMAT_UNDEFINED,
VK_FORMAT_UNDEFINED,
},
{
VK_FORMAT_R5G6B5_UNORM_PACK16,
VK_FORMAT_R5G6B5_UNORM_PACK16,
VK_FORMAT_UNDEFINED,
VK_FORMAT_UNDEFINED,
},
{ REPS_FMT(VK_FORMAT_B8G8R8) },
{ REPS_FMT(VK_FORMAT_B8G8R8A8) },
{ REPS_FMT(VK_FORMAT_R8) },
{ REPS_FMT(VK_FORMAT_R8G8) },
{ REPS_FMT(VK_FORMAT_R8G8B8) },
{ REPS_FMT(VK_FORMAT_R8G8B8A8) },
{ REPS_FMT(VK_FORMAT_R16) },
{ REPS_FMT(VK_FORMAT_R16G16) },
{ REPS_FMT(VK_FORMAT_R16G16B16) },
{ REPS_FMT(VK_FORMAT_R16G16B16A16) },
{
VK_FORMAT_R32_SFLOAT,
VK_FORMAT_R32_SFLOAT,
VK_FORMAT_UNDEFINED,
VK_FORMAT_UNDEFINED,
},
{
VK_FORMAT_R32G32B32_SFLOAT,
VK_FORMAT_R32G32B32_SFLOAT,
VK_FORMAT_UNDEFINED,
VK_FORMAT_UNDEFINED,
},
{
VK_FORMAT_R32G32B32A32_SFLOAT,
VK_FORMAT_R32G32B32A32_SFLOAT,
VK_FORMAT_UNDEFINED,
VK_FORMAT_UNDEFINED,
},
{
VK_FORMAT_R32G32B32_UINT,
VK_FORMAT_UNDEFINED,
VK_FORMAT_R32G32B32_SINT,
VK_FORMAT_R32G32B32_UINT,
},
{
VK_FORMAT_R32G32B32A32_UINT,
VK_FORMAT_UNDEFINED,
VK_FORMAT_R32G32B32A32_SINT,
VK_FORMAT_R32G32B32A32_UINT,
},
};
#undef REPS_FMT_PACK
#undef REPS_FMT
if (fmt == VK_FORMAT_UNDEFINED)
return VK_FORMAT_UNDEFINED;
for (int i = 0; i < FF_ARRAY_ELEMS(fmts_map); i++) {
if (fmts_map[i][FF_VK_REP_NATIVE] == fmt ||
fmts_map[i][FF_VK_REP_FLOAT] == fmt ||
fmts_map[i][FF_VK_REP_INT] == fmt ||
fmts_map[i][FF_VK_REP_UINT] == fmt)
return fmts_map[i][rep_fmt];
}
return VK_FORMAT_UNDEFINED;
}
int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e, int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e,
VkImageView views[AV_NUM_DATA_POINTERS], VkImageView views[AV_NUM_DATA_POINTERS],
AVFrame *f) AVFrame *f, enum FFVkShaderRepFormat rep_fmt)
{ {
int err; int err;
VkResult ret; VkResult ret;
@ -1488,7 +1575,7 @@ int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e,
.pNext = NULL, .pNext = NULL,
.image = vkf->img[FFMIN(i, nb_images - 1)], .image = vkf->img[FFMIN(i, nb_images - 1)],
.viewType = VK_IMAGE_VIEW_TYPE_2D, .viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = rep_fmts[i], .format = map_fmt_to_rep(rep_fmts[i], rep_fmt),
.components = ff_comp_identity_map, .components = ff_comp_identity_map,
.subresourceRange = { .subresourceRange = {
.aspectMask = plane_aspect[(nb_planes != nb_images) + .aspectMask = plane_aspect[(nb_planes != nb_images) +
@ -1497,6 +1584,13 @@ int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e,
.layerCount = 1, .layerCount = 1,
}, },
}; };
if (view_create_info.format == VK_FORMAT_UNDEFINED) {
av_log(s, AV_LOG_ERROR, "Unable to find a compatible representation "
"of format %i and mode %i\n",
rep_fmts[i], rep_fmt);
err = AVERROR(EINVAL);
goto fail;
}
ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info, ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
s->hwctx->alloc, &iv->views[i]); s->hwctx->alloc, &iv->views[i]);

@ -447,7 +447,7 @@ void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e);
*/ */
int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e, int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e,
VkImageView views[AV_NUM_DATA_POINTERS], VkImageView views[AV_NUM_DATA_POINTERS],
AVFrame *f); AVFrame *f, enum FFVkShaderRepFormat rep_fmt);
void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e, void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e,
AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar, AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,

Loading…
Cancel
Save