Conversation
Add material, material instance, and node-graph primitives with HLSL generation for scalar and vector channels. Cover graph generation with unit tests, tighten clang-tidy, and ignore generated shaders plus imported mesh/HDR assets from source control.
Add a graph-injectable pixel shader with image-based lighting, directional lighting, and ACES tone mapping. Generated graph code fills the surface channels while shared frame, material, texture, and environment bindings stay centralized.
Compile generated material-graph HLSL into SPIR-V at runtime and load it as a bindable shader. Add the material compiler, wire a sample graph into Dissolve, copy the template during shader staging, and fix the template's vector and float4 output expressions.
Rename WaitForAllFrames to ResetFrameUsageState to reflect that it only clears per-frame usage flags after the device is idle. Expose WaitDeviceIdle through GraphicsContext so generic graphics clients can synchronize safely.
Add texture coordinates, texture sampling, time, panner, math, and utility nodes. Coerce mixed pin widths while generating HLSL, and expose Time in the material frame buffer so animated graphs can evaluate correctly.
Make materials own their graphs and typed parameter definitions. Reject invalid graph references and incompatible instance overrides before shader compilation or resource binding.
Compile authored material schemas into stable value and texture slots. Keep generated HLSL and toolchain diagnostics with the compiled material artifact.
Compile Dissolve's graph through Material so the demo retains the compiled material artifact and reports compiler diagnostics.
Compile the particle sprite material permutation and publish immutable proxy data into a per-frame GPU material table. Batch sprite draws by compiled material shader while preserving the static sprite fallback and avoiding descriptor writes during draw submission.
Resolve immutable material texture slots through the bindless set before command recording. New texture registrations use the white fallback until the next frame publishes their descriptors, avoiding descriptor mutations during particle draws.
Apply the Dissolve graph material through an immutable render proxy before compiling the particle system. Unify the sprite push-constant contract at 72 bytes across the vertex shader and both pixel shader paths.
Compile the Surface permutation before any enabled particle permutation.\n\nReturn no shader for unsupported particle usages instead of falling back to Surface.
Generate Ribbon vertex and fragment shader permutations for enabled materials.\n\nKeep the material push-constant ABI aligned across both stages.
Publish Ribbon material proxies to the GPU material table and bind their generated shader pipelines.\n\nKeep Ribbon vertex resources isolated from fragment material bindings.
Keep Ribbon material resources in the descriptor sets expected by the bindless pipeline layout.\n\nAdd a Dissolve Ribbon material example for runtime coverage.
Compile Mesh shader permutations and publish their material proxies to the GPU material table.\n\nBind Mesh material pipelines with the same texture and push-constant contract as Sprite and Ribbon.
Move particle material frame data, texture registration and GPU storage into Engine/Material. Keep Aether as a consumer of the centralized frame snapshot and cover bindless descriptor visibility.
Move particle material pipeline selection, resource binding and pipeline caching into Engine/Material. Keep Aether responsible for particle buffers and draw submission while it consumes prepared material passes.
Move prepared material pass binding and draw dispatch into Engine/Material. Keep Aether responsible for particle geometry while it supplies draw callbacks for Sprite, Ribbon and Mesh.
Compile and own default particle material proxies in Engine/Material. Keep Aether responsible for particle geometry and submit every Sprite, Ribbon and Mesh batch through a prepared material pass.
Move default particle material proxy ownership from MaterialSystem to ParticleMaterialLibrary. Bind an explicit proxy while loading effects so Aether renders only compiled emitter materials.
Introduce MaterialRenderScene as the frame-boundary contract for particle material inputs. MaterialSystem now builds frame snapshots from the published scene while Aether retains geometry submission for the next phase.
Move particle material batching, pass preparation and draw recording into MaterialSystem. Aether now publishes immutable geometry data and no longer manipulates material shaders or pipelines.
Move legacy sprite texture selection into the default Sprite material graph. Expose BaseColor and Opacity as material channels and remove Aether texture bindings from the render contract.
Resolve effect material colors and emission into immutable graph constants during import. Move particle material compilation and caching into Engine/Material and migrate VFX assets to explicit material definitions.
Move MaterialSystem ownership to Application and inject it into Aether. Keep the frame material capacity in central configuration instead of particle pool limits.
Register default source materials and cache compiled results by material revision. Add the radial gradient exponential node for the default sprite opacity.
Move instance creation to System and let Manager add each instance once for persistent simulation and rendering. Compile on first registration, preserve immutable frame snapshots, and update lifecycle and concurrency coverage.
Use the instance map as the registry's single source of truth and remove the redundant registration-order list. Keep frame ordering unspecified so later culling and rendering stages can establish task-specific order.
|
Important Review skippedToo many files! This PR contains 165 files, which is 65 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Team Run ID: ⛔ Files ignored due to path filters (10)
📒 Files selected for processing (165)
You can disable this status message by setting the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 17589ccfac
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| // __GRAPH_BODY__ | ||
|
|
||
| return float4(surface.BaseColor + surface.Emissive, surface.Opacity); |
There was a problem hiding this comment.
Preserve simulated particle color in material shaders
When an emitter uses SetColor or ColorOverLife (including the checked FireAndFireworks.json effect), this return ignores the input.Color supplied by the particle vertex shader, so simulated RGB and alpha fades have no effect. The new ribbon and mesh templates likewise return only material surface values, meaning every material-backed particle mode loses per-particle tint and opacity; the final color and alpha need to incorporate the particle input.
Useful? React with 👍 / 👎.
| const auto allocation = m_ResourcePool.Allocate(system); | ||
| if (!allocation) |
There was a problem hiding this comment.
Allow recompilation without double-allocating pool capacity
When a registered instance changes revision while the pool cannot hold both its old and replacement ranges—for example, a valid system using more than half the particle capacity—this allocation fails before the old range is queued for retirement. ResolveSubmittedInstances then drops the instance, while its old record continues owning the space, so every later frame retries under the same pressure and the instance disappears permanently even though the replacement would fit by itself.
Useful? React with 👍 / 👎.
|
|
||
| if (input >= 0) | ||
| { | ||
| in.push_back(EmitNode((uint32_t)input, emitted, types, body, bindings)); |
There was a problem hiding this comment.
Reject cycles before recursively emitting graph nodes
When Connect creates a cycle such as A → B → A, EmitNode recurses here before either node is inserted into emitted, resulting in unbounded recursion and a stack-overflow crash during material compilation. Because Material::ValidateGraph currently checks only parameter references, cyclic graphs accepted through the public graph API need cycle detection before code generation.
Useful? React with 👍 / 👎.
| break; | ||
| } | ||
| case EMaterialNodeType::OneMinus: | ||
| expr = "(1.0 - " + in[0] + ")"; |
There was a problem hiding this comment.
Handle unconnected unary graph nodes safely
When a OneMinus node is added with the default empty Inputs vector and selected as a channel before being connected, this indexes in[0] and invokes undefined behavior during GenerateHLSL; the adjacent Saturate case has the same defect. Other node implementations already use the bounds-safe A(0) helper, so these unary nodes should do likewise or graph validation should reject the missing input.
Useful? React with 👍 / 👎.
| type = AT(0); | ||
| break; | ||
| case EMaterialNodeType::Fresnel: | ||
| expr = "pow(saturate(1.0 - dot(N, V)), 5.0)"; |
There was a problem hiding this comment.
Define Fresnel inputs for particle material templates
When a graph containing a Fresnel node enables any particle usage, code generation emits this expression into the particle pixel template, but those templates define neither N nor V; only Material.ps.hlsl declares them. As a result, the surface stage compiles and the subsequent particle permutation fails in DXC, making the otherwise public node unusable for sprite, ribbon, or mesh materials.
Useful? React with 👍 / 👎.
| if (emitter->GetMaterial()) | ||
| continue; |
There was a problem hiding this comment.
Refresh resolver-owned materials during recompilation
When an emitter was initially assigned an effect-authored or default material by this resolver, that assignment makes GetMaterial() non-null forever, so a later SetMaterialDescription or SetRenderMode followed by Manager::Recompile skips material resolution. The old generated material and usage remain attached—changing Sprite to Ribbon, for example, leaves an unsupported Sprite material and produces a compiled emitter with no render proxy—so resolver-owned assignments need to be distinguished from explicit overrides and refreshed when authored material state changes.
Useful? React with 👍 / 👎.
| m_Bindings.emplace(texture, SMaterialTextureBinding{ | ||
| .Handle = handle, | ||
| .ReadySubmission = m_SubmissionSerial + 1, | ||
| }); |
There was a problem hiding this comment.
Release texture bindings that are no longer referenced
When material instances repeatedly switch to newly created textures, every first resolution inserts a strong Ref<Texture> here, and the registry never erases the binding or calls TextureSet::RemoveTexture. Consequently, obsolete textures and their bindless descriptor slots remain alive for the full MaterialSystem lifetime; a dynamic texture workload eventually reaches the Vulkan bindless pool's finite texture capacity even after no material references the old textures.
Useful? React with 👍 / 👎.
| float3 diffuse = SampleIrradiance(N) * surface.BaseColor * (1.0f - surface.Metallic); | ||
| float3 R = reflect(-V, N); |
There was a problem hiding this comment.
Apply the graph normal output to lighting
When a graph drives EMaterialChannel::Normal, the generated body updates surface.Normal, but all lighting below the marker continues to use N, which was computed from input.Normal before the graph ran. Thus normal-map or procedural-normal nodes compile successfully but cannot affect diffuse, reflection, Fresnel, or direct lighting; the graph normal must be transformed and assigned to the normal used by those calculations. The particle mesh template has the same issue by lighting exclusively from input.Normal.
Useful? React with 👍 / 👎.
No description provided.