1# Engines 2 3Amber is designed to supported multiple graphics APIs. This is done through the 4engine layer. The parsing/executing side of Amber (which we'll call the 5frontend in this document) doesn't know anything about how the code is executed 6and is API agnostic. Mostly. 7 8 9## Engine Lifecycle 10The engine will go through several states as the script executes. First the 11engine will be created. The creation should not configure the backing graphics 12API. The creation just sets up the basic engine structure. 13 14``` 15 Engine 16 +------------------------------------+ 17 | +----------+ | 18 +---------------------->| Create | | 19 | | +----------+ | 20 | | | +------------+ 21 | | | +------>|Entry Point | 22 | | +------------+ | +---------+ | +------------+ 23 +--------------------->| Initialize | | +---------->| Shaders +----+ 24 | | +------------+ | | +---------+ | 25 | | | | | +--------------+ 26 +----------+ | | | | +------>|Shader binary | 27 | Executor +-------+ | | +----------+ | +---------------+ +--------------+ 28 +----------+ | | * +----------------+ | | | +------->| Vertex Buffers|-----+ 29 +-------------------->|Create Pipeline +-------------->| Pipeline |---+ +---------------+ | 30 | | +----------------+ | | | | +--------+ 31Executor execution | | | +----------+ | | 32flows downwards | | | | +--------------------+ | 33 | | * +---------------------+ | +------>| Colour Attachments |----------+ 34 +------------------->| Execute Do* methods | | | +--------------------+ | 35 | | +---------------------+ | | | 36 | | | | | +--------------+ 37 | | | | +-------------------------+ +----->| Backing data | 38 | | +----------+ | +----->|Depth/Stencil Attachment |------+ +--------------+ 39 +----------------------->| Destroy | | | +-------------------------+ | 40 | +----------+ | | | 41 | | | +-------------+ | 42 | | +---------->| Index Buffer|-------------+ 43 +------------------------------------+ | +-------------+ | 44 | | 45 | +---------------+ | 46 +--------->| Other Buffers |------------+ 47 +---------------+ 48``` 49 50Once created, the engine will be initialized. This initialization will receive 51the configured graphics API from the embedder. The engine can then setup any 52extra needed queues, verify features/extensions are available or do any extra 53configuration. 54 55With the engine initialized all of the pipelines will be created through a 56`CreatePipeline` method. The provided `amber::Pipeline` is fully specified 57at this point and provides: 58 * if this is a graphics or compute pipeline 59 * all shader information (including SPIR-V binary) 60 * all vertex/index buffer information. 61 * initial buffer data if provided 62 * descriptor set/binding information 63 * all colour attachments 64 * initial buffer data if provided 65 * location information 66 * all depth/stencil attachments 67 * all storage buffers 68 * initial buffer data if provided 69 * descriptor set/binding information 70 * framebuffer width/height 71 72The engine should go through and create all the needed pipeline resources. 73 74The shaders can be retrieved with `GetShaders`. The shader information provides 75the entry point to be used. The shader is pre-compiled and any optimizations 76will have been done already. 77 78Buffer data is stored depending on how it's used. For colour attachments use 79`GetcolorAttachments`. The depth/stencil is enabled if the `BufferInfo::buffer` 80pointer is not `nullptr` from `GetDepthBuffer`. The vertex buffers are retrieved 81from `GetVertexBuffers` and the index buffer is provided if `GetIndexBuffer` 82returns non-`nullptr`. For all other storage buffers the `GetBuffers` method 83will provide information on each buffer. 84 85Each of the buffers should be allocated and have the data from the buffers 86`ValuePtr` copied into the device side buffer. 87 88At this point, all information needed to run a pipeline should have been 89provided. The executor will then start running the commands provided in the 90script. This can request the engine to run compute pipelines, graphics pipelines 91or do various other things. 92 93There is an assumption that the data in the `amber::Buffer` for each of the 94buffers in the pipeline is always complete and up to date. This means when, 95for instance, a draw command executes on a pipeline each of the buffers needs 96to be read off the device and written back into the `amber::Buffer`. 97 98When the script is finished the engine destructor will be executed and must 99cleanup any resources created by the engine. It is the job of the embedder 100to shut down the graphics API. 101 102 103## API Layer 104The engine API is described in `src/engine.h`. The `Engine` base class must be 105implemented by the backend engine. 106 107 108### API Methods 109#### `Engine::Create` 110The engines are all created in `src/engine.cc`. The `Engine::Create` method 111will attempt to create the requested engine and return it if possible. When 112adding a new engine a new block needs to be added to this method. When 113`Engine::Create` is complete, the engine will be created but is _not_ 114initialized. 115 116 117#### `Initialize` 118The engine is initialized through the `Initialize` method. The initialize will 119accept engine specific configuration as an `EngineConfig` parameter. This allows 120for clients to set configuration data needed for the engine. The assumption is 121that the engine itself does not initialize the graphics API. The API should 122have been provided and all needed information provided in the `EngineConfig` 123object. 124 125A `Delegate` object is also provided to the engine. The delegate object is used 126when the engine needs to talk back to the embedder. For instance, the delegates 127can tell the engine to `LogGraphicsCalls`. The engine then, should, call the 128`Log` method on the delegate for each internal graphics API method called. 129 130If the executing script specified specific features, instance or device 131extensions they will also be provided. The engine can use these as needed. 132 133 134#### `CreatePipeline` 135The `CreatePipeline` method is responsible for creating an engine specific 136version of the given `amber::Pipeline`. Each command which needs a pipeline 137will have the pipeline provided, so the engine must provide a way to go from 138the amber pipeline to the engine pipeline. There can also be multiple pipeline 139lines of a given type. 140 141All information on the pipeline will be provided including shader and buffer 142information. 143 144 145#### `DoClearColor` 146The `DoClearColor` command provides the colour that is to be used for a given 147pipeline when executing the `DoClear` command. 148 149 150#### `DoClearStencil` 151The `DoClearStencil` command provides the value that is to be used for clearing 152the stencil buffer for a given pipeline when `DoClear` is executed. 153 154 155#### `DoClearDepth` 156The `DoClearDepth` command provides the value that is to be used for clearing 157the depth buffer for a given pipeline when `DoClear` is executed. 158 159 160#### `DoClear` 161The `DoClear` command instructs the engine to clear the various colour and 162depth attachments for the given pipeline. 163 164 165#### `DoDrawRect` 166The `DoDrawRect` instructs the engine to draw the given pipeline in the box 167at (x,y) of size (width,height). The buffers must be read back into the backing 168`amber::Buffer` at the end of this method. 169 170 171#### `DoDrawGrid` 172The `DoDrawGrid` instructs the engine to draw the given pipeline in the box 173at (x,y) of size (width,height) split into cells (columns, rows). The buffers 174must be read back into the backing `amber::Buffer` at the end of this method. 175 176 177#### `DoDrawArrays` 178The `DoDrawArrays` instructs the engine to draw the given pipeline using 179the information in the attached vertex and index buffers. The buffers must be 180read back into the backing `amber::Buffer` at the end of this method. 181 182 183#### `DoCompute` 184The `DoCompute` instructs the engine to execute the given compute pipeline with 185the provided (x,y,z) parameters. 186 187 188#### `DoEntryPoint` 189The `DoEntryPoint` command instructs the engine to change the entry point in 190the given pipeline for the give shader. 191 192 193#### `DoPatchParameterVertices` 194The `DoPatchParameterVertices` tells the engine to do a thing with some 195values....I don't really know what it means, heh. 196 197 198#### `DoBuffer` 199The `DoBuffer` command tells the engine that for a given pipeline the given 200data should be updated into the given buffer. 201 202 203#### `SetEngineData` 204There are cases where there is extra data for a given engine created by the 205front end system. That data is stored in a `EngineData` structure and passed 206into the engine through the `SetEngineData` method. The engine should make 207use if this data if it makes sense. 208 209 210## APIisms in the Frontend 211Most of the things which show up in the front end are the names for drawing 212topologies, image formats and other descriptions use the Vulkan names. So, 213`kR8G8B8A8_SINT` is directly from the Vulkan `VK_FORMAT_R8G8B8A8_SINT` type. 214In the case of image formats the engine will either need to convert to their own 215internal version, or ignore the type and use the `Format` components directly. 216