1e5c31af7Sopenharmony_ci# Amber
2e5c31af7Sopenharmony_ci
3e5c31af7Sopenharmony_ciAmber is a multi-API shader test framework. Graphics and compute bugs can be
4e5c31af7Sopenharmony_cicaptured and communicated through a scripting interface. This removes the need
5e5c31af7Sopenharmony_cito program to the low level interface when reproducing bugs.
6e5c31af7Sopenharmony_ci
7e5c31af7Sopenharmony_ciAmber is broken into multiple layers: the applications, the parsing components
8e5c31af7Sopenharmony_ciand the script execution.
9e5c31af7Sopenharmony_ci
10e5c31af7Sopenharmony_ci## Applications
11e5c31af7Sopenharmony_ciThere are currently two applications, the `[amber](../samples/amber.cc)`
12e5c31af7Sopenharmony_ciapplication and the Amber integration into the
13e5c31af7Sopenharmony_ci[Vulkan Conformance Test Suite 'CTS'](https://github.com/KhronosGroup/VK-GL-CTS/tree/master/external/vulkancts/modules/vulkan/amber). These applications are responsible
14e5c31af7Sopenharmony_cifor configuring the script execution environment (setting up Vulkan, Dawn or
15e5c31af7Sopenharmony_cianother engine), calling into the parsing code to generate a test script and
16e5c31af7Sopenharmony_cithen passing that script into the script execution component.
17e5c31af7Sopenharmony_ci
18e5c31af7Sopenharmony_ciWe require the application to configure the execution engine. This allows the
19e5c31af7Sopenharmony_ciapplication to handle loading function pointers, doing configuration and other
20e5c31af7Sopenharmony_cisetups as required. There are no hardcoded assumptions in Amber as to how you're
21e5c31af7Sopenharmony_cisetting up the API to be tested.
22e5c31af7Sopenharmony_ci
23e5c31af7Sopenharmony_ciThis engine configuration is done through the `VulkanEngineConfig` in
24e5c31af7Sopenharmony_ci`amber/amber_vulkan.h` or the `DawnEngineConfig` in `amber/amber_dawn.h`.
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ciThe sample application does this configuration through the config_helper
27e5c31af7Sopenharmony_ciclasses. `samples/config_helper_vulkan.*` and `samples/config_helper_dawn.*`.
28e5c31af7Sopenharmony_ciFor the CTS, the Vulkan engine is already configured and we just set the
29e5c31af7Sopenharmony_ci`VulkanEngineConfig` as needed.
30e5c31af7Sopenharmony_ci
31e5c31af7Sopenharmony_ciAccessing Amber itself is done through the `Amber` class in `amber/amber.h`. We
32e5c31af7Sopenharmony_cirequire the application to parse and execute a script as two separate steps.
33e5c31af7Sopenharmony_ciThis separation allows for the shaders to be retrieved after a parse command
34e5c31af7Sopenharmony_ciand then pre-compiled and passed into the execution. Passing the compiled
35e5c31af7Sopenharmony_cishaders is optional.
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ci### Delegate
38e5c31af7Sopenharmony_ciA delegate object can be provided to Amber, for observing internal operations as
39e5c31af7Sopenharmony_cithe script is executed. The delegate can be a null pointer, to indicate no
40e5c31af7Sopenharmony_ciobservations are requested.
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_ciIf the delegate is provided and the `LogGraphicsCalls` method returns
43e5c31af7Sopenharmony_ci`true` then the Vulkan API wrappers will call `Log` for each call into Vulkan.
44e5c31af7Sopenharmony_ciIf the `LogGraphicsCallsTime` also returns `true` then timings for those
45e5c31af7Sopenharmony_ciVulkan calls will also be recorded. The timestamps are retrieved from the
46e5c31af7Sopenharmony_ci`GetTimestampNS` callback.
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_ci### Buffer Extractions
49e5c31af7Sopenharmony_ciAmber can be instructed to retrieve the contents of buffers when execution is
50e5c31af7Sopenharmony_cicomplete. This is done through the `extractions` list in the Amber `Options`
51e5c31af7Sopenharmony_cistructure. You must set the `buffer_name` for each of the buffers you want to
52e5c31af7Sopenharmony_ciextract. When Amber completes it will fill out the `width`, `height` and set
53e5c31af7Sopenharmony_ciof `Value` objects for that buffer.
54e5c31af7Sopenharmony_ci
55e5c31af7Sopenharmony_ci### Execution
56e5c31af7Sopenharmony_ciThere are two methods to execute a parsed script: `Execute` and
57e5c31af7Sopenharmony_ci`ExecuteWithShaderData`. They both accept the `Recipe` and `Options`, the
58e5c31af7Sopenharmony_ci`ExecuteWithShaderData` also accepts a map of shader name to data. The data
59e5c31af7Sopenharmony_ciis the compiled SPIR-V binary for the shader. This allows you to compile and
60e5c31af7Sopenharmony_cicache the shader if needed.
61e5c31af7Sopenharmony_ci
62e5c31af7Sopenharmony_ci## Parsing component
63e5c31af7Sopenharmony_ciAmber can use scripts written in two dialects:
64e5c31af7Sopenharmony_ci[AmberScript](amber_script.md), and [VkScript](vk_script.md). The `AmberScript`
65e5c31af7Sopenharmony_ciparser will be used if the first 7 characters of the script are
66e5c31af7Sopenharmony_ci`#!amber`, otherwise the `VkScript` parser will be used. The parsers both
67e5c31af7Sopenharmony_cigenerate a `Script` which is our representation of the script file.
68e5c31af7Sopenharmony_ci
69e5c31af7Sopenharmony_ci### AmberScript
70e5c31af7Sopenharmony_ciThe AmberScript format maps closely to the format stored in the script objects.
71e5c31af7Sopenharmony_ciAs such, there is a single Parser class for AmberScript which produces all of
72e5c31af7Sopenharmony_cithe needed script components.
73e5c31af7Sopenharmony_ci
74e5c31af7Sopenharmony_ci### VkScript
75e5c31af7Sopenharmony_ciFor VkScript we do a bit of work to make the script match AmberScript. A default
76e5c31af7Sopenharmony_cipipeline is generated and all content in the script is considered part of the
77e5c31af7Sopenharmony_cigenerated pipeline. We generate names for all of the buffers in the file. The
78e5c31af7Sopenharmony_ciframebuffer is named `framebuffer`. The generated depth buffer is named
79e5c31af7Sopenharmony_ci`depth_buffer`. For other buffers, we generate a name of `AutoBuf-<num>` where
80e5c31af7Sopenharmony_cithe number is the current number of buffers seen counting from 0.
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ciThe VkScript parser is broken into three major chunks. The `Parser`,
83e5c31af7Sopenharmony_ci`SectionParser` and `CommandParser`. The `Parser` is the overall driver for the
84e5c31af7Sopenharmony_ciparser. The `SectionParser` breaks the input file into the overall chunks (each
85e5c31af7Sopenharmony_ciof the sections separated by the \[blocks]). The `CommandParser` parses the
86e5c31af7Sopenharmony_ci`[test]` section specifically. For other sections they're parsed directly in
87e5c31af7Sopenharmony_cithe `Parser` object.
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ci### Parsed Representation
90e5c31af7Sopenharmony_ciThe `Script` object owns all of the pipelines, buffers, shaders, and command
91e5c31af7Sopenharmony_ciobjects. Other objects hold pointers but the script holds the `unique_ptr` for
92e5c31af7Sopenharmony_cithese objects.
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_ci```
95e5c31af7Sopenharmony_ci                                        +--------+                 +--------------+
96e5c31af7Sopenharmony_ci                                        | Script |---------------->| Requirements |
97e5c31af7Sopenharmony_ci                                        +--------+                 +--------------+
98e5c31af7Sopenharmony_ci                                             |
99e5c31af7Sopenharmony_ci             +------------------+------------+--------+----------------------+
100e5c31af7Sopenharmony_ci             |                  |                     |                      |
101e5c31af7Sopenharmony_ci             v                  v                     v                      v
102e5c31af7Sopenharmony_ci      +---------+          +---------+        +---------+            +---------+
103e5c31af7Sopenharmony_ci      |  +--------+        |  +---------+     |  +----------+        |  +---------+
104e5c31af7Sopenharmony_ci      +--|  +--------+     +--|  +--------+   +--|  +----------+     +--|  +---------+
105e5c31af7Sopenharmony_ci         +--| Shader |        +--| Buffer |      +--| Pipeline |        +--| Command |
106e5c31af7Sopenharmony_ci            +--------+           +--------+         +----------+           +---------+
107e5c31af7Sopenharmony_ci               ^                  ^  ^                 |  |  ^               |    |
108e5c31af7Sopenharmony_ci               |                  |  |                 |  |  +---------------+    |
109e5c31af7Sopenharmony_ciEntry point    |                  |  +-----------------+  |                       |
110e5c31af7Sopenharmony_ciOptimizations  |                  |  Descriptor Set       |                       |
111e5c31af7Sopenharmony_ciType           |                  |  Binding              |                       |
112e5c31af7Sopenharmony_ciCompiled Shader|                  |  Attachment Location  |                       |
113e5c31af7Sopenharmony_ci               |                  |                       |                       |
114e5c31af7Sopenharmony_ci               +------------------------------------------+                       |
115e5c31af7Sopenharmony_ci                                  |                                               |
116e5c31af7Sopenharmony_ci                                  +-----------------------------------------------+
117e5c31af7Sopenharmony_ci                                                        BufferCommand
118e5c31af7Sopenharmony_ci```
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ciA `Script` contains shaders, pipelines, buffers, and commands. Pipelines
121e5c31af7Sopenharmony_cicontain shaders and buffers. An Amber buffer corresponds to either a buffer
122e5c31af7Sopenharmony_ciresource or an image resource in the backend engine's API.
123e5c31af7Sopenharmony_ciScript execution assumes that after executing a command, each `Buffer` object
124e5c31af7Sopenharmony_cihas a reference to the latest data for that buffer or image copied into
125e5c31af7Sopenharmony_cithe buffers memory. This means that a draw command will need to copy buffer data to
126e5c31af7Sopenharmony_cithe device, execute the draw, and then copy the device data back into the
127e5c31af7Sopenharmony_cibuffer. Amber does not do any extra calls to fill the buffers. Then engine must
128e5c31af7Sopenharmony_cikeep that data in sync.
129e5c31af7Sopenharmony_ci
130e5c31af7Sopenharmony_ciThe `Pipeline` object holds the context for a given set of tests. This includes
131e5c31af7Sopenharmony_cishaders, colour attachments, depth/stencil attachment, data buffers, etc. The
132e5c31af7Sopenharmony_cicolour attachments will have their `Attachment Location` while data buffers
133e5c31af7Sopenharmony_ciwill have a `Descriptor Set` and `Binding` provided.
134e5c31af7Sopenharmony_ci
135e5c31af7Sopenharmony_ci## Execution
136e5c31af7Sopenharmony_ciWhen the script is executed the pipeline shaders will be compiled, if not
137e5c31af7Sopenharmony_ciprovided through the shader map. This will fill in the `Compiled Shader` data
138e5c31af7Sopenharmony_ciin the each pipeline shader object. The `CreatePipeline` call will then be
139e5c31af7Sopenharmony_ciexecuted for a given pipeline.
140e5c31af7Sopenharmony_ci
141e5c31af7Sopenharmony_ciWith the pipelines created the `Command` objects will be executed. Each
142e5c31af7Sopenharmony_ci`Command` knows the Amber `Pipeline` associated with it, that `Pipeline` pointer
143e5c31af7Sopenharmony_ciis provided in the command execution and can be used to lookup the
144e5c31af7Sopenharmony_ciengine-specific representation of a pipeline.
145e5c31af7Sopenharmony_ci
146e5c31af7Sopenharmony_ciWhen the `Probe` and `ProbeSSBO` commands are encountered they are not passed
147e5c31af7Sopenharmony_cito the engine but sent to the `Verifier`. This will validate that the data
148e5c31af7Sopenharmony_ciin the specified buffer matches the test data. As mentioned above, this assumes
149e5c31af7Sopenharmony_cithat the Amber `Buffer` is kept up to date with the current device memory as we
150e5c31af7Sopenharmony_cido not attempt to fill in the buffers before executing the `Probe*` calls.
151