1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use crate::error::ShaderCompileError;
use librashader_preprocess::ShaderSource;
use shaderc::{CompileOptions, Limit, ShaderKind};
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct GlslangCompilation {
pub(crate) vertex: Vec<u32>,
pub(crate) fragment: Vec<u32>,
}
impl GlslangCompilation {
pub fn compile(source: &ShaderSource) -> Result<Self, ShaderCompileError> {
compile_spirv(source)
}
}
impl TryFrom<&ShaderSource> for GlslangCompilation {
type Error = ShaderCompileError;
fn try_from(source: &ShaderSource) -> Result<Self, Self::Error> {
GlslangCompilation::compile(source)
}
}
fn get_shaderc_options() -> Result<CompileOptions<'static>, ShaderCompileError> {
let mut options = CompileOptions::new().ok_or(ShaderCompileError::ShaderCInitError)?;
options.set_include_callback(|_, _, _, _| {
Err("RetroArch shaders must already have includes be preprocessed".into())
});
options.set_limit(Limit::MaxLights, 32);
options.set_limit(Limit::MaxClipPlanes, 6);
options.set_limit(Limit::MaxTextureUnits, 32);
options.set_limit(Limit::MaxTextureCoords, 32);
options.set_limit(Limit::MaxVertexAttribs, 64);
options.set_limit(Limit::MaxVertexUniformComponents, 4096);
options.set_limit(Limit::MaxVaryingFloats, 64);
options.set_limit(Limit::MaxVertexTextureImageUnits, 32);
options.set_limit(Limit::MaxCombinedTextureImageUnits, 80);
options.set_limit(Limit::MaxTextureImageUnits, 32);
options.set_limit(Limit::MaxFragmentUniformComponents, 4096);
options.set_limit(Limit::MaxDrawBuffers, 32);
options.set_limit(Limit::MaxVertexUniformVectors, 128);
options.set_limit(Limit::MaxVaryingVectors, 8);
options.set_limit(Limit::MaxFragmentUniformVectors, 16);
options.set_limit(Limit::MaxVertexOutputVectors, 16);
options.set_limit(Limit::MaxFragmentInputVectors, 15);
options.set_limit(Limit::MinProgramTexelOffset, -8);
options.set_limit(Limit::MaxProgramTexelOffset, 7);
options.set_limit(Limit::MaxClipDistances, 8);
options.set_limit(Limit::MaxComputeWorkGroupCountX, 65535);
options.set_limit(Limit::MaxComputeWorkGroupCountY, 65535);
options.set_limit(Limit::MaxComputeWorkGroupCountZ, 65535);
options.set_limit(Limit::MaxComputeWorkGroupSizeX, 1024);
options.set_limit(Limit::MaxComputeWorkGroupSizeY, 1024);
options.set_limit(Limit::MaxComputeWorkGroupSizeZ, 64);
options.set_limit(Limit::MaxComputeUniformComponents, 1024);
options.set_limit(Limit::MaxComputeTextureImageUnits, 16);
options.set_limit(Limit::MaxComputeImageUniforms, 8);
options.set_limit(Limit::MaxComputeAtomicCounters, 8);
options.set_limit(Limit::MaxComputeAtomicCounterBuffers, 1);
options.set_limit(Limit::MaxVaryingComponents, 60);
options.set_limit(Limit::MaxVertexOutputComponents, 64);
options.set_limit(Limit::MaxGeometryInputComponents, 64);
options.set_limit(Limit::MaxGeometryOutputComponents, 128);
options.set_limit(Limit::MaxFragmentInputComponents, 128);
options.set_limit(Limit::MaxImageUnits, 8);
options.set_limit(Limit::MaxCombinedImageUnitsAndFragmentOutputs, 8);
options.set_limit(Limit::MaxCombinedShaderOutputResources, 8);
options.set_limit(Limit::MaxImageSamples, 0);
options.set_limit(Limit::MaxVertexImageUniforms, 0);
options.set_limit(Limit::MaxTessControlImageUniforms, 0);
options.set_limit(Limit::MaxTessEvaluationImageUniforms, 0);
options.set_limit(Limit::MaxGeometryImageUniforms, 0);
options.set_limit(Limit::MaxFragmentImageUniforms, 8);
options.set_limit(Limit::MaxCombinedImageUniforms, 8);
options.set_limit(Limit::MaxGeometryTextureImageUnits, 16);
options.set_limit(Limit::MaxGeometryOutputVertices, 256);
options.set_limit(Limit::MaxGeometryTotalOutputComponents, 1024);
options.set_limit(Limit::MaxGeometryUniformComponents, 1024);
options.set_limit(Limit::MaxGeometryVaryingComponents, 64);
options.set_limit(Limit::MaxTessControlInputComponents, 128);
options.set_limit(Limit::MaxTessControlOutputComponents, 128);
options.set_limit(Limit::MaxTessControlTextureImageUnits, 16);
options.set_limit(Limit::MaxTessControlUniformComponents, 1024);
options.set_limit(Limit::MaxTessControlTotalOutputComponents, 4096);
options.set_limit(Limit::MaxTessEvaluationInputComponents, 128);
options.set_limit(Limit::MaxTessEvaluationOutputComponents, 128);
options.set_limit(Limit::MaxTessEvaluationTextureImageUnits, 16);
options.set_limit(Limit::MaxTessEvaluationUniformComponents, 1024);
options.set_limit(Limit::MaxTessPatchComponents, 120);
options.set_limit(Limit::MaxPatchVertices, 32);
options.set_limit(Limit::MaxTessGenLevel, 64);
options.set_limit(Limit::MaxViewports, 16);
options.set_limit(Limit::MaxVertexAtomicCounters, 0);
options.set_limit(Limit::MaxTessControlAtomicCounters, 0);
options.set_limit(Limit::MaxTessEvaluationAtomicCounters, 0);
options.set_limit(Limit::MaxGeometryAtomicCounters, 0);
options.set_limit(Limit::MaxFragmentAtomicCounters, 8);
options.set_limit(Limit::MaxCombinedAtomicCounters, 8);
options.set_limit(Limit::MaxAtomicCounterBindings, 1);
options.set_limit(Limit::MaxVertexAtomicCounterBuffers, 0);
options.set_limit(Limit::MaxTessControlAtomicCounterBuffers, 0);
options.set_limit(Limit::MaxTessEvaluationAtomicCounterBuffers, 0);
options.set_limit(Limit::MaxGeometryAtomicCounterBuffers, 0);
options.set_limit(Limit::MaxFragmentAtomicCounterBuffers, 1);
options.set_limit(Limit::MaxCombinedAtomicCounterBuffers, 1);
options.set_limit(Limit::MaxAtomicCounterBufferSize, 16384);
options.set_limit(Limit::MaxTransformFeedbackBuffers, 4);
options.set_limit(Limit::MaxTransformFeedbackInterleavedComponents, 64);
options.set_limit(Limit::MaxCullDistances, 8);
options.set_limit(Limit::MaxCombinedClipAndCullDistances, 8);
options.set_limit(Limit::MaxSamples, 4);
Ok(options)
}
pub(crate) fn compile_spirv(
source: &ShaderSource,
) -> Result<GlslangCompilation, ShaderCompileError> {
let compiler = shaderc::Compiler::new().ok_or(ShaderCompileError::ShaderCInitError)?;
let name = source.name.as_deref().unwrap_or("shader.slang");
let options = get_shaderc_options()?;
let vertex = compiler.compile_into_spirv(
&source.vertex,
ShaderKind::Vertex,
name,
"main",
Some(&options),
)?;
let fragment = compiler.compile_into_spirv(
&source.fragment,
ShaderKind::Fragment,
name,
"main",
Some(&options),
)?;
let vertex = Vec::from(vertex.as_binary());
let fragment = Vec::from(fragment.as_binary());
Ok(GlslangCompilation { vertex, fragment })
}
#[cfg(test)]
mod test {
use crate::front::shaderc::compile_spirv;
use librashader_preprocess::ShaderSource;
#[test]
pub fn compile_shader() {
let result = ShaderSource::load("../test/basic.slang").unwrap();
let _spirv = compile_spirv(&result).unwrap();
}
}