From 620002921c5a4b22e68aa98335361791bfc39d76 Mon Sep 17 00:00:00 2001 From: daiqingshuang Date: Fri, 6 Jun 2025 18:22:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=81=E8=A3=85=E7=BC=96=E8=AF=91=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler.py | 43 ++++++++++-------------------------------- compiler_cmd.py | 41 ++++++++++++++++++++++++++++++++++++++++ main.py | 4 ++-- shader_parser.py | 49 ++++++++++++++++++------------------------------ slangc_finder.py | 4 +++- 5 files changed, 74 insertions(+), 67 deletions(-) create mode 100644 compiler_cmd.py diff --git a/compiler.py b/compiler.py index 3ada42a..92c5a77 100644 --- a/compiler.py +++ b/compiler.py @@ -7,25 +7,25 @@ SDL3_GPU Slang Compiler - Main Compiler import os import subprocess import tempfile -from typing import List, Dict, Tuple -from shader_types import ShaderInfo, TargetFormat, ShaderStage -from slangc_finder import SlangcFinder -from shader_parser import ShaderParser +from typing import List, Dict + from binding_manager import BindingManager from code_generator import CodeGenerator +from compiler_cmd import make_cmd +from shader_parser import ShaderParser +from shader_types import ShaderInfo, TargetFormat + class SDL3GPUSlangCompiler: def __init__(self, include_paths: List[str] = None): - self.slangc_path = SlangcFinder.find_slangc() self.include_paths = include_paths or [] - self.parser = ShaderParser(self.slangc_path, self.include_paths) + self.parser = ShaderParser(self.include_paths) self.binding_manager = BindingManager() self.code_generator = CodeGenerator() - def parse_slang_shader(self, source_path: str, include_paths: List[str] = None) -> Dict[str, ShaderInfo]: + def parse_slang_shader(self, source_path: str, target: TargetFormat, include_paths: List[str] = None) -> Dict[str, ShaderInfo]: """解析Slang着色器源码,提取资源信息""" - return self.parser.parse_slang_shader(source_path, include_paths) - + return self.parser.parse_slang_shader(source_path, target, include_paths) def compile_shader(self, shader_info: ShaderInfo, target: TargetFormat) -> tuple[str, dict]: """编译着色器并返回二进制路径和绑定信息""" @@ -48,30 +48,7 @@ class SDL3GPUSlangCompiler: try: # 编译着色器 - target_flag = { - TargetFormat.SPIRV: 'spirv', - TargetFormat.DXIL: 'dxil', - TargetFormat.DXBC: 'dxbc', - TargetFormat.MSL: 'metal' - }[target] - - stage_flag = { - ShaderStage.VERTEX: 'vertex', - ShaderStage.FRAGMENT: 'fragment', - ShaderStage.COMPUTE: 'compute' - }[shader_info.stage] - - cmd = [ - self.slangc_path, - tmp_path, - '-entry', shader_info.entry_point, - '-o', output_path, - '-target', target_flag, - '-stage', stage_flag, - '-profile', 'sm_6_6', - '-I', *self.include_paths, # 添加包含路径 - ] - + cmd = make_cmd(tmp_path, target, shader_info.stage, shader_info.entry_point, self.include_paths, output_path) print(f"Compiling shader with command: {' '.join(cmd)}") subprocess.run(cmd, check=True) diff --git a/compiler_cmd.py b/compiler_cmd.py new file mode 100644 index 0000000..44235f9 --- /dev/null +++ b/compiler_cmd.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +""" +SDL3_GPU Slang Compiler - Command Generation +""" +from shader_types import TargetFormat, ShaderStage +from slangc_finder import slangc_path + + +def make_cmd(source_file: str, target: TargetFormat, stage: ShaderStage, entry_point: str, include_paths, + output_path: str): + """生成编译命令""" + target_flag = { + TargetFormat.SPIRV: 'spirv', + TargetFormat.DXIL: 'dxil', + TargetFormat.DXBC: 'dxbc', + TargetFormat.MSL: 'metal' + }[target] + + stage_flag = { + ShaderStage.VERTEX: 'vertex', + ShaderStage.FRAGMENT: 'fragment', + ShaderStage.COMPUTE: 'compute' + }[stage] + + cmd = [ + slangc_path, + source_file, + '-entry', entry_point, + '-o', output_path, + '-target', target_flag, + '-stage', stage_flag, + ] + # 添加包含路径 + for include_path in include_paths: + cmd.extend(['-I', include_path]) + + if target in [TargetFormat.DXIL, TargetFormat.DXBC]: + cmd.extend(['-profile', 'sm_6_6']) + + return cmd + diff --git a/main.py b/main.py index beaf77d..c256956 100644 --- a/main.py +++ b/main.py @@ -31,13 +31,13 @@ def main(): # 创建编译器实例 compiler = SDL3GPUSlangCompiler([input_path]) + target = TargetFormat(args.target) # 解析着色器 print(f"**Parsing** {args.input}...") - shaders = compiler.parse_slang_shader(args.input) + shaders = compiler.parse_slang_shader(args.input, target) # 编译每个入口点 - target = TargetFormat(args.target) binding_infos = [] for name, shader_info in shaders.items(): diff --git a/shader_parser.py b/shader_parser.py index 7a0bf7b..6fe6ae4 100644 --- a/shader_parser.py +++ b/shader_parser.py @@ -11,15 +11,16 @@ import tempfile import shutil import re from typing import List, Dict, Optional -from shader_types import ShaderStage, ResourceType, Resource, ShaderInfo + +from compiler_cmd import make_cmd +from shader_types import ShaderStage, ResourceType, Resource, ShaderInfo, TargetFormat from shader_layout_generator import ShaderLayoutGenerator class ShaderParser: - def __init__(self, slangc_path: str, include_paths: List[str] = None): - self.slangc_path = slangc_path + def __init__(self, include_paths: List[str] = None): self.include_paths = include_paths or [] - def parse_slang_shader(self, source_path: str, include_paths: List[str] = None) -> Dict[str, ShaderInfo]: + def parse_slang_shader(self, source_path: str, target: TargetFormat, include_paths: List[str] = None) -> Dict[str, ShaderInfo]: """解析Slang着色器源码,提取资源信息""" # 合并包含路径 @@ -48,7 +49,7 @@ class ShaderParser: print(f"\nProcessing entry point: {entry_name} (stage: {stage.value})") shader_info = self._compile_and_reflect_entry_point( - source_path, entry_name, stage, all_include_paths, source + source_path, entry_name, target, stage, all_include_paths, source ) if shader_info: @@ -160,39 +161,21 @@ class ShaderParser: print(f"Total entry points found: {len(entry_points)}") return entry_points - def _compile_and_reflect_entry_point(self, source_path: str, entry_name: str, + def _compile_and_reflect_entry_point(self, source_path: str, entry_name: str, target: TargetFormat, stage: ShaderStage, include_paths: List[str], source: str) -> Optional[ShaderInfo]: """为单个入口点进行完整编译和反射""" # 创建临时输出文件 - with tempfile.NamedTemporaryFile(suffix='.hlsl', delete=False) as tmp_output: + with tempfile.NamedTemporaryFile(suffix='.shader.tmp', delete=False) as tmp_output: output_path = tmp_output.name with tempfile.NamedTemporaryFile(suffix='.json', delete=False) as tmp_reflection: reflection_path = tmp_reflection.name - # 构建完整的slangc编译命令(类似你成功的命令) - cmd = [self.slangc_path] - - # 添加包含路径 - for include_path in include_paths: - cmd.extend(['-I', include_path]) - - # 添加编译参数 - stage_name = { - ShaderStage.VERTEX: 'vertex', - ShaderStage.FRAGMENT: 'fragment', - ShaderStage.COMPUTE: 'compute' - }[stage] - + cmd = make_cmd(source_path, target, stage, entry_name, include_paths, output_path) cmd.extend([ - source_path, # 输入文件 '-reflection-json', reflection_path, # 反射输出 - '-o', output_path, # 编译输出 - '-target', 'hlsl', # 目标格式(用于测试) - '-entry', entry_name, # 入口点 - '-stage', stage_name # 着色器阶段 ]) print(f"Command: {' '.join(cmd)}") @@ -211,6 +194,15 @@ class ShaderParser: print(f"Stderr: {result.stderr}") if result.returncode == 0: + if stage == ShaderStage.VERTEX: + # 生成顶点布局代码 + generator = ShaderLayoutGenerator() + header_content = generator.generate_header(reflection_path) + source_file_name = os.path.splitext(os.path.basename(source_path))[0] + layout_path_filename = os.path.join(os.path.dirname(output_path), f"{source_file_name}_layout.h") + with open(layout_path_filename, 'w', encoding='utf-8') as out_file: + out_file.write(header_content) + # 读取反射数据 if os.path.exists(reflection_path): with open(reflection_path, 'r', encoding='utf-8') as f: @@ -220,11 +212,6 @@ class ShaderParser: if reflection_json.strip(): try: reflection = json.loads(reflection_json) - generator = ShaderLayoutGenerator() - header_content = generator.generate_header(reflection_path) - layout_path_filename = os.path.join(os.path.dirname(output_path), f"{entry_name}_layout.h") - with open(layout_path_filename, 'w', encoding='utf-8') as out_file: - out_file.write(header_content) return self._create_shader_info_from_reflection( reflection, entry_name, stage, source ) diff --git a/slangc_finder.py b/slangc_finder.py index fae72f7..35b430e 100644 --- a/slangc_finder.py +++ b/slangc_finder.py @@ -87,4 +87,6 @@ Run the script from the same terminal where 'slangc --version' works You can also specify the path directly when creating the compiler: compiler = SDL3GPUSlangCompiler() compiler.slangc_path = r'C:\\path\\to\\slangc.exe' -""") \ No newline at end of file +""") + +slangc_path = SlangcFinder.find_slangc()