aboutsummaryrefslogtreecommitdiff
path: root/adapters/fparkan-render-vulkan/src/ffi
diff options
context:
space:
mode:
Diffstat (limited to 'adapters/fparkan-render-vulkan/src/ffi')
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/smoke.rs8
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs35
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs14
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/tests.rs4
4 files changed, 52 insertions, 9 deletions
diff --git a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
index 92db1a0..4862ca0 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
@@ -678,6 +678,14 @@ impl VulkanSmokeRenderer {
std::slice::from_ref(descriptor_set),
&[],
);
+ let alpha_cutoff = range.alpha_test_cutoff().to_ne_bytes();
+ device.device().cmd_push_constants(
+ command_buffer,
+ resources.pipeline_layout,
+ vk::ShaderStageFlags::FRAGMENT,
+ 0,
+ &alpha_cutoff,
+ );
device.device().cmd_draw_indexed(
command_buffer,
range.index_count,
diff --git a/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs b/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs
index 76bf842..70881d3 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs
@@ -73,6 +73,8 @@ pub struct VulkanStaticDrawRange {
pub material_index: u16,
/// Backend-neutral fixed-function state for this source range.
pub pipeline_state: LegacyPipelineState,
+ /// Alpha-test reference in legacy 0..=255 units; dynamic material data.
+ pub alpha_test_reference: u8,
}
impl VulkanStaticDrawRange {
@@ -81,6 +83,16 @@ impl VulkanStaticDrawRange {
pub fn pipeline_key(self) -> PipelineKey {
self.pipeline_state.into()
}
+
+ /// Returns the normalized cutoff consumed by the fragment shader.
+ #[must_use]
+ pub fn alpha_test_cutoff(self) -> f32 {
+ if self.pipeline_state.alpha_test {
+ f32::from(self.alpha_test_reference) / 255.0
+ } else {
+ 0.0
+ }
+ }
}
/// One diffuse material texture keyed by an original MSH batch selector.
@@ -185,6 +197,7 @@ impl VulkanStaticMesh {
index_count: 3,
material_index: 0,
pipeline_state: LegacyPipelineState::default(),
+ alpha_test_reference: 0,
}],
}
}
@@ -252,6 +265,7 @@ mod static_mesh_tests {
index_count: 2,
material_index: 0,
pipeline_state: LegacyPipelineState::default(),
+ alpha_test_reference: 0,
}],
};
let out_of_range_index = VulkanStaticMesh {
@@ -279,12 +293,14 @@ mod static_mesh_tests {
index_count: 3,
material_index: 7,
pipeline_state: LegacyPipelineState::default(),
+ alpha_test_reference: 0,
},
VulkanStaticDrawRange {
first_index: 3,
index_count: 3,
material_index: 2,
pipeline_state: LegacyPipelineState::default(),
+ alpha_test_reference: 0,
},
];
let texture = || VulkanStaticTexture {
@@ -323,6 +339,25 @@ mod static_mesh_tests {
assert_eq!(base.pipeline_key().packed(), 0);
assert_ne!(base.pipeline_key(), blended.pipeline_key());
}
+
+ #[test]
+ fn alpha_cutoff_is_dynamic_and_disabled_outside_alpha_test_pipeline() {
+ let base = VulkanStaticMesh::smoke_triangle().draw_ranges[0];
+ let disabled = VulkanStaticDrawRange {
+ alpha_test_reference: 200,
+ ..base
+ };
+ let enabled = VulkanStaticDrawRange {
+ pipeline_state: LegacyPipelineState {
+ alpha_test: true,
+ ..LegacyPipelineState::default()
+ },
+ alpha_test_reference: 128,
+ ..base
+ };
+ assert_eq!(disabled.alpha_test_cutoff(), 0.0);
+ assert_eq!(enabled.alpha_test_cutoff(), 128.0 / 255.0);
+ }
}
/// Shared bootstrap progress used to report partial renderer startup evidence.
diff --git a/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs b/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs
index ff797e1..529214d 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs
@@ -381,7 +381,13 @@ fn create_pipeline_layout(
descriptor_set_layout: vk::DescriptorSetLayout,
) -> Result<vk::PipelineLayout, VulkanSmokeRendererError> {
let set_layouts = [descriptor_set_layout];
- let create_info = vk::PipelineLayoutCreateInfo::default().set_layouts(&set_layouts);
+ let push_constant_ranges = [vk::PushConstantRange::default()
+ .stage_flags(vk::ShaderStageFlags::FRAGMENT)
+ .offset(0)
+ .size(u32::try_from(std::mem::size_of::<f32>()).unwrap_or(u32::MAX))];
+ let create_info = vk::PipelineLayoutCreateInfo::default()
+ .set_layouts(&set_layouts)
+ .push_constant_ranges(&push_constant_ranges);
// SAFETY: The descriptor-set layout belongs to this live logical device.
unsafe { device.device().create_pipeline_layout(&create_info, None) }.map_err(|error| {
VulkanSmokeRendererError::VulkanOperation {
@@ -562,12 +568,6 @@ fn create_graphics_pipeline(
extent: (u32, u32),
state: LegacyPipelineState,
) -> Result<vk::Pipeline, VulkanSmokeRendererError> {
- if state.alpha_test {
- return Err(VulkanSmokeRendererError::InvalidStaticMesh {
- context:
- "static renderer has no alpha-test shader variant for requested pipeline state",
- });
- }
let vertex_shader = create_shader_module(device, TRIANGLE_VERTEX_SHADER_WORDS)?;
let fragment_shader = match create_shader_module(device, TRIANGLE_FRAGMENT_SHADER_WORDS) {
Ok(module) => module,
diff --git a/adapters/fparkan-render-vulkan/src/ffi/tests.rs b/adapters/fparkan-render-vulkan/src/ffi/tests.rs
index 791fff8..44e064b 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/tests.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/tests.rs
@@ -669,11 +669,11 @@ fn triangle_shader_manifest_hashes_are_stable() {
assert!(!report.modules[0].interface_hash.is_empty());
assert_eq!(
report.modules[1].sha256,
- "49dae3e1c46d5d23cccf3b161c36ea0b3a606e89c2289dbfed3e4fe991eb8556"
+ "536a5c9a4389f9d34ca11a25f20d0acbc53d3eb0782c18375326647319336a85"
);
assert_eq!(
report.manifest_hash,
- "038ecdb57832ac2d45a1ca6da5ec058b34f4f31b7170aa68fa612ac9d0ae7565"
+ "5a16fb791e86bb790cd2d85151627e0d39193c5c073a9294130f149d4ff5ba58"
);
}