1 /* Smoke test for the C API. */
2 
3 #ifdef _MSC_VER
4 #define _CRT_SECURE_NO_WARNINGS
5 #endif
6 
7 #include <spirv_cross_c.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 
11 #define SPVC_CHECKED_CALL(x) do { \
12 	if ((x) != SPVC_SUCCESS) { \
13 		fprintf(stderr, "Failed at line %d.\n", __LINE__); \
14 		exit(1); \
15 	} \
16 } while(0)
17 #define SPVC_CHECKED_CALL_NEGATIVE(x) do { \
18 	g_fail_on_error = SPVC_FALSE; \
19 	if ((x) == SPVC_SUCCESS) { \
20 		fprintf(stderr, "Failed at line %d.\n", __LINE__); \
21 		exit(1); \
22 	} \
23 	g_fail_on_error = SPVC_TRUE; \
24 } while(0)
25 
read_file(const char * path,SpvId ** buffer,size_t * word_count)26 static int read_file(const char *path, SpvId **buffer, size_t *word_count)
27 {
28 	long len;
29 	FILE *file = fopen(path, "rb");
30 
31 	if (!file)
32 		return -1;
33 
34 	fseek(file, 0, SEEK_END);
35 	len = ftell(file);
36 	rewind(file);
37 
38 	*buffer = malloc(len);
39 	if (fread(*buffer, 1, len, file) != (size_t)len)
40 	{
41 		fclose(file);
42 		free(*buffer);
43 		return -1;
44 	}
45 
46 	fclose(file);
47 	*word_count = len / sizeof(SpvId);
48 	return 0;
49 }
50 
51 static spvc_bool g_fail_on_error = SPVC_TRUE;
52 
error_callback(void * userdata,const char * error)53 static void error_callback(void *userdata, const char *error)
54 {
55 	(void)userdata;
56 	if (g_fail_on_error)
57 	{
58 		fprintf(stderr, "Error: %s\n", error);
59 		exit(1);
60 	}
61 	else
62 		printf("Expected error hit: %s.\n", error);
63 }
64 
dump_resource_list(spvc_compiler compiler,spvc_resources resources,spvc_resource_type type,const char * tag)65 static void dump_resource_list(spvc_compiler compiler, spvc_resources resources, spvc_resource_type type, const char *tag)
66 {
67 	const spvc_reflected_resource *list = NULL;
68 	size_t count = 0;
69 	size_t i;
70 	SPVC_CHECKED_CALL(spvc_resources_get_resource_list_for_type(resources, type, &list, &count));
71 	printf("%s\n", tag);
72 	for (i = 0; i < count; i++)
73 	{
74 		printf("ID: %u, BaseTypeID: %u, TypeID: %u, Name: %s\n", list[i].id, list[i].base_type_id, list[i].type_id,
75 		       list[i].name);
76 		printf("  Set: %u, Binding: %u\n",
77 		       spvc_compiler_get_decoration(compiler, list[i].id, SpvDecorationDescriptorSet),
78 		       spvc_compiler_get_decoration(compiler, list[i].id, SpvDecorationBinding));
79 	}
80 }
81 
dump_resources(spvc_compiler compiler,spvc_resources resources)82 static void dump_resources(spvc_compiler compiler, spvc_resources resources)
83 {
84 	dump_resource_list(compiler, resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, "UBO");
85 	dump_resource_list(compiler, resources, SPVC_RESOURCE_TYPE_STORAGE_BUFFER, "SSBO");
86 	dump_resource_list(compiler, resources, SPVC_RESOURCE_TYPE_PUSH_CONSTANT, "Push");
87 	dump_resource_list(compiler, resources, SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS, "Samplers");
88 	dump_resource_list(compiler, resources, SPVC_RESOURCE_TYPE_SEPARATE_IMAGE, "Image");
89 	dump_resource_list(compiler, resources, SPVC_RESOURCE_TYPE_SAMPLED_IMAGE, "Combined image samplers");
90 	dump_resource_list(compiler, resources, SPVC_RESOURCE_TYPE_STAGE_INPUT, "Stage input");
91 	dump_resource_list(compiler, resources, SPVC_RESOURCE_TYPE_STAGE_OUTPUT, "Stage output");
92 	dump_resource_list(compiler, resources, SPVC_RESOURCE_TYPE_STORAGE_IMAGE, "Storage image");
93 	dump_resource_list(compiler, resources, SPVC_RESOURCE_TYPE_SUBPASS_INPUT, "Subpass input");
94 }
95 
compile(spvc_compiler compiler,const char * tag)96 static void compile(spvc_compiler compiler, const char *tag)
97 {
98 	const char *result = NULL;
99 	SPVC_CHECKED_CALL(spvc_compiler_compile(compiler, &result));
100 	printf("\n%s\n=======\n", tag);
101 	printf("%s\n=======\n", result);
102 }
103 
main(int argc,char ** argv)104 int main(int argc, char **argv)
105 {
106 	const char *rev = NULL;
107 
108 	spvc_context context = NULL;
109 	spvc_parsed_ir ir = NULL;
110 	spvc_compiler compiler_glsl = NULL;
111 	spvc_compiler compiler_hlsl = NULL;
112 	spvc_compiler compiler_msl = NULL;
113 	spvc_compiler compiler_cpp = NULL;
114 	spvc_compiler compiler_json = NULL;
115 	spvc_compiler compiler_none = NULL;
116 	spvc_compiler_options options = NULL;
117 	spvc_resources resources = NULL;
118 	SpvId *buffer = NULL;
119 	size_t word_count = 0;
120 
121 	rev = spvc_get_commit_revision_and_timestamp();
122 	if (!rev || *rev == '\0')
123 		return 1;
124 
125 	printf("Revision: %s\n", rev);
126 
127 	if (argc != 5)
128 		return 1;
129 
130 	if (read_file(argv[1], &buffer, &word_count) < 0)
131 		return 1;
132 
133 	unsigned abi_major, abi_minor, abi_patch;
134 	spvc_get_version(&abi_major, &abi_minor, &abi_patch);
135 	if (abi_major != strtoul(argv[2], NULL, 0))
136 	{
137 		fprintf(stderr, "VERSION_MAJOR mismatch!\n");
138 		return 1;
139 	}
140 
141 	if (abi_minor != strtoul(argv[3], NULL, 0))
142 	{
143 		fprintf(stderr, "VERSION_MINOR mismatch!\n");
144 		return 1;
145 	}
146 
147 	if (abi_patch != strtoul(argv[4], NULL, 0))
148 	{
149 		fprintf(stderr, "VERSION_PATCH mismatch!\n");
150 		return 1;
151 	}
152 
153 	SPVC_CHECKED_CALL(spvc_context_create(&context));
154 	spvc_context_set_error_callback(context, error_callback, NULL);
155 	SPVC_CHECKED_CALL(spvc_context_parse_spirv(context, buffer, word_count, &ir));
156 	SPVC_CHECKED_CALL(spvc_context_create_compiler(context, SPVC_BACKEND_GLSL, ir, SPVC_CAPTURE_MODE_COPY, &compiler_glsl));
157 	SPVC_CHECKED_CALL(spvc_context_create_compiler(context, SPVC_BACKEND_HLSL, ir, SPVC_CAPTURE_MODE_COPY, &compiler_hlsl));
158 	SPVC_CHECKED_CALL(spvc_context_create_compiler(context, SPVC_BACKEND_MSL, ir, SPVC_CAPTURE_MODE_COPY, &compiler_msl));
159 	SPVC_CHECKED_CALL(spvc_context_create_compiler(context, SPVC_BACKEND_CPP, ir, SPVC_CAPTURE_MODE_COPY, &compiler_cpp));
160 	SPVC_CHECKED_CALL(spvc_context_create_compiler(context, SPVC_BACKEND_JSON, ir, SPVC_CAPTURE_MODE_COPY, &compiler_json));
161 	SPVC_CHECKED_CALL(spvc_context_create_compiler(context, SPVC_BACKEND_NONE, ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler_none));
162 
163 	SPVC_CHECKED_CALL(spvc_compiler_create_compiler_options(compiler_none, &options));
164 	SPVC_CHECKED_CALL(spvc_compiler_install_compiler_options(compiler_none, options));
165 	SPVC_CHECKED_CALL(spvc_compiler_create_compiler_options(compiler_json, &options));
166 	SPVC_CHECKED_CALL(spvc_compiler_install_compiler_options(compiler_json, options));
167 	SPVC_CHECKED_CALL(spvc_compiler_create_compiler_options(compiler_cpp, &options));
168 	SPVC_CHECKED_CALL(spvc_compiler_install_compiler_options(compiler_cpp, options));
169 	SPVC_CHECKED_CALL(spvc_compiler_create_compiler_options(compiler_msl, &options));
170 	SPVC_CHECKED_CALL(spvc_compiler_install_compiler_options(compiler_msl, options));
171 	SPVC_CHECKED_CALL(spvc_compiler_create_compiler_options(compiler_hlsl, &options));
172 	SPVC_CHECKED_CALL(spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_HLSL_SHADER_MODEL, 50));
173 	SPVC_CHECKED_CALL_NEGATIVE(spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_MSL_PLATFORM, 1));
174 	SPVC_CHECKED_CALL(spvc_compiler_install_compiler_options(compiler_hlsl, options));
175 	SPVC_CHECKED_CALL(spvc_compiler_create_compiler_options(compiler_glsl, &options));
176 	SPVC_CHECKED_CALL(spvc_compiler_install_compiler_options(compiler_glsl, options));
177 
178 	SPVC_CHECKED_CALL(spvc_compiler_create_shader_resources(compiler_none, &resources));
179 	dump_resources(compiler_none, resources);
180 	compile(compiler_glsl, "GLSL");
181 	compile(compiler_hlsl, "HLSL");
182 	compile(compiler_msl, "MSL");
183 	compile(compiler_json, "JSON");
184 	compile(compiler_cpp, "CPP");
185 
186 	spvc_context_destroy(context);
187 	free(buffer);
188 	return 0;
189 }
190