• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Testbench for MSL constexpr samplers.
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 
64 	SPVC_CHECKED_CALL(spvc_context_create(&ctx));
65 	SPVC_CHECKED_CALL(spvc_context_parse_spirv(ctx, buffer.data(), buffer.size(), &parsed_ir));
66 	SPVC_CHECKED_CALL(spvc_context_create_compiler(ctx, SPVC_BACKEND_MSL, parsed_ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler));
67 
68 	spvc_msl_resource_binding binding;
69 	spvc_msl_resource_binding_init(&binding);
70 	binding.desc_set = 1;
71 	binding.binding = 2;
72 	binding.stage = SpvExecutionModelFragment;
73 	binding.msl_texture = 0;
74 	binding.msl_sampler = 0;
75 	SPVC_CHECKED_CALL(spvc_compiler_msl_add_resource_binding(compiler, &binding));
76 
77 	binding.binding = 3;
78 	binding.msl_texture = 1;
79 	binding.msl_sampler = 1000; // Will be remapped anyways, sanity check.
80 	SPVC_CHECKED_CALL(spvc_compiler_msl_add_resource_binding(compiler, &binding));
81 
82 	binding.desc_set = 2;
83 	binding.binding = 2;
84 	binding.msl_texture = 2;
85 	SPVC_CHECKED_CALL(spvc_compiler_msl_add_resource_binding(compiler, &binding));
86 
87 	binding.binding = 3;
88 	binding.msl_texture = 3;
89 	SPVC_CHECKED_CALL(spvc_compiler_msl_add_resource_binding(compiler, &binding));
90 
91 	spvc_msl_constexpr_sampler samp;
92 	spvc_msl_constexpr_sampler_init(&samp);
93 	samp.s_address = SPVC_MSL_SAMPLER_ADDRESS_REPEAT;
94 	samp.t_address = SPVC_MSL_SAMPLER_ADDRESS_REPEAT;
95 	samp.r_address = SPVC_MSL_SAMPLER_ADDRESS_REPEAT;
96 	SPVC_CHECKED_CALL(spvc_compiler_msl_remap_constexpr_sampler_by_binding(compiler, 1, 3, &samp));
97 
98 	samp.s_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
99 	samp.t_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
100 	samp.r_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
101 	SPVC_CHECKED_CALL(spvc_compiler_msl_remap_constexpr_sampler_by_binding(compiler, 2, 4, &samp));
102 
103 	samp.compare_enable = SPVC_TRUE;
104 	samp.compare_func = SPVC_MSL_SAMPLER_COMPARE_FUNC_LESS;
105 	samp.s_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
106 	samp.t_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
107 	samp.r_address = SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
108 	SPVC_CHECKED_CALL(spvc_compiler_msl_remap_constexpr_sampler_by_binding(compiler, 2, 5, &samp));
109 
110 	const char *str;
111 	SPVC_CHECKED_CALL(spvc_compiler_compile(compiler, &str));
112 
113 	// Should not be marked as used.
114 	if (spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 2, 4))
115 		return EXIT_FAILURE;
116 
117 	// Should not be marked as used.
118 	if (spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 2, 5))
119 		return EXIT_FAILURE;
120 
121 	// Should be marked, as a sanity check.
122 	if (!spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 1, 2))
123 		return EXIT_FAILURE;
124 	if (!spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 1, 3))
125 		return EXIT_FAILURE;
126 	if (!spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 2, 2))
127 		return EXIT_FAILURE;
128 	if (!spvc_compiler_msl_is_resource_used(compiler, SpvExecutionModelFragment, 2, 3))
129 		return EXIT_FAILURE;
130 
131 	fprintf(stderr, "Output:\n%s\n", str);
132 }
133 
134