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