#
tokens: 49854/50000 45/78 files (page 1/9)
lines: on (toggle) GitHub
raw markdown copy reset
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 | 
```
Page 1/9FirstPrevNextLast