25 #include "../ops_internal.h"
26 #include "../swscale_internal.h"
30 #if HAVE_SPIRV_HEADERS_SPIRV_H || HAVE_SPIRV_UNIFIED1_SPIRV_H
54 if (
s->vkctx.device_ref &&
s->vkctx.device_ref->data != dev_ref->
data) {
57 }
else if (
s->vkctx.device_ref &&
s->vkctx.device_ref->data == dev_ref->
data) {
78 return s ?
s->vkctx.device_ref :
NULL;
81 #define MAX_DITHER_BUFS 4
82 #define MAX_FILT_BUFS 4
83 #define MAX_DATA_BUFS (MAX_DITHER_BUFS + MAX_FILT_BUFS*4)
107 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
108 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT);
110 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
111 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT);
119 0, 0, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
121 0, 1, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
124 VkImageMemoryBarrier2 img_bar[8];
126 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
127 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
128 VK_ACCESS_SHADER_READ_BIT,
129 VK_IMAGE_LAYOUT_GENERAL,
130 VK_QUEUE_FAMILY_IGNORED);
132 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
133 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
134 VK_ACCESS_SHADER_WRITE_BIT,
135 VK_IMAGE_LAYOUT_GENERAL,
136 VK_QUEUE_FAMILY_IGNORED);
137 vk->CmdPipelineBarrier2(ec->buf, &(VkDependencyInfo) {
138 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
139 .pImageMemoryBarriers = img_bar,
140 .imageMemoryBarrierCount = nb_img_bar,
146 VK_SHADER_STAGE_COMPUTE_BIT,
152 vk->CmdDispatch(ec->buf,
153 FFALIGN(
dst->width,
p->shd.lg_size[0])/
p->shd.lg_size[0],
154 FFALIGN(
dst->height,
p->shd.lg_size[1])/
p->shd.lg_size[1],
166 for (
int i = 0;
i <
p->nb_data_bufs;
i++)
181 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
182 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
183 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
189 (uint8_t **)&weights_data, 0);
215 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
216 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
217 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
226 for (
int i = 0;
i <
size;
i++) {
227 for (
int j = 0; j <
size; j++) {
246 for (
int n = 0; n < ops->
num_ops; n++) {
251 &
p->data_bufs[
p->nb_data_bufs]);
258 &
p->data_bufs[
p->nb_data_bufs]);
266 &
p->data_bufs[
p->nb_data_bufs]);
276 for (
int i = 0;
i <
p->nb_data_bufs;
i++)
281 #if HAVE_SPIRV_HEADERS_SPIRV_H || HAVE_SPIRV_UNIFIED1_SPIRV_H
311 typedef struct SPIRVIDs {
345 int linear_deco_off[16];
346 int linear_deco_ops[16];
350 int dither_ptr_elem_id;
358 int out_img_array_id;
373 int push_const_struct_id;
374 int push_const_ptr_id;
375 int push_const_elem_ptr_id;
376 int push_const_var_id;
402 3 +
id->nb_dither_bufs +
id->nb_filter_bufs +
403 (
id->interlaced ? 1 : 0));
407 if (
id->interlaced) {
410 SpvDecorationOffset, 0);
415 SpvBuiltInGlobalInvocationId);
427 for (
int i = 0;
i <
id->nb_dither_bufs;
i++) {
431 id->dither[
i].size*
sizeof(
float));
436 id->dither[
i].binding);
439 for (
int i = 0;
i <
id->nb_filter_bufs;
i++) {
440 struct FilterData *
f = &
id->filt[
i];
444 f->filter_size*
sizeof(
float));
450 f->num_weights*
sizeof(
float));
459 for (
int n = 0; n < ops->
num_ops; n++) {
466 for (
int j = 0; j < 4; j++) {
467 nb_ops += !!
op->lin.m[j][0].num;
468 nb_ops +=
op->lin.m[j][0].num &&
op->lin.m[j][4].num;
469 for (
int i = 1;
i < 4;
i++) {
470 nb_ops += !!
op->lin.m[j][
i].num;
471 nb_ops +=
op->lin.m[j][
i].num &&
472 (
op->lin.m[j][0].num ||
op->lin.m[j][4].num);
476 id->linear_deco_off[
id->nb_linear_ops] =
spi_reserve(spi, nb_ops*4*3);
477 id->linear_deco_ops[
id->nb_linear_ops] = nb_ops;
484 SPICtx *spi, SPIRVIDs *
id)
490 id->u32_type = spi_OpTypeInt(spi, 32, 0);
491 id->i32_type = spi_OpTypeInt(spi, 32, 1);
493 id->f32_type = spi_OpTypeFloat(spi, 32);
497 id->bvec2_type = spi_OpTypeVector(spi,
id->b_type, 2);
498 id->u32vec2_type = spi_OpTypeVector(spi, u32_type, 2);
499 id->i32vec2_type = spi_OpTypeVector(spi,
id->i32_type, 2);
501 id->u32vec3_type = spi_OpTypeVector(spi, u32_type, 3);
503 id->u32vec4_type = spi_OpTypeVector(spi, u32_type, 4);
504 id->f32vec4_type = spi_OpTypeVector(spi, f32_type, 4);
505 id->f32mat4_type = spi_OpTypeMatrix(spi,
id->f32vec4_type, 4);
511 for (
int i = 0;
i < 5;
i++)
515 id->nb_const_ids = 0;
516 for (
int n = 0; n < ops->
num_ops; n++) {
528 id->const_ids[
id->nb_const_ids++] =
tmp;
532 for (
int i = 0;
i < 4;
i++) {
538 id->const_ids[
id->nb_const_ids++] =
542 id->const_ids[
id->nb_const_ids++] =
552 id->const_ids[
id->nb_const_ids++] =
tmp;
558 float q =
op->scale.factor.num/(
float)
op->scale.factor.den;
568 id->const_ids[
id->nb_const_ids++] =
tmp;
573 for (
int i = 0;
i < 4;
i++) {
576 if (!
op->clamp.limit[
i].den) {
585 id->const_ids[
id->nb_const_ids++] =
tmp;
589 for (
int i = 0;
i < 4;
i++) {
590 if (
op->dither.y_offset[
i] < 0)
593 id->const_ids[
id->nb_const_ids++] =
tmp;
599 for (
int i = 0;
i < 4;
i++) {
600 for (
int j = 0; j < 4; j++) {
604 id->const_ids[
id->nb_const_ids++] =
608 id->const_ids[
id->nb_const_ids - 4],
609 id->const_ids[
id->nb_const_ids - 3],
610 id->const_ids[
id->nb_const_ids - 2],
611 id->const_ids[
id->nb_const_ids - 1]);
612 id->const_ids[
id->nb_const_ids++] =
tmp;
616 id->const_ids[
id->nb_const_ids - 5*4 + 4],
617 id->const_ids[
id->nb_const_ids - 5*3 + 4],
618 id->const_ids[
id->nb_const_ids - 5*2 + 4],
619 id->const_ids[
id->nb_const_ids - 5*1 + 4]);
620 id->const_ids[
id->nb_const_ids++] =
tmp;
622 for (
int i = 0;
i < 4;
i++) {
624 id->const_ids[
id->nb_const_ids++] =
629 id->const_ids[
id->nb_const_ids - 4],
630 id->const_ids[
id->nb_const_ids - 3],
631 id->const_ids[
id->nb_const_ids - 2],
632 id->const_ids[
id->nb_const_ids - 1]);
633 id->const_ids[
id->nb_const_ids++] =
tmp;
643 static void define_shader_bindings(
const SwsOpList *ops,
SPICtx *spi, SPIRVIDs *
id,
644 int in_img_count,
int out_img_count)
649 struct DitherData *
dither =
id->dither;
650 for (
int i = 0;
i <
id->nb_dither_bufs;
i++) {
659 SpvStorageClassUniform, 0);
663 id->filt_o_ptr_id = 0;
664 if (
id->nb_filter_bufs)
668 for (
int i = 0;
i <
id->nb_filter_bufs;
i++) {
669 struct FilterData *
f = &
id->filt[
i];
680 SpvStorageClassUniform, 0);
684 for (
int t = 1; t <
f->filter_size; t++)
694 id->f32_type :
id->u32_type,
695 2, 0, 0, 0, 2, SpvImageFormatUnknown);
697 id->u32_cid[out_img_count]);
700 id->in_img_array_id = 0;
706 id->in_img_type = match ?
id->out_img_type :
709 id->f32_type :
id->u32_type,
710 2, 0, 0, 0, 2, SpvImageFormatUnknown);
712 id->u32_cid[in_img_count]);
719 id->out_img_array_id);
727 id->in_img_array_id);
734 SpvStorageClassInput, 0);
737 SpvStorageClassUniformConstant, 0);
740 SpvStorageClassUniformConstant, 0);
742 if (
id->interlaced) {
745 id->push_const_struct_id);
749 SpvStorageClassPushConstant, 0);
753 static int insert_vmat_linear(
const SwsOp *
op,
SPICtx *spi, SPIRVIDs *
id,
754 int data,
int const_off)
756 data = spi_OpMatrixTimesVector(spi,
id->f32vec4_type,
757 id->const_ids[const_off + 4*5],
759 return spi_OpFAdd(spi,
id->f32vec4_type,
760 id->const_ids[const_off + 4*5 + 1 + 4],
data);
763 static int insert_bitexact_linear(
const SwsOp *
op,
SPICtx *spi, SPIRVIDs *
id,
764 int data,
int linear_ops_idx,
int const_off)
767 int type_v =
op->type ==
SWS_PIXEL_F32 ?
id->f32vec4_type :
id->u32vec4_type;
776 spi->
off =
id->linear_deco_off[linear_ops_idx];
777 for (
int i = 0;
i <
id->linear_deco_ops[linear_ops_idx];
i++)
782 for (
int j = 0; j < 4; j++) {
784 if (
op->lin.m[j][0].num)
785 res[j] = spi_OpFMul(spi, type_s,
tmp[0],
786 id->const_ids[const_off + j*5 + 0]);
788 if (
op->lin.m[j][0].num &&
op->lin.m[j][4].num)
789 res[j] = spi_OpFAdd(spi, type_s,
790 id->const_ids[const_off + 4*5 + 1 + j], res[j]);
791 else if (
op->lin.m[j][4].num)
792 res[j] =
id->const_ids[const_off + 4*5 + 1 + j];
794 for (
int i = 1;
i < 4;
i++) {
795 if (!
op->lin.m[j][
i].num)
798 int v = spi_OpFMul(spi, type_s,
tmp[
i],
799 id->const_ids[const_off + j*5 +
i]);
800 if (
op->lin.m[j][0].num ||
op->lin.m[j][4].num)
801 res[j] = spi_OpFAdd(spi, type_s, res[j], v);
808 res[0], res[1], res[2], res[3]);
811 static int read_filtered(
SPICtx *spi, SPIRVIDs *
id,
const SwsOpList *ops,
812 const SwsOp *
op,
const struct FilterData *
f,
813 const int *in_img,
int gid,
int gi2)
819 const int read_vtype = src_float ?
id->f32vec4_type :
id->u32vec4_type;
826 id->u32_cid[1], axis);
827 int o =
spi_OpLoad(spi,
id->i32_type, o_ptr, SpvMemoryAccessMaskNone, 0);
835 if (src_interlaced && is_h) {
836 pos_y = spi_OpShiftLeftLogical(spi,
id->i32_type, pos_y,
id->u32_cid[1]);
837 pos_y = spi_OpIAdd(spi,
id->i32_type, pos_y,
id->field_i32);
841 int acc_s[4] = {
id->f32_0,
id->f32_0,
id->f32_0,
id->f32_0 };
842 int acc_v =
id->f32_0;
845 id->f32_0,
id->f32_0,
846 id->f32_0,
id->f32_0);
848 for (
int t = 0; t <
f->filter_size; t++) {
851 id->u32_cid[0], axis,
852 f->tap_const_base + t);
854 SpvMemoryAccessMaskNone, 0);
857 int c = t ? spi_OpIAdd(spi,
id->i32_type, o,
f->tap_const_base + t) : o;
860 if (src_interlaced && !is_h) {
861 c = spi_OpShiftLeftLogical(spi,
id->i32_type,
c,
id->u32_cid[1]);
862 c = spi_OpIAdd(spi,
id->i32_type,
c,
id->field_i32);
871 SpvImageOperandsMaskNone);
873 px = spi_OpConvertUToF(spi,
id->f32vec4_type,
px);
874 px = spi_OpVectorTimesScalar(spi,
id->f32vec4_type,
px,
w);
875 acc_v = spi_OpFAdd(spi,
id->f32vec4_type, acc_v,
px);
877 for (
int e = 0; e <
op->rw.elems; e++) {
880 SpvImageOperandsMaskNone);
885 px = spi_OpConvertUToF(spi,
id->f32_type,
px);
887 px = spi_OpFMul(spi,
id->f32_type,
w,
px);
888 acc_s[e] = spi_OpFAdd(spi,
id->f32_type, acc_s[e],
px);
896 acc_s[0], acc_s[1], acc_s[2], acc_s[3]);
901 static int rw_op_img_count(
const SwsOp *
op,
const uint8_t *
planes)
912 uint8_t spvbuf[1024*16];
913 SPICtx spi_context = { 0 }, *spi = &spi_context;
914 SPIRVIDs spid_data = { 0 }, *
id = &spid_data;
915 spi_init(spi, spvbuf,
sizeof(spvbuf));
918 p->interlaced =
id->interlaced;
921 (uint32_t []) { 32, 32, 1 }, 0);
926 VK_SHADER_STAGE_COMPUTE_BIT);
930 int out_img_count = rw_op_img_count(op_w, ops->
plane_dst);
934 int in_img_count = op_r ? rw_op_img_count(op_r, ops->
plane_src) : 0;
940 .
type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
941 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
945 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
946 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
964 id->nb_dither_bufs = 0;
965 id->nb_filter_bufs = 0;
966 int nb_data_bufs = 0;
967 for (
int n = 0; n < ops->
num_ops; n++) {
974 struct DitherData *d = &
id->dither[
id->nb_dither_bufs++];
975 d->size = 1 <<
op->dither.size_log2;
980 d->binding = nb_data_bufs;
986 struct FilterData *
f = &
id->filt[
id->nb_filter_bufs++];
987 f->filter =
op->rw.filter.op;
996 f->binding = nb_data_bufs;
1002 id->in_vars[3 + nb_data_bufs] = var_id;
1004 .
type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1005 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
1012 if (
id->interlaced) {
1015 id->in_vars[3 +
id->nb_dither_bufs +
id->nb_filter_bufs] =
1016 id->push_const_var_id;
1020 define_shader_header(sws, shd, ops, spi,
id);
1021 define_shader_consts(sws, ops, spi,
id);
1022 define_shader_bindings(ops, spi,
id, in_img_count, out_img_count);
1029 int in_img[4] = { 0 };
1030 for (
int i = 0;
i < in_img_count;
i++) {
1033 id->in_vars[1],
id->u32_cid[
i]);
1035 SpvMemoryAccessMaskNone, 0);
1039 int out_img[4] = { 0 };
1040 for (
int i = 0;
i < out_img_count;
i++) {
1042 id->in_vars[2],
id->u32_cid[
i]);
1044 SpvMemoryAccessMaskNone, 0);
1049 SpvMemoryAccessMaskNone, 0);
1053 int gi2 = spi_OpBitcast(spi,
id->i32vec2_type, gid);
1058 int dst_gid = gid, dst_gi2 = gi2;
1060 if (
id->interlaced) {
1062 id->push_const_var_id,
1064 int field_u32 =
spi_OpLoad(spi,
id->u32_type, field_u32_ptr,
1065 SpvMemoryAccessMaskNone, 0);
1066 id->field_i32 = spi_OpBitcast(spi,
id->i32_type, field_u32);
1068 int img_y_i32 = spi_OpShiftLeftLogical(spi,
id->i32_type,
1071 img_y_i32 = spi_OpIAdd(spi,
id->i32_type, img_y_i32,
id->field_i32);
1076 int mapped_gid = spi_OpBitcast(spi,
id->u32vec2_type, mapped_gi2);
1079 src_gid = mapped_gid;
1081 dst_gid = mapped_gid;
1082 dst_gi2 = mapped_gi2;
1087 int img1_s = spi_OpImageQuerySize(spi,
id->i32vec2_type, out_img[0]);
1088 int scmp = spi_OpSGreaterThanEqual(spi,
id->bvec2_type, dst_gi2, img1_s);
1089 scmp = spi_OpAny(spi,
id->b_type, scmp);
1104 id->f32_p,
id->f32_p,
1105 id->f32_p,
id->f32_p);
1108 id->u32_p,
id->u32_p,
1109 id->u32_p,
id->u32_p);
1112 int nb_const_ids = 0;
1113 int nb_dither_bufs = 0;
1114 int nb_linear_ops = 0;
1115 int nb_filter_used = 0;
1118 for (
int n = 0; n < ops->
num_ops; n++) {
1121 op->convert.to :
op->type;
1123 id->f32vec4_type :
id->u32vec4_type;
1125 id->f32_type :
id->u32_type;
1127 id->f32_p :
id->u32_p;
1133 }
else if (
op->rw.filter.op) {
1135 data = read_filtered(spi,
id, ops,
op,
1136 &
id->filt[nb_filter_used++],
1140 src_gid, SpvImageOperandsMaskNone);
1143 for (
int i = 0;
i <
op->rw.elems;
i++) {
1146 SpvImageOperandsMaskNone);
1156 if (
op->rw.frac ||
op->rw.filter.op) {
1160 SpvImageOperandsMaskNone);
1162 for (
int i = 0;
i <
op->rw.elems;
i++) {
1166 SpvImageOperandsMaskNone);
1171 for (
int i = 0;
i < 4;
i++) {
1175 id->const_ids[nb_const_ids++],
1188 data = spi_OpIMul(spi, type_v,
data,
id->const_ids[nb_const_ids++]);
1190 data = spi_OpConvertFToU(spi, type_v,
data);
1192 data = spi_OpConvertUToF(spi, type_v,
data);
1195 data = spi_OpShiftLeftLogical(spi, type_v,
data,
1196 id->const_ids[nb_const_ids++]);
1199 data = spi_OpShiftRightLogical(spi, type_v,
data,
1200 id->const_ids[nb_const_ids++]);
1204 data = spi_OpFMul(spi, type_v,
data,
1205 id->const_ids[nb_const_ids++]);
1207 data = spi_OpIMul(spi, type_v,
data,
1208 id->const_ids[nb_const_ids++]);
1213 op->op ==
SWS_OP_MIN ? GLSLstd450FMin : GLSLstd450FMax :
1214 op->op ==
SWS_OP_MIN ? GLSLstd450UMin : GLSLstd450UMax;
1215 for (
int i = 0;
i < 4;
i++) {
1216 if (!
op->clamp.limit[
i].den)
1220 tmp,
id->const_ids[nb_const_ids++]);
1226 int did = nb_dither_bufs++;
1229 x_id = spi_OpBitwiseAnd(spi,
id->u32_type, x_id,
1230 id->dither[did].mask_id);
1231 for (
int i = 0;
i < 4;
i++) {
1232 if (
op->dither.y_offset[
i] < 0)
1235 int y_id = spi_OpIAdd(spi,
id->u32_type, y_pos,
1236 id->const_ids[nb_const_ids++]);
1237 y_id = spi_OpBitwiseAnd(spi,
id->u32_type, y_id,
1238 id->dither[did].mask_id);
1241 id->dither[did].id,
id->u32_cid[0],
1244 SpvMemoryAccessMaskNone, 0);
1247 tmp = spi_OpFAdd(spi, type_s,
tmp,
val);
1254 data = insert_bitexact_linear(
op, spi,
id,
data, nb_linear_ops, nb_const_ids);
1256 data = insert_vmat_linear(
op, spi,
id,
data, nb_const_ids);
1258 nb_const_ids += 5*5 + 1;
1309 #if HAVE_SPIRV_HEADERS_SPIRV_H || HAVE_SPIRV_UNIFIED1_SPIRV_H
1310 err = add_ops_spirv(sws,
p,
s, ops, &
p->shd);
1319 for (
int i = 0;
i <
p->nb_data_bufs;
i++)
1321 1,
i, 0, &
p->data_bufs[
i],
1322 0, VK_WHOLE_SIZE, VK_FORMAT_UNDEFINED);
1338 #if HAVE_SPIRV_HEADERS_SPIRV_H || HAVE_SPIRV_UNIFIED1_SPIRV_H
1348 .compile = compile_spirv,