fix: load the assets a run-time material references - #3370
Open
sasvdw wants to merge 2 commits into
Open
Conversation
Material.New runs the generator outside the content pipeline, so the texture references its features attach stay proxies: empty objects with reference data. Nothing resolved them, so a material built in code bound a 0x0 texture for the environment lookup table. Resolve them after generation when a content manager is given, and report each one that stays empty otherwise. An asset reaches a build only when something in the content references it, so a game that builds every material in code can lack the asset; report that too rather than stop. Fixes stride3d#3369 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An asset reaches a build only when something references it. Nothing references these two, because MaterialSpecularMicrofacetEnvironmentGGXLUT names them from code, so a game that builds every material in code never gets them and the material cannot resolve them. RootAssets is the declared way to say an asset is reached from code. Stride.Engine already lists the default font and the splash screen, which the engine reaches the same way. The test moves to Stride.Graphics.Tests, which holds no material asset that references the tables. It passes there only if both halves hold. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Details
Summary — A material built by
Material.Newbound an empty texture for the environment DFG lookuptable. Fixes #3369.
The two halves
The reported bug is that
Material.Newnever resolves the references its features attach:Fixing that alone is not enough, and writing the test is what showed why. The first red run failed with
The asset ... could not be found, because the table may not be in the build at all. So there aretwo problems, and a game whose materials are all built in code needs both fixed.
The reference was never resolved.
MaterialSpecularMicrofacetEnvironmentGGXLUT.Generateattachesthe table with
AttachedReferenceManager.CreateProxyObject, which isnew T()plus reference metadata.A proxy becomes the real asset in one place only,
ReferenceSerializer, and only during a content load.Material.Newruns the generator outside that path.Material.Newnow takes an optionalContentManagerand, after generation, walks each pass'sparameters and loads anything still marked
IsProxy. It resolves generically rather than special-casingthe lookup table, so
Generatestays untouched and the asset compiler keeps serializing proxies exactlyas before.
The asset was never guaranteed to be there. The asset compiler starts from roots and follows
references.
Package.RootAssetsis the declared escape hatch for assets nothing references — "needs tobe compiled even if not directly or indirectly referenced (useful for explicit code references)".
Stride.Enginealready declares the default font, the splash screen and the debug sprite font that way;the splash screen is the identical pattern, named from code in
GameSettingsFactory.cs:23. The twolookup tables were never declared, so they reach a build only when some material asset happens to use
that environment function and drags them in.
Both are now declared. They ship in every bundle as a result, including games that never use that
environment function — 32x64
R16G16_Floatplus the 8-bit variant, the same unconditional treatment thesplash screen already has.
When it still cannot resolve
Without a
ContentManager, or when the asset is genuinely absent, the material keeps the empty objectand reports it, naming the parameter and the URL. It does not throw. Turning a subtly wrong render into
a crash would be the worse trade, and the roughly twelve existing callers — editor gizmos, previews,
debug shapes, fallbacks — pass no content manager and none of them uses a specular model.
Tests
TestMaterialProxyResolutioninStride.Graphics.Tests: the table resolves to a real texture, and theno-content-manager path reports rather than stays silent. That project holds no material asset
referencing the tables, so it passes only if both halves hold. Reverting just the
.sdpkgchange putsit back to red with
ContentManagerException, so it measures what it claims to.TestGeneratorLeavesTextureReferencesAsProxiesinStride.Assets.Tests: pins thatMaterialGenerator.Generateon its own still yields a proxy, which is what the asset compilerserializes. Four tests there already built this feature and asserted only on shader source.
Related Issue
Fixes #3369.
Types of changes
Checklist
Validation status
Stride.Renderingclean underStrideGraphicsApi=Direct3D11,=Direct3D12and=Vulkan,with
-t:Rebuildrather than an incremental build. Not=Null: that backend does not compile onmastertoday, with partial-method signature drift inNull/CommandList.Null.csandNull/Texture.Null.cs. Unrelated to this change and worth its own issue.Stride.Graphics.Tests, 7 inTestMaterialGenerator— the new contract test andthe six that were already there, so the asset compiler's path is unchanged.
MaterialLayerABBWithAPI, is[Fact(Skip = ...)]and never runs, so no baseline encodes the brokenappearance. Left skipped; the stated reason is debugging convenience and I have no evidence it relates
to this bug.
Not fixed here
Generatechooses between the 16-bit and 8-bit tables on a graphics profile when the real question istexture format support. That is a separate concern, already listed under "found, not fixed" in #3368.