FormatSource.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #!/usr/bin/python3
  2. # Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  3. # All rights reserved.
  4. # Code licensed under the BSD License.
  5. # http://www.anki3d.org/LICENSE
  6. import glob
  7. import subprocess
  8. import threading
  9. import multiprocessing
  10. import os
  11. import tempfile
  12. import platform
  13. file_extensions = ["h", "hpp", "c", "cpp", "glsl", "hlsl", "ankiprog"]
  14. directories = ["AnKi", "Tests", "Sandbox", "Tools", "Samples"]
  15. hlsl_semantics = ["TEXCOORD", "SV_POSITION", "SV_Position", "SV_TARGET0", "SV_TARGET1", "SV_TARGET2", "SV_TARGET3", "SV_TARGET4",
  16. "SV_TARGET5", "SV_TARGET6", "SV_TARGET7", "SV_Target0", "SV_Target1", "SV_Target2", "SV_Target3", "SV_Target4",
  17. "SV_Target5", "SV_Target6", "SV_Target7", "SV_DISPATCHTHREADID", "SV_DispatchThreadID", "SV_GROUPINDEX", "SV_GroupIndex",
  18. "SV_GROUPID", "SV_GroupID", "SV_GROUPTHREADID", "SV_GroupThreadID"]
  19. hlsl_attribs = ["[shader(\"closesthit\")]", "[shader(\"anyhit\")]", "[shader(\"raygeneration\")]", "[shader(\"miss\")]",
  20. "[raypayload]", "[outputtopology(\"triangle\")]"]
  21. hlsl_attribs_fake = ["______shaderclosesthit", "______shaderanyhit", "______shaderraygeneration", "______shadermiss",
  22. "[[raypaylo]]", "______outputtopology_triangle"]
  23. def thread_callback(tid):
  24. """ Call clang-format """
  25. global mutex
  26. global file_names
  27. while True:
  28. mutex.acquire()
  29. if len(file_names) > 0:
  30. file_name = file_names.pop()
  31. else:
  32. file_name = None
  33. mutex.release()
  34. if file_name is None:
  35. break
  36. unused, file_extension = os.path.splitext(file_name)
  37. is_shader = file_extension == ".hlsl" or file_extension == ".ankiprog"
  38. if is_shader:
  39. # Read all text
  40. file = open(file_name, mode="r", newline="\n")
  41. file_txt = file.read()
  42. file.close()
  43. original_file_hash = hash(file_txt)
  44. # Replace all semantics
  45. for semantic in hlsl_semantics:
  46. file_txt = file_txt.replace(": " + semantic, "__" + semantic)
  47. for i in range(0, len(hlsl_attribs)):
  48. file_txt = file_txt.replace(hlsl_attribs[i], hlsl_attribs_fake[i])
  49. # Write the new file
  50. tmp_filefd, tmp_filename = tempfile.mkstemp(suffix=".txt")
  51. with open(tmp_filename, "w", newline="\n") as f:
  52. f.write(file_txt)
  53. os.close(tmp_filefd)
  54. orig_filename = file_name
  55. file_name = tmp_filename
  56. style_file = "--style=file:.clang-format-hlsl"
  57. else:
  58. style_file = "--style=file:.clang-format"
  59. if platform.system() == "Linux":
  60. exe = "./ThirdParty/Bin/Linux64/clang-format"
  61. else:
  62. exe = "./ThirdParty/Bin/Windows64/clang-format.exe"
  63. subprocess.check_call([exe, "-sort-includes=false", style_file, "-i", file_name])
  64. if is_shader:
  65. # Read tmp file
  66. file = open(tmp_filename, mode="r", newline="\n")
  67. file_txt = file.read()
  68. file.close()
  69. # Replace all semantics
  70. for semantic in hlsl_semantics:
  71. file_txt = file_txt.replace("__" + semantic, ": " + semantic)
  72. for i in range(0, len(hlsl_attribs)):
  73. file_txt = file_txt.replace(hlsl_attribs_fake[i], hlsl_attribs[i])
  74. new_file_hash = hash(file_txt)
  75. # Write formatted file
  76. if new_file_hash != original_file_hash:
  77. file = open(orig_filename, mode="w", newline="\n")
  78. file.write(file_txt)
  79. file.close()
  80. # Cleanup
  81. os.remove(tmp_filename)
  82. # Gather the filenames
  83. file_names = []
  84. for directory in directories:
  85. for extension in file_extensions:
  86. file_names.extend(glob.glob("./" + directory + "/**/*." + extension, recursive=True))
  87. file_name_count = len(file_names)
  88. # Start the threads
  89. mutex = threading.Lock()
  90. thread_count = multiprocessing.cpu_count()
  91. threads = []
  92. for i in range(0, thread_count):
  93. thread = threading.Thread(target=thread_callback, args=(i,))
  94. threads.append(thread)
  95. thread.start()
  96. # Join the threads
  97. for i in range(0, thread_count):
  98. threads[i].join()
  99. print("Done! Formatted %d files" % file_name_count)