Skip to content

Commit 2f425cd

Browse files
committed
Use consistent code syntax
1 parent 0f30828 commit 2f425cd

File tree

3 files changed

+50
-50
lines changed

3 files changed

+50
-50
lines changed

_posts/2014-08-27-shader-param.md

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,42 +21,42 @@ We wanted gfx-rs to be low level and flexible, to provide an equally convenient
2121
_Disclaimer_: I haven't worked closely with most of these engines, so any corrections are welcome!
2222

2323
* UDK
24-
{% highlight Javascript %}
24+
```js
2525
theMaterialInstance.SetVectorParameterValue('color', FLinearColor(0.0,0.0,0.0,1.0));
26-
{% endhighlight %}
26+
```
2727
* Unity3D
28-
{% highlight C# %}
28+
```c#
2929
Properties {
3030
_Color ("color", Vector) = (0,0,0,0)
3131
}
32-
{% endhighlight %}
33-
{% highlight C %}
32+
```
33+
```c
3434
renderer.material.SetVector("_Color", Vector4(0,0,0,1));
35-
{% endhighlight %}
35+
```
3636
* Irrlight
37-
{% highlight C++ %}
37+
```cpp
3838
if (UseHighLevelShaders)
3939
services->setVertexShaderConstant("color", reinterpret_cast<f32*>(&col), 4);
4040
else //note magic constants!
4141
services->setVertexShaderConstant(reinterpret_cast<f32*>(&col), 9, 1);
42-
{% endhighlight %}
42+
```
4343
* Ogre3D
44-
{% highlight C++ %}
44+
```cpp
4545
fragment_program_ref GroundPS
4646
{
4747
param_named color float4 0
4848
}
49-
{% endhighlight %}
50-
{% highlight C++ %}
49+
```
50+
```cpp
5151
pParams = pPass->getFragmentProgramParameters();
5252
pParams->setNamedConstant("color", Ogre::Vector4(0.0,0.0,0.0,1.0));
53-
{% endhighlight %}
53+
```
5454
* Horde3D
55-
{% highlight C++ %}
55+
```cpp
5656
Horde3D::setMaterialUniform(m_Material, "color", 0.0, 0.0, 0.0, 1.0);
57-
{% endhighlight %}
57+
```
5858
* Three.js
59-
{% highlight JavaScript %}
59+
```js
6060
var uniforms = {
6161
amplitude: {
6262
type: 'v4',
@@ -69,28 +69,28 @@ var shaderMaterial = new THREE.MeshShaderMaterial({
6969
vertexShader: vShader.text(),
7070
fragmentShader: fShader.text()
7171
});
72-
{% endhighlight %}
72+
```
7373
* gfx-rs (for comparison)
74-
{% highlight Rust %}
74+
```rust
7575
#[shader_param(MyBatch)]
7676
struct Params {
7777
color: [f32, ..4],
7878
}
7979
let data = Params {
8080
color: [0.0, 0.0, 0.0, 1.0],
8181
};
82-
{% endhighlight %}
82+
```
8383

8484
### SYF 101
8585
SYF: Shoot Yourself in the Foot = "to do or say something that causes problems for you".
8686

8787
Notice how almost every implementation requires you to specify the parameter name as a string. This forces the engine to go through all known parameters and compare them with your string. Obviously, this work is wasted for any subsequent calls. It is also a violation of the [DRY](http://en.wikipedia.org/wiki/Don%27t_repeat_yourself) principle and a potential hazard: every time you ask to match the parameter by name, there is a chance of error (parameter not found because you copy-pasted the name wrong?).
8888

8989
In some engines, you can get a handle to the parameter like this:
90-
{% highlight Rust %}
90+
```rust
9191
let var_color = program.find_parameter("color");
9292
program.set_param_vec4(var_color, [0.0, 0.0, 0.0, 1.0]);
93-
{% endhighlight %}
93+
```
9494
This is a bit more verbose, and partially solves the problem, but clearly "color" is still repeated twice here (as a string and a part of the variable name). Besides, another hazard remains - what if a given parameter has an incompatible type with what shader expects?
9595

9696
Three.js comes the closest to being safe - your variable name is used to query the shader, and the type can be verified inside `MeshShaderMaterial` call. Note, however, that in _JavaScript_ you can change the variable type at run-time, which raises the SYF factor significantly.
@@ -104,14 +104,14 @@ We are using a procedural macro in Rust to generate the following code at compil
104104
3. Implementation of `fill_params()` - a function that fills up the parameter value, which can be uploaded to GPU.
105105
This is all done behind the `shader_param` attribute:
106106
4. Creates a type alias to the `RefBatch<L ,T>`, named `MyBatch` (see the macro parameter).
107-
{% highlight Rust %}
107+
```rust
108108
#[shader_param(MyBatch)]
109109
struct MyParam {
110110
color: [f32, ..4],
111111
}
112-
{% endhighlight %}
112+
```
113113
Generated code:
114-
{% highlight Rust %}
114+
```rust
115115
struct MyParam {
116116
color: [f32, ..4],
117117
}
@@ -147,24 +147,24 @@ impl ::gfx::shade::ShaderParam<_MyParamLink> for MyParam {
147147
}
148148
}
149149
}
150-
{% endhighlight %}
150+
```
151151

152152
The end product of this macro is a `MyBatch` type that we can use to create batches with `MyParam` parameters:
153-
{% highlight Rust %}
153+
```rust
154154
let batch: MyBatch = context.batch(...).unwrap();
155-
{% endhighlight %}
155+
```
156156
The `unwrap()` here ignores these possible errors (listing only those related to shader parameters):
157157
* the structure doesn't provide a parameter that shader needs
158158
* a shader parameter is not covered by the structure
159159
* some parameter type is not compatible between the shader and the structure
160160

161161
Later, you provide the `MyParam` instance by reference for every draw call with this batch:
162-
{% highlight Rust %}
162+
```rust
163163
let data = MyParam {
164164
color: [0.0, 0.0, 1.0, 0.0],
165165
};
166166
renderer.draw((&batch, &context, &data), &frame);
167-
{% endhighlight %}
167+
```
168168
Notice that the data is decoupled from the batch right until the draw call, yet the batch has all the type guarantees about data safety of the shader parameters, thus `draw()` can not fail.
169169

170170
### Serializable solution

_posts/2015-03-01-device.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ An abstract device has different types associated with it: buffer, texture, samp
1111
2. In the resource management routines (`create_buffer()` and such), which belong to the device.
1212

1313
Since both `CommandBuffer` and the `Device` needed access to all the resource types, we decided to enclose them into a separate `Resources` trait, which became an associated type for our command buffers and devices:
14-
{% highlight Rust %}
14+
```rust
1515
pub trait Resources: {
1616
type Buffer;
1717
type ArrayBuffer;
@@ -22,10 +22,10 @@ pub trait Resources: {
2222
type Texture;
2323
type Sampler;
2424
}
25-
{% endhighlight %}
25+
```
2626

2727
Here is a part of the `Device` trait:
28-
{% highlight Rust %}
28+
```rust
2929
pub trait Device {
3030
type Resources: Resources;
3131
type Mapper: Clone + RawMapping;
@@ -36,10 +36,10 @@ pub trait Device {
3636
fn create_sampler(&mut self, info: tex::SamplerInfo) -> SamplerHandle<Self::Resources>;
3737
...
3838
}
39-
{% endhighlight %}
39+
```
4040

4141
The GL backend implements `Resources` with a phantom enum:
42-
{% highlight Rust %}
42+
```rust
4343
#[derive(Copy, Clone, PartialEq, Debug)]
4444
pub enum GlResources {}
4545

@@ -53,7 +53,7 @@ impl Resources for GlResources {
5353
type Texture = Texture;
5454
type Sampler = Sampler;
5555
}
56-
{% endhighlight %}
56+
```
5757

5858

5959
The migration was started by @bjz in a long series of pull requests ([#564](https://github.com/gfx-rs/gfx-rs/issues/564), [#589](https://github.com/gfx-rs/gfx-rs/issues/589), [#590](https://github.com/gfx-rs/gfx-rs/issues/590), [#592](https://github.com/gfx-rs/gfx-rs/issues/592), [#593](https://github.com/gfx-rs/gfx-rs/issues/593), [#597](https://github.com/gfx-rs/gfx-rs/issues/597)) and finished by @kvark ([`gfx-rs`/#598](https://github.com/gfx-rs/gfx-rs/pull/598), [`gfx-rs`/#609](https://github.com/gfx-rs/gfx-rs/pull/609), [`gfx_device_gl`/#1](https://github.com/gfx-rs/gfx_device_gl/pull/1)). The result - [`gfx_device_gl`](https://github.com/gfx-rs/gfx_device_gl) is a separate crate now that `gfx` itself doesn't depend on. Examples are moved into [their own home](https://github.com/gfx-rs/gfx_examples) as well. Even the macro-generated implementations for shader parameters and vertex formats are API-independent now.

_posts/2016-01-22-pso.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ How do we define it? One observation is that all of these 3 structs just carry s
1919

2020
### Gfx-rs Solution
2121
The user can define a PSO in one place with a macro:
22-
{% highlight Rust %}
22+
```rust
2323
use gfx::format::{Depth, Rgba8}; // Used texture formats
2424
gfx_pipeline_base!( pipe {
2525
vertex: gfx::VertexBuffer<Vertex>, // `Vertex` implements `gfx::Structure`
@@ -29,9 +29,9 @@ gfx_pipeline_base!( pipe {
2929
pixel_color: gfx::RenderTarget<Rgba8>,
3030
depth: gfx::DepthTarget<Depth>,
3131
});
32-
{% endhighlight %}
32+
```
3333
The `gfx_pipeline_base` macro generates a trio of `Data`, `Meta`, and `Init` structs (inside the new module `pipe`) from this definiton, where the user-specified types are exactly what the `Meta` part is going to have. The other two generated structs will look like this:
34-
{% highlight Rust %}
34+
```rust
3535
use gfx::handle::{Buffer, ShaderResourceView, Sampler, RenderTargetView, DepthStencilView};
3636
struct Data {
3737
vertex: Buffer<Vertex>,
@@ -49,12 +49,12 @@ struct Init<'a> {
4949
pixel_color: &'a str,
5050
depth: gfx::state::Depth,
5151
}
52-
{% endhighlight %}
52+
```
5353
Since the `Init` one will need to be passed for PSO construction by the user, it's clear that our solution doesn't require (or even allow) the user to specify any redundant information, or miss anything. Let's say the user wants to enable blending for the `pixel_color`. All that needs to be done is changing the meta type from `RenderTarget<T>` into `BlendTarget<T>`. This would not change the corresponding `Data` component (which will still be `RenderTargetView<R, T>`), but it would add a mandatory `gfx::state::Blend` to the `Init` struct field.
5454

5555
### In-place Init
5656
For simple applications the PSO initialization format is often known in advance. To save the user from a burden of instantiating the `Init` struct, we provide a convenient extended macro to specify the values in place:
57-
{% highlight Rust %}
57+
```rust
5858
gfx_pipeline!( pipe {
5959
vertex: gfx::VertexBuffer<Vertex> = (),
6060
const_locals: gfx::ConstantBuffer<Local> = "Locals",
@@ -66,55 +66,55 @@ gfx_pipeline!( pipe {
6666
write: false,
6767
},
6868
});
69-
{% endhighlight %}
69+
```
7070
This extended version will also generate the trio of structs, but in addition have the `Init::new()` method to give you an instance right away! Here is an example code for PSO creation after this macro is invoked:
71-
{% highlight Rust %}
71+
```rust
7272
let pso = factory.create_pipeline_state( // defined in `gfx::traits::FactoryExt`
7373
&shaders, // `gfx::ShaderSet<R>` - has all the shaders
7474
gfx::Primitive::PointList, // primitive topology
7575
gfx::state::Rasterizer::new_fill(gfx::state::CullFace::Nothing),
7676
Init::new() // our new shiny initializer
7777
).unwrap();
78-
{% endhighlight %}
78+
```
7979
There is a simpler version of this function too:
80-
{% highlight Rust %}
80+
```rust
8181
let pso = factory.create_pipeline_simple( // defined in `gfx::traits::FactoryExt`
8282
&vertex_shader, &fragment_shader,
8383
gfx::state::CullFace::Nothing, Init::new()
8484
).unwrap();
85-
{% endhighlight %}
85+
```
8686

8787
### Drawing
8888
The resulting type will be `gfx::PipelineState<pipe::Meta>`, but fortunately the compiler can infer that for you. Using this PSO is rather trivial - the user is only required to construct the `Data` portion themselves:
89-
{% highlight Rust %}
89+
```rust
9090
let data = pipe::Data {
9191
vertex: .., const_locals: ..,
9292
tex_diffuse: .., buf_noise: ..,
9393
pixel_color: .., depth: ..,
9494
};
9595
let slice = gfx::mesh::Slice {...};
9696
encoder.draw(&slice, &pso, &data);
97-
{% endhighlight %}
97+
```
9898
This is rather minimalistic, but, more importantly, there is next to no opportunity to shoot yourself in the foot! All the inputs of the PSO are guaranteed at compile time. Performance-wise the solution is also perfect - all the mapping from the user data and the PSO inputs is already ready for us (contained in the `Meta`, which is constructed during PSO creation), so the actual binding doesn't involve any lookups.
9999

100100
### Structure
101101
Some PSO components operate on structured data. Namely, vertex buffers and constant buffers are supposed to map to Rust structures. In order to assist the user in defining one, we have a special macro:
102-
{% highlight Rust %}
102+
```rust
103103
gfx_vertex_struct!(Vertex {
104104
x@ _x: i8,
105105
y@ _y: f32,
106106
//shader_name@ field_name: type,
107107
});
108-
{% endhighlight %}
108+
```
109109
The macro will create `Vertex` struct that implements `gfx::Structure<gfx::format::Format>`, allowing it to be used as a generic parameter to vertex buffers. The rust fields are then guaranteed to map the corresponding shader fields, at run-time during PSO creation.
110110

111111
A similar macro is introduced for the constant buffers, it implements `gfx::Structure<gfx::shade::ConstFormat>`:
112-
{% highlight Rust %}
112+
```rust
113113
gfx_constant_struct!(Local {
114114
x: i8,
115115
y: f32,
116116
});
117-
{% endhighlight %}
117+
```
118118

119119
## Analysis
120120
PSO is the new paradigm of Gfx-rs interface. It deprecates a lot of the old core concepts (`Batch`, `Output`, `Mesh`, and others), and cleans up the internal structure quite a bit. The [implementation](https://github.com/gfx-rs/gfx/pull/828) can almost be seen as a rewrite of Gfx-rs as we knew it. Moreover, it is perfectly compatible with DX12 and Metal, while still allowing older APIs to emulate PSOs efficiently (see our GL backend).

0 commit comments

Comments
 (0)