封装编译命令函数
This commit is contained in:
43
compiler.py
43
compiler.py
@@ -7,25 +7,25 @@ SDL3_GPU Slang Compiler - Main Compiler
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
from typing import List, Dict, Tuple
|
from typing import List, Dict
|
||||||
from shader_types import ShaderInfo, TargetFormat, ShaderStage
|
|
||||||
from slangc_finder import SlangcFinder
|
|
||||||
from shader_parser import ShaderParser
|
|
||||||
from binding_manager import BindingManager
|
from binding_manager import BindingManager
|
||||||
from code_generator import CodeGenerator
|
from code_generator import CodeGenerator
|
||||||
|
from compiler_cmd import make_cmd
|
||||||
|
from shader_parser import ShaderParser
|
||||||
|
from shader_types import ShaderInfo, TargetFormat
|
||||||
|
|
||||||
|
|
||||||
class SDL3GPUSlangCompiler:
|
class SDL3GPUSlangCompiler:
|
||||||
def __init__(self, include_paths: List[str] = None):
|
def __init__(self, include_paths: List[str] = None):
|
||||||
self.slangc_path = SlangcFinder.find_slangc()
|
|
||||||
self.include_paths = include_paths or []
|
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.binding_manager = BindingManager()
|
||||||
self.code_generator = CodeGenerator()
|
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着色器源码,提取资源信息"""
|
"""解析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]:
|
def compile_shader(self, shader_info: ShaderInfo, target: TargetFormat) -> tuple[str, dict]:
|
||||||
"""编译着色器并返回二进制路径和绑定信息"""
|
"""编译着色器并返回二进制路径和绑定信息"""
|
||||||
@@ -48,30 +48,7 @@ class SDL3GPUSlangCompiler:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# 编译着色器
|
# 编译着色器
|
||||||
target_flag = {
|
cmd = make_cmd(tmp_path, target, shader_info.stage, shader_info.entry_point, self.include_paths, output_path)
|
||||||
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, # 添加包含路径
|
|
||||||
]
|
|
||||||
|
|
||||||
print(f"Compiling shader with command: {' '.join(cmd)}")
|
print(f"Compiling shader with command: {' '.join(cmd)}")
|
||||||
|
|
||||||
subprocess.run(cmd, check=True)
|
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])
|
compiler = SDL3GPUSlangCompiler([input_path])
|
||||||
|
target = TargetFormat(args.target)
|
||||||
|
|
||||||
# 解析着色器
|
# 解析着色器
|
||||||
print(f"**Parsing** {args.input}...")
|
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 = []
|
binding_infos = []
|
||||||
|
|
||||||
for name, shader_info in shaders.items():
|
for name, shader_info in shaders.items():
|
||||||
|
|||||||
@@ -11,15 +11,16 @@ import tempfile
|
|||||||
import shutil
|
import shutil
|
||||||
import re
|
import re
|
||||||
from typing import List, Dict, Optional
|
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
|
from shader_layout_generator import ShaderLayoutGenerator
|
||||||
|
|
||||||
class ShaderParser:
|
class ShaderParser:
|
||||||
def __init__(self, slangc_path: str, include_paths: List[str] = None):
|
def __init__(self, include_paths: List[str] = None):
|
||||||
self.slangc_path = slangc_path
|
|
||||||
self.include_paths = include_paths or []
|
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着色器源码,提取资源信息"""
|
"""解析Slang着色器源码,提取资源信息"""
|
||||||
|
|
||||||
# 合并包含路径
|
# 合并包含路径
|
||||||
@@ -48,7 +49,7 @@ class ShaderParser:
|
|||||||
print(f"\nProcessing entry point: {entry_name} (stage: {stage.value})")
|
print(f"\nProcessing entry point: {entry_name} (stage: {stage.value})")
|
||||||
|
|
||||||
shader_info = self._compile_and_reflect_entry_point(
|
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:
|
if shader_info:
|
||||||
@@ -160,39 +161,21 @@ class ShaderParser:
|
|||||||
print(f"Total entry points found: {len(entry_points)}")
|
print(f"Total entry points found: {len(entry_points)}")
|
||||||
return 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],
|
stage: ShaderStage, include_paths: List[str],
|
||||||
source: str) -> Optional[ShaderInfo]:
|
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
|
output_path = tmp_output.name
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(suffix='.json', delete=False) as tmp_reflection:
|
with tempfile.NamedTemporaryFile(suffix='.json', delete=False) as tmp_reflection:
|
||||||
reflection_path = tmp_reflection.name
|
reflection_path = tmp_reflection.name
|
||||||
|
|
||||||
# 构建完整的slangc编译命令(类似你成功的命令)
|
cmd = make_cmd(source_path, target, stage, entry_name, include_paths, output_path)
|
||||||
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.extend([
|
cmd.extend([
|
||||||
source_path, # 输入文件
|
|
||||||
'-reflection-json', reflection_path, # 反射输出
|
'-reflection-json', reflection_path, # 反射输出
|
||||||
'-o', output_path, # 编译输出
|
|
||||||
'-target', 'hlsl', # 目标格式(用于测试)
|
|
||||||
'-entry', entry_name, # 入口点
|
|
||||||
'-stage', stage_name # 着色器阶段
|
|
||||||
])
|
])
|
||||||
|
|
||||||
print(f"Command: {' '.join(cmd)}")
|
print(f"Command: {' '.join(cmd)}")
|
||||||
@@ -211,6 +194,15 @@ class ShaderParser:
|
|||||||
print(f"Stderr: {result.stderr}")
|
print(f"Stderr: {result.stderr}")
|
||||||
|
|
||||||
if result.returncode == 0:
|
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):
|
if os.path.exists(reflection_path):
|
||||||
with open(reflection_path, 'r', encoding='utf-8') as f:
|
with open(reflection_path, 'r', encoding='utf-8') as f:
|
||||||
@@ -220,11 +212,6 @@ class ShaderParser:
|
|||||||
if reflection_json.strip():
|
if reflection_json.strip():
|
||||||
try:
|
try:
|
||||||
reflection = json.loads(reflection_json)
|
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(
|
return self._create_shader_info_from_reflection(
|
||||||
reflection, entry_name, stage, source
|
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:
|
You can also specify the path directly when creating the compiler:
|
||||||
compiler = SDL3GPUSlangCompiler()
|
compiler = SDL3GPUSlangCompiler()
|
||||||
compiler.slangc_path = r'C:\\path\\to\\slangc.exe'
|
compiler.slangc_path = r'C:\\path\\to\\slangc.exe'
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
slangc_path = SlangcFinder.find_slangc()
|
||||||
|
|||||||
Reference in New Issue
Block a user