This is page 1 of 9. Use http://codebase.md/mehmetoguzderin/shaderc-vkrunner-mcp?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .devcontainer
│ ├── devcontainer.json
│ ├── docker-compose.yml
│ └── Dockerfile
├── .gitattributes
├── .github
│ └── workflows
│ └── build-push-image.yml
├── .gitignore
├── .vscode
│ └── mcp.json
├── Cargo.lock
├── Cargo.toml
├── Dockerfile
├── LICENSE
├── README.adoc
├── shaderc-vkrunner-mcp.jpg
├── src
│ └── main.rs
└── vkrunner
├── .editorconfig
├── .gitignore
├── .gitlab-ci.yml
├── build.rs
├── Cargo.toml
├── COPYING
├── examples
│ ├── compute-shader.shader_test
│ ├── cooperative-matrix.shader_test
│ ├── depth-buffer.shader_test
│ ├── desc_set_and_binding.shader_test
│ ├── entrypoint.shader_test
│ ├── float-framebuffer.shader_test
│ ├── frexp.shader_test
│ ├── geometry.shader_test
│ ├── indices.shader_test
│ ├── layouts.shader_test
│ ├── properties.shader_test
│ ├── push-constants.shader_test
│ ├── require-subgroup-size.shader_test
│ ├── row-major.shader_test
│ ├── spirv.shader_test
│ ├── ssbo.shader_test
│ ├── tolerance.shader_test
│ ├── tricolore.shader_test
│ ├── ubo.shader_test
│ ├── vertex-data-piglit.shader_test
│ └── vertex-data.shader_test
├── include
│ ├── vk_video
│ │ ├── vulkan_video_codec_av1std_decode.h
│ │ ├── vulkan_video_codec_av1std_encode.h
│ │ ├── vulkan_video_codec_av1std.h
│ │ ├── vulkan_video_codec_h264std_decode.h
│ │ ├── vulkan_video_codec_h264std_encode.h
│ │ ├── vulkan_video_codec_h264std.h
│ │ ├── vulkan_video_codec_h265std_decode.h
│ │ ├── vulkan_video_codec_h265std_encode.h
│ │ ├── vulkan_video_codec_h265std.h
│ │ └── vulkan_video_codecs_common.h
│ └── vulkan
│ ├── vk_platform.h
│ ├── vulkan_core.h
│ └── vulkan.h
├── precompile-script.py
├── README.md
├── scripts
│ └── update-vulkan.sh
├── src
│ └── main.rs
├── test-build.sh
└── vkrunner
├── allocate_store.rs
├── buffer.rs
├── compiler
│ └── fake_process.rs
├── compiler.rs
├── config.rs
├── context.rs
├── enum_table.rs
├── env_var_test.rs
├── executor.rs
├── fake_vulkan.rs
├── features.rs
├── flush_memory.rs
├── format_table.rs
├── format.rs
├── half_float.rs
├── hex.rs
├── inspect.rs
├── lib.rs
├── logger.rs
├── make-enums.py
├── make-features.py
├── make-formats.py
├── make-pipeline-key-data.py
├── make-vulkan-funcs-data.py
├── parse_num.rs
├── pipeline_key_data.rs
├── pipeline_key.rs
├── pipeline_set.rs
├── requirements.rs
├── result.rs
├── script.rs
├── shader_stage.rs
├── slot.rs
├── small_float.rs
├── source.rs
├── stream.rs
├── temp_file.rs
├── tester.rs
├── tolerance.rs
├── util.rs
├── vbo.rs
├── vk.rs
├── vulkan_funcs_data.rs
├── vulkan_funcs.rs
├── window_format.rs
└── window.rs
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | /target
2 |
```
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
```
1 | * text=auto eol=lf
2 |
```
--------------------------------------------------------------------------------
/vkrunner/.gitignore:
--------------------------------------------------------------------------------
```
1 | /Cargo.lock
2 | /target
3 | /tmp-build
4 |
```
--------------------------------------------------------------------------------
/vkrunner/.editorconfig:
--------------------------------------------------------------------------------
```
1 | # To use this config on you editor, follow the instructions at:
2 | # http://editorconfig.org
3 |
4 | root = true
5 |
6 | [*]
7 | charset = utf-8
8 | insert_final_newline = true
9 | tab_width = 8
10 |
11 | [*.{c,h,cpp,hpp,cc,hh}]
12 | indent_style = space
13 | indent_size = 8
14 |
15 | [{Makefile*,*.mk}]
16 | indent_style = tab
17 |
18 | [{*.py,SCons*}]
19 | indent_style = space
20 | indent_size = 4
21 |
```
--------------------------------------------------------------------------------
/vkrunner/.gitlab-ci.yml:
--------------------------------------------------------------------------------
```yaml
1 | include:
2 | - project: 'freedesktop/ci-templates'
3 | ref: ea3f77641d91765396beba192b8defd3085fa343
4 | file: '/templates/fedora.yml'
5 |
6 | stages:
7 | - prep
8 | - test
9 |
10 | variables:
11 | FDO_UPSTREAM_REPO: mesa/vkrunner
12 |
13 | .vkrunner.fedora:42:
14 | variables:
15 | FDO_DISTRIBUTION_VERSION: 42
16 | FDO_DISTRIBUTION_TAG: '2025-04-17.1'
17 |
18 | build-fedora-container:
19 | extends:
20 | - .fdo.container-build@fedora
21 | - .vkrunner.fedora:42
22 | stage: prep
23 | variables:
24 | FDO_DISTRIBUTION_PACKAGES: "cargo bindgen-cli glslang"
25 |
26 | cargo-test:
27 | extends:
28 | - .fdo.distribution-image@fedora
29 | - .vkrunner.fedora:42
30 | stage: test
31 | script:
32 | - cargo test
33 |
```
--------------------------------------------------------------------------------
/vkrunner/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # VkRunner
2 |
3 | VkRunner is a Vulkan shader tester based on `shader_runner` in
4 | [Piglit](https://piglit.freedesktop.org/). The goal is to make it be
5 | able to test scripts as similar to Piglit’s shader_test format as
6 | possible.
7 |
8 | ## Building
9 |
10 | VkRunner requires Cargo and a rust compiler to build.
11 |
12 | To build it type:
13 |
14 | ```
15 | cargo build
16 | ```
17 |
18 | Can can then run VkRunner by typing:
19 |
20 | ```
21 | cargo run
22 | ```
23 |
24 | ## Installing
25 |
26 | The vkrunner binary can be installed like so:
27 |
28 | ```
29 | cargo install --path . --root <install_root>
30 | ```
31 |
32 | ## Running
33 |
34 | VkRunner requires glslangValidator to compile GLSL to SPIR-V. It is
35 | invoked on the fly while executing the test. It must either be
36 | available in your path or you can set the variable
37 | `PIGLIT_GLSLANG_VALIDATOR_BINARY` to point to it. It can be obtained
38 | from [here](https://github.com/KhronosGroup/glslang/).
39 |
40 | ## [test] section:
41 |
42 | The `[test]` section supports the following commands:
43 |
44 | > draw rect [ortho] [patch] _x_ _y_ _width_ _height_
45 |
46 | Draws a rectangle at the given normalised coordinates. The vertices
47 | will be uploaded at vertex input location 0 as a vec3. Remember that
48 | Vulkan’s normalised coordinate system is different from OpenGL’s. If
49 | `ortho` is specified then the coordinates are scaled from the range
50 | [0,window size] to [-1,1] to make it easier to specify the positions
51 | in pixels. If `patch` is given then a patch topology will be used with
52 | a patch size of four.
53 |
54 | > draw arrays [indexed] [instanced] _topology_ _firstVertex_ _vertexCount_ [_instanceCount_]
55 |
56 | Calls `vkCmdDraw` with the given parameters. The vertex data will be
57 | sourced from the `[vertex data]` section. The _topology_ should be one
58 | of the values of VkPrimitiveTopology minus the VK\_PRIMITIVE\_TOPOLOGY
59 | prefix. Alternatively it can be a GLenum value as used in Piglit.
60 |
61 | If `indexed` is specified then `vkCmdDrawIndexed` will be use to draw
62 | the primitive instead. The indices will be sourced from the
63 | `[indices]` section. _vertexCount_ will be used as the index count,
64 | _firstVertex_ becomes the vertex offset and _firstIndex_ will always
65 | be zero.
66 |
67 | > compute _x_ _y_ _z_
68 |
69 | Dispatch the compute shader with the given parameters.
70 |
71 | > [relative] probe [rect] (rgb|rgba) (_x_, _y_[, _width_, _height_]) (_r_, _g_, _b_[, _a_])
72 |
73 | Verifies that a given rectangle matches the given colour. If the
74 | command begins with the keyword `relative` then the coordinates are
75 | normalised from 0.0 to 1.0, otherwise they are pixel coordinates.
76 | Either way the origin is the top-left corner of the image. If `rect`
77 | is not specified then the width and height are set to 1 pixel. The
78 | alpha component of the image can be ignored or not by specifying
79 | either `rgb` or `rgba`.
80 |
81 | > probe all (rgb|rgba) _r_ _g_ _b_ [_a_]
82 |
83 | The same as above except that it probes the entire window.
84 |
85 | > push _type_ _offset_ _values_…
86 |
87 | Sets a push constant at the given offset. Note that unlike Piglit, the
88 | offset is a byte offset into the push constant buffer rather than a
89 | uniform location. For a description of how the arguments work see
90 | “Setting buffer subdata” below.
91 |
92 | > (ubo|ssbo) _binding_ subdata _type_ _offset_ _values_…
93 |
94 | Sets a value within a uniform or storage buffer. The first time a
95 | value is set within a buffer it will be created with the minimum size
96 | needed to contain all of the values set on it via test commands. It
97 | will then be bound to the descriptor set at the given binding point.
98 | The rest of the arguments are used as described in “Setting buffer
99 | subdata” below.
100 |
101 | Note that the buffer is just updated by writing into a memory mapped
102 | view of it which means that if you do an update, draw call, update and
103 | then another draw call both draws will use the values from the second
104 | update. This is because the draws are not flushed until the next probe
105 | command or the test completes.
106 |
107 | > (ubo|ssbo) _binding_ _size_
108 |
109 | Sets the size of a uniform or storage buffer. This is optional if
110 | there are buffer subdata commands because in that case it will just
111 | take the size of the largest offset.
112 |
113 | > probe ssbo _type_ _binding_ _offset_ _comparison_ _values_…
114 |
115 | Probes a value in the storage buffer at _binding_. The _comparison_
116 | can be one of `==`, `!=`, `<`, `>=`, `>`, `<=` or `~=`. If the type
117 | has more than one component then they are compared individually until
118 | one of them fails the comparison. `~=` is the same with `==` but `~=`
119 | allows errors for `double` or `float` type numbers while `==` does
120 | not. Allowed errors can be set by the following `tolerance` command.
121 | See [examples/tolerance.shader_test](examples/tolerance.shader_test)
122 | for the usage of `~=`. Multiple values can be listed to compare an
123 | array of values. In that case the buffer is assumed to have the layout
124 | specified with the last `ssbo layout` command.
125 |
126 | > tolerance _tolerance0 tolerance1 tolerance2 tolerance3_
127 |
128 | Sets four tolerances i.e., allowed errors. `vecN` type values will
129 | use first `N` tolerances among those four. Each column of `matMxN` type
130 | values will also use first `N` tolerances. `float` and `double` type
131 | values will use only the first tolerance. Each tolerance value can be
132 | an `double` type real number or percentage e.g., `0.01%`. `tolerance`
133 | command can be also used for comparisons of pixels. See
134 | [examples/tolerance.shader_test]( examples/tolerance.shader_test) for
135 | the usage of `tolerance` command.
136 |
137 | > tolerance _tolerance0_
138 |
139 | Sets a tolerance i.e., an allowed error. If this command is set, all
140 | components of `vecN` and `matMxN` type values will use the same
141 | tolerance. Each tolerance value can be an `double` type real number or
142 | percentage e.g., `0.01%`. See [examples/tolerance.shader_test](
143 | examples/tolerance.shader_test) for the usage of `tolerance` command.
144 |
145 | > push layout [std140|std430] [row_major|column_major]
146 |
147 | > ssbo layout [std140|std430] [row_major|column_major]
148 |
149 | > ubo layout [std140|std430] [row_major|column_major]
150 |
151 | Sets the expected layout for subsequent commands that operate on push
152 | constants, SSBOs and UBOs respectively. All layouts default to std430
153 | and column_major except the UBO layout which defaults to std140. This
154 | matches the defaults in GLSL. If row_major or column_major is not
155 | specified then it will be set back to column_major (ie, it does not
156 | leave it at as row_major if a previous layout command set it to that).
157 | Note that setting the matrix major axis only affects the layout of the
158 | data in memory. The values are still specified in test commands in
159 | column-major order.
160 |
161 | > clear color _r_ _g_ _b_ _a_
162 |
163 | Sets the color to use for subsequent clear commands. Defaults to all
164 | zeros.
165 |
166 | > clear depth _value_
167 |
168 | Sets the value to clear the depth buffer to in subsequent clear
169 | commands. Defaults to 1.0.
170 |
171 | > clear stencil _value_
172 |
173 | Sets the value to clear the stencil buffer to in subsequent clear
174 | commands. Defaults to 0.
175 |
176 | > clear
177 |
178 | Clears the entire framebuffer to the previously set clear color, depth
179 | and stencil values.
180 |
181 | > patch parameter vertices _vertices_
182 |
183 | Sets the number of control points for tessellation patches in
184 | subsequent draw calls. Defaults to 3.
185 |
186 | > topology, primitiveRestartEnable, patchControlPoints,
187 | > depthClampEnable, rasterizerDiscardEnable, polygonMode, cullMode,
188 | > frontFace, depthBiasEnable, depthBiasConstantFactor, depthBiasClamp,
189 | > depthBiasSlopeFactor, lineWidth, logicOpEnable, logicOp,
190 | > blendEnable, srcColorBlendFactor, dstColorBlendFactor, colorBlendOp,
191 | > srcAlphaBlendFactor, dstAlphaBlendFactor, alphaBlendOp,
192 | > colorWriteMask, depthTestEnable, depthWriteEnable, depthCompareOp,
193 | > depthBoundsTestEnable, stencilTestEnable, front.failOp,
194 | > front.passOp, front.depthFailOp, front.compareOp, front.compareMask,
195 | > front.writeMask, front.reference, back.failOp, back.passOp,
196 | > back.depthFailOp, back.compareOp, back.compareMask, back.writeMask,
197 | > back.reference
198 |
199 | These properties can be set on a pipeline by specifying their name
200 | followed by a value in the test section. This will affect subsequent
201 | draw calls. If multiple draw calls are issued with different values
202 | for these properties then a separate pipeline will be created for each
203 | set of state. See the `properties.shader_test` example for details.
204 |
205 | > _stage_ entrypoint _name_
206 |
207 | Sets the entrypoint function to _name_ for the given stage. This will
208 | be used for subsequent draw calls or compute dispatches.
209 |
210 | > uniform _type_ _offset_ _values_…
211 |
212 | This is equivalent to push _type_ _offset_ _values_. It is provided
213 | for compatibility with Piglit.
214 |
215 | > uniform ubo _binding_ _type_ _offset_ _values_…
216 |
217 | This is equivalent to ubo _binding_ subdata _type_ _offset_ _values_.
218 | It is provided for compatibility with Piglit.
219 |
220 | Take a look in the examples directory for more examples.
221 |
222 | ## Setting buffer subdata
223 |
224 | The commands to set push constants, ubo data and ssbo data all take
225 | the same three arguments `type`, `offset` and `values…`. These are
226 | used to describe a chunk of data to store at the given offset in the
227 | corresponding buffer. The commands can be used multiple times with
228 | different offsets to set data at different locations.
229 |
230 | The type can be one of int, uint, int8_t, uint8_t, int16_t, uint16_t,
231 | int64_t, uint64_t, float16_t, float, double, f16vec[234], vec[234],
232 | dvec[234], ivec[234], uvec[234], i8vec[234], u8vec[234], i16vec[234],
233 | u16vec[234], i64vec[234], u64vec[234], mat[234]x[234] or
234 | dmat[234]x[234].
235 |
236 | The values argument contains one integer or float for each component
237 | of the given type. Multiple values can be specified in a single
238 | command to set an array of values of the given type.
239 |
240 | Each buffer type (push constant, UBO and SSBO) has a corresponding
241 | current layout which is either std140 or std430. The current layout
242 | only matters for matrix types or for specifying array values with a
243 | single command. It is used to calculate the array stride and matrix
244 | stride for the given type. The default layouts for each buffer type
245 | correspond to the defaults for the corresponding buffer type in GLSL.
246 | Note that the layout is only used as a convenience to set values in
247 | memory. If you want to use a custom layout it is still always possible
248 | to set all the values using multiple commands and explicit offsets.
249 |
250 | Some examples:
251 |
252 | ssbo 0 subdata float 12 42.0
253 |
254 | This will write the float value 42 twelve bytes into the buffer at
255 | binding 0.
256 |
257 | ssbo layout std140
258 | ssbo 0 subdata float 32 1 2 3
259 |
260 | This will write the float values 1, 2, 3 into the buffer starting at
261 | byte 32 arranged such so that it would be suitable for an array of floats
262 | declared as std140 such as this:
263 |
264 | ```GLSL
265 | layout(binding = 0, std140) buffer block {
266 | layout(offset = 32) float one_two_three[3];
267 | };
268 | ```
269 |
270 | The rules of std140 force the array stride to be a multiple of a vec4
271 | so this will effectively write the following floats starting at byte
272 | 32:
273 |
274 | ```
275 | 1 0 0 0 2 0 0 0 3
276 | ```
277 |
278 | ```
279 | ssbo layout std430
280 | ssbo 0 subdata mat3 12 1 2 3 4 5 6 7 8 9
281 | ```
282 |
283 | This will write a mat3 starting at offset 12. std430 treats this like
284 | an array of 3 vec3s. The stride for vec3s is padded up to vec4 so it
285 | would write the floats like this:
286 |
287 | ```
288 | 1 2 3 0 4 5 6 0 7 8 9
289 | ```
290 |
291 | ```
292 | ssbo layout std430 row_major
293 | ssbo 0 subdata mat3 12 1 2 3 4 5 6 7 8 9
294 | ```
295 |
296 | This will write the same matrix but laid out in a way suitable for a
297 | uniform declared as row_major. It will look like this:
298 |
299 | 1 4 7 0 2 5 8 0 3 6 9
300 |
301 | ## [require] section
302 |
303 | > _feature_
304 |
305 | The `[require]` section can contain names of members from
306 | VkPhysicalDeviceFeatures. These will be searched for when deciding
307 | which physical device to open. If no physical device with the
308 | corresponding requirements can be found then it will report an error.
309 |
310 | In addition to VkPhysicalDeviceFeatures, the name of a feature from
311 | any feature struct from an extension that VkRunner is aware of can
312 | also be requested. In that case VkRunner will also implicitly require
313 | the corresponding device extension. It will also need the
314 | `VK_KHR_get_physical_device_properties2` instance extension in order
315 | to check for the feature. For example, specifying `shaderFloat16` in
316 | the require section will make it also require the
317 | `VK_KHR_shader_float16_int8` extension. VkRunner will then enable the
318 | feature via the VkPhysicalDeviceFloat16Int8FeaturesKHR struct when
319 | creating the device.
320 |
321 | > _extension_
322 |
323 | Any line that is not a feature and contains entirely alphanumeric and
324 | underscore characters is assumed to be a device extension name. This
325 | will be checked for when searching for a suitable device and if no
326 | device with the extension is found then the test will report that it
327 | was skipped. Otherwise the extension will be enabled when creating the
328 | device.
329 |
330 | The required Vulkan implementation version for the test can also be
331 | set in this section. If the version is not supported by the device
332 | driver the test will be skipped.
333 |
334 | > framebuffer _format_
335 |
336 | Use this to specify the format of the framebuffer using a format from
337 | VkFormat minus the VK_FORMAT prefix.
338 |
339 | > depthstencil _format_
340 |
341 | If this is specified VkRunner will try to add a depth-stencil
342 | attachment to the framebuffer with the given format. Without it no
343 | depth-stencil buffer will be created.
344 |
345 | > fbsize _width_ _height_
346 |
347 | Specify the size of the framebuffer. If not specified it defaults to
348 | 250x250.
349 |
350 | > vulkan _major_._minor_._patch_
351 |
352 | Use this to specify the Vulkan implementation version against which
353 | the test should run.
354 |
355 | > subgroup_size _size_
356 |
357 | Specify the required subgroup size for the compute shaders in the pipeline.
358 | See Vulkan documentation for `VkPipelineShaderStageRequiredSubgroupSizeCreateInfo`
359 | for more details.
360 |
361 | > cooperative_matrix [params...]
362 |
363 | Specify that Cooperative Matrix support is required. It will automatically
364 | require VK_KHR_cooperative_matrix extension and the cooperativeMatrix feature.
365 |
366 | Matrix configuration requirements is provided by passing the attributes
367 | for each item, e.g. `m=16 a=float`. The items available are `m=`, `n=`
368 | and `k=` for the matrix sizes; `a=`, `b=`, `c=` and `result=` for the
369 | element types of each matrix; `saturating_accumulation=true|false` and
370 | `scope=` for extra options. See Vulkan documentation for
371 | `VkCooperativeMatrixPropertiesKHR` for more details.
372 |
373 | If an item is not specified, it will match any value available. If
374 | multiple different configurations are required, use multiple
375 | `cooperative_matrix` lines.
376 |
377 | ## Shader sections
378 |
379 | Shaders can be stored in sections like `[vertex shader]` just like in
380 | `shader_runner`. Multiple GLSL shaders can be given for a single stage
381 | and they will be linked together via glslangValidator.
382 |
383 | Alternatively, the disassembly of the SPIR-V source can be provided
384 | with a section like `[vertex shader spirv]`. This will be assembled
385 | with `spirv-as`. If a SPIR-V section is given for a stage there can be
386 | no other shaders for that stage.
387 |
388 | The vertex shader can also be skipped with an empty section called
389 | `[vertex shader passthrough]`. That will create a simple vertex shader
390 | than just copies a vec4 for input location 0 to `gl_Position`.
391 |
392 | ## [vertex data] section
393 |
394 | The `[vertex data]` section is used to specify vertex attributes and
395 | data for use with the draw arrays command. It is similar to Piglit
396 | except that integer locations are used instead of names and matrices
397 | are specifed by using a location within the matrix rather than having
398 | a separate field.
399 |
400 | The format consists of a row of column headers followed by any number
401 | of rows of data. Each column header has the form _ATTRLOC_/_FORMAT_
402 | where _ATTRLOC_ is the location of the vertex attribute to be bound to
403 | this column and _FORMAT_ is the name of a VkFormat minus the VK_FORMAT
404 | prefix.
405 |
406 | Alternatively the column header can use something closer the Piglit
407 | format like _ATTRLOC_/_GL\_TYPE_/_GLSL\_TYPE_. _GL\_TYPE_ is the GL
408 | type of data that follows (“half”, “float”, “double”, “byte”, “ubyte”,
409 | “short”, “ushort”, “int” or “uint”), _GLSL\_TYPE_ is the GLSL type of
410 | the data (“int”, “uint”, “float”, “double”, “ivec”\*, “uvec”\*,
411 | “vec”\*, “dvec”\*).
412 |
413 | The data follows the column headers in space-separated form. “#” can
414 | be used for comments, as in shell scripts. See the
415 | `vertex-data.shader_test` file as an example.
416 |
417 | ## [indices] section
418 |
419 | The `[indices]` section just contains a list of indices to use along
420 | with the vertices in `[vertex data]`. It will be used if the `indexed`
421 | option is given to the `draw arrays` test command.
422 |
423 | ## Long lines
424 |
425 | Long lines anywhere in the script can be split into multiple lines by
426 | using a backslash to combine them. For example a line to set an array
427 | of ints could be split up as follows:
428 |
429 | ```
430 | ubo 0 subdata int 0 \
431 | 1 2 3 5 8 13 21 34 55 89 144 233 377 610 \
432 | 987 1597 2584 4181 6765 10946 17711 28657 \
433 | 46368 75025 121393 196418 317811 514229
434 | ```
435 |
436 | ## Command line arguments
437 |
438 | usage: vkrunner [OPTION]... SCRIPT...
439 | Runs the shader test script SCRIPT
440 |
441 | Options:
442 | -h Show this help message
443 | -i IMG Write the final rendering to IMG as a PPM image
444 | -d Show the SPIR-V disassembly
445 | -D TOK=REPL Replace occurences of TOK with REPL in the scripts
446 | --device-id DEVID Select the Vulkan device
447 |
448 | ## Precompiling shaders
449 |
450 | As an alternative to specifying the shaders in GLSL or SPIR-V
451 | assembly, the test scripts can contain a hex dump of the SPIR-V. That
452 | way VkRunner does not need to invoke the compiler or assembler to run
453 | the script. This can be useful either to speed up the execution of the
454 | tests or to run them on hardware where installing the compiler is not
455 | practical. VkRunner also includes a Python script to precompile the
456 | test scripts to binary. It can be run for example as below:
457 |
458 | ./precompile-script.py -o compiled-examples examples/*.shader_test
459 | ./src/vkrunner compiled-examples/*.shader_test
460 |
461 | If glslangValidator and spirv-as are not in the path, you can indicate
462 | where the binaries are with the following command line arguments:
463 |
464 | ./precompile-script.py -o compiled-examples examples/*.shader_test -g PATH_GLSLANG/glslangValidator -s PATH_SPIRV_AS/spirv-as
465 |
```
--------------------------------------------------------------------------------
/.devcontainer/docker-compose.yml:
--------------------------------------------------------------------------------
```yaml
1 | version: '3'
2 |
3 | services:
4 | app:
5 | build:
6 | context: ..
7 | dockerfile: .devcontainer/Dockerfile
8 | volumes:
9 | - ..:/workspace:cached
10 | command: sleep infinity
11 | # Keep the container running
12 | tty: true
```
--------------------------------------------------------------------------------
/vkrunner/Cargo.toml:
--------------------------------------------------------------------------------
```toml
1 | [package]
2 | name = "vkrunner"
3 | version = "0.1.0"
4 | edition = "2021"
5 | license = "MIT"
6 | description = "A shader testing tool for Vulkan"
7 | repository = "https://gitlab.freedesktop.org/mesa/vkrunner/"
8 | default-run = "vkrunner"
9 |
10 | [lib]
11 | path = "vkrunner/lib.rs"
12 |
13 | [build-dependencies]
14 | bindgen = "0.66.1"
15 |
```
--------------------------------------------------------------------------------
/vkrunner/include/vk_video/vulkan_video_codecs_common.h:
--------------------------------------------------------------------------------
```
1 | #ifndef VULKAN_VIDEO_CODECS_COMMON_H_
2 | #define VULKAN_VIDEO_CODECS_COMMON_H_ 1
3 |
4 | /*
5 | ** Copyright 2015-2025 The Khronos Group Inc.
6 | **
7 | ** SPDX-License-Identifier: Apache-2.0
8 | */
9 |
10 | /*
11 | ** This header is generated from the Khronos Vulkan XML API Registry.
12 | **
13 | */
14 |
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 |
21 |
22 | // vulkan_video_codecs_common is a preprocessor guard. Do not pass it to API calls.
23 | #define vulkan_video_codecs_common 1
24 | #if !defined(VK_NO_STDINT_H)
25 | #include <stdint.h>
26 | #endif
27 |
28 | #define VK_MAKE_VIDEO_STD_VERSION(major, minor, patch) \
29 | ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch)))
30 |
31 |
32 | #ifdef __cplusplus
33 | }
34 | #endif
35 |
36 | #endif
37 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/lib.rs:
--------------------------------------------------------------------------------
```rust
1 | mod small_float;
2 | mod half_float;
3 | mod hex;
4 | mod format;
5 | mod tolerance;
6 | mod util;
7 | mod parse_num;
8 | mod vbo;
9 | mod vk;
10 | mod vulkan_funcs;
11 | mod requirements;
12 | mod slot;
13 | pub mod result;
14 | mod shader_stage;
15 | mod pipeline_key;
16 | mod window_format;
17 | mod source;
18 | mod config;
19 | mod stream;
20 | mod script;
21 | mod context;
22 | mod buffer;
23 | mod window;
24 | mod allocate_store;
25 | mod executor;
26 | mod temp_file;
27 | mod logger;
28 | mod compiler;
29 | mod pipeline_set;
30 | mod flush_memory;
31 | pub mod inspect;
32 | mod tester;
33 |
34 | #[cfg(test)]
35 | mod fake_vulkan;
36 | #[cfg(test)]
37 | mod env_var_test;
38 |
39 | // Re-export the public API
40 | pub use config::Config;
41 | pub use executor::Executor;
42 | pub use format::Format;
43 | pub use script::Script;
44 | pub use shader_stage::Stage;
45 | pub use source::Source;
46 |
```
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "shaderc-vkrunner-mcp",
3 | "dockerComposeFile": "docker-compose.yml",
4 | "service": "app",
5 | "workspaceFolder": "/workspace",
6 | "customizations": {
7 | "vscode": {
8 | "extensions": [
9 | "GitHub.copilot",
10 | "GitHub.copilot-chat",
11 | "charliermarsh.ruff",
12 | "eamodio.gitlens",
13 | "llvm-vs-code-extensions.vscode-clangd",
14 | "ms-python.python",
15 | "ms-vscode.cmake-tools",
16 | "rust-lang.rust-analyzer",
17 | "tamasfe.even-better-toml"
18 | ],
19 | "settings": {
20 | "terminal.integrated.defaultProfile.linux": "bash"
21 | }
22 | }
23 | },
24 | "remoteUser": "root"
25 | }
```
--------------------------------------------------------------------------------
/.vscode/mcp.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "servers": {
3 | "shaderc-vkrunner-mcp-dev": {
4 | "type": "stdio",
5 | "command": "cargo",
6 | "args": [
7 | "run",
8 | "--release",
9 | "--manifest-path",
10 | "${workspaceFolder}/Cargo.toml",
11 | "--",
12 | "--work-dir",
13 | "${workspaceFolder}"
14 | ]
15 | },
16 | "shaderc-vkrunner-mcp": {
17 | "type": "stdio",
18 | "command": "docker",
19 | "args": [
20 | "run",
21 | "--rm",
22 | "-i",
23 | "-v",
24 | "${workspaceFolder}:/work",
25 | "shaderc-vkrunner-mcp",
26 | "--work-dir",
27 | "/work"
28 | ]
29 | }
30 | }
31 | }
```
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
```toml
1 | [package]
2 | name = "shaderc-vkrunner-mcp"
3 | version = "0.1.0"
4 | edition = "2024"
5 |
6 | [dependencies]
7 | rmcp = { git = "https://github.com/modelcontextprotocol/rust-sdk", branch = "main", features = [
8 | "server",
9 | "transport-sse-server",
10 | "transport-io",
11 | ] }
12 | tokio = { version = "1", features = [
13 | "macros",
14 | "rt",
15 | "rt-multi-thread",
16 | "io-std",
17 | "signal",
18 | ] }
19 | serde = { version = "1.0", features = ["derive"] }
20 | serde_json = "1.0"
21 | anyhow = "1.0"
22 | tracing = "0.1"
23 | tracing-subscriber = { version = "0.3", features = [
24 | "env-filter",
25 | "std",
26 | "fmt",
27 | ] }
28 | futures = "0.3"
29 | rand = { version = "0.9" }
30 | axum = { version = "0.8", features = ["macros"] }
31 | schemars = { version = "0.8", optional = true }
32 | image = "0.25.6"
33 | clap = { version = "4.5.36", features = ["derive"] }
34 | shaderc = "0.9.1"
35 | vkrunner = { path = "./vkrunner", features = [] }
36 |
37 | [dev-dependencies]
38 | tokio-stream = { version = "0.1" }
39 | tokio-util = { version = "0.7", features = ["codec"] }
40 |
```
--------------------------------------------------------------------------------
/vkrunner/scripts/update-vulkan.sh:
--------------------------------------------------------------------------------
```bash
1 | #!/usr/bin/env bash
2 | #
3 | # Copyright 2025 Intel Corporation
4 | # SPDX-License-Identifier: MIT
5 |
6 | set -e
7 |
8 | if [ ! -f "Cargo.toml" ]; then
9 | echo "Run the script from the root of the repository."
10 | exit 1
11 | fi
12 |
13 | SKIP_DOWNLOAD=
14 |
15 | for arg in "$@"; do
16 | case $arg in
17 | --skip-download)
18 | SKIP_DOWNLOAD=1
19 | shift
20 | ;;
21 | *)
22 | shift
23 | ;;
24 | esac
25 | done
26 |
27 | if [ -z "$SKIP_DOWNLOAD" ]; then
28 | VULKAN_HEADERS=$(mktemp -d)
29 | git clone https://github.com/KhronosGroup/Vulkan-Headers.git "$VULKAN_HEADERS"
30 | git -C "$VULKAN_HEADERS" log -1
31 |
32 | cp -f $VULKAN_HEADERS/include/vk_video/*.h include/vk_video/
33 | cp -f $VULKAN_HEADERS/include/vulkan/{vulkan.h,vulkan_core.h,vk_platform.h} include/vulkan/
34 | fi
35 |
36 | # TODO: Most of these scripts should be using the registry/vk.xml instead of
37 | # parsing the C headers.
38 |
39 | echo | gcc -include "./include/vulkan/vulkan.h" -E - | vkrunner/make-enums.py > vkrunner/enum_table.rs
40 | vkrunner/make-features.py < include/vulkan/vulkan_core.h > vkrunner/features.rs
41 | vkrunner/make-formats.py < include/vulkan/vulkan_core.h > vkrunner/format_table.rs
42 | vkrunner/make-pipeline-key-data.py > vkrunner/pipeline_key_data.rs
43 | vkrunner/make-vulkan-funcs-data.py > vkrunner/vulkan_funcs_data.rs
44 |
```
--------------------------------------------------------------------------------
/vkrunner/test-build.sh:
--------------------------------------------------------------------------------
```bash
1 | #!/bin/bash
2 |
3 | set -eu
4 |
5 | src_dir="$(cd $(dirname "$0") && pwd)"
6 | build_dir="$src_dir/tmp-build"
7 | install_dir="$build_dir/install"
8 | device_id=""
9 |
10 | if [ $# -gt 0 ] && [ "$1" = "--device-id" ]; then
11 | if [ -z "${2:-}" ]; then
12 | echo "--device-id must be followed by a number"
13 | exit 1
14 | fi
15 | device_id="--device-id $2"
16 | fi
17 |
18 | rm -fr -- "$build_dir"
19 |
20 | cargo test --target-dir "$build_dir"
21 | cargo install --target-dir "$build_dir" --path . --root "$install_dir"
22 |
23 | # Run the built executable with all of the examples and enable the
24 | # validation layer. Verify that nothing was written to the output.
25 | VKRUNNER_ALWAYS_FLUSH_MEMORY=true \
26 | VK_LOADER_LAYERS_ENABLE="*validation" \
27 | "$install_dir/bin/vkrunner" \
28 | -q \
29 | "$src_dir/examples"/*.shader_test \
30 | 2>&1 \
31 | | tee "$build_dir/output.txt"
32 |
33 | if grep -q --invert-match '^/tmp' "$build_dir/output.txt"; then
34 | echo "FAIL VkRunner had output with quiet flag"
35 | exit 1;
36 | fi
37 |
38 | # Try again with precompiled scripts
39 | "$src_dir"/precompile-script.py -o "$build_dir/precompiled-examples" \
40 | "$src_dir/examples"/*.shader_test
41 | "$install_dir/bin/vkrunner" $device_id \
42 | "$build_dir/precompiled-examples/"*.shader_test
43 |
44 | echo
45 | echo "Test build succeeded."
46 |
```
--------------------------------------------------------------------------------
/vkrunner/include/vulkan/vulkan.h:
--------------------------------------------------------------------------------
```
1 | #ifndef VULKAN_H_
2 | #define VULKAN_H_ 1
3 |
4 | /*
5 | ** Copyright 2015-2025 The Khronos Group Inc.
6 | **
7 | ** SPDX-License-Identifier: Apache-2.0
8 | */
9 |
10 | #include "vk_platform.h"
11 | #include "vulkan_core.h"
12 |
13 | #ifdef VK_USE_PLATFORM_ANDROID_KHR
14 | #include "vulkan_android.h"
15 | #endif
16 |
17 | #ifdef VK_USE_PLATFORM_FUCHSIA
18 | #include <zircon/types.h>
19 | #include "vulkan_fuchsia.h"
20 | #endif
21 |
22 | #ifdef VK_USE_PLATFORM_IOS_MVK
23 | #include "vulkan_ios.h"
24 | #endif
25 |
26 |
27 | #ifdef VK_USE_PLATFORM_MACOS_MVK
28 | #include "vulkan_macos.h"
29 | #endif
30 |
31 | #ifdef VK_USE_PLATFORM_METAL_EXT
32 | #include "vulkan_metal.h"
33 | #endif
34 |
35 | #ifdef VK_USE_PLATFORM_VI_NN
36 | #include "vulkan_vi.h"
37 | #endif
38 |
39 |
40 | #ifdef VK_USE_PLATFORM_WAYLAND_KHR
41 | #include "vulkan_wayland.h"
42 | #endif
43 |
44 |
45 | #ifdef VK_USE_PLATFORM_WIN32_KHR
46 | #include <windows.h>
47 | #include "vulkan_win32.h"
48 | #endif
49 |
50 |
51 | #ifdef VK_USE_PLATFORM_XCB_KHR
52 | #include <xcb/xcb.h>
53 | #include "vulkan_xcb.h"
54 | #endif
55 |
56 |
57 | #ifdef VK_USE_PLATFORM_XLIB_KHR
58 | #include <X11/Xlib.h>
59 | #include "vulkan_xlib.h"
60 | #endif
61 |
62 |
63 | #ifdef VK_USE_PLATFORM_DIRECTFB_EXT
64 | #include <directfb.h>
65 | #include "vulkan_directfb.h"
66 | #endif
67 |
68 |
69 | #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
70 | #include <X11/Xlib.h>
71 | #include <X11/extensions/Xrandr.h>
72 | #include "vulkan_xlib_xrandr.h"
73 | #endif
74 |
75 |
76 | #ifdef VK_USE_PLATFORM_GGP
77 | #include <ggp_c/vulkan_types.h>
78 | #include "vulkan_ggp.h"
79 | #endif
80 |
81 |
82 | #ifdef VK_USE_PLATFORM_SCREEN_QNX
83 | #include <screen/screen.h>
84 | #include "vulkan_screen.h"
85 | #endif
86 |
87 |
88 | #ifdef VK_USE_PLATFORM_SCI
89 | #include <nvscisync.h>
90 | #include <nvscibuf.h>
91 | #include "vulkan_sci.h"
92 | #endif
93 |
94 |
95 | #ifdef VK_ENABLE_BETA_EXTENSIONS
96 | #include "vulkan_beta.h"
97 | #endif
98 |
99 | #endif // VULKAN_H_
100 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/window_format.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright (C) 2013, 2014, 2015, 2017, 2023 Neil Roberts
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a
6 | // copy of this software and associated documentation files (the "Software"),
7 | // to deal in the Software without restriction, including without limitation
8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | // and/or sell copies of the Software, and to permit persons to whom the
10 | // Software is furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice (including the next
13 | // paragraph) shall be included in all copies or substantial portions of the
14 | // Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 | // DEALINGS IN THE SOFTWARE.
23 |
24 | use crate::format::Format;
25 | use crate::vk;
26 |
27 | #[derive(Clone, Debug, PartialEq)]
28 | pub struct WindowFormat {
29 | pub color_format: &'static Format,
30 | pub depth_stencil_format: Option<&'static Format>,
31 | pub width: usize,
32 | pub height: usize,
33 | }
34 |
35 | impl Default for WindowFormat {
36 | fn default() -> WindowFormat {
37 | let color_format =
38 | Format::lookup_by_vk_format(vk::VK_FORMAT_B8G8R8A8_UNORM);
39 |
40 | WindowFormat {
41 | color_format,
42 | depth_stencil_format: None,
43 | width: 250,
44 | height: 250,
45 | }
46 | }
47 | }
48 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/vk.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright 2023 Neil Roberts
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a
6 | // copy of this software and associated documentation files (the "Software"),
7 | // to deal in the Software without restriction, including without limitation
8 | // on the rights to use, copy, modify, merge, publish, distribute, sub
9 | // license, and/or sell copies of the Software, and to permit persons to whom
10 | // the Software is furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice (including the next
13 | // paragraph) shall be included in all copies or substantial portions of the
14 | // Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 | // VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 | // USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | #![allow(non_camel_case_types)]
25 | #![allow(dead_code)]
26 | #![allow(non_upper_case_globals)]
27 | #![allow(non_snake_case)]
28 |
29 | mod bindings {
30 | #![allow(unused_imports)]
31 | include!(concat!(env!("OUT_DIR"), "/vulkan_bindings.rs"));
32 | }
33 |
34 | pub use self::bindings::*;
35 |
36 | /// Function to return a value that can be used where the Vulkan
37 | /// documentation specifies that `VK_NULL_HANDLE` can be used.
38 | #[cfg(target_pointer_width = "64")]
39 | pub fn null_handle<T>() -> *mut T {
40 | std::ptr::null_mut()
41 | }
42 |
43 | #[cfg(not(target_pointer_width = "64"))]
44 | pub fn null_handle() -> u64 {
45 | // On 32-bit platforms the non-dispatchable handles are defined as
46 | // a 64-bit integer instead of a pointer.
47 | 0u64
48 | }
49 |
```
--------------------------------------------------------------------------------
/vkrunner/include/vk_video/vulkan_video_codec_h265std_decode.h:
--------------------------------------------------------------------------------
```
1 | #ifndef VULKAN_VIDEO_CODEC_H265STD_DECODE_H_
2 | #define VULKAN_VIDEO_CODEC_H265STD_DECODE_H_ 1
3 |
4 | /*
5 | ** Copyright 2015-2025 The Khronos Group Inc.
6 | **
7 | ** SPDX-License-Identifier: Apache-2.0
8 | */
9 |
10 | /*
11 | ** This header is generated from the Khronos Vulkan XML API Registry.
12 | **
13 | */
14 |
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 |
21 |
22 | // vulkan_video_codec_h265std_decode is a preprocessor guard. Do not pass it to API calls.
23 | #define vulkan_video_codec_h265std_decode 1
24 | #include "vulkan_video_codec_h265std.h"
25 |
26 | #define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0)
27 |
28 | #define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_1_0_0
29 | #define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_decode"
30 | #define STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE 8
31 | typedef struct StdVideoDecodeH265PictureInfoFlags {
32 | uint32_t IrapPicFlag : 1;
33 | uint32_t IdrPicFlag : 1;
34 | uint32_t IsReference : 1;
35 | uint32_t short_term_ref_pic_set_sps_flag : 1;
36 | } StdVideoDecodeH265PictureInfoFlags;
37 |
38 | typedef struct StdVideoDecodeH265PictureInfo {
39 | StdVideoDecodeH265PictureInfoFlags flags;
40 | uint8_t sps_video_parameter_set_id;
41 | uint8_t pps_seq_parameter_set_id;
42 | uint8_t pps_pic_parameter_set_id;
43 | uint8_t NumDeltaPocsOfRefRpsIdx;
44 | int32_t PicOrderCntVal;
45 | uint16_t NumBitsForSTRefPicSetInSlice;
46 | uint16_t reserved;
47 | uint8_t RefPicSetStCurrBefore[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE];
48 | uint8_t RefPicSetStCurrAfter[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE];
49 | uint8_t RefPicSetLtCurr[STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE];
50 | } StdVideoDecodeH265PictureInfo;
51 |
52 | typedef struct StdVideoDecodeH265ReferenceInfoFlags {
53 | uint32_t used_for_long_term_reference : 1;
54 | uint32_t unused_for_reference : 1;
55 | } StdVideoDecodeH265ReferenceInfoFlags;
56 |
57 | typedef struct StdVideoDecodeH265ReferenceInfo {
58 | StdVideoDecodeH265ReferenceInfoFlags flags;
59 | int32_t PicOrderCntVal;
60 | } StdVideoDecodeH265ReferenceInfo;
61 |
62 |
63 | #ifdef __cplusplus
64 | }
65 | #endif
66 |
67 | #endif
68 |
```
--------------------------------------------------------------------------------
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
1 | FROM ubuntu:25.04 AS devcontainer
2 |
3 | ENV DEBIAN_FRONTEND=noninteractive
4 |
5 | RUN apt-get update && apt-get install -y \
6 | bc \
7 | build-essential \
8 | clang \
9 | clang-format \
10 | clang-tidy \
11 | clang-tools \
12 | clangd \
13 | cmake \
14 | curl \
15 | ffmpeg \
16 | git \
17 | glslang-tools \
18 | glslc \
19 | jq \
20 | libshaderc-dev \
21 | libshaderc1 \
22 | imagemagick \
23 | libgl1-mesa-dri \
24 | libvulkan-dev \
25 | libvulkan1 \
26 | mesa-utils \
27 | mesa-vulkan-drivers \
28 | ninja-build \
29 | npm \
30 | pipx \
31 | python3 \
32 | python3-pip \
33 | python3-venv \
34 | rustup \
35 | sudo \
36 | unzip \
37 | vulkan-tools \
38 | wget \
39 | x11-utils \
40 | xvfb \
41 | && apt-get clean \
42 | && rm -rf /var/lib/apt/lists/*
43 |
44 | RUN rustup install 1.86.0 && \
45 | rustup default 1.86.0
46 |
47 | RUN rustup component add rustfmt && \
48 | rustup component add clippy && \
49 | rustup component add rust-src && \
50 | rustup component add rust-analyzer
51 |
52 | RUN sh -c "pipx ensurepath" && \
53 | bash -c "pipx ensurepath"
54 |
55 | RUN pipx install uv \
56 | && pipx install ruff \
57 | && pipx install pre-commit
58 |
59 | RUN echo '#!/bin/bash \n\
60 | export VK_ICD_FILES=$(find /usr/share/vulkan/icd.d/ -name "lvp_icd*.json") \n\
61 | export VK_ICD_FILENAMES=$VK_ICD_FILES \n\
62 | export VK_DRIVER_FILES=$VK_ICD_FILES \n\
63 | export LIBGL_ALWAYS_SOFTWARE=1 \n\
64 | export GALLIUM_DRIVER=llvmpipe \n\
65 | if ! DISPLAY=:99 xdpyinfo >/dev/null 2>&1; then \n\
66 | rm -f /tmp/.X11-unix/X99 \n\
67 | rm -f /tmp/.X99-lock \n\
68 | Xvfb :99 -screen 0 960x540x24 & \n\
69 | fi \n\
70 | export DISPLAY=:99 \n\
71 | export XDG_RUNTIME_DIR=/tmp/xdg-runtime-dir \n\
72 | mkdir -p $XDG_RUNTIME_DIR && chmod 700 $XDG_RUNTIME_DIR \n\
73 | ' > /usr/local/bin/setup-vulkan-env.sh && chmod +x /usr/local/bin/setup-vulkan-env.sh
74 |
75 | RUN echo '#!/bin/bash \n\
76 | source /usr/local/bin/setup-vulkan-env.sh \n\
77 | exec "$@"' > /entrypoint.sh && chmod +x /entrypoint.sh
78 |
79 | RUN echo '. /usr/local/bin/setup-vulkan-env.sh' >> /etc/bash.bashrc
80 |
81 | RUN echo '#!/bin/bash \n\
82 | vulkaninfo --summary \n\
83 | vkcube --width 256 --height 256 & \n\
84 | for attempt in $(seq 1 64); do \n\
85 | import -window root /setup-vulkan-env.png \n\
86 | mean=$(identify -format "%[fx:mean]" /setup-vulkan-env.png) \n\
87 | if (( $(echo "$mean > 0.01" | bc -l) )); then \n\
88 | break \n\
89 | fi \n\
90 | sleep 0.1 \n\
91 | done \n\
92 | ' | ./entrypoint.sh bash
93 |
94 | COPY vkrunner /vkrunner
95 |
96 | WORKDIR /vkrunner
97 |
98 | RUN cargo build --release && \
99 | cp /vkrunner/target/release/vkrunner /usr/local/bin/ && \
100 | chmod +x /usr/local/bin/vkrunner
101 |
102 | WORKDIR /
103 |
104 | ENTRYPOINT ["/entrypoint.sh"]
105 |
106 | CMD ["bash"]
107 |
```
--------------------------------------------------------------------------------
/vkrunner/build.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright 2023 Neil Roberts
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a
6 | // copy of this software and associated documentation files (the "Software"),
7 | // to deal in the Software without restriction, including without limitation
8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | // and/or sell copies of the Software, and to permit persons to whom the
10 | // Software is furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice (including the next
13 | // paragraph) shall be included in all copies or substantial portions of the
14 | // Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 | // DEALINGS IN THE SOFTWARE.
23 |
24 | use std::env;
25 | use std::path::PathBuf;
26 |
27 | fn main() {
28 | let header = ["include", "vulkan", "vulkan.h"].iter().collect::<PathBuf>();
29 |
30 | let bindings = bindgen::Builder::default()
31 | // The input header we would like to generate
32 | // bindings for.
33 | .header(header.to_str().unwrap())
34 | // Only generate types and variables
35 | .with_codegen_config(
36 | bindgen::CodegenConfig::TYPES
37 | | bindgen::CodegenConfig::VARS
38 | )
39 | // Don’t prepend the enum name
40 | .prepend_enum_name(false)
41 | // Limit the types that we generate bindings for
42 | .allowlist_type(r"^(PFN|Vk).*")
43 | .allowlist_var(r"^VK_.*")
44 | // Derive the default trait
45 | .derive_default(true)
46 | // Specifiy the include path so that it can find the other headers
47 | .clang_arg("-Iinclude")
48 | // Tell cargo to invalidate the built crate whenever any of the
49 | // included header files changed.
50 | .parse_callbacks(Box::new(bindgen::CargoCallbacks))
51 | // Finish the builder and generate the bindings
52 | .generate()
53 | // Unwrap the Result and panic on failure
54 | .expect("Unable to generate bindings");
55 |
56 | // Write the bindings to the $OUT_DIR/vulkan_bindings.rs file.
57 | let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
58 | bindings
59 | .write_to_file(out_path.join("vulkan_bindings.rs"))
60 | .expect("Couldn't write bindings!");
61 | }
62 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/shader_stage.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright (C) 2018 Intel Corporation
4 | // Copyright 2023 Neil Roberts
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a
7 | // copy of this software and associated documentation files (the "Software"),
8 | // to deal in the Software without restriction, including without limitation
9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 | // and/or sell copies of the Software, and to permit persons to whom the
11 | // Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice (including the next
14 | // paragraph) shall be included in all copies or substantial portions of the
15 | // Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | // DEALINGS IN THE SOFTWARE.
24 |
25 | use crate::vk;
26 |
27 | /// An enum of all the possible shader stages known to VkRunner.
28 | #[derive(Copy, Clone, Eq, PartialEq, Debug)]
29 | #[repr(C)]
30 | pub enum Stage {
31 | Vertex = 0,
32 | TessCtrl,
33 | TessEval,
34 | Geometry,
35 | Fragment,
36 | Compute
37 | }
38 |
39 | /// The number of shader stages known to VkRunner. This should match
40 | /// the number of values in [Stage].
41 | pub(crate) const N_STAGES: usize = 6;
42 |
43 | /// All the possible stage values.
44 | pub(crate) static ALL_STAGES: [Stage; N_STAGES] = [
45 | Stage::Vertex,
46 | Stage::TessCtrl,
47 | Stage::TessEval,
48 | Stage::Geometry,
49 | Stage::Fragment,
50 | Stage::Compute,
51 | ];
52 |
53 | impl Stage {
54 | /// Get the corresponding flag for this stage. This can be used to
55 | /// store the stages in a bitmask.
56 | pub(crate) const fn flag(self) -> vk::VkShaderStageFlagBits {
57 | vk::VK_SHADER_STAGE_VERTEX_BIT << self as usize
58 | }
59 | }
60 |
61 | #[cfg(test)]
62 | mod test {
63 | use super::*;
64 |
65 | #[test]
66 | fn flags() {
67 | assert_eq!(Stage::Vertex.flag(), vk::VK_SHADER_STAGE_VERTEX_BIT);
68 | assert_eq!(
69 | Stage::TessCtrl.flag(),
70 | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
71 | );
72 | assert_eq!(
73 | Stage::TessEval.flag(),
74 | vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
75 | );
76 | assert_eq!(Stage::Geometry.flag(), vk::VK_SHADER_STAGE_GEOMETRY_BIT);
77 | assert_eq!(Stage::Fragment.flag(), vk::VK_SHADER_STAGE_FRAGMENT_BIT);
78 | assert_eq!(Stage::Compute.flag(), vk::VK_SHADER_STAGE_COMPUTE_BIT);
79 | }
80 | }
81 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/tolerance.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright (C) 2018 Google LLC
4 | // Copyright 2023 Neil Roberts
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a
7 | // copy of this software and associated documentation files (the "Software"),
8 | // to deal in the Software without restriction, including without limitation
9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 | // and/or sell copies of the Software, and to permit persons to whom the
11 | // Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice (including the next
14 | // paragraph) shall be included in all copies or substantial portions of the
15 | // Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | // DEALINGS IN THE SOFTWARE.
24 |
25 | #[derive(Debug, Clone, PartialEq)]
26 | pub struct Tolerance {
27 | value: [f64; 4],
28 | is_percent: bool,
29 | }
30 |
31 | impl Tolerance {
32 | pub fn new(value: [f64; 4], is_percent: bool) -> Tolerance {
33 | Tolerance { value, is_percent }
34 | }
35 |
36 | pub fn equal(&self, component: usize, a: f64, b: f64) -> bool {
37 | if self.is_percent {
38 | (a - b).abs() <= (self.value[component] / 100.0 * b).abs()
39 | } else {
40 | (a - b).abs() <= self.value[component]
41 | }
42 | }
43 | }
44 |
45 | impl Default for Tolerance {
46 | fn default() -> Tolerance {
47 | Tolerance {
48 | value: [0.01; 4],
49 | is_percent: false,
50 | }
51 | }
52 | }
53 |
54 | #[cfg(test)]
55 | mod test {
56 | use super::*;
57 |
58 | #[test]
59 | fn test_percentage() {
60 | let tolerance = Tolerance::new([25.0, 50.0, 1.0, 1.0], true);
61 |
62 | assert!(tolerance.equal(0, 0.76, 1.0));
63 | assert!(!tolerance.equal(0, 0.74, 1.0));
64 | assert!(tolerance.equal(1, 41.0, 80.0));
65 | assert!(!tolerance.equal(1, 39.0, 1.0));
66 | assert!(tolerance.equal(2, 100.5, 100.0));
67 | assert!(!tolerance.equal(2, 101.5, 100.0));
68 | }
69 |
70 | #[test]
71 | fn test_direct() {
72 | let tolerance = Tolerance::new([1.0, 2.0, 3.0, 4.0], false);
73 |
74 | assert!(tolerance.equal(0, 5.9, 5.0));
75 | assert!(!tolerance.equal(0, 6.1, 5.0));
76 | assert!(tolerance.equal(1, 3.1, 5.0));
77 | assert!(!tolerance.equal(1, 2.9, 5.0));
78 | assert!(tolerance.equal(3, 186.1, 190.0));
79 | assert!(!tolerance.equal(3, 185.9, 190.0));
80 | }
81 | }
82 |
```
--------------------------------------------------------------------------------
/vkrunner/include/vk_video/vulkan_video_codec_h264std_decode.h:
--------------------------------------------------------------------------------
```
1 | #ifndef VULKAN_VIDEO_CODEC_H264STD_DECODE_H_
2 | #define VULKAN_VIDEO_CODEC_H264STD_DECODE_H_ 1
3 |
4 | /*
5 | ** Copyright 2015-2025 The Khronos Group Inc.
6 | **
7 | ** SPDX-License-Identifier: Apache-2.0
8 | */
9 |
10 | /*
11 | ** This header is generated from the Khronos Vulkan XML API Registry.
12 | **
13 | */
14 |
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 |
21 |
22 | // vulkan_video_codec_h264std_decode is a preprocessor guard. Do not pass it to API calls.
23 | #define vulkan_video_codec_h264std_decode 1
24 | #include "vulkan_video_codec_h264std.h"
25 |
26 | #define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0)
27 |
28 | #define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_1_0_0
29 | #define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_decode"
30 | #define STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE 2
31 |
32 | typedef enum StdVideoDecodeH264FieldOrderCount {
33 | STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_TOP = 0,
34 | STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_BOTTOM = 1,
35 | STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_INVALID = 0x7FFFFFFF,
36 | STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_MAX_ENUM = 0x7FFFFFFF
37 | } StdVideoDecodeH264FieldOrderCount;
38 | typedef struct StdVideoDecodeH264PictureInfoFlags {
39 | uint32_t field_pic_flag : 1;
40 | uint32_t is_intra : 1;
41 | uint32_t IdrPicFlag : 1;
42 | uint32_t bottom_field_flag : 1;
43 | uint32_t is_reference : 1;
44 | uint32_t complementary_field_pair : 1;
45 | } StdVideoDecodeH264PictureInfoFlags;
46 |
47 | typedef struct StdVideoDecodeH264PictureInfo {
48 | StdVideoDecodeH264PictureInfoFlags flags;
49 | uint8_t seq_parameter_set_id;
50 | uint8_t pic_parameter_set_id;
51 | uint8_t reserved1;
52 | uint8_t reserved2;
53 | uint16_t frame_num;
54 | uint16_t idr_pic_id;
55 | int32_t PicOrderCnt[STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE];
56 | } StdVideoDecodeH264PictureInfo;
57 |
58 | typedef struct StdVideoDecodeH264ReferenceInfoFlags {
59 | uint32_t top_field_flag : 1;
60 | uint32_t bottom_field_flag : 1;
61 | uint32_t used_for_long_term_reference : 1;
62 | uint32_t is_non_existing : 1;
63 | } StdVideoDecodeH264ReferenceInfoFlags;
64 |
65 | typedef struct StdVideoDecodeH264ReferenceInfo {
66 | StdVideoDecodeH264ReferenceInfoFlags flags;
67 | uint16_t FrameNum;
68 | uint16_t reserved;
69 | int32_t PicOrderCnt[STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE];
70 | } StdVideoDecodeH264ReferenceInfo;
71 |
72 |
73 | #ifdef __cplusplus
74 | }
75 | #endif
76 |
77 | #endif
78 |
```
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
1 | FROM ubuntu:25.04 AS builder
2 |
3 | ENV DEBIAN_FRONTEND=noninteractive
4 |
5 | RUN apt-get update && apt-get install -y \
6 | bc \
7 | build-essential \
8 | clang \
9 | clang-format \
10 | clang-tidy \
11 | clang-tools \
12 | clangd \
13 | cmake \
14 | curl \
15 | ffmpeg \
16 | git \
17 | glslang-tools \
18 | glslc \
19 | jq \
20 | libshaderc-dev \
21 | libshaderc1 \
22 | imagemagick \
23 | libgl1-mesa-dri \
24 | libvulkan-dev \
25 | libvulkan1 \
26 | mesa-utils \
27 | mesa-vulkan-drivers \
28 | ninja-build \
29 | npm \
30 | pipx \
31 | python3 \
32 | python3-pip \
33 | python3-venv \
34 | rustup \
35 | sudo \
36 | unzip \
37 | vulkan-tools \
38 | wget \
39 | x11-utils \
40 | xvfb \
41 | && apt-get clean \
42 | && rm -rf /var/lib/apt/lists/*
43 |
44 | RUN rustup install 1.86.0 && \
45 | rustup default 1.86.0
46 |
47 | RUN rustup component add rustfmt && \
48 | rustup component add clippy && \
49 | rustup component add rust-src && \
50 | rustup component add rust-analyzer
51 |
52 | RUN sh -c "pipx ensurepath" && \
53 | bash -c "pipx ensurepath"
54 |
55 | RUN pipx install uv \
56 | && pipx install ruff \
57 | && pipx install pre-commit
58 |
59 | WORKDIR /app
60 | COPY . .
61 |
62 | RUN cargo build --release
63 |
64 | COPY vkrunner /vkrunner
65 |
66 | WORKDIR /vkrunner
67 |
68 | RUN cargo build --release && \
69 | cp /vkrunner/target/release/vkrunner /usr/local/bin/ && \
70 | chmod +x /usr/local/bin/vkrunner
71 |
72 | FROM ubuntu:25.04
73 |
74 | ENV DEBIAN_FRONTEND=noninteractive
75 |
76 | RUN apt-get update && apt-get install -y \
77 | bc \
78 | glslang-tools \
79 | glslc \
80 | imagemagick \
81 | jq \
82 | libgl1-mesa-dri \
83 | libshaderc1 \
84 | libvulkan1 \
85 | mesa-utils \
86 | mesa-vulkan-drivers \
87 | vulkan-tools \
88 | x11-utils \
89 | xvfb \
90 | && apt-get clean \
91 | && rm -rf /var/lib/apt/lists/*
92 |
93 | RUN echo '#!/bin/bash \n\
94 | export VK_ICD_FILES=$(find /usr/share/vulkan/icd.d/ -name "lvp_icd*.json") \n\
95 | export VK_ICD_FILENAMES=$VK_ICD_FILES \n\
96 | export VK_DRIVER_FILES=$VK_ICD_FILES \n\
97 | export LIBGL_ALWAYS_SOFTWARE=1 \n\
98 | export GALLIUM_DRIVER=llvmpipe \n\
99 | if ! ps aux | grep -v grep | grep "Xvfb :99" > /dev/null; then \n\
100 | rm -f /tmp/.X11-unix/X99 \n\
101 | rm -f /tmp/.X99-lock \n\
102 | Xvfb :99 -screen 0 960x540x24 > /dev/null 2>&1 & \n\
103 | fi \n\
104 | export DISPLAY=:99 \n\
105 | export XDG_RUNTIME_DIR=/tmp/xdg-runtime-dir \n\
106 | mkdir -p $XDG_RUNTIME_DIR && chmod 700 $XDG_RUNTIME_DIR \n\
107 | ' > /usr/local/bin/setup-vulkan-env.sh && chmod +x /usr/local/bin/setup-vulkan-env.sh
108 |
109 | RUN echo '#!/bin/bash \n\
110 | source /usr/local/bin/setup-vulkan-env.sh \n\
111 | if [[ "${1}" == --* ]]; then \n\
112 | /usr/local/bin/shaderc-vkrunner-mcp "$@" \n\
113 | else \n\
114 | exec "$@" \n\
115 | fi \n\
116 | ' > /entrypoint.sh && chmod +x /entrypoint.sh
117 |
118 | COPY --from=builder /app/target/release/shaderc-vkrunner-mcp /usr/local/bin/
119 | COPY --from=builder /usr/local/bin/vkrunner /usr/local/bin/
120 |
121 | WORKDIR /work
122 |
123 | ENTRYPOINT ["/entrypoint.sh"]
124 |
```
--------------------------------------------------------------------------------
/vkrunner/include/vulkan/vk_platform.h:
--------------------------------------------------------------------------------
```
1 | //
2 | // File: vk_platform.h
3 | //
4 | /*
5 | ** Copyright 2014-2025 The Khronos Group Inc.
6 | **
7 | ** SPDX-License-Identifier: Apache-2.0
8 | */
9 |
10 |
11 | #ifndef VK_PLATFORM_H_
12 | #define VK_PLATFORM_H_
13 |
14 | #ifdef __cplusplus
15 | extern "C"
16 | {
17 | #endif // __cplusplus
18 |
19 | /*
20 | ***************************************************************************************************
21 | * Platform-specific directives and type declarations
22 | ***************************************************************************************************
23 | */
24 |
25 | /* Platform-specific calling convention macros.
26 | *
27 | * Platforms should define these so that Vulkan clients call Vulkan commands
28 | * with the same calling conventions that the Vulkan implementation expects.
29 | *
30 | * VKAPI_ATTR - Placed before the return type in function declarations.
31 | * Useful for C++11 and GCC/Clang-style function attribute syntax.
32 | * VKAPI_CALL - Placed after the return type in function declarations.
33 | * Useful for MSVC-style calling convention syntax.
34 | * VKAPI_PTR - Placed between the '(' and '*' in function pointer types.
35 | *
36 | * Function declaration: VKAPI_ATTR void VKAPI_CALL vkCommand(void);
37 | * Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void);
38 | */
39 | #if defined(_WIN32)
40 | // On Windows, Vulkan commands use the stdcall convention
41 | #define VKAPI_ATTR
42 | #define VKAPI_CALL __stdcall
43 | #define VKAPI_PTR VKAPI_CALL
44 | #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
45 | #error "Vulkan is not supported for the 'armeabi' NDK ABI"
46 | #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
47 | // On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
48 | // calling convention, i.e. float parameters are passed in registers. This
49 | // is true even if the rest of the application passes floats on the stack,
50 | // as it does by default when compiling for the armeabi-v7a NDK ABI.
51 | #define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
52 | #define VKAPI_CALL
53 | #define VKAPI_PTR VKAPI_ATTR
54 | #else
55 | // On other platforms, use the default calling convention
56 | #define VKAPI_ATTR
57 | #define VKAPI_CALL
58 | #define VKAPI_PTR
59 | #endif
60 |
61 | #if !defined(VK_NO_STDDEF_H)
62 | #include <stddef.h>
63 | #endif // !defined(VK_NO_STDDEF_H)
64 |
65 | #if !defined(VK_NO_STDINT_H)
66 | #if defined(_MSC_VER) && (_MSC_VER < 1600)
67 | typedef signed __int8 int8_t;
68 | typedef unsigned __int8 uint8_t;
69 | typedef signed __int16 int16_t;
70 | typedef unsigned __int16 uint16_t;
71 | typedef signed __int32 int32_t;
72 | typedef unsigned __int32 uint32_t;
73 | typedef signed __int64 int64_t;
74 | typedef unsigned __int64 uint64_t;
75 | #else
76 | #include <stdint.h>
77 | #endif
78 | #endif // !defined(VK_NO_STDINT_H)
79 |
80 | #ifdef __cplusplus
81 | } // extern "C"
82 | #endif // __cplusplus
83 |
84 | #endif
85 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/small_float.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright (C) 2018, 2019 Intel Corporation
4 | // Copyright 2023 Neil Roberts
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a
7 | // copy of this software and associated documentation files (the "Software"),
8 | // to deal in the Software without restriction, including without limitation
9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 | // and/or sell copies of the Software, and to permit persons to whom the
11 | // Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice (including the next
14 | // paragraph) shall be included in all copies or substantial portions of the
15 | // Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | // DEALINGS IN THE SOFTWARE.
24 |
25 | pub fn load_unsigned(part: u32, e_bits: u32, m_bits: u32) -> f64 {
26 | let e_max = u32::MAX >> (32 - e_bits);
27 | let mut e = ((part >> m_bits) & e_max) as i32;
28 | let mut m = part & (u32::MAX >> (32 - m_bits));
29 |
30 | if e == e_max as i32 {
31 | if m == 0 {
32 | f64::INFINITY
33 | } else {
34 | f64::NAN
35 | }
36 | } else {
37 | if e == 0 {
38 | e = 1;
39 | } else {
40 | m += 1 << m_bits;
41 | }
42 |
43 | m as f64 / (1 << m_bits) as f64
44 | * ((e - (e_max >> 1) as i32) as f64).exp2()
45 | }
46 | }
47 |
48 | pub fn load_signed(part: u32, e_bits: u32, m_bits: u32) -> f64 {
49 | let res = load_unsigned(part, e_bits, m_bits);
50 |
51 | if !res.is_nan() && (part & (1 << (e_bits + m_bits))) != 0 {
52 | -res
53 | } else {
54 | res
55 | }
56 | }
57 |
58 | #[cfg(test)]
59 | mod test {
60 | use super::*;
61 |
62 | fn assert_float_equal(a: f64, b: f64) {
63 | assert!(
64 | (a - b).abs() < 0.001,
65 | "a={}, b={}",
66 | a,
67 | b
68 | );
69 | }
70 |
71 | #[test]
72 | fn test_load_unsigned() {
73 | assert_eq!(load_unsigned(0x30, 2, 4), f64::INFINITY);
74 | assert!(load_unsigned(0x3f, 2, 4).is_nan());
75 |
76 | assert_float_equal(load_unsigned(0, 3, 4), 0.0);
77 | assert_float_equal(load_unsigned(0x3555, 5, 10), 1.0 / 3.0);
78 | }
79 |
80 | #[test]
81 | fn test_load_signed() {
82 | assert_eq!(load_signed(0x70, 2, 4), -f64::INFINITY);
83 | assert!(load_signed(0x7f, 2, 4).is_nan());
84 |
85 | assert_float_equal(load_signed(0, 3, 4), 0.0);
86 | assert_float_equal(load_signed(0x3555, 5, 10), 1.0 / 3.0);
87 | assert_float_equal(load_signed(0xb555, 5, 10), -1.0 / 3.0);
88 | }
89 | }
90 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/make-enums.py:
--------------------------------------------------------------------------------
```python
1 | #!/usr/bin/env python
2 |
3 | # Copyright (C) 2018 Intel Corporation
4 | # Copyright 2023 Neil Roberts
5 |
6 | # Permission is hereby granted, free of charge, to any person obtaining a
7 | # copy of this software and associated documentation files (the "Software"),
8 | # to deal in the Software without restriction, including without limitation
9 | # the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 | # and/or sell copies of the Software, and to permit persons to whom the
11 | # Software is furnished to do so, subject to the following conditions:
12 |
13 | # The above copyright notice and this permission notice (including the next
14 | # paragraph) shall be included in all copies or substantial portions of the
15 | # Software.
16 |
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | # DEALINGS IN THE SOFTWARE.
24 |
25 | from __future__ import (
26 | absolute_import, division, print_function, unicode_literals
27 | )
28 |
29 | # This script is used to generate enum_table.rs from vulkan.h. It
30 | # is not run automatically as part of the build process but if need be
31 | # it can be used to update the file as follows:
32 | #
33 | # echo | gcc -include "vulkan/vulkan.h" -E - | ./make-enums.py > enum_table.rs
34 |
35 | import re
36 | import sys
37 | from mako.template import Template
38 |
39 | ENUMS = [
40 | 'VkPolygonMode',
41 | 'VkCullModeFlagBits',
42 | 'VkFrontFace',
43 | 'VkPrimitiveTopology',
44 | 'VkLogicOp',
45 | 'VkBlendFactor',
46 | 'VkBlendOp',
47 | 'VkColorComponentFlagBits',
48 | 'VkCompareOp',
49 | 'VkStencilOp',
50 | 'VkComponentTypeKHR',
51 | 'VkScopeKHR',
52 | ]
53 | VALUE_RE = re.compile(r'\s*\b(VK_(?:[A-Z0-9_]+))\b')
54 | ENUM_START_RE = re.compile(r'\s*typedef\s+enum\s+(Vk[A-Za-z0-9]+)')
55 | ENUM_END_RE = re.compile('}')
56 | PREPROCESSOR_RE = re.compile(r' *#')
57 |
58 | TEMPLATE="""\
59 | // Automatically generated by make-enums.py
60 | static ENUM_VALUES: [EnumValue; ${len(enums)}] = [
61 | % for e in enums:
62 | EnumValue {
63 | name: "${e}",
64 | value: vk::${e} as i32
65 | },
66 | % endfor
67 | ];"""
68 |
69 |
70 | def get_enums(data):
71 | enums = set()
72 | in_enum = False
73 |
74 | for line in data:
75 | if PREPROCESSOR_RE.match(line):
76 | continue
77 | md = ENUM_START_RE.match(line)
78 | if md:
79 | in_enum = md.group(1) in ENUMS
80 | if ENUM_END_RE.match(line):
81 | in_enum = False
82 | if not in_enum:
83 | continue
84 | md = VALUE_RE.match(line)
85 | if md:
86 | enums.add(md.group(1))
87 |
88 | return sorted(enums)
89 |
90 |
91 | def main():
92 | template = Template(TEMPLATE)
93 | print(template.render(enums = get_enums(sys.stdin)))
94 |
95 |
96 | if __name__ == '__main__':
97 | main()
98 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/inspect.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright (C) 2018 Intel Corporation
4 | // Copyright 2023 Neil Roberts
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a
7 | // copy of this software and associated documentation files (the "Software"),
8 | // to deal in the Software without restriction, including without limitation
9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 | // and/or sell copies of the Software, and to permit persons to whom the
11 | // Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice (including the next
14 | // paragraph) shall be included in all copies or substantial portions of the
15 | // Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | // DEALINGS IN THE SOFTWARE.
24 |
25 | use crate::format::Format;
26 | use std::ffi::{c_int, c_void};
27 | use std::fmt;
28 |
29 | #[repr(C)]
30 | pub struct Image {
31 | /// Width of the buffer
32 | pub width: c_int,
33 | /// Height of the buffer
34 | pub height: c_int,
35 |
36 | /// The stride in bytes from one row of the image to the next
37 | pub stride: usize,
38 |
39 | /// A description the format of each pixel in the buffer
40 | pub format: &'static Format,
41 |
42 | /// The buffer data
43 | pub data: *const c_void,
44 | }
45 |
46 | #[repr(C)]
47 | pub struct Buffer {
48 | /// The binding number of the buffer
49 | pub binding: c_int,
50 | /// Size in bytes of the buffer
51 | pub size: usize,
52 | /// The buffer data
53 | pub data: *const c_void,
54 | }
55 |
56 | #[repr(C)]
57 | pub struct Data {
58 | /// The color buffer
59 | pub color_buffer: Image,
60 | /// An array of buffers used as UBOs or SSBOs
61 | pub n_buffers: usize,
62 | pub buffers: *const Buffer,
63 | }
64 |
65 | /// A callback used to report the buffer and image data after
66 | /// executing each test.
67 | pub type Callback = extern "C" fn(
68 | data: &Data,
69 | user_data: *mut c_void,
70 | );
71 |
72 | /// A struct to combine the inspection callback with its user data pointer
73 | #[derive(Clone)]
74 | pub(crate) struct Inspector {
75 | callback: Callback,
76 | user_data: *mut c_void,
77 | }
78 |
79 | impl Inspector {
80 | pub fn new(callback: Callback, user_data: *mut c_void) -> Inspector {
81 | Inspector { callback, user_data }
82 | }
83 |
84 | pub fn inspect(&self, data: &Data) {
85 | (self.callback)(data, self.user_data);
86 | }
87 | }
88 |
89 | impl fmt::Debug for Inspector {
90 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91 | f.debug_struct("Inspector")
92 | .field("callback", &(self.callback as usize))
93 | .field("user_data", &self.user_data)
94 | .finish()
95 | }
96 | }
97 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/util.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright 2013, 2014, 2023 Neil Roberts
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a
6 | // copy of this software and associated documentation files (the "Software"),
7 | // to deal in the Software without restriction, including without limitation
8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | // and/or sell copies of the Software, and to permit persons to whom the
10 | // Software is furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice (including the next
13 | // paragraph) shall be included in all copies or substantial portions of the
14 | // Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 | // DEALINGS IN THE SOFTWARE.
23 |
24 | use std::env;
25 | use std::ffi::OsStr;
26 |
27 | /// Align a value, only works on power-of-two alignments
28 | #[inline]
29 | pub const fn align(value: usize, alignment: usize) -> usize {
30 | debug_assert!(alignment.is_power_of_two());
31 | debug_assert!(alignment > 0);
32 |
33 | (value + alignment - 1) & !(alignment - 1)
34 | }
35 |
36 | /// Reads an environment variable and interprets its value as a boolean.
37 | ///
38 | /// Recognizes 0/false/no and 1/true/yes. Other values result in the
39 | /// default value.
40 | pub fn env_var_as_boolean<K: AsRef<OsStr>>(
41 | var_name: K,
42 | default_value: bool,
43 | ) -> bool {
44 | match env::var(var_name) {
45 | Ok(value) => match value.as_str() {
46 | "1" | "true" | "yes" => true,
47 | "0" | "false" | "no" => false,
48 | _ => default_value,
49 | },
50 | Err(_) => default_value,
51 | }
52 | }
53 |
54 | #[cfg(test)]
55 | mod test {
56 | use super::*;
57 | use crate::env_var_test::EnvVarLock;
58 |
59 | #[test]
60 | fn test_align() {
61 | assert_eq!(align(3, 4), 4);
62 | assert_eq!(align(4, 4), 4);
63 | assert_eq!(align(0, 8), 0);
64 | assert_eq!(align(9, 8), 16);
65 | }
66 |
67 | fn test_env_var_value<V: AsRef<OsStr>>(
68 | value: V,
69 | default_value: bool,
70 | expected_result: bool
71 | ) {
72 | const TEST_VAR: &'static str = "VKRUNNER_TEST_ENV_VAR";
73 |
74 | let _env_var_lock = EnvVarLock::new(&[
75 | (TEST_VAR, value)
76 | ]);
77 |
78 | assert_eq!(
79 | env_var_as_boolean(TEST_VAR, default_value),
80 | expected_result
81 | );
82 | }
83 |
84 | #[test]
85 | fn test_env_var_as_boolean() {
86 | test_env_var_value("1", false, true);
87 | test_env_var_value("true", false, true);
88 | test_env_var_value("yes", false, true);
89 | test_env_var_value("0", true, false);
90 | test_env_var_value("false", true, false);
91 | test_env_var_value("no", true, false);
92 |
93 | assert_eq!(
94 | env_var_as_boolean("ENVIRONMENT_VARIABLE_THAT_DOESNT_EXIST", true),
95 | true,
96 | );
97 | assert_eq!(
98 | env_var_as_boolean("ENVIRONMENT_VARIABLE_THAT_DOESNT_EXIST", false),
99 | false,
100 | );
101 |
102 | test_env_var_value("other_value", false, false);
103 | test_env_var_value("other_value", true, true);
104 |
105 | // Test using a byte sequence that isn’t valid UTF-8. I think
106 | // this can’t happen on Windows.
107 | #[cfg(unix)]
108 | {
109 | use std::os::unix::ffi::OsStrExt;
110 |
111 | test_env_var_value(
112 | OsStr::from_bytes(b"Echant\xe9 in Latin-1"),
113 | false,
114 | false,
115 | );
116 | test_env_var_value(
117 | OsStr::from_bytes(b"Echant\xe9 in Latin-1"),
118 | true,
119 | true,
120 | );
121 | }
122 | }
123 | }
124 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/result.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright (C) 2018 Intel Corporation
4 | // Copyright 2023 Neil Roberts
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a
7 | // copy of this software and associated documentation files (the "Software"),
8 | // to deal in the Software without restriction, including without limitation
9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 | // and/or sell copies of the Software, and to permit persons to whom the
11 | // Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice (including the next
14 | // paragraph) shall be included in all copies or substantial portions of the
15 | // Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | // DEALINGS IN THE SOFTWARE.
24 |
25 | use std::fmt;
26 |
27 | /// Enum representing the possible results of a test.
28 | #[derive(Debug, Clone, Copy, Eq, PartialEq)]
29 | #[repr(C)]
30 | pub enum Result {
31 | Pass,
32 | Fail,
33 | Skip,
34 | }
35 |
36 | impl Result {
37 | /// Merge this result with another one. If either test is skipped
38 | /// then the value of the other result is returned. Otherwise if
39 | /// either of the tests failed then the global result is a
40 | /// failure. Finally if both tests passed then the global result
41 | /// is a pass.
42 | pub fn merge(self, other: Result) -> Result {
43 | match self {
44 | Result::Pass => {
45 | if other == Result::Skip {
46 | self
47 | } else {
48 | other
49 | }
50 | },
51 | Result::Fail => Result::Fail,
52 | Result::Skip => other,
53 | }
54 | }
55 |
56 | // Returns the name with a NULL terminator. This is needed because
57 | // there is a function in the public API which returns a static
58 | // string to C code.
59 | fn name_with_terminator(self) -> &'static str {
60 | match self {
61 | Result::Fail => "fail\0",
62 | Result::Skip => "skip\0",
63 | Result::Pass => "pass\0",
64 | }
65 | }
66 |
67 | /// Return either `"fail"`, `"skip"` or `"pass"` to describe the
68 | /// result. The result is a static string. You can also use the
69 | /// [to_string](ToString::to_string) method to get an owned string
70 | /// because [Result] implements [Display](std::fmt::Display).
71 | pub fn name(self) -> &'static str {
72 | let name = self.name_with_terminator();
73 | &name[0..name.len() - 1]
74 | }
75 | }
76 |
77 | impl fmt::Display for Result {
78 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79 | write!(f, "{}", self.name())
80 | }
81 | }
82 |
83 | #[cfg(test)]
84 | mod test {
85 | use super::*;
86 |
87 | #[test]
88 | fn test_merge() {
89 | assert_eq!(Result::Fail.merge(Result::Fail), Result::Fail);
90 | assert_eq!(Result::Fail.merge(Result::Skip), Result::Fail);
91 | assert_eq!(Result::Fail.merge(Result::Pass), Result::Fail);
92 | assert_eq!(Result::Skip.merge(Result::Fail), Result::Fail);
93 | assert_eq!(Result::Skip.merge(Result::Skip), Result::Skip);
94 | assert_eq!(Result::Skip.merge(Result::Pass), Result::Pass);
95 | assert_eq!(Result::Pass.merge(Result::Fail), Result::Fail);
96 | assert_eq!(Result::Pass.merge(Result::Skip), Result::Pass);
97 | assert_eq!(Result::Pass.merge(Result::Pass), Result::Pass);
98 | }
99 |
100 | #[test]
101 | fn test_name() {
102 | assert_eq!(Result::Fail.name(), "fail");
103 | assert_eq!(Result::Skip.name(), "skip");
104 | assert_eq!(Result::Pass.name(), "pass");
105 |
106 | for res in [Result::Fail, Result::Skip, Result::Pass] {
107 | assert_eq!(&res.to_string(), res.name());
108 | }
109 | }
110 | }
111 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/env_var_test.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright 2023 Neil Roberts
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a
6 | // copy of this software and associated documentation files (the "Software"),
7 | // to deal in the Software without restriction, including without limitation
8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | // and/or sell copies of the Software, and to permit persons to whom the
10 | // Software is furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice (including the next
13 | // paragraph) shall be included in all copies or substantial portions of the
14 | // Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 | // DEALINGS IN THE SOFTWARE.
23 |
24 | //! Helper to serialise unit tests that set environment variables so
25 | //! that there won’t be a race condition if the tests are run in
26 | //! parallel.
27 |
28 | use std::sync::{Mutex, MutexGuard};
29 | use std::collections::HashMap;
30 | use std::env;
31 | use std::ffi::{OsString, OsStr};
32 |
33 | // Mutex to make sure only one test is testing environment variables at a time
34 | static LOCK: Mutex<()> = Mutex::new(());
35 |
36 | /// Struct to help make unit tests that set environment variables.
37 | /// Only one EnvValLock can exist in the process at any one time. If a
38 | /// thread tries to construct a second one it will block until the
39 | /// first one is dropped. The environment variables will be restored
40 | /// when the EnvVarLock is dropped.
41 | pub struct EnvVarLock {
42 | old_values: HashMap<&'static str, Option<OsString>>,
43 | _mutex_lock: MutexGuard<'static, ()>,
44 | }
45 |
46 | impl EnvVarLock {
47 | /// Construct a new EnvVarLock and set the environment variables
48 | /// from the hash table. This will block if another EnvVarLock
49 | /// already exists. When the object is dropped the environment
50 | /// variables will be restored to their original values.
51 | ///
52 | /// Note that the object has no useful methods or members but you
53 | /// need to keep it alive in order to hold the mutex lock. One way
54 | /// to do this is to put the lock in a local variable prefixed
55 | /// with `_`:
56 | ///
57 | /// ```
58 | /// let _env_var_lock = EnvVarLock::new(&[
59 | /// ("MY_ENVIRONMENT_VARIABLE", "true")
60 | /// ]);
61 | /// assert_eq!(std::env::var("MY_ENVIRONMENT_VARIABLE").unwrap(), "true");
62 | /// ```
63 | pub fn new<V: AsRef<OsStr>>(
64 | variables: &[(&'static str, V)]
65 | ) -> EnvVarLock {
66 | let mutex_lock = LOCK.lock().unwrap();
67 |
68 | let old_values: HashMap<&'static str, Option<OsString>> = variables
69 | .iter()
70 | .map(|(variable, value)| {
71 | let old_value = env::var_os(variable);
72 | env::set_var(*variable, value);
73 | (*variable, old_value)
74 | })
75 | .collect();
76 |
77 | EnvVarLock { old_values, _mutex_lock: mutex_lock }
78 | }
79 | }
80 |
81 | impl Drop for EnvVarLock {
82 | fn drop(&mut self) {
83 | for (variable, value) in self.old_values.iter() {
84 | match value {
85 | Some(value) => env::set_var(variable, value),
86 | None => env::remove_var(variable),
87 | }
88 | }
89 | }
90 | }
91 |
92 | #[test]
93 | fn env_var_lock_test() {
94 | {
95 | let _env_var_lock = EnvVarLock::new(&[
96 | ("ENV_VAR_LOCK_TEST_ENVIRONMENT_VARIABLE", "true")
97 | ]);
98 | assert_eq!(
99 | std::env::var("ENV_VAR_LOCK_TEST_ENVIRONMENT_VARIABLE").unwrap(),
100 | "true"
101 | );
102 | }
103 |
104 | assert!(matches!(
105 | std::env::var("ENV_VAR_LOCK_TEST_ENVIRONMENT_VARIABLE"),
106 | Err(std::env::VarError::NotPresent),
107 | ));
108 | }
109 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/half_float.rs:
--------------------------------------------------------------------------------
```rust
1 | // Copyright (c) The Piglit project 2007
2 | // Copyright 2023 Neil Roberts
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a
5 | // copy of this software and associated documentation files (the "Software"),
6 | // to deal in the Software without restriction, including without limitation
7 | // on the rights to use, copy, modify, merge, publish, distribute, sub
8 | // license, and/or sell copies of the Software, and to permit persons to whom
9 | // the Software is furnished to do so, subject to the following conditions:
10 | //
11 | // The above copyright notice and this permission notice (including the next
12 | // paragraph) shall be included in all copies or substantial portions of the
13 | // Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 | // VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 | // USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | use crate::small_float;
24 |
25 | // Convert a 4-byte float to a 2-byte half float.
26 | // Based on code from:
27 | // http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html
28 | //
29 | // Taken over from Piglit which took it from Mesa.
30 | pub fn from_f32(val: f32) -> u16 {
31 | let fi = val.to_bits();
32 | let flt_m = fi & 0x7fffff;
33 | let flt_e = (fi >> 23) & 0xff;
34 | // sign bit
35 | let flt_s = (fi >> 31) & 0x1;
36 |
37 | let e;
38 | let m;
39 |
40 | // handle special cases
41 | if flt_e == 0 && flt_m == 0 {
42 | // zero
43 | m = 0;
44 | e = 0;
45 | } else if (flt_e == 0) && (flt_m != 0) {
46 | // denorm -- denorm float maps to 0 half
47 | m = 0;
48 | e = 0;
49 | } else if (flt_e == 0xff) && (flt_m == 0) {
50 | // infinity
51 | m = 0;
52 | e = 31;
53 | } else if (flt_e == 0xff) && (flt_m != 0) {
54 | // NaN
55 | m = 1;
56 | e = 31;
57 | } else {
58 | // regular number
59 | let new_exp = flt_e as i32 - 127;
60 | if new_exp < -24 {
61 | // this maps to 0
62 | m = 0;
63 | e = 0;
64 | } else if new_exp < -14 {
65 | // this maps to a denorm
66 | // 2^-exp_val
67 | let exp_val = (-14 - new_exp) as u32;
68 |
69 | e = 0;
70 |
71 | match exp_val {
72 | 0 => m = 0,
73 | 1 => m = 512 + (flt_m >> 14),
74 | 2 => m = 256 + (flt_m >> 15),
75 | 3 => m = 128 + (flt_m >> 16),
76 | 4 => m = 64 + (flt_m >> 17),
77 | 5 => m = 32 + (flt_m >> 18),
78 | 6 => m = 16 + (flt_m >> 19),
79 | 7 => m = 8 + (flt_m >> 20),
80 | 8 => m = 4 + (flt_m >> 21),
81 | 9 => m = 2 + (flt_m >> 22),
82 | 10 => m = 1,
83 | _ => unreachable!(),
84 | }
85 | } else if new_exp > 15 {
86 | // map this value to infinity
87 | m = 0;
88 | e = 31;
89 | } else {
90 | /* regular */
91 | e = (new_exp + 15) as u32;
92 | m = flt_m >> 13;
93 | }
94 | }
95 |
96 | ((flt_s << 15) | (e << 10) | m) as u16
97 | }
98 |
99 | pub fn to_f64(half: u16) -> f64 {
100 | small_float::load_signed(half as u32, 5, 10)
101 | }
102 |
103 | #[cfg(test)]
104 | mod test {
105 | use super::*;
106 |
107 | #[test]
108 | fn test_from_f32() {
109 | assert_eq!(from_f32(0.0), 0);
110 | assert_eq!(from_f32(1.0 / 3.0), 0x3555);
111 | assert_eq!(from_f32(-1.0 / 3.0), 0xb555);
112 | assert_eq!(from_f32(f32::INFINITY), 0x7c00);
113 | assert_eq!(from_f32(-f32::INFINITY), 0xfc00);
114 | assert_eq!(from_f32(f32::NAN), 0x7c01);
115 | assert_eq!(from_f32(f32::MAX), 0x7c00);
116 | }
117 |
118 | fn assert_float_equal(a: f64, b: f64) {
119 | assert!(
120 | (a - b).abs() < 0.001,
121 | "a={}, b={}",
122 | a,
123 | b
124 | );
125 | }
126 |
127 | #[test]
128 | fn test_to_f64() {
129 | assert_eq!(to_f64(0x7c00), f64::INFINITY);
130 | assert_eq!(to_f64(0xfc00), -f64::INFINITY);
131 | assert_float_equal(to_f64(0x3555), 1.0 / 3.0);
132 | }
133 | }
134 |
```
--------------------------------------------------------------------------------
/vkrunner/include/vk_video/vulkan_video_codec_av1std_decode.h:
--------------------------------------------------------------------------------
```
1 | #ifndef VULKAN_VIDEO_CODEC_AV1STD_DECODE_H_
2 | #define VULKAN_VIDEO_CODEC_AV1STD_DECODE_H_ 1
3 |
4 | /*
5 | ** Copyright 2015-2025 The Khronos Group Inc.
6 | **
7 | ** SPDX-License-Identifier: Apache-2.0
8 | */
9 |
10 | /*
11 | ** This header is generated from the Khronos Vulkan XML API Registry.
12 | **
13 | */
14 |
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 |
21 |
22 | // vulkan_video_codec_av1std_decode is a preprocessor guard. Do not pass it to API calls.
23 | #define vulkan_video_codec_av1std_decode 1
24 | #include "vulkan_video_codec_av1std.h"
25 |
26 | #define VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0)
27 |
28 | #define VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_API_VERSION_1_0_0
29 | #define VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_av1_decode"
30 | typedef struct StdVideoDecodeAV1PictureInfoFlags {
31 | uint32_t error_resilient_mode : 1;
32 | uint32_t disable_cdf_update : 1;
33 | uint32_t use_superres : 1;
34 | uint32_t render_and_frame_size_different : 1;
35 | uint32_t allow_screen_content_tools : 1;
36 | uint32_t is_filter_switchable : 1;
37 | uint32_t force_integer_mv : 1;
38 | uint32_t frame_size_override_flag : 1;
39 | uint32_t buffer_removal_time_present_flag : 1;
40 | uint32_t allow_intrabc : 1;
41 | uint32_t frame_refs_short_signaling : 1;
42 | uint32_t allow_high_precision_mv : 1;
43 | uint32_t is_motion_mode_switchable : 1;
44 | uint32_t use_ref_frame_mvs : 1;
45 | uint32_t disable_frame_end_update_cdf : 1;
46 | uint32_t allow_warped_motion : 1;
47 | uint32_t reduced_tx_set : 1;
48 | uint32_t reference_select : 1;
49 | uint32_t skip_mode_present : 1;
50 | uint32_t delta_q_present : 1;
51 | uint32_t delta_lf_present : 1;
52 | uint32_t delta_lf_multi : 1;
53 | uint32_t segmentation_enabled : 1;
54 | uint32_t segmentation_update_map : 1;
55 | uint32_t segmentation_temporal_update : 1;
56 | uint32_t segmentation_update_data : 1;
57 | uint32_t UsesLr : 1;
58 | uint32_t usesChromaLr : 1;
59 | uint32_t apply_grain : 1;
60 | uint32_t reserved : 3;
61 | } StdVideoDecodeAV1PictureInfoFlags;
62 |
63 | typedef struct StdVideoDecodeAV1PictureInfo {
64 | StdVideoDecodeAV1PictureInfoFlags flags;
65 | StdVideoAV1FrameType frame_type;
66 | uint32_t current_frame_id;
67 | uint8_t OrderHint;
68 | uint8_t primary_ref_frame;
69 | uint8_t refresh_frame_flags;
70 | uint8_t reserved1;
71 | StdVideoAV1InterpolationFilter interpolation_filter;
72 | StdVideoAV1TxMode TxMode;
73 | uint8_t delta_q_res;
74 | uint8_t delta_lf_res;
75 | uint8_t SkipModeFrame[STD_VIDEO_AV1_SKIP_MODE_FRAMES];
76 | uint8_t coded_denom;
77 | uint8_t reserved2[3];
78 | uint8_t OrderHints[STD_VIDEO_AV1_NUM_REF_FRAMES];
79 | uint32_t expectedFrameId[STD_VIDEO_AV1_NUM_REF_FRAMES];
80 | const StdVideoAV1TileInfo* pTileInfo;
81 | const StdVideoAV1Quantization* pQuantization;
82 | const StdVideoAV1Segmentation* pSegmentation;
83 | const StdVideoAV1LoopFilter* pLoopFilter;
84 | const StdVideoAV1CDEF* pCDEF;
85 | const StdVideoAV1LoopRestoration* pLoopRestoration;
86 | const StdVideoAV1GlobalMotion* pGlobalMotion;
87 | const StdVideoAV1FilmGrain* pFilmGrain;
88 | } StdVideoDecodeAV1PictureInfo;
89 |
90 | typedef struct StdVideoDecodeAV1ReferenceInfoFlags {
91 | uint32_t disable_frame_end_update_cdf : 1;
92 | uint32_t segmentation_enabled : 1;
93 | uint32_t reserved : 30;
94 | } StdVideoDecodeAV1ReferenceInfoFlags;
95 |
96 | typedef struct StdVideoDecodeAV1ReferenceInfo {
97 | StdVideoDecodeAV1ReferenceInfoFlags flags;
98 | uint8_t frame_type;
99 | uint8_t RefFrameSignBias;
100 | uint8_t OrderHint;
101 | uint8_t SavedOrderHints[STD_VIDEO_AV1_NUM_REF_FRAMES];
102 | } StdVideoDecodeAV1ReferenceInfo;
103 |
104 |
105 | #ifdef __cplusplus
106 | }
107 | #endif
108 |
109 | #endif
110 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/compiler/fake_process.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright 2023 Neil Roberts
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a
6 | // copy of this software and associated documentation files (the "Software"),
7 | // to deal in the Software without restriction, including without limitation
8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | // and/or sell copies of the Software, and to permit persons to whom the
10 | // Software is furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice (including the next
13 | // paragraph) shall be included in all copies or substantial portions of the
14 | // Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 | // DEALINGS IN THE SOFTWARE.
23 |
24 | //! This module is just for the unit tests. It makes an alternative
25 | //! version of the Stdio, Command and Output structs from std::process
26 | //! that run a fake compiler so we can get code coverage in
27 | //! compiler.rs without depending a real GLSL compiler.
28 |
29 | use std::process::Stdio;
30 | use std::io::{Write, BufWriter, BufReader, BufRead};
31 | use std::fs::File;
32 | use std::ffi::OsStr;
33 | use std::num::ParseIntError;
34 |
35 | pub struct ExitStatus {
36 | success: bool,
37 | }
38 |
39 | pub struct Output {
40 | pub status: ExitStatus,
41 | pub stdout: Vec<u8>,
42 | pub stderr: Vec<u8>,
43 | }
44 |
45 | pub struct Command {
46 | args: Vec<String>,
47 | }
48 |
49 | impl Command {
50 | pub fn new<S: AsRef<OsStr>>(_program: S) -> Command {
51 | Command {
52 | args: Vec::new(),
53 | }
54 | }
55 |
56 | pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
57 | self.args.push(arg.as_ref().to_str().unwrap().to_string());
58 |
59 | self
60 | }
61 |
62 | pub fn args<I, S>(&mut self, args: I) -> &mut Command
63 | where
64 | I: IntoIterator<Item = S>,
65 | S: AsRef<OsStr>,
66 | {
67 | for arg in args {
68 | self.arg(arg);
69 | }
70 |
71 | self
72 | }
73 |
74 | pub fn stdout<T: Into<Stdio>>(&mut self, _cfg: T) -> &mut Command {
75 | self
76 | }
77 |
78 | pub fn stderr<T: Into<Stdio>>(&mut self, _cfg: T) -> &mut Command {
79 | self
80 | }
81 |
82 | pub fn output(&mut self) -> std::io::Result<Output> {
83 | let mut inputs = Vec::new();
84 | let mut output = None;
85 | let mut stdout = Vec::new();
86 | let mut stderr = Vec::new();
87 | let mut success = true;
88 |
89 | let mut args = self.args.iter();
90 |
91 | while let Some(arg) = args.next() {
92 | match arg.as_str() {
93 | "--quiet" => writeln!(&mut stdout, "quiet").unwrap(),
94 | "-V" => writeln!(&mut stdout, "vulkan_spirv").unwrap(),
95 | "--target-env" => {
96 | writeln!(
97 | &mut stdout,
98 | "target_env: {}",
99 | args.next().unwrap()
100 | ).unwrap();
101 | },
102 | "-S" => {
103 | writeln!(&mut stdout, "stage: {}", args.next().unwrap())
104 | .unwrap();
105 | },
106 | "-o" => output = Some(args.next().unwrap()),
107 | other_arg if other_arg.starts_with("-") => {
108 | unreachable!("unexpected arg: {}", other_arg);
109 | },
110 | input_file => inputs.push(input_file.to_owned()),
111 | }
112 | }
113 |
114 | match output {
115 | None => {
116 | // Pretend to output the disassembly
117 | writeln!(&mut stdout, "disassembly").unwrap();
118 | },
119 | Some(output) => {
120 | if let Err(e) = copy_inputs(&inputs, &output) {
121 | writeln!(&mut stderr, "{}", e).unwrap();
122 | success = false;
123 | }
124 | }
125 | }
126 |
127 | Ok(Output {
128 | status: ExitStatus { success },
129 | stdout,
130 | stderr,
131 | })
132 | }
133 | }
134 |
135 | impl ExitStatus {
136 | pub fn success(&self) -> bool {
137 | self.success
138 | }
139 | }
140 |
141 | fn copy_inputs(inputs: &[String], output: &str) -> Result<(), ParseIntError> {
142 | let mut output = BufWriter::new(File::create(output).unwrap());
143 |
144 | for input in inputs {
145 | let input = File::open(input).unwrap();
146 |
147 | for line in BufReader::new(input).lines() {
148 | for byte in line.unwrap().split_whitespace() {
149 | let byte_array = [u8::from_str_radix(byte, 16)?];
150 | output.write_all(&byte_array).unwrap();
151 | }
152 | }
153 | }
154 |
155 | Ok(())
156 | }
157 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/make-formats.py:
--------------------------------------------------------------------------------
```python
1 | #!/usr/bin/env python
2 |
3 | # Copyright (C) 2018 Intel Corporation
4 | # Copyright 2023 Neil Roberts
5 |
6 | # Permission is hereby granted, free of charge, to any person obtaining a
7 | # copy of this software and associated documentation files (the "Software"),
8 | # to deal in the Software without restriction, including without limitation
9 | # the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 | # and/or sell copies of the Software, and to permit persons to whom the
11 | # Software is furnished to do so, subject to the following conditions:
12 |
13 | # The above copyright notice and this permission notice (including the next
14 | # paragraph) shall be included in all copies or substantial portions of the
15 | # Software.
16 |
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | # DEALINGS IN THE SOFTWARE.
24 |
25 | from __future__ import (
26 | absolute_import, division, print_function, unicode_literals
27 | )
28 |
29 | # This script is used to generate format_table.rs from vulkan.h. It is
30 | # not run automatically as part of the build process but if need be it
31 | # can be used to update the file as follows:
32 | #
33 | # ./make-formats.py < /usr/include/vulkan/vulkan.h > format_table.rs
34 |
35 | import re
36 | import sys
37 | from mako.template import Template
38 |
39 | FORMAT_RE = re.compile(r'\bVK_FORMAT_([A-Z0-9_]+)\s*=\s*((?:0x)?[a-fA-F0-9]+)')
40 | SKIP_RE = re.compile(r'(?:_BLOCK(?:_IMG)?|_KHR|^UNDEFINED|'
41 | r'^RANGE_SIZE|^MAX_ENUM|_RANGE)$')
42 | COMPONENT_RE = re.compile('([A-Z]+)([0-9]+)')
43 | COMPONENTS_RE = re.compile('(?:[A-Z][0-9]+)+$')
44 | STUB_RE = re.compile('X([0-9]+)$')
45 | PACK_RE = re.compile('PACK([0-9]+)$')
46 | MODE_RE = re.compile('(?:[US](?:NORM|SCALED|INT|FLOAT)|SRGB)$')
47 |
48 | TEMPLATE="""\
49 | // Automatically generated by make-formats.py
50 |
51 | static FORMATS: [Format; ${len(formats)}] = [
52 | % for format in formats:
53 | Format {
54 | vk_format: vk::VK_FORMAT_${format['name']},
55 | name: "${format['name']}",
56 | % if format['packed_size'] is None:
57 | packed_size: None,
58 | % else:
59 | packed_size: Some(unsafe {
60 | NonZeroUsize::new_unchecked(${format['packed_size']})
61 | }),
62 | % endif
63 | n_parts: ${len(format['components'])},
64 | parts: [
65 | % for letter, size, mode in format['components']:
66 | Part {
67 | bits: ${size},
68 | component: Component::${letter},
69 | mode: Mode::${mode},
70 | },
71 | % endfor
72 | % for _ in range(len(format['components']), 4):
73 | // stub to fill the array
74 | Part { bits: 0, component: Component::R, mode: Mode::UNORM },
75 | % endfor
76 | ]
77 | },
78 | % endfor
79 | ];"""
80 |
81 |
82 | def get_format_names(data):
83 | in_enum = False
84 |
85 | for line in data:
86 | if line.startswith('typedef enum VkFormat '):
87 | in_enum = True
88 | elif line.startswith('}'):
89 | in_enum = False
90 | if not in_enum:
91 | continue
92 |
93 | md = FORMAT_RE.search(line)
94 | if md is None:
95 | continue
96 | name = md.group(1)
97 | if SKIP_RE.search(name):
98 | continue
99 | yield name, int(md.group(2), base=0)
100 |
101 |
102 | def get_formats(data):
103 | for name, value in sorted(set(get_format_names(data))):
104 | parts = name.split('_')
105 |
106 | components, packed_size = get_components(parts)
107 |
108 | if components is None:
109 | continue
110 |
111 | yield {'name': name,
112 | 'value': value,
113 | 'packed_size': packed_size,
114 | 'components': components}
115 |
116 |
117 | def get_components(parts):
118 | packed_size = None
119 | components = []
120 |
121 | i = 0
122 | while i < len(parts):
123 | md = STUB_RE.match(parts[i])
124 | if md:
125 | components.append(('X', int(md.group(1)), 'UNORM'))
126 | i += 1
127 | continue
128 |
129 | md = COMPONENTS_RE.match(parts[i])
130 | if md:
131 | if i + 2 > len(parts):
132 | return None, None
133 | mode_md = MODE_RE.match(parts[i + 1])
134 | if mode_md is None:
135 | return None, None
136 |
137 | comps = [(md.group(1), int(md.group(2)), parts[i + 1])
138 | for md in COMPONENT_RE.finditer(parts[i])]
139 |
140 | for letter, size, mode in comps:
141 | if letter not in "RGBADSX":
142 | return None, None
143 |
144 | components.extend(comps)
145 | i += 2
146 | continue
147 |
148 | md = PACK_RE.match(parts[i])
149 | if md:
150 | packed_size = int(md.group(1))
151 | i += 1
152 | continue
153 |
154 | return None, None
155 |
156 | return components, packed_size
157 |
158 |
159 | def main():
160 | template = Template(TEMPLATE)
161 | print(template.render(formats = list(get_formats(sys.stdin))))
162 |
163 |
164 | if __name__ == '__main__':
165 | main()
166 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/source.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright (C) 2018 Intel Corporation
4 | // Copyright 2023 Neil Roberts
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a
7 | // copy of this software and associated documentation files (the "Software"),
8 | // to deal in the Software without restriction, including without limitation
9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 | // and/or sell copies of the Software, and to permit persons to whom the
11 | // Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice (including the next
14 | // paragraph) shall be included in all copies or substantial portions of the
15 | // Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | // DEALINGS IN THE SOFTWARE.
24 |
25 | use std::path::PathBuf;
26 |
27 | /// Struct representing the requested source for the data of a
28 | /// [Source]. This can either be a filename to open and read
29 | /// or directly a string containing the source code.
30 | #[derive(Clone, Debug)]
31 | pub(crate) enum Data {
32 | File { filename: PathBuf },
33 | String { source: String },
34 | }
35 |
36 | #[derive(Clone, Debug)]
37 | /// A token replacement that should be used for the source. The reader
38 | /// should replace any occurences of `token` in the source with the
39 | /// string in `replacement`.
40 | pub(crate) struct TokenReplacement {
41 | pub token: String,
42 | pub replacement: String,
43 | }
44 |
45 | /// A source for a shader script. The [Source] struct just contains
46 | /// the details of where the data is stored along with any token
47 | /// replacements to be used while reading the data.
48 | #[derive(Clone, Debug)]
49 | pub struct Source {
50 | token_replacements: Vec<TokenReplacement>,
51 | data: Data,
52 | }
53 |
54 | type TokenReplacementIter<'a> = std::slice::Iter<'a, TokenReplacement>;
55 |
56 | impl Source {
57 | fn from_data(data: Data) -> Source {
58 | Source {
59 | token_replacements: Vec::new(),
60 | data,
61 | }
62 | }
63 |
64 | /// Creates a source that will read lines from the given string.
65 | pub fn from_string(source: String) -> Source {
66 | Self::from_data(Data::String { source })
67 | }
68 |
69 | /// Creates a source that will read lines from the given file.
70 | pub fn from_file(filename: PathBuf) -> Source {
71 | Self::from_data(Data::File { filename })
72 | }
73 |
74 | /// Adds a token replacement to the source. When lines are read
75 | /// from the source, any mentions of the token will be replaced
76 | /// with the replacement. The replacement can also contain tokens
77 | /// which will be replaced as well. This can cause the line
78 | /// reading to fail and return an error if it causes an infinite
79 | /// loop.
80 | pub fn add_token_replacement(
81 | &mut self,
82 | token: String,
83 | replacement: String,
84 | ) {
85 | self.token_replacements.push(TokenReplacement { token, replacement });
86 | }
87 |
88 | /// Return an iterator over the token replacements that were
89 | /// previously set with
90 | /// [add_token_replacement](Source::add_token_replacement).
91 | pub(crate) fn token_replacements(&self) -> TokenReplacementIter {
92 | self.token_replacements.iter()
93 | }
94 |
95 | /// Get the data that the source points to.
96 | pub(crate) fn data(&self) -> &Data {
97 | &self.data
98 | }
99 | }
100 |
101 | #[cfg(test)]
102 | mod test {
103 | use super::*;
104 |
105 | #[test]
106 | fn test_constructors() {
107 | let source = Source::from_string("my script".to_owned());
108 | assert!(matches!(
109 | source.data(),
110 | Data::String { source } if source == "my script"
111 | ));
112 |
113 | let source = Source::from_file(
114 | "my_script.shader_test".to_owned().into()
115 | );
116 | assert!(matches!(
117 | source.data(),
118 | Data::File { filename }
119 | if filename.to_str().unwrap() == "my_script.shader_test",
120 | ));
121 | }
122 |
123 | #[test]
124 | fn test_token_replacements() {
125 | let mut source = Source::from_string("test".to_string());
126 |
127 | assert_eq!(source.token_replacements.len(), 0);
128 |
129 | source.add_token_replacement("COLOUR".to_string(), "0xf00".to_string());
130 |
131 | assert_eq!(source.token_replacements.len(), 1);
132 | assert_eq!(source.token_replacements[0].token, "COLOUR");
133 | assert_eq!(source.token_replacements[0].replacement, "0xf00");
134 |
135 | let mut iter = source.token_replacements();
136 | assert_eq!(iter.next().unwrap().token, "COLOUR");
137 | assert!(iter.next().is_none());
138 |
139 | source.add_token_replacement("X".to_string(), "12".to_string());
140 |
141 | assert_eq!(source.token_replacements.len(), 2);
142 | assert_eq!(source.token_replacements[0].token, "COLOUR");
143 | assert_eq!(source.token_replacements[0].replacement, "0xf00");
144 | assert_eq!(source.token_replacements[1].token, "X");
145 | assert_eq!(source.token_replacements[1].replacement, "12");
146 |
147 | let mut iter = source.token_replacements();
148 | assert_eq!(iter.next().unwrap().token, "COLOUR");
149 | assert_eq!(iter.next().unwrap().token, "X");
150 | assert!(iter.next().is_none());
151 | }
152 | }
153 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/config.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright (C) 2018 Intel Corporation
4 | // Copyright 2023 Neil Roberts
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a
7 | // copy of this software and associated documentation files (the "Software"),
8 | // to deal in the Software without restriction, including without limitation
9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 | // and/or sell copies of the Software, and to permit persons to whom the
11 | // Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice (including the next
14 | // paragraph) shall be included in all copies or substantial portions of the
15 | // Software.
16 | //
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | // DEALINGS IN THE SOFTWARE.
24 |
25 | use crate::logger::{self, Logger};
26 | use crate::inspect;
27 | use std::ffi::c_void;
28 | use std::ptr;
29 | use std::cell::{Cell, RefCell};
30 | use std::rc::Rc;
31 | use std::fmt;
32 |
33 | pub type ErrorCallback = logger::WriteCallback;
34 |
35 | pub struct Config {
36 | show_disassembly: bool,
37 | device_id: Option<usize>,
38 |
39 | error_cb: Option<logger::WriteCallback>,
40 | inspect_cb: Option<inspect::Callback>,
41 | user_data: *mut c_void,
42 |
43 | logger: Cell<Option<Rc<RefCell<Logger>>>>,
44 | }
45 |
46 | impl Config {
47 | pub fn new() -> Config {
48 | Config {
49 | show_disassembly: false,
50 | device_id: None,
51 | error_cb: None,
52 | inspect_cb: None,
53 | user_data: ptr::null_mut(),
54 | logger: Cell::new(None),
55 | }
56 | }
57 |
58 | /// Sets whether the SPIR-V disassembly of the shaders should be
59 | /// shown when a script is run. The disassembly will be shown on
60 | /// the standard out or it will be passed to the `error_cb` if one
61 | /// has been set. The disassembly is generated with the
62 | /// `spirv-dis` program which needs to be found in the path or it
63 | /// can be specified with the `PIGLIT_SPIRV_DIS_BINARY`
64 | /// environment variable.
65 | pub fn set_show_disassembly(&mut self, show_disassembly: bool) {
66 | self.show_disassembly = show_disassembly;
67 | }
68 |
69 | /// Sets or removes a callback that will receive error messages
70 | /// generated during the script execution. The callback will be
71 | /// invoked one line at a time without the trailing newline
72 | /// terminator. If no callback is specified then the output will
73 | /// be printed on the standard output instead. The callback can
74 | /// later be removed by passing `None`.
75 | pub fn set_error_cb(&mut self, error_cb: Option<ErrorCallback>) {
76 | self.error_cb = error_cb;
77 | self.reset_logger();
78 | }
79 |
80 | /// Sets or removes an inspection callback. The callback will be
81 | /// invoked after executing a script so that the application can
82 | /// have a chance to examine the framebuffer and any storage or
83 | /// uniform buffers created by the script.
84 | pub fn set_inspect_cb(&mut self, inspect_cb: Option<inspect::Callback>) {
85 | self.inspect_cb = inspect_cb;
86 | }
87 |
88 | /// Sets a pointer that will be passed to the `error_cb` and the
89 | /// `inspect_cb`.
90 | pub fn set_user_data(&mut self, user_data: *mut c_void) {
91 | self.user_data = user_data;
92 | self.reset_logger();
93 | }
94 |
95 | /// Sets or removes a device number to pick out of the list of
96 | /// `vkPhysicalDevice`s returned by `vkEnumeratePhysicalDevices`.
97 | /// The device will still be checked to see if it is compatible
98 | /// with the script and the test will report Skip if not. If no
99 | /// device ID is set then VkRunner will pick the first one that is
100 | /// compatible with the script.
101 | pub fn set_device_id(&mut self, device_id: Option<usize>) {
102 | self.device_id = device_id;
103 | }
104 |
105 | /// Get a logger that will write to the current `error_cb` of the
106 | /// `Config`. The logger will be shared between calls to this
107 | /// until the callback is changed.
108 | pub(crate) fn logger(&self) -> Rc<RefCell<Logger>> {
109 | let logger = self.logger.take().unwrap_or_else(|| {
110 | Rc::new(RefCell::new(Logger::new(self.error_cb, self.user_data)))
111 | });
112 |
113 | self.logger.set(Some(Rc::clone(&logger)));
114 |
115 | logger
116 | }
117 |
118 | pub(crate) fn inspector(&self) -> Option<inspect::Inspector> {
119 | self.inspect_cb.map(|cb| inspect::Inspector::new(cb, self.user_data))
120 | }
121 |
122 | pub(crate) fn show_disassembly(&self) -> bool {
123 | self.show_disassembly
124 | }
125 |
126 | pub(crate) fn device_id(&self) -> Option<usize> {
127 | self.device_id
128 | }
129 |
130 | fn reset_logger(&self) {
131 | // Reset the logger back to None so that it will be
132 | // reconstructed the next time it is requested.
133 | self.logger.take();
134 | }
135 | }
136 |
137 | // Need to implement this manually because the derive macro can’t
138 | // handle Cells
139 | impl fmt::Debug for Config {
140 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 | f.debug_struct("Config")
142 | .field("show_disassembly", &self.show_disassembly)
143 | .field("device_id", &self.device_id)
144 | .field("user_data", &self.user_data)
145 | .finish()
146 | }
147 | }
148 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/make-vulkan-funcs-data.py:
--------------------------------------------------------------------------------
```python
1 | #!/usr/bin/env python
2 |
3 | # Copyright 2023 Neil Roberts
4 |
5 | # Permission is hereby granted, free of charge, to any person obtaining a
6 | # copy of this software and associated documentation files (the "Software"),
7 | # to deal in the Software without restriction, including without limitation
8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | # and/or sell copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following conditions:
11 |
12 | # The above copyright notice and this permission notice (including the next
13 | # paragraph) shall be included in all copies or substantial portions of the
14 | # Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 | # DEALINGS IN THE SOFTWARE.
23 |
24 | from __future__ import (
25 | absolute_import, division, print_function, unicode_literals
26 | )
27 |
28 | # This script is used to generate vulkan_funcs_data.rs. It is not run
29 | # automatically as part of the build process but if need be it can be
30 | # used to update the file as follows:
31 | #
32 | # ./make-vulkan-funcs-data.py > vulkan_funcs_data.rs
33 |
34 | from mako.template import Template
35 |
36 |
37 | CORE_FUNCS = [
38 | "vkGetInstanceProcAddr",
39 | "vkCreateInstance",
40 | "vkEnumerateInstanceExtensionProperties",
41 | ]
42 |
43 |
44 | INSTANCE_FUNCS = [
45 | "vkCreateDevice",
46 | "vkDestroyInstance",
47 | "vkEnumerateDeviceExtensionProperties",
48 | "vkEnumeratePhysicalDevices",
49 | "vkGetDeviceProcAddr",
50 | "vkGetPhysicalDeviceFeatures",
51 | "vkGetPhysicalDeviceFeatures2KHR",
52 | "vkGetPhysicalDeviceFormatProperties",
53 | "vkGetPhysicalDeviceMemoryProperties",
54 | "vkGetPhysicalDeviceProperties",
55 | "vkGetPhysicalDeviceProperties2",
56 | "vkGetPhysicalDeviceQueueFamilyProperties",
57 | "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR",
58 | ]
59 |
60 |
61 | DEVICE_FUNCS = [
62 | "vkAllocateCommandBuffers",
63 | "vkAllocateDescriptorSets",
64 | "vkAllocateMemory",
65 | "vkBeginCommandBuffer",
66 | "vkBindBufferMemory",
67 | "vkBindImageMemory",
68 | "vkCmdBeginRenderPass",
69 | "vkCmdBindDescriptorSets",
70 | "vkCmdBindIndexBuffer",
71 | "vkCmdBindPipeline",
72 | "vkCmdBindVertexBuffers",
73 | "vkCmdClearAttachments",
74 | "vkCmdCopyBufferToImage",
75 | "vkCmdCopyImageToBuffer",
76 | "vkCmdDispatch",
77 | "vkCmdDraw",
78 | "vkCmdDrawIndexed",
79 | "vkCmdDrawIndexedIndirect",
80 | "vkCmdEndRenderPass",
81 | "vkCmdPipelineBarrier",
82 | "vkCmdPushConstants",
83 | "vkCmdSetScissor",
84 | "vkCmdSetViewport",
85 | "vkCreateBuffer",
86 | "vkCreateCommandPool",
87 | "vkCreateComputePipelines",
88 | "vkCreateDescriptorPool",
89 | "vkCreateDescriptorSetLayout",
90 | "vkCreateFence",
91 | "vkCreateFramebuffer",
92 | "vkCreateGraphicsPipelines",
93 | "vkCreateImage",
94 | "vkCreateImageView",
95 | "vkCreatePipelineCache",
96 | "vkCreatePipelineLayout",
97 | "vkCreateRenderPass",
98 | "vkCreateSampler",
99 | "vkCreateSemaphore",
100 | "vkCreateShaderModule",
101 | "vkDestroyBuffer",
102 | "vkDestroyCommandPool",
103 | "vkDestroyDescriptorPool",
104 | "vkDestroyDescriptorSetLayout",
105 | "vkDestroyDevice",
106 | "vkDestroyFence",
107 | "vkDestroyFramebuffer",
108 | "vkDestroyImage",
109 | "vkDestroyImageView",
110 | "vkDestroyPipeline",
111 | "vkDestroyPipelineCache",
112 | "vkDestroyPipelineLayout",
113 | "vkDestroyRenderPass",
114 | "vkDestroySampler",
115 | "vkDestroySemaphore",
116 | "vkDestroyShaderModule",
117 | "vkEndCommandBuffer",
118 | "vkFlushMappedMemoryRanges",
119 | "vkFreeCommandBuffers",
120 | "vkFreeDescriptorSets",
121 | "vkFreeMemory",
122 | "vkGetBufferMemoryRequirements",
123 | "vkGetDeviceQueue",
124 | "vkGetImageMemoryRequirements",
125 | "vkGetImageSubresourceLayout",
126 | "vkInvalidateMappedMemoryRanges",
127 | "vkMapMemory",
128 | "vkQueueSubmit",
129 | "vkQueueWaitIdle",
130 | "vkResetFences",
131 | "vkUnmapMemory",
132 | "vkUpdateDescriptorSets",
133 | "vkWaitForFences",
134 | ]
135 |
136 |
137 | TEMPLATE = """\
138 | // Automatically generated by make-vulkan-funcs-data.py
139 |
140 | #[derive(Debug, Clone)]
141 | #[allow(non_snake_case)]
142 | pub struct Library {
143 | lib_vulkan: *const c_void,
144 | lib_vulkan_is_fake: bool,
145 |
146 | % for func in core_funcs:
147 | pub ${func}: vk::PFN_${func},
148 | % endfor
149 | }
150 |
151 | #[derive(Debug, Clone)]
152 | #[allow(non_snake_case)]
153 | pub struct Instance {
154 | % for func in instance_funcs:
155 | pub ${func}: vk::PFN_${func},
156 | % endfor
157 | }
158 |
159 | #[derive(Debug, Clone)]
160 | #[allow(non_snake_case)]
161 | #[allow(dead_code)]
162 | pub struct Device {
163 | % for func in device_funcs:
164 | pub ${func}: vk::PFN_${func},
165 | % endfor
166 | }
167 |
168 | impl Instance {
169 | pub unsafe fn new(
170 | get_instance_proc_cb: GetInstanceProcFunc,
171 | user_data: *const c_void,
172 | ) -> Instance {
173 | Instance {
174 | % for func in instance_funcs:
175 | ${func}: std::mem::transmute(get_instance_proc_cb(
176 | "${func}\\0".as_ptr().cast(),
177 | user_data,
178 | )),
179 | % endfor
180 | }
181 | }
182 | }
183 |
184 | #[allow(dead_code)]
185 | impl Device {
186 | pub fn new(instance: &Instance, device: vk::VkDevice) -> Device {
187 | Device {
188 | % for func in device_funcs:
189 | ${func}: unsafe {
190 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()(
191 | device,
192 | "${func}\\0".as_ptr().cast(),
193 | ))
194 | },
195 | % endfor
196 | }
197 | }
198 | }
199 | """
200 |
201 |
202 | def main():
203 | template = Template(TEMPLATE)
204 | print(template.render(core_funcs = CORE_FUNCS,
205 | instance_funcs = INSTANCE_FUNCS,
206 | device_funcs = DEVICE_FUNCS),
207 | end="")
208 |
209 |
210 | if __name__ == '__main__':
211 | main()
212 |
```
--------------------------------------------------------------------------------
/vkrunner/include/vk_video/vulkan_video_codec_av1std_encode.h:
--------------------------------------------------------------------------------
```
1 | #ifndef VULKAN_VIDEO_CODEC_AV1STD_ENCODE_H_
2 | #define VULKAN_VIDEO_CODEC_AV1STD_ENCODE_H_ 1
3 |
4 | /*
5 | ** Copyright 2015-2025 The Khronos Group Inc.
6 | **
7 | ** SPDX-License-Identifier: Apache-2.0
8 | */
9 |
10 | /*
11 | ** This header is generated from the Khronos Vulkan XML API Registry.
12 | **
13 | */
14 |
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 |
21 |
22 | // vulkan_video_codec_av1std_encode is a preprocessor guard. Do not pass it to API calls.
23 | #define vulkan_video_codec_av1std_encode 1
24 | #include "vulkan_video_codec_av1std.h"
25 |
26 | #define VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0)
27 |
28 | #define VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_API_VERSION_1_0_0
29 | #define VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_av1_encode"
30 | typedef struct StdVideoEncodeAV1DecoderModelInfo {
31 | uint8_t buffer_delay_length_minus_1;
32 | uint8_t buffer_removal_time_length_minus_1;
33 | uint8_t frame_presentation_time_length_minus_1;
34 | uint8_t reserved1;
35 | uint32_t num_units_in_decoding_tick;
36 | } StdVideoEncodeAV1DecoderModelInfo;
37 |
38 | typedef struct StdVideoEncodeAV1ExtensionHeader {
39 | uint8_t temporal_id;
40 | uint8_t spatial_id;
41 | } StdVideoEncodeAV1ExtensionHeader;
42 |
43 | typedef struct StdVideoEncodeAV1OperatingPointInfoFlags {
44 | uint32_t decoder_model_present_for_this_op : 1;
45 | uint32_t low_delay_mode_flag : 1;
46 | uint32_t initial_display_delay_present_for_this_op : 1;
47 | uint32_t reserved : 29;
48 | } StdVideoEncodeAV1OperatingPointInfoFlags;
49 |
50 | typedef struct StdVideoEncodeAV1OperatingPointInfo {
51 | StdVideoEncodeAV1OperatingPointInfoFlags flags;
52 | uint16_t operating_point_idc;
53 | uint8_t seq_level_idx;
54 | uint8_t seq_tier;
55 | uint32_t decoder_buffer_delay;
56 | uint32_t encoder_buffer_delay;
57 | uint8_t initial_display_delay_minus_1;
58 | } StdVideoEncodeAV1OperatingPointInfo;
59 |
60 | typedef struct StdVideoEncodeAV1PictureInfoFlags {
61 | uint32_t error_resilient_mode : 1;
62 | uint32_t disable_cdf_update : 1;
63 | uint32_t use_superres : 1;
64 | uint32_t render_and_frame_size_different : 1;
65 | uint32_t allow_screen_content_tools : 1;
66 | uint32_t is_filter_switchable : 1;
67 | uint32_t force_integer_mv : 1;
68 | uint32_t frame_size_override_flag : 1;
69 | uint32_t buffer_removal_time_present_flag : 1;
70 | uint32_t allow_intrabc : 1;
71 | uint32_t frame_refs_short_signaling : 1;
72 | uint32_t allow_high_precision_mv : 1;
73 | uint32_t is_motion_mode_switchable : 1;
74 | uint32_t use_ref_frame_mvs : 1;
75 | uint32_t disable_frame_end_update_cdf : 1;
76 | uint32_t allow_warped_motion : 1;
77 | uint32_t reduced_tx_set : 1;
78 | uint32_t skip_mode_present : 1;
79 | uint32_t delta_q_present : 1;
80 | uint32_t delta_lf_present : 1;
81 | uint32_t delta_lf_multi : 1;
82 | uint32_t segmentation_enabled : 1;
83 | uint32_t segmentation_update_map : 1;
84 | uint32_t segmentation_temporal_update : 1;
85 | uint32_t segmentation_update_data : 1;
86 | uint32_t UsesLr : 1;
87 | uint32_t usesChromaLr : 1;
88 | uint32_t show_frame : 1;
89 | uint32_t showable_frame : 1;
90 | uint32_t reserved : 3;
91 | } StdVideoEncodeAV1PictureInfoFlags;
92 |
93 | typedef struct StdVideoEncodeAV1PictureInfo {
94 | StdVideoEncodeAV1PictureInfoFlags flags;
95 | StdVideoAV1FrameType frame_type;
96 | uint32_t frame_presentation_time;
97 | uint32_t current_frame_id;
98 | uint8_t order_hint;
99 | uint8_t primary_ref_frame;
100 | uint8_t refresh_frame_flags;
101 | uint8_t coded_denom;
102 | uint16_t render_width_minus_1;
103 | uint16_t render_height_minus_1;
104 | StdVideoAV1InterpolationFilter interpolation_filter;
105 | StdVideoAV1TxMode TxMode;
106 | uint8_t delta_q_res;
107 | uint8_t delta_lf_res;
108 | uint8_t ref_order_hint[STD_VIDEO_AV1_NUM_REF_FRAMES];
109 | int8_t ref_frame_idx[STD_VIDEO_AV1_REFS_PER_FRAME];
110 | uint8_t reserved1[3];
111 | uint32_t delta_frame_id_minus_1[STD_VIDEO_AV1_REFS_PER_FRAME];
112 | const StdVideoAV1TileInfo* pTileInfo;
113 | const StdVideoAV1Quantization* pQuantization;
114 | const StdVideoAV1Segmentation* pSegmentation;
115 | const StdVideoAV1LoopFilter* pLoopFilter;
116 | const StdVideoAV1CDEF* pCDEF;
117 | const StdVideoAV1LoopRestoration* pLoopRestoration;
118 | const StdVideoAV1GlobalMotion* pGlobalMotion;
119 | const StdVideoEncodeAV1ExtensionHeader* pExtensionHeader;
120 | const uint32_t* pBufferRemovalTimes;
121 | } StdVideoEncodeAV1PictureInfo;
122 |
123 | typedef struct StdVideoEncodeAV1ReferenceInfoFlags {
124 | uint32_t disable_frame_end_update_cdf : 1;
125 | uint32_t segmentation_enabled : 1;
126 | uint32_t reserved : 30;
127 | } StdVideoEncodeAV1ReferenceInfoFlags;
128 |
129 | typedef struct StdVideoEncodeAV1ReferenceInfo {
130 | StdVideoEncodeAV1ReferenceInfoFlags flags;
131 | uint32_t RefFrameId;
132 | StdVideoAV1FrameType frame_type;
133 | uint8_t OrderHint;
134 | uint8_t reserved1[3];
135 | const StdVideoEncodeAV1ExtensionHeader* pExtensionHeader;
136 | } StdVideoEncodeAV1ReferenceInfo;
137 |
138 |
139 | #ifdef __cplusplus
140 | }
141 | #endif
142 |
143 | #endif
144 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/buffer.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright 2023 Neil Roberts
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a
6 | // copy of this software and associated documentation files (the "Software"),
7 | // to deal in the Software without restriction, including without limitation
8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | // and/or sell copies of the Software, and to permit persons to whom the
10 | // Software is furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice (including the next
13 | // paragraph) shall be included in all copies or substantial portions of the
14 | // Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 | // DEALINGS IN THE SOFTWARE.
23 |
24 | //! Module containing helper structs to automatically free vkBuffers,
25 | //! vkDeviceMemorys and to unmap mapped memory.
26 |
27 | use crate::vk;
28 | use crate::context::Context;
29 | use crate::allocate_store;
30 | use std::ffi::c_void;
31 | use std::rc::Rc;
32 | use std::ptr;
33 | use std::fmt;
34 |
35 | #[derive(Debug)]
36 | pub enum Error {
37 | MapMemoryError,
38 | AllocateStoreError(String),
39 | BufferError,
40 | }
41 |
42 | impl fmt::Display for Error {
43 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44 | match self {
45 | Error::BufferError => write!(
46 | f,
47 | "Error creating vkBuffer",
48 | ),
49 | Error::MapMemoryError => write!(
50 | f,
51 | "vkMapMemory failed",
52 | ),
53 | Error::AllocateStoreError(s) => write!(f, "{}", s),
54 | }
55 | }
56 | }
57 |
58 | #[derive(Debug)]
59 | pub struct MappedMemory {
60 | pub pointer: *mut c_void,
61 | memory: vk::VkDeviceMemory,
62 | // Needed for the destructor
63 | context: Rc<Context>,
64 | }
65 |
66 | impl Drop for MappedMemory {
67 | fn drop(&mut self) {
68 | unsafe {
69 | self.context.device().vkUnmapMemory.unwrap()(
70 | self.context.vk_device(),
71 | self.memory,
72 | );
73 | }
74 | }
75 | }
76 |
77 | impl MappedMemory {
78 | pub fn new(
79 | context: Rc<Context>,
80 | memory: vk::VkDeviceMemory,
81 | ) -> Result<MappedMemory, Error> {
82 | let mut pointer: *mut c_void = ptr::null_mut();
83 |
84 | let res = unsafe {
85 | context.device().vkMapMemory.unwrap()(
86 | context.vk_device(),
87 | memory,
88 | 0, // offset
89 | vk::VK_WHOLE_SIZE as u64,
90 | 0, // flags,
91 | ptr::addr_of_mut!(pointer),
92 | )
93 | };
94 |
95 | if res == vk::VK_SUCCESS {
96 | Ok(MappedMemory { pointer, memory, context })
97 | } else {
98 | Err(Error::MapMemoryError)
99 | }
100 | }
101 | }
102 |
103 | #[derive(Debug)]
104 | pub struct DeviceMemory {
105 | pub memory: vk::VkDeviceMemory,
106 | pub memory_type_index: u32,
107 | // Needed for the destructor
108 | context: Rc<Context>,
109 | }
110 |
111 | impl Drop for DeviceMemory {
112 | fn drop(&mut self) {
113 | unsafe {
114 | self.context.device().vkFreeMemory.unwrap()(
115 | self.context.vk_device(),
116 | self.memory,
117 | ptr::null(), // allocator
118 | );
119 | }
120 | }
121 | }
122 |
123 | impl DeviceMemory {
124 | pub fn new_buffer(
125 | context: Rc<Context>,
126 | memory_type_flags: vk::VkMemoryPropertyFlags,
127 | buffer: vk::VkBuffer,
128 | ) -> Result<DeviceMemory, Error> {
129 | let res = allocate_store::allocate_buffer(
130 | context.as_ref(),
131 | memory_type_flags,
132 | buffer,
133 | );
134 | DeviceMemory::new_from_result(context, res)
135 | }
136 |
137 | pub fn new_image(
138 | context: Rc<Context>,
139 | memory_type_flags: vk::VkMemoryPropertyFlags,
140 | image: vk::VkImage,
141 | ) -> Result<DeviceMemory, Error> {
142 | let res = allocate_store::allocate_image(
143 | context.as_ref(),
144 | memory_type_flags,
145 | image,
146 | );
147 | DeviceMemory::new_from_result(context, res)
148 | }
149 |
150 | fn new_from_result(
151 | context: Rc<Context>,
152 | result: Result<(vk::VkDeviceMemory, u32), String>,
153 | ) -> Result<DeviceMemory, Error> {
154 | match result {
155 | Ok((memory, memory_type_index)) => Ok(DeviceMemory {
156 | memory,
157 | memory_type_index,
158 | context,
159 | }),
160 | Err(e) => Err(Error::AllocateStoreError(e)),
161 | }
162 | }
163 | }
164 |
165 | #[derive(Debug)]
166 | pub struct Buffer {
167 | pub buffer: vk::VkBuffer,
168 | // Needed for the destructor
169 | context: Rc<Context>,
170 | }
171 |
172 | impl Drop for Buffer {
173 | fn drop(&mut self) {
174 | unsafe {
175 | self.context.device().vkDestroyBuffer.unwrap()(
176 | self.context.vk_device(),
177 | self.buffer,
178 | ptr::null(), // allocator
179 | );
180 | }
181 | }
182 | }
183 |
184 | impl Buffer {
185 | pub fn new(
186 | context: Rc<Context>,
187 | size: usize,
188 | usage: vk::VkBufferUsageFlagBits,
189 | ) -> Result<Buffer, Error> {
190 | let buffer_create_info = vk::VkBufferCreateInfo {
191 | sType: vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
192 | pNext: ptr::null(),
193 | flags: 0,
194 | size: size as vk::VkDeviceSize,
195 | usage,
196 | sharingMode: vk::VK_SHARING_MODE_EXCLUSIVE,
197 | queueFamilyIndexCount: 0,
198 | pQueueFamilyIndices: ptr::null(),
199 | };
200 |
201 | let mut buffer: vk::VkBuffer = vk::null_handle();
202 |
203 | let res = unsafe {
204 | context.device().vkCreateBuffer.unwrap()(
205 | context.vk_device(),
206 | ptr::addr_of!(buffer_create_info),
207 | ptr::null(), // allocator
208 | ptr::addr_of_mut!(buffer),
209 | )
210 | };
211 |
212 | if res == vk::VK_SUCCESS {
213 | Ok(Buffer { buffer, context })
214 | } else {
215 | Err(Error::BufferError)
216 | }
217 | }
218 | }
219 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/temp_file.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright 2023 Neil Roberts
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a
6 | // copy of this software and associated documentation files (the "Software"),
7 | // to deal in the Software without restriction, including without limitation
8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | // and/or sell copies of the Software, and to permit persons to whom the
10 | // Software is furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice (including the next
13 | // paragraph) shall be included in all copies or substantial portions of the
14 | // Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 | // DEALINGS IN THE SOFTWARE.
23 |
24 | use std::path::{Path, PathBuf};
25 | use std::fs::File;
26 | use std::io;
27 | use std::fmt;
28 | use std::fmt::Write;
29 |
30 | /// An error that can be returned from [TempFile::new]
31 | #[derive(Debug)]
32 | pub enum Error {
33 | /// All of the possible unique names were tried and all of the
34 | /// files exist. This should probably not really be possible.
35 | NoAvailableFilename,
36 | /// An I/O error other than `AlreadyExists` and `Interrupted`
37 | /// occurred while opening the file.
38 | IoError(io::Error),
39 | }
40 |
41 | impl fmt::Display for Error {
42 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
43 | match self {
44 | Error::NoAvailableFilename => {
45 | write!(f, "No available temporary filenames")
46 | },
47 | Error::IoError(e) => e.fmt(f),
48 | }
49 | }
50 | }
51 |
52 | /// Class to handle creating a tempory file and deleting it when
53 | /// dropped.
54 | ///
55 | /// The file will be created in the directory returned by
56 | /// [std::env::temp_dir]. It will have a generated name beginning with
57 | /// `vkrunner-` followed by an integer. The file will be opened in
58 | /// write-only mode and the corresponding [File] object can be
59 | /// accessed with [TempFile::file]. The file will be automatically
60 | /// closed and deleted when the `TempFile` is dropped.
61 | #[derive(Debug)]
62 | pub struct TempFile {
63 | filename: PathBuf,
64 | file: Option<File>,
65 | }
66 |
67 | fn find_available_file(prefix: &str, filename: &mut PathBuf) -> Result<File, Error> {
68 | let mut filename_part = String::new();
69 |
70 | for i in 0..=u64::MAX {
71 | filename_part.clear();
72 | write!(&mut filename_part, "{}{}", prefix, i).unwrap();
73 |
74 | filename.push(&filename_part);
75 |
76 | match File::options()
77 | .write(true)
78 | .read(true)
79 | .create_new(true)
80 | .open(&filename)
81 | {
82 | Ok(file) => return Ok(file),
83 | Err(e) => {
84 | if e.kind() != io::ErrorKind::AlreadyExists
85 | && e.kind() != io::ErrorKind::Interrupted
86 | {
87 | return Err(Error::IoError(e));
88 | }
89 | // Otherwise just try again with a new name
90 | },
91 | }
92 |
93 | filename.pop();
94 | }
95 |
96 | Err(Error::NoAvailableFilename)
97 | }
98 |
99 | impl TempFile {
100 | /// Creates a new temporary file or returns an error.
101 | pub fn new() -> Result<TempFile, Error> {
102 | Self::new_with_prefix("vkrunner-")
103 | }
104 |
105 | /// Creates a new temporary file or returns an error.
106 | pub fn new_with_prefix(prefix: &str) -> Result<TempFile, Error> {
107 | let mut filename = std::env::temp_dir();
108 | let file = find_available_file(prefix, &mut filename)?;
109 |
110 | Ok(TempFile {
111 | filename,
112 | file: Some(file),
113 | })
114 | }
115 |
116 | /// Gets the [File] object. This can be `None` if
117 | /// [TempFile::close] has been called.
118 | pub fn file(&mut self) -> Option<&mut File> {
119 | self.file.as_mut()
120 | }
121 |
122 | /// Gets the filename of the temporary file.
123 | pub fn filename(&self) -> &Path {
124 | &self.filename
125 | }
126 |
127 | /// Closes the file. The file will still exist and won’t be
128 | /// deleted until the `TempFile` is dropped.
129 | pub fn close(&mut self) {
130 | self.file = None
131 | }
132 | }
133 |
134 | impl Drop for TempFile {
135 | fn drop(&mut self) {
136 | // Make sure the file is closed before trying to delete it
137 | self.file = None;
138 | // We can’t do anything if the remove fails so just ignore the error
139 | let _ = std::fs::remove_file(&self.filename);
140 | }
141 | }
142 |
143 | #[cfg(test)]
144 | mod test {
145 | use super::*;
146 | use std::io::Seek;
147 | use std::io::{Write, Read};
148 |
149 | #[test]
150 | fn two_files() {
151 | // This test checks for files being present and not present, so use
152 | // an unique prefix to avoid conflict with other tests running in
153 | // parallel.
154 | let prefix = "twofiles-vkrunner-";
155 | let mut file_a = TempFile::new_with_prefix(prefix).unwrap();
156 |
157 | assert!(file_a.file().is_some());
158 | assert!(
159 | file_a
160 | .filename()
161 | .display()
162 | .to_string()
163 | .find(prefix)
164 | .is_some()
165 | );
166 | assert!(file_a.filename().is_file());
167 |
168 | file_a.close();
169 | assert!(file_a.file().is_none());
170 | assert!(file_a.filename().is_file());
171 |
172 | let mut file_b = TempFile::new_with_prefix(prefix).unwrap();
173 |
174 | assert!(file_b.file().is_some());
175 | assert!(file_a.filename() != file_b.filename());
176 | assert!(file_b.filename().is_file());
177 |
178 | let file_a_filename = file_a.filename().to_owned();
179 | drop(file_a);
180 | assert!(!file_a_filename.is_file());
181 |
182 | assert!(file_b.filename.is_file());
183 |
184 | let file_b_filename = file_b.filename().to_owned();
185 | drop(file_b);
186 | assert!(!file_b_filename.is_file());
187 | }
188 |
189 | #[test]
190 | fn read() {
191 | let mut temp_file = TempFile::new().unwrap();
192 |
193 | temp_file.file().unwrap().write(b"hello").unwrap();
194 |
195 | temp_file.file().unwrap().rewind().unwrap();
196 |
197 | let mut contents = String::new();
198 |
199 | temp_file.file().unwrap().read_to_string(&mut contents).unwrap();
200 |
201 | assert_eq!(&contents, "hello");
202 |
203 | temp_file.close();
204 |
205 | let contents = std::fs::read_to_string(temp_file.filename()).unwrap();
206 |
207 | assert_eq!(contents, "hello");
208 | }
209 | }
210 |
```
--------------------------------------------------------------------------------
/vkrunner/vkrunner/make-features.py:
--------------------------------------------------------------------------------
```python
1 | #!/usr/bin/env python
2 |
3 | # Copyright (C) 2019 Intel Corporation
4 |
5 | # Permission is hereby granted, free of charge, to any person obtaining a
6 | # copy of this software and associated documentation files (the "Software"),
7 | # to deal in the Software without restriction, including without limitation
8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | # and/or sell copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following conditions:
11 |
12 | # The above copyright notice and this permission notice (including the next
13 | # paragraph) shall be included in all copies or substantial portions of the
14 | # Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 | # DEALINGS IN THE SOFTWARE.
23 |
24 | from __future__ import (
25 | absolute_import, division, print_function, unicode_literals
26 | )
27 |
28 | # This script is used to generate features.rs from vulkan.h. It
29 | # is not run automatically as part of the build process but if need be
30 | # it can be used to update the file as follows:
31 | #
32 | # ./make-features.py < /usr/include/vulkan/vulkan_core.h > features.rs
33 |
34 | import re
35 | import sys
36 | from mako.template import Template
37 |
38 |
39 | EXTENSIONS = [
40 | "KHR_16BIT_STORAGE",
41 | "KHR_8BIT_STORAGE",
42 | {
43 | "name": "EXT_ASTC_DECODE_MODE",
44 | "struct": "VkPhysicalDeviceASTCDecodeFeaturesEXT",
45 | "struct_type": "ASTC_DECODE_FEATURES_EXT"
46 | },
47 | "EXT_BLEND_OPERATION_ADVANCED",
48 | "EXT_BUFFER_DEVICE_ADDRESS",
49 | "KHR_COMPUTE_SHADER_DERIVATIVES",
50 | "EXT_CONDITIONAL_RENDERING",
51 | "NV_CORNER_SAMPLED_IMAGE",
52 | "EXT_DESCRIPTOR_INDEXING",
53 | {
54 | "name": "NV_SCISSOR_EXCLUSIVE",
55 | "struct_type": "EXCLUSIVE_SCISSOR_FEATURES_NV"
56 | },
57 | "KHR_SHADER_FLOAT16_INT8",
58 | "EXT_FRAGMENT_DENSITY_MAP",
59 | "KHR_FRAGMENT_SHADER_BARYCENTRIC",
60 | "EXT_INLINE_UNIFORM_BLOCK",
61 | "EXT_MEMORY_PRIORITY",
62 | "NV_MESH_SHADER",
63 | "KHR_MULTIVIEW",
64 | "NV_REPRESENTATIVE_FRAGMENT_TEST",
65 | "KHR_SAMPLER_YCBCR_CONVERSION",
66 | "EXT_SCALAR_BLOCK_LAYOUT",
67 | "KHR_SHADER_ATOMIC_INT64",
68 | "NV_SHADER_IMAGE_FOOTPRINT",
69 | "NV_SHADING_RATE_IMAGE",
70 | "EXT_TRANSFORM_FEEDBACK",
71 | "KHR_VARIABLE_POINTERS",
72 | "EXT_VERTEX_ATTRIBUTE_DIVISOR",
73 | "KHR_VULKAN_MEMORY_MODEL",
74 | "KHR_COOPERATIVE_MATRIX",
75 | "EXT_SUBGROUP_SIZE_CONTROL",
76 | ]
77 |
78 |
79 | TEMPLATE="""\
80 | // Automatically generated by make-features.py
81 |
82 | static EXTENSIONS: [Extension; ${len(extensions)}] = [
83 | % for e in extensions:
84 | Extension {
85 | name_bytes: vk::VK_${e.name}_EXTENSION_NAME,
86 | struct_size: mem::size_of::<vk::${e.struct}>(),
87 | struct_type: vk::${e.struct_type},
88 | features: &[
89 | % for f in e.features:
90 | "${f}",
91 | % endfor
92 | ],
93 | },
94 | % endfor
95 | ];
96 |
97 | const N_BASE_FEATURES: usize = ${len(base_features)};
98 |
99 | static BASE_FEATURES: [&'static str; N_BASE_FEATURES] = [
100 | % for f in base_features:
101 | "${f}",
102 | % endfor
103 | ];
104 | """
105 |
106 |
107 | class Extension:
108 | def __init__(self, name, struct, struct_type, features):
109 | self.name = name
110 | self.struct = struct
111 | self.struct_type = struct_type
112 | self.features = features
113 |
114 |
115 | def capitalize_part(part):
116 | md = re.match(r'([0-9]*)(.*)', part)
117 | return md.group(1) + md.group(2).capitalize()
118 |
119 |
120 | def extension_to_struct_name(ext):
121 | parts = ext.split("_")
122 | vendor = parts[0]
123 | rest = parts[1:]
124 |
125 | return ("VkPhysicalDevice" +
126 | "".join(capitalize_part(part) for part in rest) +
127 | "Features" +
128 | vendor)
129 |
130 |
131 | def struct_to_regexp(struct):
132 | # Make the vendor in the struct name optional
133 | md = re.match(r'(.*?)([A-Z]+)$', struct)
134 | return re.compile(r'^typedef\s+struct\s+' +
135 | re.escape(md.group(1)) +
136 | r'(?:' + re.escape(md.group(2)) + r')?\s+' +
137 | r'{\s*$',
138 | flags=re.MULTILINE)
139 |
140 |
141 | def get_struct_features(header, struct):
142 | struct_re = struct_to_regexp(struct)
143 | md = struct_re.search(header)
144 |
145 | if md is None:
146 | raise Exception("Couldn't find extension {} in vulkan header".format(
147 | struct))
148 |
149 | header_tail = header[md.end() + 1 :]
150 | header_end = re.search(r'^}', header_tail, flags=re.MULTILINE).start()
151 | members = header_tail[:header_end]
152 |
153 | for line in members.splitlines():
154 | md = re.match(r'\s*VkStructureType\s+[A-Za-z]+\s*;\s*$', line)
155 | if md:
156 | continue
157 | md = re.match(r'\s*void\s*\*\s+pNext\s*;\s*$', line)
158 | if md:
159 | continue
160 | md = re.match(r'\s*VkBool32\s+([a-zA-Z][a-zA-Z0-9_]*)\s*;\s*$', line)
161 | if not md:
162 | raise Exception("Unknown member in struct: " + line)
163 |
164 | yield md.group(1)
165 |
166 |
167 | def main():
168 | header = sys.stdin.read()
169 |
170 | extensions = []
171 |
172 | for ext in EXTENSIONS:
173 | if not isinstance(ext, dict):
174 | ext = { "name": ext }
175 |
176 | name = ext["name"]
177 |
178 | try:
179 | struct_type = ext["struct_type"]
180 | except KeyError:
181 | parts = name.split("_")
182 | struct_type = ("_".join(parts[1:]) + "_" +
183 | "FEATURES_" +
184 | parts[0])
185 |
186 | try:
187 | struct = ext["struct"]
188 | except KeyError:
189 | parts = struct_type.split("_")
190 | struct = ("VkPhysicalDevice" +
191 | "".join(capitalize_part(part)
192 | for part in parts[:-1]) +
193 | parts[-1])
194 |
195 | struct_type_enum = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_" + struct_type
196 |
197 | features = list(get_struct_features(header, struct))
198 | extension = Extension(name, struct, struct_type_enum, features)
199 | extensions.append(extension)
200 |
201 | base_features = list(
202 | get_struct_features(header, "VkPhysicalDeviceFeaturesKHR")
203 | )
204 |
205 | # Validate that all of the feature names are unique
206 | all_features = [feature for extension in extensions
207 | for feature in extension.features] + base_features
208 |
209 | feature_names = set()
210 | for feature in all_features:
211 | if feature in feature_names:
212 | raise Exception("Feature {} is not unique".format(feature))
213 | feature_names.add(feature)
214 |
215 | template = Template(TEMPLATE)
216 | print(template.render(extensions = extensions,
217 | base_features = base_features))
218 |
219 |
220 | if __name__ == '__main__':
221 | main()
222 |
```
--------------------------------------------------------------------------------
/vkrunner/precompile-script.py:
--------------------------------------------------------------------------------
```python
1 | #!/usr/bin/env python
2 |
3 | # Copyright (C) 2018 Intel Corporation
4 |
5 | # Permission is hereby granted, free of charge, to any person obtaining a
6 | # copy of this software and associated documentation files (the "Software"),
7 | # to deal in the Software without restriction, including without limitation
8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | # and/or sell copies of the Software, and to permit persons to whom the
10 | # Software is furnished to do so, subject to the following conditions:
11 |
12 | # The above copyright notice and this permission notice (including the next
13 | # paragraph) shall be included in all copies or substantial portions of the
14 | # Software.
15 |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 | # DEALINGS IN THE SOFTWARE.
23 |
24 | from __future__ import (
25 | absolute_import, division, print_function, unicode_literals
26 | )
27 |
28 | import re
29 | import tempfile
30 | import sys
31 | import subprocess
32 | import argparse
33 | import os
34 | import struct
35 |
36 | TARGET_ENV = "vulkan1.0"
37 |
38 | SECTION_RE = re.compile(r'^\[([^]]+)\]\s*$')
39 | VERSION_RE = re.compile(r'^(\s*vulkan\s*\d+\.\d+)(\.\d+\s*)$')
40 | TRIM_RE = re.compile(r'\s+')
41 |
42 | STAGE_MAP = {
43 | 'vertex shader': 'vert',
44 | 'tessellation control shader': 'tesc',
45 | 'tessellation evaluation shader': 'tese',
46 | 'geometry shader': 'geom',
47 | 'fragment shader': 'frag',
48 | 'compute shader': 'comp',
49 | }
50 |
51 | class Converter:
52 | def __init__(self, type, stage, fout, binary, version):
53 | self._type = type
54 | self._stage = stage
55 | self._fout = fout
56 | self._tempfile = tempfile.NamedTemporaryFile('w+')
57 | self._binary = binary
58 | self._version = version
59 |
60 | def add_line(self, line):
61 | self._tempfile.write(line)
62 |
63 | def finish(self):
64 | self._tempfile.flush()
65 |
66 | with tempfile.NamedTemporaryFile() as temp_outfile:
67 | if self._type == 'glsl':
68 | subprocess.check_call([self._binary,
69 | "--quiet",
70 | "-S", self._stage,
71 | "-G",
72 | "-V",
73 | "--target-env", self._version,
74 | "-o", temp_outfile.name,
75 | self._tempfile.name])
76 | else:
77 | subprocess.check_call([self._binary,
78 | "--target-env", self._version,
79 | "-o", temp_outfile.name,
80 | self._tempfile.name])
81 |
82 | data = temp_outfile.read()
83 |
84 | self._tempfile.close()
85 |
86 | if len(data) < 4 or len(data) % 4 != 0:
87 | print("Resulting binary SPIR-V file has an invalid size",
88 | file=sys.stderr)
89 | sys.exit(1)
90 |
91 | magic_header = struct.unpack(">I", data[0:4])[0]
92 |
93 | if magic_header == 0x07230203:
94 | byte_order = ">I"
95 | elif magic_header == 0x03022307:
96 | byte_order = "<I"
97 | else:
98 | print("Resulting binary SPIR-V has an invalid magic number",
99 | file=sys.stderr)
100 | sys.exit(1)
101 |
102 | line_pos = 0
103 | for offset in range(0, len(data), 4):
104 | value = struct.unpack(byte_order, data[offset:offset+4])[0]
105 | hex_str = "{:x}".format(value)
106 | if len(hex_str) + line_pos + 1 > 80:
107 | line_pos = 0
108 | print(file=self._fout)
109 | elif line_pos > 0:
110 | print(' ', file=self._fout, end='')
111 | line_pos += 1
112 | print(hex_str, file=self._fout, end='')
113 | line_pos += len(hex_str)
114 |
115 | if line_pos > 0:
116 | print(file=self._fout)
117 | print(file=self._fout)
118 |
119 | def convert_stream(fin, fout, glslang, spirv_as):
120 | section_name = None
121 | converter = None
122 | version = TARGET_ENV
123 |
124 | for line in fin:
125 | md = SECTION_RE.match(line)
126 | if md:
127 | if converter:
128 | converter.finish()
129 | converter = None
130 |
131 | section_name = md.group(1)
132 |
133 | if section_name.endswith(' spirv'):
134 | stage_name = section_name[:-6]
135 | converter = Converter('spirv',
136 | STAGE_MAP[stage_name],
137 | fout,
138 | spirv_as,
139 | version)
140 | print("[{} binary]".format(stage_name), file=fout)
141 | elif section_name in STAGE_MAP:
142 | converter = Converter('glsl',
143 | STAGE_MAP[section_name],
144 | fout, glslang, version)
145 | print("[{} binary]".format(section_name), file=fout)
146 | else:
147 | fout.write(line)
148 | elif converter:
149 | converter.add_line(line)
150 | else:
151 | if section_name == 'require':
152 | vmd = VERSION_RE.match(line)
153 | if vmd:
154 | version = vmd.group(1)
155 | version = TRIM_RE.sub('', version)
156 | fout.write(line)
157 |
158 | if converter:
159 | converter.finish()
160 |
161 |
162 | parser = argparse.ArgumentParser(description='Precompile VkRunner scripts.')
163 | parser.add_argument('inputs', metavar='INPUT', type=str, nargs='+',
164 | help='an input file process')
165 | parser.add_argument('-o', dest='output', metavar='OUTPUT',
166 | help='an output file or directory', required=True)
167 |
168 | parser.add_argument('-g', dest='glslang', metavar='GLSLANG',
169 | help='glslangValidator binary path', required=False, default="glslangValidator")
170 |
171 | parser.add_argument('-s', dest='spirv_as', metavar='SPIRV_AS',
172 | help='spirv-as binary path', required=False, default="spirv-as")
173 |
174 | args = parser.parse_args()
175 | output_is_directory = len(args.inputs) >= 2 or os.path.isdir(args.output)
176 |
177 | if output_is_directory:
178 | try:
179 | os.mkdir(args.output)
180 | except OSError:
181 | pass
182 |
183 | for input in args.inputs:
184 | if output_is_directory:
185 | output = os.path.join(args.output, os.path.basename(input))
186 | else:
187 | output = args.output
188 |
189 | with open(input, 'r') as fin:
190 | with open(output, 'w') as fout:
191 | convert_stream(fin, fout, args.glslang, args.spirv_as)
192 |
```
--------------------------------------------------------------------------------
/vkrunner/include/vk_video/vulkan_video_codec_h264std_encode.h:
--------------------------------------------------------------------------------
```
1 | #ifndef VULKAN_VIDEO_CODEC_H264STD_ENCODE_H_
2 | #define VULKAN_VIDEO_CODEC_H264STD_ENCODE_H_ 1
3 |
4 | /*
5 | ** Copyright 2015-2025 The Khronos Group Inc.
6 | **
7 | ** SPDX-License-Identifier: Apache-2.0
8 | */
9 |
10 | /*
11 | ** This header is generated from the Khronos Vulkan XML API Registry.
12 | **
13 | */
14 |
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 |
21 |
22 | // vulkan_video_codec_h264std_encode is a preprocessor guard. Do not pass it to API calls.
23 | #define vulkan_video_codec_h264std_encode 1
24 | #include "vulkan_video_codec_h264std.h"
25 |
26 | #define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0)
27 |
28 | #define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_API_VERSION_1_0_0
29 | #define VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_encode"
30 | typedef struct StdVideoEncodeH264WeightTableFlags {
31 | uint32_t luma_weight_l0_flag;
32 | uint32_t chroma_weight_l0_flag;
33 | uint32_t luma_weight_l1_flag;
34 | uint32_t chroma_weight_l1_flag;
35 | } StdVideoEncodeH264WeightTableFlags;
36 |
37 | typedef struct StdVideoEncodeH264WeightTable {
38 | StdVideoEncodeH264WeightTableFlags flags;
39 | uint8_t luma_log2_weight_denom;
40 | uint8_t chroma_log2_weight_denom;
41 | int8_t luma_weight_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF];
42 | int8_t luma_offset_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF];
43 | int8_t chroma_weight_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES];
44 | int8_t chroma_offset_l0[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES];
45 | int8_t luma_weight_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF];
46 | int8_t luma_offset_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF];
47 | int8_t chroma_weight_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES];
48 | int8_t chroma_offset_l1[STD_VIDEO_H264_MAX_NUM_LIST_REF][STD_VIDEO_H264_MAX_CHROMA_PLANES];
49 | } StdVideoEncodeH264WeightTable;
50 |
51 | typedef struct StdVideoEncodeH264SliceHeaderFlags {
52 | uint32_t direct_spatial_mv_pred_flag : 1;
53 | uint32_t num_ref_idx_active_override_flag : 1;
54 | uint32_t reserved : 30;
55 | } StdVideoEncodeH264SliceHeaderFlags;
56 |
57 | typedef struct StdVideoEncodeH264PictureInfoFlags {
58 | uint32_t IdrPicFlag : 1;
59 | uint32_t is_reference : 1;
60 | uint32_t no_output_of_prior_pics_flag : 1;
61 | uint32_t long_term_reference_flag : 1;
62 | uint32_t adaptive_ref_pic_marking_mode_flag : 1;
63 | uint32_t reserved : 27;
64 | } StdVideoEncodeH264PictureInfoFlags;
65 |
66 | typedef struct StdVideoEncodeH264ReferenceInfoFlags {
67 | uint32_t used_for_long_term_reference : 1;
68 | uint32_t reserved : 31;
69 | } StdVideoEncodeH264ReferenceInfoFlags;
70 |
71 | typedef struct StdVideoEncodeH264ReferenceListsInfoFlags {
72 | uint32_t ref_pic_list_modification_flag_l0 : 1;
73 | uint32_t ref_pic_list_modification_flag_l1 : 1;
74 | uint32_t reserved : 30;
75 | } StdVideoEncodeH264ReferenceListsInfoFlags;
76 |
77 | typedef struct StdVideoEncodeH264RefListModEntry {
78 | StdVideoH264ModificationOfPicNumsIdc modification_of_pic_nums_idc;
79 | uint16_t abs_diff_pic_num_minus1;
80 | uint16_t long_term_pic_num;
81 | } StdVideoEncodeH264RefListModEntry;
82 |
83 | typedef struct StdVideoEncodeH264RefPicMarkingEntry {
84 | StdVideoH264MemMgmtControlOp memory_management_control_operation;
85 | uint16_t difference_of_pic_nums_minus1;
86 | uint16_t long_term_pic_num;
87 | uint16_t long_term_frame_idx;
88 | uint16_t max_long_term_frame_idx_plus1;
89 | } StdVideoEncodeH264RefPicMarkingEntry;
90 |
91 | typedef struct StdVideoEncodeH264ReferenceListsInfo {
92 | StdVideoEncodeH264ReferenceListsInfoFlags flags;
93 | uint8_t num_ref_idx_l0_active_minus1;
94 | uint8_t num_ref_idx_l1_active_minus1;
95 | uint8_t RefPicList0[STD_VIDEO_H264_MAX_NUM_LIST_REF];
96 | uint8_t RefPicList1[STD_VIDEO_H264_MAX_NUM_LIST_REF];
97 | uint8_t refList0ModOpCount;
98 | uint8_t refList1ModOpCount;
99 | uint8_t refPicMarkingOpCount;
100 | uint8_t reserved1[7];
101 | const StdVideoEncodeH264RefListModEntry* pRefList0ModOperations;
102 | const StdVideoEncodeH264RefListModEntry* pRefList1ModOperations;
103 | const StdVideoEncodeH264RefPicMarkingEntry* pRefPicMarkingOperations;
104 | } StdVideoEncodeH264ReferenceListsInfo;
105 |
106 | typedef struct StdVideoEncodeH264PictureInfo {
107 | StdVideoEncodeH264PictureInfoFlags flags;
108 | uint8_t seq_parameter_set_id;
109 | uint8_t pic_parameter_set_id;
110 | uint16_t idr_pic_id;
111 | StdVideoH264PictureType primary_pic_type;
112 | uint32_t frame_num;
113 | int32_t PicOrderCnt;
114 | uint8_t temporal_id;
115 | uint8_t reserved1[3];
116 | const StdVideoEncodeH264ReferenceListsInfo* pRefLists;
117 | } StdVideoEncodeH264PictureInfo;
118 |
119 | typedef struct StdVideoEncodeH264ReferenceInfo {
120 | StdVideoEncodeH264ReferenceInfoFlags flags;
121 | StdVideoH264PictureType primary_pic_type;
122 | uint32_t FrameNum;
123 | int32_t PicOrderCnt;
124 | uint16_t long_term_pic_num;
125 | uint16_t long_term_frame_idx;
126 | uint8_t temporal_id;
127 | } StdVideoEncodeH264ReferenceInfo;
128 |
129 | typedef struct StdVideoEncodeH264SliceHeader {
130 | StdVideoEncodeH264SliceHeaderFlags flags;
131 | uint32_t first_mb_in_slice;
132 | StdVideoH264SliceType slice_type;
133 | int8_t slice_alpha_c0_offset_div2;
134 | int8_t slice_beta_offset_div2;
135 | int8_t slice_qp_delta;
136 | uint8_t reserved1;
137 | StdVideoH264CabacInitIdc cabac_init_idc;
138 | StdVideoH264DisableDeblockingFilterIdc disable_deblocking_filter_idc;
139 | const StdVideoEncodeH264WeightTable* pWeightTable;
140 | } StdVideoEncodeH264SliceHeader;
141 |
142 |
143 | #ifdef __cplusplus
144 | }
145 | #endif
146 |
147 | #endif
148 |
```