封装编译命令函数

This commit is contained in:
daiqingshuang
2025-06-06 18:22:46 +08:00
parent ece556b138
commit 620002921c
5 changed files with 74 additions and 67 deletions

View File

@@ -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)

41
compiler_cmd.py Normal file
View File

@@ -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

View File

@@ -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():

View File

@@ -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
)

View File

@@ -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'
""")
""")
slangc_path = SlangcFinder.find_slangc()