LINUX.ORG.RU

Divinity Original Sin Enhanced Edition @ Mesa r600g

 ,


21

5
Divinity Original Sin Enhanced Edition @ Mesa r600g

Я таки заставил эту игру работать 😊

В процессе была куча сегфолтов и адовые артефакты.

По сути проблемы всего три (конкретно для r600g, в целом для месы – 2):

  1. Контекст OpenGL 4.2. Драйвер r600g рапортует версию 3.3, а движок игры, в свою очередь, работает по принципу segfault driven error handling. Решается просто:
    MESA_GL_VERSION_OVERRIDE=4.2 
    MESA_GLSL_VERSION_OVERRIDE=420
  2. Невалидные шейдеры. Тут сразу:
    • Во-первых, разрабы используют расширение ARB_shading_language_include, которое не поддерживается ничем кроме невидиевской проприетарщины. Но во имя амдшной проприетарщины они запилили в движок fallback режим, в котором это расширение реализуется прямо в движке на коленке, однако включается этот fallback режим (немного) через жопу – они (только) проверяют возвращаемое значение функции glXGetProcAddressARB на nullptr. А glXGetProcAddressARB не обязан возвращать nullptr, кроме адреса надо смотреть еще в список расширений, чего они не делают, а месовская реализация никогда не возвращает nullptr -> segfault driven error handling. Чинится этот баг подстановкой костыля в LD_PRELOAD.
    • Во-вторых, в шейдерах постобработки SMAA/FXAA у них где-то в дебрях кода обложенное ifdef'ами лежит включение очередного расширения, что, блджад, не правильно. После обнаружения этой фигни месовский GLSL компилятор совершенно справедливо прерывает компиляцию, а так как ребята не умеют в обработку ошибок — см. выше. Этот баг обходится с помощью месовского механизма подмены шейдеров в рантайме и костыля-решейпера их кода шейдеров. файла drirc, в который нужно добавить
      <application name='Divinity Original Sin Enhanced Edition' executable='EoCApp'>
          <option name='allow_glsl_extension_directive_midshader' value='true' />
      </application>
  3. Графические артефакты. У них в движке (насколько я понял) есть две принципиально разные ветки кода/рендеринга, которые разделяются по (внимание!) строке в GL_VENDOR: если в этой строке что угодно кроме "ATI Technologies Inc.", то активируется невидиевская ветвь, что на месе приводит к аду, если же доставить в LD_PRELOAD еще один костыль с этой строкой, то рендеринг становится мягким и шелковистым.

TL;DR: Gentoo, дефолтные кеды, ШГ, панелька с автоскрытием.

>>> Просмотр (1600x900, 1682 Kb)

★★★★★

Проверено: JB ()

Костыль в LD_PRELOAD

#define _GNU_SOURCE
#include <GL/gl.h>
#include <string.h>
#include <dlfcn.h>

const char* vendor = "ATI Technologies Inc.";
const GLubyte* (*o_glGetString)(GLenum name);
void (*(*o_glXGetProcAddressARB)(const GLubyte*)) (void);
 
void _init(void)
{
    o_glGetString = dlsym(RTLD_NEXT, "glGetString");
    o_glXGetProcAddressARB = dlsym(RTLD_NEXT, "glXGetProcAddressARB");
}

const GLubyte* glGetString(GLenum name)
{
    if (name == GL_VENDOR)
        return (const GLubyte*) vendor;
    return o_glGetString(name);
}

void (*glXGetProcAddressARB(const GLubyte* procName)) (void)
{
    if (strcmp((const char*)procName, "glNamedStringARB") == 0 ||
        strcmp((const char*)procName, "glDeleteNamedStringARB") == 0 ||
        strcmp((const char*)procName, "glCompileShaderIncludeARB") == 0 ||
        strcmp((const char*)procName, "glIsNamedStringARB") == 0 ||
        strcmp((const char*)procName, "glGetNamedStringARB") == 0 ||
        strcmp((const char*)procName, "glGetNamedStringivARB") == 0)
        return NULL;
    return o_glXGetProcAddressARB(procName);
}

собирать так:

gcc -Wall -fPIC -DPIC -c dos_ee_workaround.c
ld -shared -o dos_ee_workaround.so dos_ee_workaround.o -ldl -lGL

Stil ★★★★★ ()

Костыль для шейдеров

#!/usr/bin/env python3

import sys
import os
import re

def fix_shaders(src_dir, dst_dir, ATI_PADDINGBUG=None):
    ati_re = re.compile(r'^\s*#define\sATI_PADDINGBUG')
    if ATI_PADDINGBUG != None:
        ati_str = '#define ATI_PADDINGBUG {:d}'.format(ATI_PADDINGBUG)
    ext_re = re.compile(r'^\s*#extension GL_ARB_gpu_shader5\s+:\s+enable')
    ext_str = '#extension GL_ARB_gpu_shader5 : enable\n'

    for filename in os.listdir(src_dir):
        src_file = '{:s}/{:s}'.format(src_dir, filename)
        with open(src_file, 'r') as f:
            src = f.readlines()
        dst = []
        for line in src:
            if ATI_PADDINGBUG != None and ati_re.match(line):
                dst.append(ati_str)
                continue
            if ext_re.match(line):
                dst.insert(2, ext_str)
                continue
            dst.append(line)
        dst_file = '{:s}/{:s}'.format(dst_dir, filename)
        with open(dst_file, 'w') as f:
            f.writelines(dst)

if __name__ == '__main__':
    if len(sys.argv) < 3:
        print('usage: ', file=sys.stderr)
        print('{:s} src_dir dst_dir [ATI_PADDINGBUG]'.format(sys.argv[0]),
              file=sys.stderr)
        exit(1)
    ATI_PADDINGBUG = None
    if len(sys.argv) > 3:
        ATI_PADDINGBUG = int(sys.argv[3])
    fix_shaders(sys.argv[1], sys.argv[2], ATI_PADDINGBUG)
Stil ★★★★★ ()

Что со всем этим делать

Сначала — создать где-нибудь рядом с игрой каталог workaround и скинуть туда костыли. Потом — пытаться играть, запуская fix-shaders при очередном сегфолте.

Мой my-start.sh выглядит так

GAME_DIR="/media/Storage/Games/GOG/Linux/DivinityOriginalSinEnhancedEdition"

MESA_GL_VERSION_OVERRIDE=4.2 \
MESA_GLSL_VERSION_OVERRIDE=420 \
MESA_SHADER_READ_PATH="${GAME_DIR}/workaround/read" \
MESA_SHADER_DUMP_PATH="${GAME_DIR}/workaround/dump" \
LD_PRELOAD="${GAME_DIR}/workaround/dos_ee_workaround.so" \
LD_LIBRARY_PATH="${GAME_DIR}/game" \
${GAME_DIR}/game/EoCApp

Если игра падает с сегфолтом — прогонять fix-shaders.sh

GAME_DIR="/media/Storage/Games/GOG/Linux/DivinityOriginalSinEnhancedEdition"

${GAME_DIR}/workaround/fix-shaders.py "${GAME_DIR}/workaround/dump" "${GAME_DIR}/workaround/read" 0

Где fix-shaders.py — это «Костыль для шейдеров»

Stil ★★★★★ ()

И, да, у меня нету бложика, простите.

Stil ★★★★★ ()

Маньяк, круто, респект!

Я себе с помощью костылей через LD_PRELOAD когда-то виброотклик по нажатию клавиш в меню Linux'ового смартфона делал.

EXL ★★★★ ()

О ужас. И это всё, только ради того, чтобы запустилась одна игра.

sudopacman ★★★★★ ()

эпично конечно, показывает всю суть «портов» и криворуков их делающих.

Novell-ch ★★★★★ ()

Зато работает изкаробки, не то что всякие блобы.

tides ()

Ты реально мужик, вот что достойно уважения!

Какое же быдлофуфло вся эта проприетарщина.

curufinwe ★★★★ ()

без всяких фиксов шейдеров заработало на 7970 и гитовой месе.

Novell-ch ★★★★★ ()

Я таки

заработал, возми с полки пирожок ))

gray ★★★★★ ()

Хорошо что я так и не купил это говно. Как я понимаю авторы дропнули поддержку игры и не будут пилить эти баги.

ТСу респект за проделанную работу.

Behem0th ★★★★★ ()

Упорство достойное уважения!

Пойду посмотрю, что хоть за игра. :)

ssh2 ()

Я помню у Larian Studios спрашивали, собарились ли они портировать игру под линукс - они ответили, что нету времени...

deathangel908 ()

Во-первых разрабы используют расширение ARB_shading_language_include

Вроде же были патчи в рассылке с добавлением этого расширения. Но вроде не приняли, не помню почему.

Behem0th ★★★★★ ()

Отличная работа! Буду запускать на Radeon HD 5050. А есть ускорялки и твики?

ZenitharChampion ★★★★★ ()

Круто.

У них в движке (насколько я понял) есть две принципиально разные ветки кода/рендеринга, которые разделяются по (внимание!) строке в GL_VENDOR

А это как обнаружил?

i-rinat ★★★★★ ()

Я обычно равнодушен к играм, но присоединяюсь к толпе плюсующих хотя бы за маньячение с LD_PRELOAD и прочим хотпатчингом. Круто.

segfault driven error handling

Порадовало :)

intelfx ★★★★★ ()
Ответ на: комментарий от Novell-ch

У меня не запускается. Появляется окно с прогресс-баром, он доходит до конца и игра сегфолтится. Что делать с фиксом шейдеров не понял, мой питон говорит syntax error.

Khnazile ★★★ ()
Ответ на: комментарий от Khnazile

у меня еще в глобале идет
allow_glsl_extension_directive_midshader=true
glsl_zero_init=true
мож они и влияют

Novell-ch ★★★★★ ()
Ответ на: комментарий от Novell-ch

это куда добавлять? В drirc или это просто переменные окружения?

Khnazile ★★★ ()
Ответ на: комментарий от Novell-ch

Тогда не помогает. Может игра сама где-нибудь какой-нибудь кэш хранит? Я ее раньше пытался запускать, даже окно появлялось, может остались какие-нибудь ошметки?

Khnazile ★★★ ()
Ответ на: комментарий от Khnazile

врятли, я тож раньше гоговские версии пускал безрезультатно, а щас новую версию поставил и заработало

Novell-ch ★★★★★ ()
Ответ на: комментарий от Novell-ch

А, типа, в гоге и стиме на самая новая? Жесть какая :)

Khnazile ★★★ ()

С горем пополам запустил, используя хаки предоставленные ТС. Правда дальше меню не пробился, уж слишком часто падает. Явно что-то не то с фильтрацией текстур, хорошо заметно на моделях на заднем плане. Загляну лучше еще через годик, вдруг у разработчиков этой игры случится помутнение рассудка и они выпустят патч.

Khnazile ★★★ ()
Ответ на: комментарий от tides

Зато работает изкаробки, не то что всякие блобы.

Что?

Stil ★★★★★ ()
Ответ на: комментарий от Behem0th

Во-первых разрабы используют расширение ARB_shading_language_include

Вроде же были патчи в рассылке с добавлением этого расширения. Но вроде не приняли, не помню почему.

Там были костыли для запуска конкретно Divinity.

https://lists.freedesktop.org/archives/mesa-dev/2016-March/109789.html

Stil ★★★★★ ()
Ответ на: комментарий от i-rinat

У них в движке (насколько я понял) есть две принципиально разные ветки кода/рендеринга, которые разделяются по (внимание!) строке в GL_VENDOR

А это как обнаружил?

Когда она не взлетела первый раз, я пошёл на баг-трекер месы и нашёл там это: https://bugs.freedesktop.org/show_bug.cgi?id=93551

Кроме этого — strings-based grep по файлам игры не обнаружил ничего похожего на vendor-string кроме того, что выше.

Кроме этого — я как-то случайно наткнулся на разрабов этого порта и просто спросил :)

Ну и в довершение — эта гипотеза подтвердилась экспериментально :)

Stil ★★★★★ ()
Ответ на: комментарий от Novell-ch

allow_glsl_extension_directive_midshader=true

Вот это было сильно, спасибо бро. Так фикс шейдеров действительно не нужен.

Stil ★★★★★ ()
Ответ на: комментарий от Khnazile

Добавь в drirc

       <application name="Divinity Original Sin Enhanced Edition" executable="EoCApp">
            <option name="allow_glsl_extension_directive_midshader" value="true" />
        </application>

Stil ★★★★★ ()
Ответ на: комментарий от Novell-ch

врятли, я тож раньше гоговские версии пускал безрезультатно, а щас новую версию поставил и заработало

Я, кстати, в версию с GOG играю. Игра рапортует версию 2.0.119.430.

Stil ★★★★★ ()

Пользуясь случаем

Хочу послать лучи поноса мудакам, которые сами не читают стандартов, которые «реализуют».

Stil ★★★★★ ()

Неплохое расследование, одобряю.

andreyu ★★★★★ ()

похвальное количество усилий! но зачем на ATI? сами создаем препятствия, сами их преодолеваем?:( игра-то хоть хорошая? никогда раньше не слышал.

p.s.

панелька страшная ужасно.

crypt ★★★★ ()
Ответ на: комментарий от Stil

Мне казалось что позже была именно реализация, наверно показалось.

Behem0th ★★★★★ ()
Ответ на: комментарий от Novell-ch

Я пробовал с allow_glsl_extension_directive_midshader=true у меня не работало. Но это была не последняя версия игры. Поставил на закачку, попробую.

Behem0th ★★★★★ ()
Ответ на: комментарий от quantum-troll

из интереса скачал посмотреть. а на nvidia «все просто работает». (с)

crypt ★★★★ ()
Ответ на: комментарий от Stil

Это всё конечно хорошо, но ntfs, mp3, wine и тд в линуксе есть. В открытых дровах нет говёных, но используемых фич — дрова не готовы.

tides ()
Последнее исправление: tides (всего исправлений: 1)

Да, громадная работа проделана. Больше бы таких энтузиастов.

Odalist ★★★★★ ()
Ответ на: комментарий от tides

Это не «дрова не готовы», это «жопорукие разработчики не готовы». В данном случае: 1) вообще и никогда не проверяли никаких ошибок; 2) опирались на UB в определении расширения; 3) в конце-концов просто клали с прибором на стандарт с которым работают.

Помнишь знаменитое мелкомягкое «embrace, extend and extinguish»? Так вот невидия в своих дровах делает точно то же самое.

Stil ★★★★★ ()
Ответ на: комментарий от sudopacman

Следует отметить, что _очень_ хорошая игра.

Evgueni ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.