Загрузка ресурсов

GraphicsLoadingTask

GraphicsLoadingTask — базовый класс для асинхронной загрузки/выгрузки GPU-ресурсов (шейдеры, текстуры, буферы и т.д.).

Базовая реализация

public abstract class GraphicsLoadingTask
{
    public bool Loaded { get; private set; }
    
    public void Load()
    {
        if (Loaded) return;
        OnLoad();  // вызовите реализацию
        Loaded = true;
    }
    
    public void Unload()
    {
        if (!Loaded) return;
        OnUnload();
        Loaded = false;
    }
    
    protected abstract void OnLoad();
    protected abstract void OnUnload();
}

Примеры встроенных задач

ShaderLoadingTask

Загружает шейдер из исходного текста:

// Создаём из исходника
var shaders = new List<ShaderScript>
{
    new ShaderScript(ShaderType.Vertex, vertexSource),
    new ShaderScript(ShaderType.Fragment, fragmentSource)
};
Igdrasil.LoadShader("myShader", shaders);

// Выгружаем
Igdrasil.UnloadShader("myShader");

RawShaderLoadingTask

Загружает уже скомпилированный шейдер (если у вас есть кеш):

var compiled = new CompiledShaderProgram { /* ... */ };
Igdrasil.LoadShader("precompiled", compiled);

TextureLoadingTask

Загружает текстуру из RawImage:

var image = new RawImage(width, height, pixelData);
Igdrasil.LoadTexture("albedo", image);

Igdrasil.UnloadTexture("albedo");

Очередь загрузки

Все задачи хранятся в глобальной очереди:

// Добавить задачу
var task = new MyLoadingTask();
Igdrasil.AddLoadingTask(task);
// Если Context уже есть, автоматически вызовется task.Load()

// Удалить задачу (выгружает ресурс)
Igdrasil.RemoveLoadingTask(task);

// Получить все задачи
var allTasks = Igdrasil.GraphicsLoaders;

Кастомные задачи

public class TextMeshLoadingTask : GraphicsLoadingTask
{
    private readonly string _fontPath;
    private Font _font;
    
    public TextMeshLoadingTask(string fontPath)
    {
        _fontPath = fontPath;
    }
    
    protected override void OnLoad()
    {
        // Загружаем шрифт в GPU
        _font = Font.Load(_fontPath);
        Igdrasil.Logger.Info("Font loaded: {0}", _fontPath);
    }
    
    protected override void OnUnload()
    {
        // Выгружаем из GPU
        _font?.Dispose();
        Igdrasil.Logger.Info("Font unloaded: {0}", _fontPath);
    }
}

// Использование
Igdrasil.AddLoadingTask(new TextMeshLoadingTask("fonts/arial.ttf"));

Порядок загрузки

Все задачи в очереди выполняются пайплайном в порядке добавления:

// Очередь выполнения:
Igdrasil.AddLoadingTask(task1); // выполнится первой
Igdrasil.AddLoadingTask(task2); // выполнится второй
Igdrasil.AddLoadingTask(task3); // выполнится третьей

// На выгрузку ― в обратном порядке:
// task3, task2, task1

Это важно для зависимостей (например, шейдер перед использованием его текстур).

Обработка ошибок

public class SafeTextureLoadingTask : GraphicsLoadingTask
{
    private readonly string _path;
    private readonly RawImage _fallback;
    private Texture _texture;
    
    public SafeTextureLoadingTask(string path, RawImage fallback)
    {
        _path = path;
        _fallback = fallback;
    }
    
    protected override void OnLoad()
    {
        try
        {
            var image = Image.Load(_path);
            _texture = CreateTexture(image);
            Igdrasil.Logger.Info("Loaded texture: {0}", _path);
        }
        catch (Exception ex)
        {
            Igdrasil.Logger.Warning("Failed to load {0}, using fallback: {1}", _path, ex.Message);
            _texture = CreateTexture(_fallback);
        }
    }
    
    protected override void OnUnload()
    {
        _texture?.Dispose();
    }
}

Асинхронная загрузка

Для длительной загрузки используйте TaskManager:

public class AsyncTextureLoadingTask : GraphicsLoadingTask
{
    private readonly string _path;
    private Texture _texture;
    
    protected override void OnLoad()
    {
        // Загружаем файл в отдельном потоке
        TaskManager.AddTask(async () =>
        {
            var data = await LoadImageAsync(_path);
            // Используем GPU только в главном потоке
            _texture = CreateTextureOnMainThread(data);
            Igdrasil.Logger.Info("Async loaded: {0}", _path);
        });
    }
    
    protected override void OnUnload()
    {
        _texture?.Dispose();
    }
}

Версия: 1.0