Formalize gaussian splat prepare-order pass

This commit is contained in:
2026-04-11 03:02:30 +08:00
parent 5191bb1149
commit fac6e588a8
16 changed files with 1529 additions and 68 deletions

View File

@@ -16,7 +16,7 @@ namespace Resources {
constexpr Core::uint32 kTextureArtifactSchemaVersion = 1;
constexpr Core::uint32 kMaterialArtifactSchemaVersion = 6;
constexpr Core::uint32 kMeshArtifactSchemaVersion = 2;
constexpr Core::uint32 kShaderArtifactSchemaVersion = 5;
constexpr Core::uint32 kShaderArtifactSchemaVersion = 6;
constexpr Core::uint32 kUIDocumentArtifactSchemaVersion = 2;
constexpr Core::uint32 kVolumeFieldArtifactSchemaVersion = 2;
constexpr Core::uint32 kModelArtifactSchemaVersion = 1;
@@ -104,7 +104,7 @@ struct ModelMaterialBindingArtifact {
};
struct ShaderArtifactFileHeader {
char magic[8] = { 'X', 'C', 'S', 'H', 'D', '0', '5', '\0' };
char magic[8] = { 'X', 'C', 'S', 'H', 'D', '0', '6', '\0' };
Core::uint32 schemaVersion = kShaderArtifactSchemaVersion;
};
@@ -138,6 +138,14 @@ struct ShaderVariantArtifactHeader {
Core::uint32 backend = 0;
Core::uint32 keywordCount = 0;
Core::uint64 compiledBinarySize = 0;
Core::uint32 backendCompiledBinaryCount = 0;
Core::uint32 reserved = 0;
};
struct ShaderBackendCompiledBinaryArtifactHeader {
Core::uint32 backend = 0;
Core::uint32 reserved = 0;
Core::uint64 compiledBinarySize = 0;
};
struct ShaderKeywordDeclarationArtifactHeader {

View File

@@ -30,6 +30,10 @@ public:
const D3D_SHADER_MACRO* macros,
const char* entryPoint,
const char* target);
bool InitializeFromBytecode(
const void* bytecodeData,
size_t bytecodeSize,
const char* target = nullptr);
void Shutdown() override;
const D3D12_SHADER_BYTECODE GetD3D12Bytecode() const;

View File

@@ -21,6 +21,7 @@
namespace XCEngine {
namespace Components {
class GameObject;
class GaussianSplatRendererComponent;
} // namespace Components
namespace Resources {
@@ -31,6 +32,11 @@ class Shader;
namespace Rendering {
struct VisibleGaussianSplatItem;
namespace Passes {
namespace Internal {
class BuiltinGaussianSplatPassResources;
} // namespace Internal
} // namespace Passes
namespace Passes {
@@ -84,16 +90,20 @@ private:
std::vector<BuiltinPassSetLayoutMetadata> setLayouts;
PassResourceBindingLocation perObject = {};
PassResourceBindingLocation material = {};
PassResourceBindingLocation gaussianSplatSortDistanceBuffer = {};
PassResourceBindingLocation gaussianSplatOrderBuffer = {};
PassResourceBindingLocation gaussianSplatPositionBuffer = {};
PassResourceBindingLocation gaussianSplatOtherBuffer = {};
PassResourceBindingLocation gaussianSplatColorBuffer = {};
PassResourceBindingLocation gaussianSplatSHBuffer = {};
PassResourceBindingLocation gaussianSplatViewDataBuffer = {};
};
struct DynamicDescriptorSetKey {
PassLayoutKey passLayout = {};
Core::uint32 setIndex = 0;
Core::uint64 objectId = 0;
const Components::GaussianSplatRendererComponent* gaussianSplatRenderer = nullptr;
const Resources::Material* material = nullptr;
const Resources::GaussianSplat* gaussianSplat = nullptr;
@@ -101,6 +111,7 @@ private:
return passLayout == other.passLayout &&
setIndex == other.setIndex &&
objectId == other.objectId &&
gaussianSplatRenderer == other.gaussianSplatRenderer &&
material == other.material &&
gaussianSplat == other.gaussianSplat;
}
@@ -111,6 +122,7 @@ private:
size_t hash = PassLayoutKeyHash()(key.passLayout);
hash ^= std::hash<Core::uint32>{}(key.setIndex) + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= std::hash<Core::uint64>{}(key.objectId) + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= reinterpret_cast<size_t>(key.gaussianSplatRenderer) + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= reinterpret_cast<size_t>(key.material) + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= reinterpret_cast<size_t>(key.gaussianSplat) + 0x9e3779b9u + (hash << 6) + (hash >> 2);
return hash;
@@ -120,10 +132,13 @@ private:
struct CachedDescriptorSet {
OwnedDescriptorSet descriptorSet = {};
Core::uint64 materialVersion = 0;
RHI::RHIResourceView* sortDistanceView = nullptr;
RHI::RHIResourceView* orderView = nullptr;
RHI::RHIResourceView* positionsView = nullptr;
RHI::RHIResourceView* otherView = nullptr;
RHI::RHIResourceView* colorView = nullptr;
RHI::RHIResourceView* shView = nullptr;
RHI::RHIResourceView* viewDataView = nullptr;
};
struct ResolvedShaderPass {
@@ -171,6 +186,32 @@ private:
}
};
struct ComputePipelineKey {
const Resources::Shader* shader = nullptr;
Containers::String passName;
Containers::String keywordSignature;
bool operator==(const ComputePipelineKey& other) const {
return shader == other.shader &&
passName == other.passName &&
keywordSignature == other.keywordSignature;
}
};
struct ComputePipelineKeyHash {
size_t operator()(const ComputePipelineKey& key) const noexcept {
size_t hash = reinterpret_cast<size_t>(key.shader);
hash ^= std::hash<Containers::String>{}(key.passName) + 0x9e3779b9u + (hash << 6) + (hash >> 2);
hash ^= std::hash<Containers::String>{}(key.keywordSignature) + 0x9e3779b9u + (hash << 6) + (hash >> 2);
return hash;
}
};
enum class PassLayoutUsage : Core::uint8 {
Draw,
PrepareOrder
};
bool EnsureInitialized(const RenderContext& context);
bool CreateResources(const RenderContext& context);
void DestroyResources();
@@ -180,14 +221,19 @@ private:
ResolvedShaderPass ResolveGaussianSplatShaderPass(
const RenderSceneData& sceneData,
const Resources::Material* material) const;
ResolvedShaderPass ResolvePrepareOrderShaderPass(const RenderSceneData& sceneData) const;
PassResourceLayout* GetOrCreatePassResourceLayout(
const RenderContext& context,
const ResolvedShaderPass& resolvedShaderPass);
const ResolvedShaderPass& resolvedShaderPass,
PassLayoutUsage usage);
RHI::RHIPipelineState* GetOrCreatePipelineState(
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData,
const Resources::Material* material);
RHI::RHIPipelineState* GetOrCreateComputePipelineState(
const RenderContext& context,
const RenderSceneData& sceneData);
bool CreateOwnedDescriptorSet(
const BuiltinPassSetLayoutMetadata& setLayout,
OwnedDescriptorSet& descriptorSet);
@@ -197,12 +243,20 @@ private:
const BuiltinPassSetLayoutMetadata& setLayout,
Core::uint32 setIndex,
Core::uint64 objectId,
const Components::GaussianSplatRendererComponent* gaussianSplatRenderer,
const Resources::Material* material,
const Resources::GaussianSplat* gaussianSplat,
const MaterialConstantPayloadView& materialConstants,
const RenderResourceCache::CachedGaussianSplat& cachedGaussianSplat);
const RenderResourceCache::CachedGaussianSplat& cachedGaussianSplat,
RHI::RHIResourceView* sortDistanceView,
RHI::RHIResourceView* orderView,
RHI::RHIResourceView* viewDataView);
void DestroyOwnedDescriptorSet(OwnedDescriptorSet& descriptorSet);
void DestroyPassResourceLayout(PassResourceLayout& passLayout);
bool PrepareVisibleGaussianSplat(
const RenderContext& context,
const RenderSceneData& sceneData,
const VisibleGaussianSplatItem& visibleGaussianSplat);
bool DrawVisibleGaussianSplat(
const RenderContext& context,
const RenderSurface& surface,
@@ -212,11 +266,14 @@ private:
RHI::RHIDevice* m_device = nullptr;
RHI::RHIType m_backendType = RHI::RHIType::D3D12;
Resources::ResourceHandle<Resources::Shader> m_builtinGaussianSplatShader;
Resources::ResourceHandle<Resources::Shader> m_builtinGaussianSplatUtilitiesShader;
std::unique_ptr<Resources::Material> m_builtinGaussianSplatMaterial;
RenderResourceCache m_resourceCache;
Internal::BuiltinGaussianSplatPassResources* m_passResources = nullptr;
std::unordered_map<PassLayoutKey, PassResourceLayout, PassLayoutKeyHash> m_passResourceLayouts;
std::unordered_map<PipelineStateKey, RHI::RHIPipelineState*, PipelineStateKeyHash> m_pipelineStates;
std::unordered_map<ComputePipelineKey, RHI::RHIPipelineState*, ComputePipelineKeyHash> m_computePipelineStates;
std::unordered_map<DynamicDescriptorSetKey, CachedDescriptorSet, DynamicDescriptorSetKeyHash> m_dynamicDescriptorSets;
};

View File

@@ -87,6 +87,11 @@ struct ShaderResourceBindingDesc {
Containers::String semantic;
};
struct ShaderBackendCompiledBinary {
ShaderBackend backend = ShaderBackend::Generic;
Containers::Array<Core::uint8> payload;
};
struct ShaderStageVariant {
ShaderType stage = ShaderType::Fragment;
ShaderLanguage language = ShaderLanguage::GLSL;
@@ -96,6 +101,16 @@ struct ShaderStageVariant {
Containers::String profile;
Containers::String sourceCode;
Containers::Array<Core::uint8> compiledBinary;
Containers::Array<ShaderBackendCompiledBinary> backendCompiledBinaries;
const Containers::Array<Core::uint8>* GetCompiledBinaryForBackend(
ShaderBackend targetBackend) const;
void SetCompiledBinaryForBackend(
ShaderBackend targetBackend,
const Containers::Array<Core::uint8>& binary);
void SetCompiledBinaryForBackend(
ShaderBackend targetBackend,
Containers::Array<Core::uint8>&& binary);
};
struct ShaderPass {