cmake -> Shader neu bauen wenn sich ein header aendert.

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Matthias Gubisch
Establishment
Beiträge: 470
Registriert: 01.03.2009, 19:09

cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von Matthias Gubisch »

Hallo Leute,

ich brauche mal wieder etwas experten wissen im Bereich CMAKE

Aktuell mache ich folgendes:

Ich sammle alle shader files in meinem Projekt (liegen per Konvention alle im gleiche Folder)

Code: Alles auswählen

# find all the shader files under the shaders folder
file(GLOB_RECURSE GLSL_SOURCE_FILES
    "${PROJECT_SOURCE_DIR}/shaders/*.frag"
    "${PROJECT_SOURCE_DIR}/shaders/*.vert"
    "${PROJECT_SOURCE_DIR}/shaders/*.comp"
    "${PROJECT_SOURCE_DIR}/shaders/*.mesh"
    "${PROJECT_SOURCE_DIR}/shaders/*.task"
    )
und jage sie nacheinander durch den glsl validator

Code: Alles auswählen

## iterate each shader
foreach(GLSL ${GLSL_SOURCE_FILES})
  message(STATUS "BUILDING SHADER")
  get_filename_component(FILE_NAME ${GLSL} NAME)
  set(SPIRV "${PROJECT_SOURCE_DIR}/shaders/${FILE_NAME}.spv")
  message(STATUS ${GLSL})
  ##execute glslang command to compile that specific shader
  add_custom_command(
    OUTPUT ${SPIRV}
    COMMAND ${GLSL_VALIDATOR} --target-env vulkan1.3 -V ${GLSL} -o ${SPIRV} #--target-env vulkan1.3 sets spir-v version to 1.6
    DEPENDS ${GLSL})
  list(APPEND SPIRV_BINARY_FILES ${SPIRV})
endforeach(GLSL)

add_custom_target(
    Shaders 
    DEPENDS ${SPIRV_BINARY_FILES}
    SOURCES ${GLSL_SOURCE_FILES}
    )
Das klappt auch soweit ganz gut.
Nur habe ich auch diverse include Files fuer meine Shader.
Wie bekomme ich jetzt cmake dazu bei aenderungen in den header files die entsprechendend shader neu zu kompilieren?
Jedesmal von hand einen Rebuild des shader Targets aufzurufen funktioniert zwar, wird aber leicht vergessen....
Bevor man den Kopf schüttelt, sollte man sich vergewissern einen zu haben
Benutzeravatar
TomasRiker
Beiträge: 36
Registriert: 18.07.2011, 11:45
Echter Name: David Scherfgen
Wohnort: Hildesheim

Re: cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von TomasRiker »

Kannst du nicht einfach die Header als zusätzliche Dependencies für das Shader-Target hinzufügen? https://cmake.org/cmake/help/latest/com ... om_command
Benutzeravatar
Schrompf
Moderator
Beiträge: 4856
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von Schrompf »

Das wird der Trick sein, spekuliere ich. Ich frage mich gerade, wie CMake bei ner normalen C++-Datei rauskriegt, welche Includes einen Neubau verursachen. Und da ich irgendwie nicht so recht glaube, dass da ein echter Präprozessor drüberläuft und Includes sammelt, liegt's wahrscheinlich ganz plump daran, dass die Header mit zum CMake-Projekt hinzugefügt werden. Also könnte das auch für einen Custom Build Step funktionieren.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von Krishty »

Bei normalen C++-Dateien schreibt der Compiler eine Liste aller rekursiv inkludierten Dateien (-MMD bei GCC, /showIncludes bei MSVC). Diese Liste wird vom Build-System verwertet – bei GNU Make wird sie schlicht direkt ins Makefile inkludiert; bei Ninja in eine Datenbank geschrieben.

Wenn also nicht gerade der GLSL-Compiler eine Option gleich GCCs -MMD hat und CMake die auch für GLSL-Targets unterstützt, bleibt nur das Einsammeln von Hand.

Edit: Microsofts HLSL-Compiler hat eine Option -H, die in diese Richtung geht. Na toll, wieder ein Abend weg :D
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Matthias Gubisch
Establishment
Beiträge: 470
Registriert: 01.03.2009, 19:09

Re: cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von Matthias Gubisch »

TomasRiker hat geschrieben: 20.06.2023, 23:04 Kannst du nicht einfach die Header als zusätzliche Dependencies für das Shader-Target hinzufügen? https://cmake.org/cmake/help/latest/com ... om_command
Nein so einfach ist das leider nicht, den Versuch hatte ich auch schon. Das Buildsystem weiss halt dann trotzdem nicht welcher Shader welchen Header nutzt...
Krishty hat geschrieben: 20.06.2023, 23:40 Bei normalen C++-Dateien schreibt der Compiler eine Liste aller rekursiv inkludierten Dateien (-MMD bei GCC, /showIncludes bei MSVC). Diese Liste wird vom Build-System verwertet – bei GNU Make wird sie schlicht direkt ins Makefile inkludiert; bei Ninja in eine Datenbank geschrieben.

Wenn also nicht gerade der GLSL-Compiler eine Option gleich GCCs -MMD hat und CMake die auch für GLSL-Targets unterstützt, bleibt nur das Einsammeln von Hand.

Edit: Microsofts HLSL-Compiler hat eine Option -H, die in diese Richtung geht. Na toll, wieder ein Abend weg :D
Guter Tipp!!
glslValidator kann das zwar nicht (zumindest habe ich in der Doku nichts gefunden) aber glslc sollte das koennen. Scheint als muesste ich den Shader compiler wechseln, ich werde das mal testen und berichte dann weiter.

Danke schonmal bis hierhin.
Bevor man den Kopf schüttelt, sollte man sich vergewissern einen zu haben
Benutzeravatar
TomasRiker
Beiträge: 36
Registriert: 18.07.2011, 11:45
Echter Name: David Scherfgen
Wohnort: Hildesheim

Re: cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von TomasRiker »

Matthias Gubisch hat geschrieben: 21.06.2023, 08:25
TomasRiker hat geschrieben: 20.06.2023, 23:04 Kannst du nicht einfach die Header als zusätzliche Dependencies für das Shader-Target hinzufügen? https://cmake.org/cmake/help/latest/com ... om_command
Nein so einfach ist das leider nicht, den Versuch hatte ich auch schon. Das Buildsystem weiss halt dann trotzdem nicht welcher Shader welchen Header nutzt...
Und wenn du sämtliche Header als Abhängigkeit auflistest?
Klar, dann werden ggf. Shader unnötigerweise neu kompiliert, aber immer noch besser als immer dran denken zu müssen es manuell zu machen.
Matthias Gubisch
Establishment
Beiträge: 470
Registriert: 01.03.2009, 19:09

Re: cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von Matthias Gubisch »

Wäre eventuell eine Alternative wenn es mit dem Wechsel auf glslc wie oben geschrieben nicht klappt.

Mittlerweile habe ich doch relativ viele und auch längliche shader da würde ich es gern vermeiden immer alle zu compilieren 😉
Bevor man den Kopf schüttelt, sollte man sich vergewissern einen zu haben
Matthias Gubisch
Establishment
Beiträge: 470
Registriert: 01.03.2009, 19:09

Re: cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von Matthias Gubisch »

Nach etwas recherche habe ich jetzt rausgefunden dass der glslangValidator den ich als compiler verwende eine Option hat um dependencyfiles fuer das Buildsystem zu schreiben.

Kingt erstmal Top, allerdings baut der auf windows escape characters in den Filepfad ein den dann wiederum Ninja nicht interpretieren kann....
Was dazu fuehrt dass jetzt immer all shader gebaut werden...

Ich forsche dann mal weiter...
Bevor man den Kopf schüttelt, sollte man sich vergewissern einen zu haben
Matthias Gubisch
Establishment
Beiträge: 470
Registriert: 01.03.2009, 19:09

Re: cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von Matthias Gubisch »

Nachdem ich gestern noch ein wenig rumgespielt habe:
Des Raetsels Loesung sind relative Pfade...

So sieht die fertige Loesung auch, eigentlich ganz einfach wenn man die verschiedenen Fallstricke kennt...

Code: Alles auswählen

## iterate each shader
foreach(GLSL ${GLSL_SOURCE_FILES})
  message(STATUS "BUILDING SHADER")
  get_filename_component(FILE_NAME ${GLSL} NAME)
  set(SPIRV "${PROJECT_SOURCE_DIR}/shaders/${FILE_NAME}.spv")
  message(STATUS ${GLSL})
  file(RELATIVE_PATH SPIRV_REL ${PROJECT_SOURCE_DIR}/shaders/ ${SPIRV})
  ##execute glslang command to compile that specific shader
  add_custom_command(
    OUTPUT ${SPIRV_REL}
    COMMAND ${GLSL_VALIDATOR} --target-env vulkan1.3 -V ${GLSL} -o ${SPIRV_REL} --depfile ${SPIRV}.d #--target-env vulkan1.3 sets spir-v version to 1.6
    DEPENDS ${GLSL}
    DEPFILE ${SPIRV}.d)
  list(APPEND SPIRV_BINARY_FILES ${SPIRV_REL})
endforeach(GLSL)
Bevor man den Kopf schüttelt, sollte man sich vergewissern einen zu haben
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von Krishty »

Großartig! 👍
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4856
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von Schrompf »

Ah, --depfile $VAR.d produziert das Dependencies-File für die nächste Runde?
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: cmake -> Shader neu bauen wenn sich ein header aendert.

Beitrag von Krishty »

Allgemein ja, genau.

Wobei Ninja konkret das Depfile in seine interne Datenbank mergt, weil die sehr viel schneller ist als das Parsen von einer Textdatei pro potentiell zu bauender Datei. AFAIK gibt es Tricks, den Inhalt direkt nach Ninja zu pipen, ohne dass etwas auf der Platte landet – aber die sind auch mir zu spacig.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten