Руки дошли написать про найденную ошибку в движке. Но мой английский не позволит толком объяснить ее суть. Даже по русски не факт что смогу:)
Короче - сидел и думал - почему в студии включаемые include шейдеры hlsl не находит - из-за чего шейдеры не компилируются
Вот например есть шейдер hlsl
В его коде есть что-то типа:
#include "CommonCode.vs"
Сам шейдер находится. а вот CommonCode.vs - пишет что такого файла нет.
Стал выяснять. И выяснил.
В студии путь к экзешнику (рабочий каталог) задается через настройки и обычно я всегда ставлю $(TargetDir).
Студия разворачивает этот путь на подобие:
C:\Users\1\Desktop\engine\code\..\bin\Debug
Причина того что он туда вставляет эти вот \..\ в том что путь начинается от местонахождения солюшена project.sln который у меня и находится в code\
А приложение отправляется на уровень выше, то есть в:
C:\Users\1\Desktop\engine\bin\Debug
Вот.
Теперь смотрим код юрхо. а именно загрузку шейдера в Shader.cpp
if (line.StartsWith( "#include")) { String includeFileName = GetPath( source.GetName( )) + line.Substring( 9).Replaced( "\"", "").Trimmed( ); SharedPtr<File> includeFile = cache->GetFile( includeFileName);
А именно обратите внимание на GetPath(source.GetName())
Эта функция как раз и возвращает рабочий каталог (который моя студия обозвала C:\Users\1\Desktop\engine\code\..\bin\Debug)
То есть на этом моменте полный путь к встраиваемому коду будет
C:\Users\1\Desktop\engine\code\..\bin\Debug\Data\CommonCode.vs
Именно эта строчка будет отправлена в cache->GetFile()
А теперь собственно и показываю - где ошибка.
открываем ResourceCache.cpp
и ищем там эту функцию:
SharedPtr<File> ResourceCache::GetFile(const String& nameIn, bool sendEventOnFailure) { MutexLock lock( resourceMutex_); String name = SanitateResourceName( nameIn);
Здесь пока норм.
Заходим в функцию SanitateResourceName()
String ResourceCache::SanitateResourceName(const String& nameIn) const { String name = GetInternalPath( nameIn); name.Replace( "../", ""); name.Replace( "./", "");
И что мы тут видим? а видим что оно тупо вырезает путь наверх из пути к файлу.
В итоге мой шейдер ищется не там где он лежит, а в:
C:\Users\1\Desktop\engine\code\bin\Debug\Data\CommonCode.vs
То есть в путь затесалась лишняя папка code\ Внутри этой папки никаких папок bin нет.
Я считаю это грубой ошибкой. шанс что пользователь запустит с таким же символом ../ есть. Например если он запускает через батник и там по хитрому строит пути.
Нельзя вот так вот просто взять и вырезать из пути к файлу кусок
Почему ошибку не нашли? потому что если использовать для генерации солюшена CMake - он не умеет пользоваться такими вот макросами для задачи пути к экзешнику - и все пути в нем захардкорены - если перетащить папку с проектом куда-то еще - оно не соберется правильно.
Я уже давно говорю - что использование CMake - зло:)
Надеюсь кто-нибудь заинтересованный отпишет об этой ошибке разработчику движка
radio
> то же поступает не по человечески.
в сложных батниках такое тоже бывает
radio
> Да и не вижу большого смысла компилить шейдеры в процессе разработки.
ты не совсем понял - я запускаю экзешник через студию чтобы отдебажить студией. При запуске оно грузит шейдеры. Шейдеры содержат в себе инклюд другого шейдера - ну чтобы не копипастить общий код между разными шейдерами.
Так вот - первый шейдер нормально грузится файловой системой движка. А вот все инклюды в этом шейдере вот так вот бажат - потому что в их пути затирается переход на верхний уровень
И ошибка конкретно в загрузке шейдеров. Материалы нормально грузят файлы которые в них прописаны (там своя функция получения полного имени файла)
radio
> может есть причины.
может и есть - поэтому проблему должен решать разраб движка
но там например есть ./
А в том же линуксе без ./ могут быть проблемы с загрузкой
Урхо ищет каждый файл в правильной директории. Смени расширение на hlsl и он будет его искать в Shaders/HLSL без каких-то проблем
1vanK
> Урхо ищет каждый файл в правильной директории. Смени расширение на hlsl и он
> будет его искать в Shaders/HLSL без каких-то проблем
нет. Там в коде ищется именно так как написал я, и оно будет искать папку bin\CoreData\Shaders\HLSL в папке кода с солюшеном - где ее нет
Я ничего не придумал - я показал код - он делает именно то что в нем написано, а именно:
- при парсинге шейдера ищет все инклюды
- при этом путь этих инклюдов вычисляется не по папке Shaders\HLSL а по папке родительского шейдера
- при этом после того как он вычислит полный путь к инклюду. он просто стирает в нем ../ уже это ошибка. нельзя вот так просто взять и в пути стереть команду перехода на верхний уровень
И в итоге оно так:
экзешник и CoreData лежат в c:\project\bin.
Код и солюшен в c:\project\code.
при запуске из студии в дебаге экзешника - его рабочая папка становится c:\project\code\..\bin\
родительский шейдер реально лежит в c:\project\bin\CoreData\Shaders\HLSL\shader.hlsl
После запуска в студии рабочая папка шейдера c:\project\code\..\bin\CoreData\Shaders\HLSL\shader.hlsl
его инклюд там же - c:\project\code\..\bin\CoreData\Shaders\HLSL\Core.hlsl
И вот при загрузке инклюда, он в коде просто вырезает ..\
получаем что оно ищет шейдер c:\project\code\bin\CoreData\Shaders\HLSL\Core.hlsl
Которого конечно же там нет.
при этом это не проблема студии. вместо студии может быть любой профайл запускаемый из батника с относительными путями в которые залезет по разным причинам ..\ (да такая вещь есть даже в cmake)
1vanK
> Урхо ищет каждый файл в правильной директории. Смени расширение на hlsl и он
> будет его искать в Shaders/HLSL без каких-то проблем
Вот я тебе еще раз покажу код который грузит инклюды
Shader.cpp
if (line.StartsWith( "#include")) { String includeFileName = GetPath( source.GetName( )) + line.Substring( 9).Replaced( "\"", "").Trimmed( ); }
То есть source имеет правильный путь - это файл который юрхо нашла по твоему алгоритму. Теперь оно ищет путь к инлудам этого шейдера. и вот тут и начинается неверный ход.
Оно берет полное имяосновноого шейдера и извлекает из него путь к папке шейдера через GetPath() (можешь сам глянуть что делает)
Далее к полученному пути оно добавляет имя инклюда. Это полный путь, поэтому юрхо ищет именно так, как прописано в строчке includeFileName
На самом деле чтобы было правильней - надо из кода убрать "GetPath(source.GetName()) +". Тогда юрхо автоматически подставит путь к шейдерам как ты и написал
Но я же и пишу что тут он так не делает потому что ему четко говорят - этот шейдер лежит вот здесь
И здесь все правильно
Но у нас есть следующая строчка
cache->GetFile(includeFileName);
А вот она и должна искать там где ты написал - если бы ей передали только имя файла. Но ей передали полный путь к файлу
и в первой же строчке своего кода:
SharedPtr<File> ResourceCache::GetFile(const String& nameIn, bool sendEventOnFailure) { MutexLock lock( resourceMutex_); String name = SanitateResourceName( nameIn);
Она берет этот путь и отправляет в функцию SanitateResourceName()
которая вырезает
String ResourceCache::SanitateResourceName(const String& nameIn) const { // Sanitate unsupported constructs from the resource name String name = GetInternalPath( nameIn); name.Replace( "../", ""); name.Replace( "./", "");
Часть пути.
Ну шли пулреквест)
>Я уже давно говорю - что использование CMake - зло:)
Как мне кажется Вайтжонг тут бы злостно посмеялся )
по теме: собираю через смake 3.4.2 полет норм, единственное что огорчает это в релиз версии проектов-скетчей постоянно приходиться убирать ..\lib\Urho3D_d.lib
codingmonkey
> по теме: собираю через смake 3.4.2 полет норм, единственное что огорчает это в
> релиз версии проектов-скетчей постоянно приходиться убирать ..\lib\Urho3D_d.lib
Я имел ввиду что из-за cmake они не увидели эту ошибку - через ее солюшен для студии поймать сложно. Я то руками делаю солюшен как мне надо.
И у пользователя вполне будет падать игра если он ее запустит через какого-нибудь запускатора (мало ли что прийдет в голову игроку - имеет право - он же не игру ковыряет - а просто запускает ее через что-нибудь)
1vanK
> Ну шли пулреквест)
Я тут по русски толком не смог объяснить. со своим гуглоанглийским и подавно. а разработчик юрхо очень не любит чужие реквесты - я уже имел на этом опыт - мне не понравилось что-то ему(им) отправлять
>со своим гуглоанглийским и подавно
норм я им только и пользуюсь, и понимают вроде же.
интернациональный англицкий это не настоящий англицкий там может быть перепутано все, важно чтобы слова в предложении встречались какие нужно )
>а разработчик юрхо очень не любит чужие реквесты
а знаешь почему? потому что ему это потом и поддерживать, мы зареквестили и умыли руки а ему %%сь дальше с поддержкой и разбиранием новых багов спровоцированных новым кодом, от сюда надо полагать и концепция tiny library )
radio
> Вот при запуске приложения оно ведь работает или нет.
при запуске самого приложения оно работает - потому что в пути к рабочей папке нет (что логично) таких вещей как /../
radio
> в самом шейдере задать относительный путь ../CommonCode.vs
в том и прикол что загрузчик шейдера сотрет ../
я это исправил так:
Вместо:
String includeFileName = GetPath(source.GetName( )) + line.Substring( 9).Replaced( "\"", "").Trimmed( );
Я написал:
String includeFileName = line.Substring(9).Replaced( "\"", "").Trimmed( );
Что это дает - это позволяет юрхо самому искать шейдер там где вы и написали в Shader/HLSL.
Какой минус - если я попытаюсь загрузить шейдер хранящийся где-то в другом месте, то инклюды оно теперь будет искать не там где этот шейдер а в Shader/HLSL. что тоже плохо, например в случае редактора (вон в юнити шейдеры можно хранить в любой папке - да и в определенный момент их накопится... но решение есть - задать все стороние папки в настройках ресурсменеджера... но тоже не очень).
нашел такую ошибку:
CollisionShape умеет правильно делать коллижен по CustomGeometry (SetCustomTriangleMesh) только, если там геометрия задана как TRIANGLE_LIST, в остальных случаях - коллижен строится неверно, в реализации SetCustomTriangleMesh просто не учитывается PrimitiveType
Тема в архиве.