lightspeed.trex.asset_pipeline.core#
SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the “License”);
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
- class lightspeed.trex.asset_pipeline.core.AssetKind(*values)#
Top-level asset families supported by the Remix asset pipeline.
- class lightspeed.trex.asset_pipeline.core.AssetPipelineCoreExtension#
Register process-owned texture- and mesh-optimization persistence codecs and Apply handlers.
- on_shutdown() None#
Keep codecs and handlers available until the queue core drains active jobs and destroys its registry.
- on_startup(_ext_id: str) None#
Register the texture- and mesh-optimization persistence codecs and Apply handlers.
- Parameters:
_ext_id – Extension identifier supplied by Kit.
- class lightspeed.trex.asset_pipeline.core.PipelineOutputPath(
- work_path: Path,
- output_path: Path,
Runner-owned paths for one publishable pipeline output.
Steps write
work_pathand may inspectoutput_pathfor valid reuse. The runner later publisheswork_pathto the sameoutput_path.
- class lightspeed.trex.asset_pipeline.core.RemixAssetItem(
- value: TValue,
- kind: AssetKind,
- source_path: pathlib.Path,
- textures: list[TextureAsset] = <factory>,
- texture_bindings: list[TextureBinding] = <factory>,
- collected_dependencies: dict[pathlib.Path,
- pathlib.Path] = <factory>,
Stable item type for the whole Remix asset pipeline.
valueis the current primary asset path. For a model, it starts as the source model and becomes the generated/collected USD path after import. For a texture, it remains the source texture path whiletextures[0].pathbecomes the processed texture path.collected_dependenciesmaps original dependency paths to workspace copies. The collector supplies these runtime identities when it imports the model.- classmethod from_model(
- path: Path,
Create a model item.
- classmethod from_texture(
- path: Path,
- texture_type: TextureTypes,
Create a texture item with one typed texture record.
- class lightspeed.trex.asset_pipeline.core.RemixAssetPipelineConfig(
- output_dir: Path,
- texture_type: TextureTypes | None,
Constructor configuration shared by Remix asset pipeline steps.
Callers must pass explicit constructor options when building a pipeline. This is intentionally small; do not turn step configuration into an auto-discovered schema or a generic metadata dictionary.
- output_dir#
Local directory receiving final pipeline outputs.
- Type:
pathlib.Path
- texture_type#
Semantic used only when synthesizing a missing texture record.
- Type:
omni.flux.asset_importer.core.data_models.enums.TextureTypes | None
- class lightspeed.trex.asset_pipeline.core.RemixAssetPipelineContext(
- items: list[PipelineItemT] = <factory>,
- execution_state: dict[str,
- PipelineStepState] = <factory>,
- source_root: pathlib.Path | None = None,
- work_dir: pathlib.Path | None = None,
- output_dir: pathlib.Path | None = None,
- replace_udim_textures_by_empty: bool = False,
- force_dds_reencode: bool = False,
- referenced_layers: tuple[str,
- ...] = (),
- texture_ledger: tuple[TextureLedgerEntry,
- ...] = (),
Typed context for the linear Remix asset processing pipeline.
A caller must use this context inside
async with. The first stage open leases one ingestion USD context. The outermost scope exit closes its stage, whether the block finished or raised, and returns the lease for reuse. A stage that fails to close stays in the context until the nextopen_stageon that context replaces it.- source_root#
Stable project or import root preserved under the output directory.
- Type:
pathlib.Path | None
- work_dir#
Runner-owned temporary workspace.
- Type:
pathlib.Path | None
- output_dir#
Final local publication directory.
- Type:
pathlib.Path | None
- replace_udim_textures_by_empty#
Author an empty asset path for a UDIM texture instead of a
<UDIM>pattern. Model ingestion sets this toTrueto match the legacymodel_ingestion.jsonschema. Standalone texture optimization leaves itFalse.- Type:
bool
- force_dds_reencode#
Re-encode a source texture that is already a
.ddsfile. By default a DDS source is copied to its output unchanged, so an encoded texture is never compressed twice.- Type:
bool
- referenced_layers#
Every layer identifier the model composes, recorded by the discovery step.
- Type:
tuple[str, …]
- texture_ledger#
Every texture binding discovered, stored so the prepare job can freeze it into
PrepareOptimizationResult.- Type:
tuple[TextureLedgerEntry, …]
- sub_usd_lineage#
Every (source_path, published_path) pair for sub-USD layers the runner published alongside the model. Populated by the publication step so the mesh job can include them in the complete asset lineage.
- Type:
list[tuple[pathlib.Path, pathlib.Path]]
- clear_output_paths() None#
Clear final output path reservations for a fresh pipeline run.
- async close_stage() None#
Close the open stage and keep the leased ingestion context alive.
This is the counterpart of
open_stage. The context stays alive, so the nextopen_stagecall reuses it. A step that runs one pass for each layer must close between rounds, because a context that still holds a layer keeps stale in-memory state after the step saves that layer to disk.The USD context holds a reference to every layer of the open stage, so this releases the root layer before it closes the stage. Layers that stay held break a later stage open in the same process.
- copy_to_work_dir(
- path: Path,
Copy a source file into this pipeline run’s collision-safe workspace.
- copy_to_work_path(
- path: Path,
- work_path: Path,
Copy a source file into an explicit runner-owned workspace path.
- get_output_path(
- work_path: Path,
- *,
- source_path: Path | None = None,
Return the final collision-safe output path for a workspace file.
Steps may use this to find reusable outputs from earlier runs. The runner uses the same reservation table when publishing final files, so steps never need to hand-roll deduplication suffixes.
- get_work_path(
- source_path: Path,
- *,
- stem: str | None = None,
- stem_suffix: str = '',
- suffix: str | None = None,
- create_parent: bool = True,
Return a runner-owned workspace path for a step output.
The context owns collision isolation so steps do not hand-roll temp filenames. The returned filename stays readable while the parent directory is keyed by the absolute source path.
stemreplaces the source filename stem. A step needs this when the legacy output name rewrites part of the stem instead of appending to it.
- is_in_work_dir(path: Path) bool#
Return whether the path already belongs to this pipeline run’s workspace.
- async open_stage(
- stage_path: Path,
Open a USD stage in this scope’s leased ingestion context.
The scope leases the context exclusively, so ingestion never replaces the interactive stage in the app’s default context. The context holds one stage at a time, so a later call with a different path replaces the stage this call returned. A caller must not hold a stage, prim, or layer handle across a call with a different path.
- Raises:
RuntimeError – If the caller is outside an
async withscope, or if the stage cannot be opened.
- reserve_output_path(
- input_path: Path,
- *,
- source_path: Path | None = None,
- stem_suffix: str = '',
- suffix: str | None = None,
- create_parent: bool = True,
Reserve collision-safe workspace and final paths for one output.
input_pathcontrols the readable output filename and source-scoped workspace directory.source_pathcan provide a stable original input for final-name deduplication wheninput_pathis an intermediate.
- async save_stage() None#
Save the stage that is open in the leased ingestion context.
- Raises:
RuntimeError – If no stage is open in the leased context.
- property textures: Iterator[TextureAsset]#
Yield every texture record currently owned by the pipeline items.
- validate_output_dir(
- step_name: str,
Return validation errors for steps that need runner-owned final output paths.
- validate_work_dir(
- step_name: str,
Return validation errors for steps that need runner-owned workspace files.
- class lightspeed.trex.asset_pipeline.core.TextureAsset(
- path: Path,
- texture_type: TextureTypes,
- key: str = '',
- original_path: Path | None = None,
- udim_tiles: tuple[Path, ...] = (),
- channel: str | None = None,
- factor: tuple[float, ...] | None = None,
One image file to process into a Remix-ready texture.
The conversion steps do not care whether this came from ComfyUI, Asset Library, a referenced model texture, or an extracted embedded model texture.
For a non-UDIM texture
udim_tilesis an empty tuple andpathis the sole concrete output. For a UDIM textureudim_tilescarries every converted concrete tile andpathis the first tile, so downstream steps and publication walk the complete set.- property source_path: Path#
Return the stable source path used for output naming and reuse checks.
- class lightspeed.trex.asset_pipeline.core.TextureBinding(
- shader_path: Path,
- input_name: str,
- original_asset_path: AssetPath,
- texture: TextureAsset,
- material_path: str = '',
Typed USD binding from a model shader input to one TextureAsset.
This is model rewrite state, not texture conversion state. It lets the final model step replace the original USD asset path with the processed texture path.
material_pathis the correlation identity. Material conversion rewrites the shader between the prepare walk and the mesh walk, so only the owning material prim path survives both. Seelightspeed.trex.asset_pipeline.core.jobs.models.derive_texture_key().
- lightspeed.trex.asset_pipeline.core.build_prepare_optimization_steps(
- config: RemixAssetPipelineConfig,
Build the model-preparation step list.
The returned steps import the model, clean up and convert its materials to AperturePBR, then discover its textures and record every composed layer. Conversion runs before discovery, as the legacy schema ran
MaterialShadersbeforeConvertToDDS, so discovery reads the AperturePBR input names and every source-shader texture reaches the texture job.- Parameters:
config – Run configuration consumed by the standardize-input step.
- Returns:
The prepare phase steps, in order.
- lightspeed.trex.asset_pipeline.core.build_remix_mesh_pipeline(
- config: RemixAssetPipelineConfig,
- processed_textures: dict[tuple[str, TextureTypes], ProcessedTexture],
Build the mesh-optimization step list that consumes the processed textures.
The import step runs first, because each queue job owns its own workspace. The prepare job’s workspace is gone by now, so this job materializes the model and its textures again before any step reads them.
Material cleanup and conversion ran in the prepare phase. They run again here because each job materializes the model afresh, and both skip a model that is already AperturePBR. The legacy model ingestion schema never triangulated meshes, so this pipeline keeps the authored topology. Texture application runs after material conversion, so the collected shader paths and input names are the post-conversion ones.
An empty map means the model has no processed textures, so the step keeps the bindings the model already authored.
- Parameters:
config – Run configuration consumed by the import step.
processed_textures – Map from
(material_path, texture_type)to the resolvedProcessedTexture. Must be built byresolve_processed_textures()from the ledger and texture result before this builder is called.
- Returns:
The mesh phase steps, in order.
- lightspeed.trex.asset_pipeline.core.build_remix_texture_pipeline() list[PipelineStep]#
Build the texture-processing step list for one standalone batch.
Float source standardization, channel extraction, normal conversion, and DDS encoding process each texture item. The model-only steps are omitted rather than relied on to skip themselves.
- Returns:
The texture phase steps, in order.
- async lightspeed.trex.asset_pipeline.core.run_remix_asset_pipeline(
- config: RemixAssetPipelineConfig,
- context: RemixAssetPipelineContext,
- steps: Iterable[PipelineStep],
- *,
- on_step_started: Callable[[PipelineStep, int, int], Awaitable[None]] | None = None,
- on_item_completed: Callable[[RemixAssetItem, int, int], Awaitable[None]] | None = None,
Run the Remix asset pipeline and publish its outputs as the final reported phase.
- Parameters:
config – Canonical pipeline configuration.
context – Remix items and runner-owned paths for this run.
steps – Configured processing steps. The caller must state its step list.
on_step_started – Async callback awaited before each runnable phase.
on_item_completed – Async callback awaited after each source item finishes processing.
- Raises:
PipelineValidationError – If the configured steps cannot run against
context.OSError – If the output directory or temporary workspace cannot be created or removed.