mirror of
https://github.com/SK8-ENGINE/skate-3-rust-engine.git
synced 2026-10-26 19:47:44 +00:00
Restore original material path after v6 native crash
This commit is contained in:
1 parent
46ae9834f8
commit
0b89cb8f47
6 files changed
+55
-164
No files matched your search
@@ -5,25 +5,17 @@
|
||||
#ifdef MOTION_VECTOR_PREPASS
|
||||
#import bevy_pbr::pbr_prepass_functions::calculate_motion_vector
|
||||
#endif
|
||||
#import skate_retail::material_bindings as bindings
|
||||
#ifdef BINDLESS
|
||||
#import bevy_pbr::mesh_bindings::mesh
|
||||
#endif
|
||||
struct WorldParams { mode: vec4<f32>, foliage_debug: vec4<f32>, surface: vec4<f32>, family: vec4<f32>, fog_ramp: vec4<f32>, fog_color: vec4<f32>, shadow_color: vec4<f32>, sun_direction: vec4<f32>, decal: vec4<f32>, water: array<vec4<f32>, 4> }
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(0) var<uniform> p: WorldParams;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(1) var diffuse: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(2) var diffuse_sampler: sampler;
|
||||
@fragment
|
||||
fn fragment(i: VertexOutput)
|
||||
#ifdef PREPASS_FRAGMENT
|
||||
-> FragmentOutput
|
||||
#endif
|
||||
{
|
||||
#ifdef BINDLESS
|
||||
let index = bindings::indices[mesh[i.instance_index].material_and_lightmap_bind_group_slot & 0xffffu];
|
||||
let alpha = textureSample(bindings::textures[index.diffuse],bindings::samplers[index.diffuse_sampler],i.uv).a;
|
||||
let cutoff = bindings::params[index.params].mode.z;
|
||||
#else
|
||||
let alpha = textureSample(bindings::diffuse,bindings::diffuse_sampler,i.uv).a;
|
||||
let cutoff = bindings::p.mode.z;
|
||||
#endif
|
||||
if alpha < cutoff { discard; }
|
||||
if textureSample(diffuse,diffuse_sampler,i.uv).a < p.mode.z { discard; }
|
||||
#ifdef PREPASS_FRAGMENT
|
||||
var out: FragmentOutput;
|
||||
#ifdef NORMAL_PREPASS
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
#define_import_path skate_retail::material_bindings
|
||||
struct WorldParams {
|
||||
mode: vec4<f32>, foliage_debug: vec4<f32>, surface: vec4<f32>, family: vec4<f32>,
|
||||
fog_ramp: vec4<f32>, fog_color: vec4<f32>, shadow_color: vec4<f32>, sun_direction: vec4<f32>, decal: vec4<f32>, water: array<vec4<f32>, 4>,
|
||||
}
|
||||
struct FrameState { shadow: vec4<f32>, clock: vec4<f32>, pca: array<vec4<f32>, 7> }
|
||||
|
||||
#ifdef BINDLESS
|
||||
struct MaterialIndices {
|
||||
params: u32,
|
||||
diffuse: u32,
|
||||
diffuse_sampler: u32,
|
||||
lightmap: u32,
|
||||
lm_sampler: u32,
|
||||
normal_map: u32,
|
||||
normal_sampler: u32,
|
||||
detail_map: u32,
|
||||
detail_sampler: u32,
|
||||
macro_map: u32,
|
||||
macro_sampler: u32,
|
||||
decal_map: u32,
|
||||
decal_sampler: u32,
|
||||
specular_map: u32,
|
||||
specular_sampler: u32,
|
||||
environment_map: u32,
|
||||
frame_state: u32,
|
||||
}
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(0) var<storage> indices: array<MaterialIndices>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(1) var samplers: binding_array<sampler>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(5) var textures: binding_array<texture_2d<f32>>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(8) var cubes: binding_array<texture_cube<f32>>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(17) var<storage> params: array<WorldParams>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(18) var<storage> frames: binding_array<FrameState>;
|
||||
#else
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(0) var<uniform> p: WorldParams;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(1) var diffuse: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(2) var diffuse_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(3) var lightmap: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(4) var lm_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(5) var normal_map: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(6) var normal_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(7) var detail_map: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(8) var detail_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(9) var macro_map: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(10) var macro_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(11) var decal_map: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(12) var decal_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(13) var specular_map: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(14) var specular_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(15) var environment_map: texture_cube<f32>;
|
||||
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(16) var<storage, read> frame_state: FrameState;
|
||||
|
||||
#endif
|
||||
@@ -12,8 +12,8 @@ use std::collections::BTreeMap;
|
||||
|
||||
pub(crate) struct RetailRenderPlugin;
|
||||
#[cfg(test)]
|
||||
#[path = "retail_bindless_tests.rs"]
|
||||
mod bindless_tests;
|
||||
#[path = "retail_shader_tests.rs"]
|
||||
mod shader_tests;
|
||||
// Use the same path derivation as embedded_asset!: alternate binary targets
|
||||
// have a different crate namespace even though they share these source files.
|
||||
fn retail_shader(path: &str) -> ShaderRef {
|
||||
@@ -31,7 +31,6 @@ impl Plugin for RetailRenderPlugin {
|
||||
eprintln!("SKATE_FOLIAGE_DEBUG: solid cyan tree-wall cards, magenta other foliage; alpha rejection disabled for foliage only");
|
||||
}
|
||||
embedded_asset!(app, "retail_world.wgsl");
|
||||
bevy::shader::load_shader_library!(app, "retail_material_bindings.wgsl");
|
||||
embedded_asset!(app, "retail_tone.wgsl");
|
||||
embedded_asset!(app, "retail_depth.wgsl");
|
||||
embedded_asset!(app, "retail_sky.wgsl");
|
||||
@@ -114,9 +113,8 @@ pub(crate) struct WorldParams {
|
||||
|
||||
#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
|
||||
#[bind_group_data(RetailKey)]
|
||||
#[data(0, WorldParams, binding_array(17))]
|
||||
#[bindless(limit(64))]
|
||||
pub(crate) struct RetailWorldMaterial {
|
||||
#[uniform(0)]
|
||||
pub params: WorldParams,
|
||||
#[texture(1)]
|
||||
#[sampler(2)]
|
||||
@@ -141,14 +139,11 @@ pub(crate) struct RetailWorldMaterial {
|
||||
pub specular: Option<Handle<Image>>,
|
||||
#[texture(15, dimension = "cube")]
|
||||
pub environment: Option<Handle<Image>>,
|
||||
#[storage(16, read_only, binding_array(18))]
|
||||
#[storage(16, read_only)]
|
||||
pub shadow_state: Handle<bevy::render::storage::ShaderStorageBuffer>,
|
||||
pub alpha: AlphaMode,
|
||||
pub two_sided: bool,
|
||||
}
|
||||
impl From<&RetailWorldMaterial> for WorldParams {
|
||||
fn from(material: &RetailWorldMaterial) -> Self { material.params.clone() }
|
||||
}
|
||||
/// Identity of the actual GPU inputs, independent of unused source metadata.
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
pub(crate) struct WorldMaterialKey {
|
||||
|
||||
+7
-20
@@ -1,26 +1,14 @@
|
||||
//! GPU-free validation of the actual material shaders and binding-array access.
|
||||
//! GPU-free validation of the original retail material shaders.
|
||||
//! Bevy vertex interfaces are real; unrelated lighting functions/resources use
|
||||
//! interface fixtures. Runtime pipeline/device validation remains a user check.
|
||||
use naga_oil::compose::{Composer, ComposableModuleDescriptor, NagaModuleDescriptor, ShaderDefValue};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[test]
|
||||
fn material_index_table_matches_shader_resources() {
|
||||
use bevy::render::render_resource::{AsBindGroup, BindlessResourceType as R};
|
||||
let descriptor = super::RetailWorldMaterial::bindless_descriptor().unwrap();
|
||||
assert_eq!(descriptor.resources.as_ref(), &[
|
||||
R::DataBuffer, R::Texture2d, R::SamplerFiltering,
|
||||
R::Texture2d, R::SamplerFiltering, R::Texture2d, R::SamplerFiltering,
|
||||
R::Texture2d, R::SamplerFiltering, R::Texture2d, R::SamplerFiltering,
|
||||
R::Texture2d, R::SamplerFiltering, R::Texture2d, R::SamplerFiltering,
|
||||
R::TextureCube, R::Buffer,
|
||||
]);
|
||||
assert_eq!(descriptor.index_tables.len(), 1);
|
||||
let table = &descriptor.index_tables[0];
|
||||
assert_eq!((table.binding_number.0, table.indices.start.0, table.indices.end.0), (0, 0, 17));
|
||||
let mut buffers: Vec<_> = descriptor.buffers.iter().map(|b| (b.bindless_index.0, b.binding_number.0)).collect();
|
||||
buffers.sort_unstable();
|
||||
assert_eq!(buffers, [(0, 17), (16, 18)]);
|
||||
fn retail_material_uses_original_bindings() {
|
||||
use bevy::render::render_resource::AsBindGroup;
|
||||
assert!(super::RetailWorldMaterial::bindless_descriptor().is_none());
|
||||
assert!(super::RetailWorldMaterial::bindless_slot_count().is_none());
|
||||
}
|
||||
|
||||
fn validate(bindless: bool, prepass: bool, extras: &[&str]) {
|
||||
@@ -37,7 +25,6 @@ fn validate(bindless: bool, prepass: bool, extras: &[&str]) {
|
||||
("frame", "#define_import_path bevy_pbr::mesh_view_bindings\nstruct View {view_from_world:mat4x4<f32>,viewport:vec4<f32>,world_position:vec3<f32>,padding:f32}\nstruct Light {flags:u32}\nstruct Lights {n_directional_lights:u32,directional_lights:array<Light,10>}\n@group(0) @binding(0) var<uniform> view:View;\n@group(0) @binding(1) var<storage> lights:Lights;"),
|
||||
("shadows", "#define_import_path bevy_pbr::shadows\nfn fetch_directional_shadow(id:u32,p:vec4<f32>,n:vec3<f32>,z:f32)->f32 {return 1.0;}"),
|
||||
("motion", "#define_import_path bevy_pbr::pbr_prepass_functions\nfn calculate_motion_vector(p:vec4<f32>,q:vec4<f32>)->vec2<f32> {return vec2<f32>(0.0);}"),
|
||||
("bindings",include_str!("retail_material_bindings.wgsl")),
|
||||
];
|
||||
for (path,source) in fixtures {
|
||||
if let Err(error) = composer.add_composable_module(ComposableModuleDescriptor {source,file_path:path,shader_defs:defs.clone(),..Default::default()}) {
|
||||
@@ -51,8 +38,8 @@ fn validate(bindless: bool, prepass: bool, extras: &[&str]) {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn material_shaders_validate_with_bindless_and_fallback_bindings() {
|
||||
for bindless in [false,true] {
|
||||
fn original_material_shaders_validate() {
|
||||
for bindless in [false] {
|
||||
validate(bindless,false,&[]);
|
||||
validate(bindless,true,&[]);
|
||||
validate(bindless,true,&["PREPASS_FRAGMENT","NORMAL_PREPASS","NORMAL_PREPASS_OR_DEFERRED_PREPASS","MOTION_VECTOR_PREPASS","UNCLIPPED_DEPTH_ORTHO_EMULATION"]);
|
||||
@@ -1,11 +1,29 @@
|
||||
#import bevy_pbr::{forward_io::VertexOutput, mesh_view_bindings as frame}
|
||||
#import bevy_pbr::shadows::fetch_directional_shadow
|
||||
|
||||
#import skate_retail::material_bindings::{WorldParams, FrameState}
|
||||
#import skate_retail::material_bindings as bindings
|
||||
#ifdef BINDLESS
|
||||
#import bevy_pbr::mesh_bindings::mesh
|
||||
#endif
|
||||
struct WorldParams {
|
||||
mode: vec4<f32>, foliage_debug: vec4<f32>, surface: vec4<f32>, family: vec4<f32>,
|
||||
fog_ramp: vec4<f32>, fog_color: vec4<f32>, shadow_color: vec4<f32>, sun_direction: vec4<f32>, decal: vec4<f32>, water: array<vec4<f32>, 4>,
|
||||
}
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(0) var<uniform> p: WorldParams;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(1) var diffuse: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(2) var diffuse_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(3) var lightmap: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(4) var lm_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(5) var normal_map: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(6) var normal_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(7) var detail_map: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(8) var detail_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(9) var macro_map: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(10) var macro_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(11) var decal_map: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(12) var decal_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(13) var specular_map: texture_2d<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(14) var specular_sampler: sampler;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(15) var environment_map: texture_cube<f32>;
|
||||
|
||||
struct FrameState { shadow: vec4<f32>, clock: vec4<f32>, pca: array<vec4<f32>, 7> }
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(16) var<storage, read> frame_state: FrameState;
|
||||
|
||||
// Textures and base UVs both have V flipped by the exporter. Scale in the
|
||||
// authored coordinate system, then return to the flipped texture rows.
|
||||
@@ -13,25 +31,8 @@ fn scaled_uv(uv: vec2<f32>, scale: f32) -> vec2<f32> {
|
||||
return vec2<f32>(uv.x*scale, 1.0-(1.0-uv.y)*scale);
|
||||
}
|
||||
|
||||
fn shade(i: VertexOutput,
|
||||
p: WorldParams,
|
||||
frame_state: FrameState,
|
||||
diffuse: texture_2d<f32>,
|
||||
diffuse_sampler: sampler,
|
||||
lightmap: texture_2d<f32>,
|
||||
lm_sampler: sampler,
|
||||
normal_map: texture_2d<f32>,
|
||||
normal_sampler: sampler,
|
||||
detail_map: texture_2d<f32>,
|
||||
detail_sampler: sampler,
|
||||
macro_map: texture_2d<f32>,
|
||||
macro_sampler: sampler,
|
||||
decal_map: texture_2d<f32>,
|
||||
decal_sampler: sampler,
|
||||
specular_map: texture_2d<f32>,
|
||||
specular_sampler: sampler,
|
||||
environment_map: texture_cube<f32>
|
||||
) -> vec4<f32> {
|
||||
@fragment
|
||||
fn fragment(i: VertexOutput) -> @location(0) vec4<f32> {
|
||||
let fam = u32(p.mode.x);
|
||||
let flags = u32(p.mode.y);
|
||||
var diffuse_uv=i.uv;
|
||||
@@ -268,47 +269,3 @@ fn shade(i: VertexOutput,
|
||||
if a.a < p.mode.z { discard; }
|
||||
return vec4<f32>(xe,alpha);
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fragment(i: VertexOutput) -> @location(0) vec4<f32> {
|
||||
#ifdef BINDLESS
|
||||
let index = bindings::indices[mesh[i.instance_index].material_and_lightmap_bind_group_slot & 0xffffu];
|
||||
return shade(i,
|
||||
bindings::params[index.params],
|
||||
bindings::frames[index.frame_state],
|
||||
bindings::textures[index.diffuse],
|
||||
bindings::samplers[index.diffuse_sampler],
|
||||
bindings::textures[index.lightmap],
|
||||
bindings::samplers[index.lm_sampler],
|
||||
bindings::textures[index.normal_map],
|
||||
bindings::samplers[index.normal_sampler],
|
||||
bindings::textures[index.detail_map],
|
||||
bindings::samplers[index.detail_sampler],
|
||||
bindings::textures[index.macro_map],
|
||||
bindings::samplers[index.macro_sampler],
|
||||
bindings::textures[index.decal_map],
|
||||
bindings::samplers[index.decal_sampler],
|
||||
bindings::textures[index.specular_map],
|
||||
bindings::samplers[index.specular_sampler],
|
||||
bindings::cubes[index.environment_map]);
|
||||
#else
|
||||
return shade(i,
|
||||
bindings::p,
|
||||
bindings::frame_state,
|
||||
bindings::diffuse,
|
||||
bindings::diffuse_sampler,
|
||||
bindings::lightmap,
|
||||
bindings::lm_sampler,
|
||||
bindings::normal_map,
|
||||
bindings::normal_sampler,
|
||||
bindings::detail_map,
|
||||
bindings::detail_sampler,
|
||||
bindings::macro_map,
|
||||
bindings::macro_sampler,
|
||||
bindings::decal_map,
|
||||
bindings::decal_sampler,
|
||||
bindings::specular_map,
|
||||
bindings::specular_sampler,
|
||||
bindings::environment_map);
|
||||
#endif
|
||||
}
|
||||
@@ -1,5 +1,19 @@
|
||||
# CPU material binding experiment
|
||||
|
||||
**Withdrawn after the user's runtime test.** Build `bea625f` exited with native
|
||||
access violation `0xC0000005` about 11.4 seconds after launch, shortly after map
|
||||
initialization, on an RTX 5090 using Vulkan. The report contains no native stack
|
||||
or module map, so it cannot establish the faulting subsystem or blame the driver.
|
||||
The binding-array change is treated as a suspected regression, not a confirmed
|
||||
root cause. Passing Naga tests did not establish runtime safety.
|
||||
|
||||
The recovery revision restores the exact pre-v6 main/depth shader source and
|
||||
original uniform, texture and storage bindings. It removes the array shader
|
||||
library and adds a regression assertion that RetailWorldMaterial has no bindless
|
||||
descriptor or slot count. The v5 shadow proxies remain disabled. Recovery does
|
||||
not claim an FPS improvement or a confirmed crash fix until the user runs it.
|
||||
The remaining sections describe the withdrawn experiment for reference.
|
||||
|
||||
The user reports poor FPS while looking into University and good FPS looking out
|
||||
of the map, still CPU bound. The map being resident does not establish that every
|
||||
triangle is drawn. The captured CPU render work is the actionable bottleneck.
|
||||
|
||||
Reference in new issue
Block a user