Search
Write a publication
Pull to refresh
14
0

Game Developer по образованию. Пописываю на Rust-е

Send message

Dreamside Interactive использует Unreal Engine и активно работает с фидбеком сообщества. Игра долго находилась в раннем доступе в Steam и Epic Games Store. Официальный релиз состоялся в ноябре 2023 года, но студия продолжает развивать игру: планируются рейды, гильдии, новый континент, улучшение сюжетной кампании, патчи, сезонные события, балансировка и новые квестовые линии. В долгосрочной перспективе Dreamside хотят превратить Frozen Flame в мир-сервис, который живет годами и расширяется сообществом и лором.

Вы хотя бы проверяйте, что пишете. Из стима:

Обратите внимание: разработчики выпустили последнее обновление более 24 мес. назад. Информация и сроки, указанные разработчиками, могут больше не соответствовать действительности.

Судя по отзывам, разрабы просто забросили игру.

Если одна карта явно ждет другую, то просто такой алгоритм разделения работы - не самый оптимальный.

Автор тоже приходит к такому выводу и демонстрирует асинхронный подход, но почему-то на графиках также присутствуют "Ожидание GPU0 другой GPU1". Мне это не понравилось, потому что у себя в реализации у меня никакого ожидания: рендеринг карт теней и передача полученной текстуры происходят асинхронно. Я могу посчитать отдельно сколько что занимает, но в общее время кадра оно не входит.

Абстрактный наброс. Будут примеры?

этом создают проблемы с которыми придётся иметь дело позже

много желающих запихать туда еще больше.

При этом вообще-то никак не решена проблема разрастания зависимостей

Можно и не добавлять зависимости. Либо напишите, как надо решить, мы RFC-ку расту напишем.

В DirectX12 помимо общей кучи (ID3D12Heap) можно сделать общий фенс (ID3D12Fence). Его могут сигналить и ожидать другие GPU.

Автор в своем коде ставит метки для разных рендер-проходов. У него есть проход с копированием ресурсов, в котором происходит синхронизация двух очередей из разных видеокарт и само копирование. То есть он ставит метку до самой синхронизации и метку после копирования.

Интересно, каким инструментом получены Диаграммы распределения времени на двух видеокартах?

С помощью ID3D12QueryHeap я ставлю временные метки (timestamps) на GPU, потом пытаюсь прочитать полученные результаты. Эти результаты отправляю по TCP программе-бенчеру, которая выполняет вычисления средних значений. После сохраняю это в CSV-формате и импортирую в Excel.

Хочется понять, чего именно ждет GPU -может, данных из памяти (независимо от второй карты) или вообще окончания чего-то на CPU?

Не понял вопроса.

Мое предположение, что производительность будет +- такой же.

К сожалению, не разбираюсь DXVK экосистеме, но я пробежался по vkd3d и vkd3d-proton и понял, что прототип не запустится на vkd3d, так как отсутствует реализация функции d3d12_device_OpenSharedHandle, которая используется в моем коде.

В vkd3d:

static HRESULT STDMETHODCALLTYPE d3d12_device_OpenSharedHandle(ID3D12Device9 *iface,
        HANDLE handle, REFIID riid, void **object)
{
    FIXME("iface %p, handle %p, riid %s, object %p stub!\n",
            iface, handle, debugstr_guid(riid), object);

    return E_NOTIMPL;
}

В vkd3d-proton есть реализация, но только для Windows.

Связка дискретная + интегрированная видеокарта встречается не мало. Наибольший прирост популярности и самая большая доля использования среди GPU за последний месяц у NVIDIA GeForce RTX 4060 Laptop GPU. https://store.steampowered.com/hwsurvey/directx/?sort=chg

Да, возможно. Я встречал работы, которые как раз этому посвящены. Только для VR понадобятся видеокарты с одинаковой производительностью.

что 2 гпу это решение....

Я нигде не утверждал, что это решение всех проблем. У меня был гипотеза "Перенос рендера Cascaded Shadow Maps на вторую видеокарту может увеличить производительность". Я реализовал прототип и подтвердил свою гипотезу.

Если сейчас все начнут требовать 2 гпу для очередной даже не ыыыы подделки, это будет мягко говоря победа мракобесия.

2 гпу - это не требование, а опция. Условная галочка в настройках "задействовать вторую видеокарту" для систем, где несколько видях.

Миллисекунды надо искать не посредством 2 карточки а посредством оптимизаций.

Оптимизации могут быть разные. В данном случае это перенос рендера теней на вторую видеокарту. Если это не оптимизация, то, по вашему мнению, использование нескольких ядер ЦПУ не является оптимизацией?

Тут другой вопрос - а зачем? Что бы все еще быстрее летало?

Дополнительные миллисекунды для бюджета кадра лишними не бывают.

Решать надо не проблему мощностей а проблему оптимизации, которой никто не хочет заморачиваться. Учить дизайнеров эффективно рисовать \ моделировать и программистов писать эффективный код. Вместо этого, у нас (псевдо)2д стратегии которые на минималках выдают 10-15 фпс - потому что дизайнер решил что проще обмазаться шейдерами чем потратить условно неделю-месяц на нечто более оптимальное - или накидал 500 текстурок, моделек и еще кучу эффектов в один файл облака лишь бы облако выглядело естественно, когда какой нибудь средний шутер вполне себе уверенно работает на средних на том самом встроенном железе и по графике практически не отличим от передовых "ыыыы" шыдэвров.

Согласен. Сейчас современные игры без DLSS не вывозят стабильный и высокий фреймрейт.

В Rust работают над решением проблемы цветных фукнций.

В крейте bytemuck есть функция cast_mut. Если без крейта хотите, то через касты указателей в unsafe-е.

Hidden text
use indextree::*;
use rand::Rng;

struct Foo {
    _p: [u8; 256],
}

fn main() {
    let mut linked_list = std::collections::LinkedList::new();
    let mut arena = Arena::new();

    let query = (0..1_000_000).map(|_| rand::thread_rng().gen_range(0..1_000usize)).collect::<Vec<_>>();

    for _ in 0..1_000_000 {
        linked_list.push_back(Foo { _p: [0; 256] });
    }

    let mut last_node = arena.new_node(Foo { _p: [0; 256] });
    let first_node = last_node;
    for _ in 0..(1_000_000 - 1) {
        let node = arena.new_node(Foo { _p: [0; 256] });
        node.append(last_node, &mut arena);
        last_node = node;
    }

    let time = std::time::Instant::now();
    for i in &query {
        let _ = std::hint::black_box(linked_list.iter().skip(*i).next());
    }
    println!("Linked list: {:?}", time.elapsed());

    let time = std::time::Instant::now();
    for i in &query {
        let _ = std::hint::black_box(first_node.descendants(&arena).skip(*i).next());
    }
    println!("Indextree: {:?}", time.elapsed());
}

Linked list: 589.368393ms
Indextree: 1.937983ms

Зато прыгать по указателям быстро ?

19 марта выходит обновление 1.6

Надо мерить. Всё зависит от LIMIT , если оно большое, то время на синхронизацию будет меньше, чем вычисления, соответственно на бенчмарки сильно не повлияет. Я бы составил таблицу с зависимостью времени от LIMIT.

Метод init3 работает некорректно, так как он недетерминированный - результаты выполнения потоков объединяются в неопределенном порядке. Из-за этого результат метода init3 может отличаться от результатов других методов. В данном случае необходима другая логика объединения результатов.

По второй ссылке представлены другие варианты бага, например, вместо placeholder-а используется Option:
let f: fn(Option<&'d &'d ()>, &'c T) -> &'d T = foo; (Сигнатура helper-а другая).
Возникнуть теоретически может, если писать код с временами жизни и с вложенными ссылками, а не с Rc<RefCell<T>> :)

Information

Rating
451-st
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity

Specialization

Game Developer, System Software Engineer
Middle
Rust
C++
Vulkan API
Computer graphics
Golang
gRPC
PostgreSQL
Redis
DirectX