// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Core/Types/DataContainer.h" #include "Engine/Content/BinaryAsset.h" #include "Engine/Graphics/GPUDevice.h" #include "ShaderStorage.h" /// /// Base class for assets that can contain shader. /// class FLAXENGINE_API ShaderAssetBase { protected: ShaderStorage::Header _shaderHeader; public: /// /// Gets internal shader cache chunk index /// /// Chunk index FORCE_INLINE static int32 GetCacheChunkIndex() { return GetCacheChunkIndex(GPUDevice::Instance->GetShaderProfile()); } /// /// Gets internal shader cache chunk index /// /// Shader profile /// Chunk index static int32 GetCacheChunkIndex(ShaderProfile profile); #if USE_EDITOR /// /// Prepare shader compilation options /// /// Options virtual void InitCompilationOptions(struct ShaderCompilationOptions& options) { } #endif protected: /// /// Gets the parent asset. /// /// The asset. virtual BinaryAsset* GetShaderAsset() const = 0; #if USE_EDITOR /// /// Saves this shader asset to the storage container. /// /// True if failed, otherwise false. bool Save(); #endif /// /// Shader cache loading result data container. /// struct ShaderCacheResult { /// /// The shader cache data. Allocated or linked (if gathered from asset chunk). /// DataContainer Data; #if COMPILE_WITH_SHADER_COMPILER /// /// The list of files included by the shader source (used by the given cache on the runtime graphics platform shader profile). Paths are absolute and unique. /// Array Includes; #endif }; /// /// Loads shader cache (it may call compilation or gather precached data). /// /// The output data. /// True if cannot load data, otherwise false. bool LoadShaderCache(ShaderCacheResult& result); #if COMPILE_WITH_SHADER_COMPILER /// /// Registers shader asset for the automated reloads on source includes changes. /// /// The asset. /// The loaded shader cache. void RegisterForShaderReloads(Asset* asset, const ShaderCacheResult& shaderCache); /// /// Unregisters shader asset from the automated reloads on source includes changes. /// /// The asset. void UnregisterForShaderReloads(Asset* asset); #endif }; /// /// Base class for assets that can contain shader /// template class ShaderAssetTypeBase : public BaseType, public ShaderAssetBase { public: static const uint32 ShadersSerializedVersion = ShaderStorage::Header::Version; protected: /// /// Init /// /// Asset scripting class metadata /// Asset information explicit ShaderAssetTypeBase(const ScriptingObjectSpawnParams& params, const AssetInfo* info) : BaseType(params, info) { } protected: // [BaseType] BinaryAsset* GetShaderAsset() const override { return (BinaryAsset*)this; } bool init(AssetInitData& initData) override { // Validate version if (initData.SerializedVersion != ShadersSerializedVersion) { LOG(Warning, "Invalid shader serialized version."); return true; } // Validate data if (initData.CustomData.Length() != sizeof(_shaderHeader)) { LOG(Warning, "Invalid shader header."); return true; } // Load header 'as-is' Platform::MemoryCopy(&_shaderHeader, initData.CustomData.Get(), sizeof(_shaderHeader)); return false; } AssetChunksFlag getChunksToPreload() const override { AssetChunksFlag result = 0; const auto cachingMode = ShaderStorage::GetCachingMode(); if (cachingMode == ShaderStorage::CachingMode::AssetInternal && GPUDevice::Instance->GetRendererType() != RendererType::Null) result |= GET_CHUNK_FLAG(GetCacheChunkIndex()); return result; } };