aboutsummaryrefslogtreecommitdiff
path: root/adapters/fparkan-render-vulkan/src/shader.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2026-09-06 04:22:12 +0300
committerValentin Popov <valentin@popov.link>2026-09-06 04:22:12 +0300
commitaa51f3574d3d4d4e0fa59653eedd718fceb5d1bd (patch)
tree9a43f6a3f3c86767e4e2b7316051562d96789f06 /adapters/fparkan-render-vulkan/src/shader.rs
parentda03e77f53bb33b2fe203ac45578289953a1b524 (diff)
downloadfparkan-aa51f3574d3d4d4e0fa59653eedd718fceb5d1bd.tar.xz
fparkan-aa51f3574d3d4d4e0fa59653eedd718fceb5d1bd.zip
chore: simplify project to engine docs and tests
Remove planning and acceptance scaffolding while retaining the native Vulkan mission preview, format readers, runtime algorithms, and ordinary Rust tests. Keep the book aligned with the runnable project and validate checked-in shaders without generated tool metadata.
Diffstat (limited to 'adapters/fparkan-render-vulkan/src/shader.rs')
-rw-r--r--adapters/fparkan-render-vulkan/src/shader.rs82
1 files changed, 82 insertions, 0 deletions
diff --git a/adapters/fparkan-render-vulkan/src/shader.rs b/adapters/fparkan-render-vulkan/src/shader.rs
new file mode 100644
index 0000000..2e3184a
--- /dev/null
+++ b/adapters/fparkan-render-vulkan/src/shader.rs
@@ -0,0 +1,82 @@
+use crate::ffi::{
+ SPIRV_MAGIC, SPIRV_VERSION_1_0, TRIANGLE_FRAGMENT_SHADER_WORDS, TRIANGLE_VERTEX_SHADER_WORDS,
+};
+
+/// Error found while checking a checked-in SPIR-V module.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum VulkanShaderError {
+ /// SPIR-V module is too short to contain a header.
+ TooShort {
+ /// Shader name.
+ name: &'static str,
+ },
+ /// SPIR-V module has an invalid magic word.
+ InvalidMagic {
+ /// Shader name.
+ name: &'static str,
+ /// Found magic word.
+ found: u32,
+ },
+ /// SPIR-V module version is below 1.0.
+ UnsupportedVersion {
+ /// Shader name.
+ name: &'static str,
+ /// Found version word.
+ found: u32,
+ },
+ /// SPIR-V module declares an invalid bound.
+ InvalidBound {
+ /// Shader name.
+ name: &'static str,
+ },
+}
+
+impl std::fmt::Display for VulkanShaderError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::TooShort { name } => write!(f, "shader {name} SPIR-V module is too short"),
+ Self::InvalidMagic { name, found } => {
+ write!(f, "shader {name} has invalid SPIR-V magic 0x{found:08x}")
+ }
+ Self::UnsupportedVersion { name, found } => write!(
+ f,
+ "shader {name} has unsupported SPIR-V version 0x{found:08x}"
+ ),
+ Self::InvalidBound { name } => write!(f, "shader {name} has invalid SPIR-V bound"),
+ }
+ }
+}
+
+impl std::error::Error for VulkanShaderError {}
+
+/// Checks the checked-in triangle shader containers before creating a pipeline.
+pub(crate) fn validate_triangle_shaders() -> Result<(), VulkanShaderError> {
+ validate_spirv_container("triangle.vert", TRIANGLE_VERTEX_SHADER_WORDS)?;
+ validate_spirv_container("triangle.frag", TRIANGLE_FRAGMENT_SHADER_WORDS)?;
+ Ok(())
+}
+
+pub(crate) fn validate_spirv_container(
+ name: &'static str,
+ words: &[u32],
+) -> Result<(), VulkanShaderError> {
+ if words.len() < 5 {
+ return Err(VulkanShaderError::TooShort { name });
+ }
+ if words[0] != SPIRV_MAGIC {
+ return Err(VulkanShaderError::InvalidMagic {
+ name,
+ found: words[0],
+ });
+ }
+ if words[1] < SPIRV_VERSION_1_0 {
+ return Err(VulkanShaderError::UnsupportedVersion {
+ name,
+ found: words[1],
+ });
+ }
+ if words[3] == 0 {
+ return Err(VulkanShaderError::InvalidBound { name });
+ }
+ Ok(())
+}