封装编译命令函数
This commit is contained in:
43
compiler.py
43
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)
|
||||
|
||||
41
compiler_cmd.py
Normal file
41
compiler_cmd.py
Normal 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
|
||||
|
||||
4
main.py
4
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():
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user