// 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;
}
};