1 // Testbench for MSL constexpr samplers, with Y'CbCr conversion.
2 // It does not validate output, but it's useful for ad-hoc testing.
3
4 #ifdef _MSC_VER
5 #define _CRT_SECURE_NO_WARNINGS
6 #endif
7
8 #include <spirv_cross_c.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <vector>
12
13 #define SPVC_CHECKED_CALL(x) do { \
14 if ((x) != SPVC_SUCCESS) { \
15 fprintf(stderr, "Failed at line %d.\n", __LINE__); \
16 exit(1); \
17 } \
18 } while(0)
19 #define SPVC_CHECKED_CALL_NEGATIVE(x) do { \
20 g_fail_on_error = SPVC_FALSE; \
21 if ((x) == SPVC_SUCCESS) { \
22 fprintf(stderr, "Failed at line %d.\n", __LINE__); \
23 exit(1); \
24 } \
25 g_fail_on_error = SPVC_TRUE; \
26 } while(0)
27
read_file(const char * path)28 static std::vector<SpvId> read_file(const char *path)
29 {
30 long len;
31 FILE *file = fopen(path, "rb");
32
33 if (!file)
34 return {};
35
36 fseek(file, 0, SEEK_END);
37 len = ftell(file);
38 rewind(file);
39
40 std::vector<SpvId> buffer(len / sizeof(SpvId));
41 if (fread(buffer.data(), 1, len, file) != (size_t)len)
42 {
43 fclose(file);
44 return {};
45 }
46
47 fclose(file);
48 return buffer;
49 }
50
main(int argc,char ** argv)51 int main(int argc, char **argv)
52 {
53 if (argc != 2)
54 return EXIT_FAILURE;
55
56 auto buffer = read_file(argv[1]);
57 if (buffer.empty())
58 return EXIT_FAILURE;
59
60 spvc_context ctx;
61 spvc_parsed_ir parsed_ir;
62 spvc_compiler compiler;
63 spvc_compiler_options options;
64
65 SPVC_CHECKED_CALL(spvc_context_create(&ctx));
66 SPVC_CHECKED_CALL(spvc_context_parse_spirv(ctx, buffer.data(), buffer.size(), &parsed_ir));
67 SPVC_CHECKED_CALL(spvc_context_create_compiler(ctx, SPVC_BACKEND_MSL, parsed_ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler));
68 SPVC_CHECKED_CALL(spvc_compiler_create_compiler_options(compiler, &options));
69 SPVC_CHECKED_CALL(spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_MSL_VERSION, SPVC_MAKE_MSL_VERSION(2, 0, 0)));
70 SPVC_CHECKED_CALL(spvc_compiler_install_compiler_options(compiler, options));
71
72 spvc_msl_resource_binding binding;
73 spvc_msl_resource_binding_init(&binding);
74 binding.desc_set = 1;
75 binding.binding = 2;
76 binding.stage = SpvExecutionModelFragment;
77 binding.msl_texture = 0;
78 binding.msl_sampler = 0;
79 SPVC_CHECKED_CALL(spvc_compiler_msl_add_resource_binding(compiler, &binding));
80
81 spvc_msl_constexpr_sampler samp;
82 spvc_msl_sampler_ycbcr_conversion conv;
83 spvc_msl_constexpr_sampler_init(&samp);
84 spvc_msl_sampler_ycbcr_conversion_init(&conv);
85 conv.planes = 3;
86 conv.resolution = SPVC_MSL_FORMAT_RESOLUTION_422;
87 conv.chroma_filter = SPVC_MSL_SAMPLER_FILTER_LINEAR;
88 conv.x_chroma_offset = SPVC_MSL_CHROMA_LOCATION_MIDPOINT;
89 conv.ycbcr_model = SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_2020;
90 conv.ycbcr_range = SPVC_MSL_SAMPLER_YCBCR_RANGE_ITU_NARROW;
91 conv.bpc = 8;
92 SPVC_CHECKED_CALL(spvc_compiler_msl_remap_constexpr_sampler_by_binding_ycbcr(compiler, 1, 2, &samp, &conv));
93
94 const char *str;
95 SPVC_CHECKED_CALL(spvc_compiler_compile(compiler, &str));
96
97 // Should be marked, as a sanity check.
98 if (!spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 1, 2))
99 return EXIT_FAILURE;
100
101 fprintf(stderr, "Output:\n%s\n", str);
102 }
103
104