(WIIU) add a better converter for slang shaders.

This commit is contained in:
aliaspider 2018-01-09 03:05:29 +01:00
parent 8d7ea32e0d
commit 42905d9bbb
6 changed files with 3180 additions and 47 deletions

View File

@ -1,8 +1,80 @@
all: slang-convert
GLSLC = glslc
slang-convert: main.c
$(CC) $< -o $@ -g -O0 -Wall -Werror
GSH_COMPILER = ./compiler.exe
GSH_COMPILER_V = -v
GSH_COMPILER_P = -p
GSH_COMPILER_O = -o
GSH_COMPILER_ALIGN = -align
clean:
rm slang-convert main.o
SLANG_DIR = slang-shaders
BLACKLIST :=
BLACKLIST += $(SLANG_DIR)/dithering/shaders/bayer-matrix-dithering.slang
BLACKLIST += $(SLANG_DIR)/scalefx/shaders/old/scalefx-pass3.slang
BLACKLIST += $(SLANG_DIR)/scalefx/shaders/old/scalefx-pass7.slang
BLACKLIST += $(SLANG_DIR)/scalefx/shaders/scalefx-pass1.slang
BLACKLIST += $(SLANG_DIR)/scalefx/shaders/scalefx-pass2.slang
BLACKLIST += $(SLANG_DIR)/scalefx/shaders/scalefx-pass4.slang
BLACKLIST += $(SLANG_DIR)/scalefx/shaders/scalefx-pass4-hybrid.slang
BLACKLIST += $(SLANG_DIR)/test/decode-format.slang
BLACKLIST += $(SLANG_DIR)/test/format.slang
BLACKLIST += $(wildcard $(SLANG_DIR)/crt/shaders/crt-royale/src/*.slang)
BLACKLIST += $(SLANG_DIR)/slang-shaders/blurs/blur12x12shared.slang
BLACKLIST += $(SLANG_DIR)/blurs/blur5x5-gamma-encode-every-fbo.slang
BLACKLIST += $(SLANG_DIR)/blurs/blur12x12shared.slang
BLACKLIST += $(SLANG_DIR)/ntsc/shaders/ntsc-xot.slang
BLACKLIST += $(SLANG_DIR)/nedi/shaders/nedi-pass0.slang
BLACKLIST += $(SLANG_DIR)/nedi/shaders/nedi-pass1.slang
BLACKLIST += $(SLANG_DIR)/nedi/shaders/nedi-pass2.slang
BLACKLIST += $(wildcard $(SLANG_DIR)/anti-aliasing/shaders/smaa/*.slang)
EXE_EXT :=
ifneq ($(findstring Linux,$(shell uname -a)),)
else ifneq ($(findstring Darwin,$(shell uname -a)),)
else
EXE_EXT := .exe
endif
SLANG_PARSER = ./slang-parse$(EXE_EXT)
rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
SLANG_SHADERS := $(call rwildcard,$(SLANG_DIR)/,*.slang)
SLANG_SHADERS := $(filter-out $(BLACKLIST),$(SLANG_SHADERS))
SLANG_SHADERS := $(SLANG_SHADERS:.slang=.gsh)
all: $(SLANG_SHADERS)
parser: $(SLANG_PARSER)
$(SLANG_PARSER): slang-parse.cpp
$(CXX) $< -o $@ -g -O0 -Wall -I.
shaders: $(SLANG_SHADERS)
%.ppslang : %.slang
$(GLSLC) -E $< -o $@
%.vert %.frag: %.ppslang $(SLANG_PARSER) grammar.txt
$(SLANG_PARSER) --slang $< --vsh $*.vert --psh $*.frag
%.gsh: %.vert %.frag
$(GSH_COMPILER) $(GSH_COMPILER_ALIGN) $(GSH_COMPILER_V) $*.vert $(GSH_COMPILER_P) $*.frag $(GSH_COMPILER_O) $@
.PRECIOUS: %.vert %.frag %.ppslang
clean-shaders:
rm -rf $(SLANG_SHADERS)
clean-temp:
rm -rf $(SLANG_SHADERS:.gsh=.ppslang)
rm -rf $(SLANG_SHADERS:.gsh=.vert)
rm -rf $(SLANG_SHADERS:.gsh=.frag)
clean-parser:
rm -rf $(SLANG_PARSER) slang-parse.o
clean: clean-parser clean-shaders clean-temp

View File

@ -1,42 +0,0 @@
#!/bin/sh
#### options ####
slang_dir=slang-shaders
gshcompiler=$(pwd)/compiler.exe
vshflag=--vsh
pshflag=--psh
outputflag=--out
alignflag=--align
#################
currentdir=$(pwd)
die ()
{
echo error while converting $name
#mv -f tmp.vsh $currentdir
#mv -f tmp.psh $currentdir
#cp $1 $currentdir 2> /dev/null
#exit 1
}
make
cd $slang_dir
slang_dir=$(pwd)
slang_files=`find $slang_dir -name "*.slang"`
for name in $slang_files ; do
echo $name
echo cd $(dirname $name)
cd $(dirname $name)
echo $currentdir/slang-convert --slang $name --vsh tmp.vsh --psh tmp.psh
$currentdir/slang-convert --slang $(basename $name) --vsh tmp.vsh --psh tmp.psh
echo $gshcompiler $alignflag $vshflag tmp.vsh $pshflag tmp.psh $outputflag `echo "$name" | sed "s/\.slang//"`.gsh
$gshcompiler $alignflag $vshflag tmp.vsh $pshflag tmp.psh $outputflag `echo "$name" | sed "s/\.slang//"`.gsh || die $name
rm -rf tmp.vsh tmp.psh
done

55
wiiu/slang/grammar.txt Normal file
View File

@ -0,0 +1,55 @@
Program <- Version? (LineMarker / GoogleIncludeExtensionEnable / UniformBlock / Declaration / ConstArray / Stage / Indent / IgnoredKeyword / Line)*
~LineMarker <- '#line' (!EndOfLine .)* EndOfLine
~GoogleIncludeExtensionEnable <- '#extension GL_GOOGLE_include_directive' (!EndOfLine .)* EndOfLine
Line <- <(!EndOfLine !EndOfFile .)*> (EndOfLine / EndOfFile)
~IgnoredKeyword <- !'const int' ('inline' / 'static ' / 'const ')
Version <- '#'_'version' Space+ <Int> <(!EndOfLine .)*> EndOfLine
Stage <- '#'_'pragma' Space+ 'stage' Space? <(!EndOfLine .)*> EndOfLine
#.*Include <- '#'_'include' _ '"' <(!'"' .)*> '"' _ EndOfLine
Declaration <- Layout? _ Qualifier Space _ Type Space _ Name _ ArraySize? _ EndOfStatement
ConstArray <- Type Space _ Name _ ArraySize? _ '=' _ Array _ EndOfStatement
UniformBlock <- Layout? _ 'uniform' _ StructName? _ '{' Member* '}' _ Name? _ EndOfStatement
Member <- (_ Type Space _ Name _ ArraySize? _ EndOfStatement? _ Comment?)
~Comment <- ('//' Line)
Value <- (Float / Int / (!EndOfStatement .)*)
Array <- ('{' ( _ ArrayItem+ _ ',')* (_ ArrayItem+ _ )? '}')
ArrayItem <- <(!'}'!',' (groupedItem/.))+>
groupedItem <- '(' (!')' (groupedItem/.))+ ')'
Qualifier <- 'in' / 'out' / 'uniform'
Type <- <'uint' / 'int' / 'ivec2' / 'ivec3' / 'ivec4' /
'float' / 'vec2' / 'vec3' / 'vec4' /
'bool' / 'bvec2' / 'bvec3' / 'bvec4' /
'mat2x2' / 'mat2' /
'mat3x2' / 'mat3x3' / 'mat3' /
'mat4x2' / 'mat4x3' / 'mat4x4' / 'mat4' /
'void' / 'sampler2D' / Name>
StructName <- <Name>
ArraySize <- '[' _ <Int> _ ']'
Name <- ([a-z]/[A-Z]/'_'/[0-9])+
Layout <- 'layout' _ '(' ( _ (Location / Binding / Set / PushConstant / Std) _ ','?)+ ')'
Location <- 'location' _ '=' _ <Int>
Binding <- 'binding' _ '=' _ <Int>
Set <- 'set' _ '=' _ <Int>
PushConstant <- 'push_constant'
Std <- 'std' <Int>
#.*Block <- '{' (Directive/ Statement / Block _)* '}'
Float <- $< '-'? [0-9]+ '.' ([0-9]+ ('e-'[0-9]+)? )? 'f'? >
Int <- < '-'? [0-9]+ >
~EndOfStatement <- ';'
~EndOfLine <- '\r\n' / '\n' / '\r'
EndOfFile <- !.
End <- EndOfLine / EndOfFile
~_ <- [ \t\r\n]*
Indent <- [ \t]
~Space <- [ \t]

View File

@ -134,6 +134,8 @@ int main(int argc, const char** argv)
fclose(vs_out_fp);
fclose(ps_out_fp);
free(slang_buffer);
return 0;
}

2775
wiiu/slang/peglib.h Normal file

File diff suppressed because it is too large Load Diff

271
wiiu/slang/slang-parse.cpp Normal file
View File

@ -0,0 +1,271 @@
#include <iostream>
#include <peglib.h>
#include <fstream>
#include <sstream>
int main(int argc, const char** argv)
{
const char* slang_fn = NULL;
const char* vs_asm_fn = NULL;
const char* ps_asm_fn = NULL;
const char* vs_out_fn = NULL;
const char* ps_out_fn = NULL;
bool verbose = false;
for(int i = 1; i < argc - 1; i++)
{
if(!strcmp(argv[i], "--slang"))
slang_fn = argv[++i];
else if(!strcmp(argv[i], "--vsource"))
vs_asm_fn = argv[++i];
else if(!strcmp(argv[i], "--psource"))
ps_asm_fn = argv[++i];
else if(!strcmp(argv[i], "--vsh"))
vs_out_fn = argv[++i];
else if(!strcmp(argv[i], "--psh"))
ps_out_fn = argv[++i];
else if(!strcmp(argv[i], "--verbose"))
verbose = true;
}
if(!slang_fn || !vs_out_fn || !ps_out_fn || (!vs_asm_fn && ps_asm_fn) || (vs_asm_fn && !ps_asm_fn))
{
printf("Usage :\n");
printf("%s --slang <slang input> --vsh <vsh output> --psh <psh output>\n", argv[0]);
printf("%s --slang <slang input> --vsource <vsh asm input> --psource <psh asm input> --vsh <vsh output> --psh <psh output>\n", argv[0]);
}
std::string slang;
{
std::ifstream fs(slang_fn);
std::stringstream ss;
ss << fs.rdbuf();
slang = ss.str();
}
std::string slang_grammar;
{
std::ifstream fs("grammar.txt");
std::stringstream ss;
ss << fs.rdbuf();
slang_grammar = ss.str();
}
peg::parser parser;
parser.log = [&](size_t ln, size_t col, const std::string &msg) {
std::cout << "Error parsing grammar:" << ln << ":" << col << ": " << msg << std::endl;
};
if (!parser.load_grammar(slang_grammar.c_str())) {
std::cout << "Failed to load grammar" << std::endl;
return 1;
}
parser.log = [&](size_t ln, size_t col, const std::string &msg) {
std::cout << slang_fn << ":" << ln << ":" << col << ": " << msg << std::endl;
};
parser.enable_ast();
std::shared_ptr<peg::Ast> ast;
if (!parser.parse_n(slang.c_str(), slang.size(), ast)) {
std::cout << "Error parsing slang file: " << slang_fn << std::endl;
return 1;
}
ast = peg::AstOptimizer(false).optimize(ast);
if(verbose)
std::cout << peg::ast_to_s(ast) << std::flush;
if (ast->name != "Program") {
std::cout << "Expected root node to be Program, not" << ast->name << std::endl;
return 1;
}
std::stringstream common;
std::stringstream vs;
std::stringstream ps;
std::stringstream* out = &common;
common << "#version 150\n";
common << "#define float2 vec2\n";
common << "#define float3 vec3\n";
common << "#define float4 vec4\n";
for (std::shared_ptr<peg::Ast> &node : ast->nodes) {
if (node->name == "Version") {
/* do nothing */
} else if (node->name == "UniformBlock") {
int location = 0;
int binding = 0;
int set = 0;
int std_val = 0;
bool push_constant = false;
std::string struct_name;
std::string name;
struct member_type
{
std::string type;
std::string name;
};
std::vector<member_type> members;
for (std::shared_ptr<peg::Ast> &child : node->nodes) {
if (child->name == "Layout") {
for (std::shared_ptr<peg::Ast> &layout : child->nodes) {
if (layout->name == "PushConstant") {
push_constant = true;
} else if (layout->name == "Location") {
location = std::stoul(layout->token);
} else if (layout->name == "Binding") {
binding = std::stoul(layout->token);
} else if (layout->name == "Set") {
set = std::stoul(layout->token);
} else if (layout->name == "Std") {
std_val = std::stoul(layout->token);
}
}
} else if (child->name == "StructName") {
struct_name = child->token;
} else if (child->name == "Name") {
name = child->token;
} else if (child->name == "Member") {
member_type new_member;
for (std::shared_ptr<peg::Ast> &member : child->nodes) {
if (member->name == "Type") {
new_member.type = member->token;
} else if (member->name == "Name") {
new_member.name = member->token;
}
}
members.push_back(new_member);
}
}
#if 0
*out << "layout(location = " << (push_constant? "1" : "0");
if(std_val)
*out << ", std" << std_val;
*out << ") ";
#else
if(std_val)
*out << "layout(std" << std_val << ") ";
#endif
*out << "uniform " << struct_name << "\n{\n";
for(member_type &member : members) {
*out << " " << member.type << " " << member.name << ";\n";
}
*out << "}" << name << ";";
} else if (node->name == "Declaration") {
int location = 0;
int binding = 0;
int set = 0;
std::string qualifier;
std::string type;
std::string name;
int array_size = 0;
bool has_layout = false;
for (std::shared_ptr<peg::Ast> &child : node->nodes) {
if (child->name == "Layout") {
has_layout = true;
for (std::shared_ptr<peg::Ast> &layout : child->nodes) {
if (layout->name == "Location") {
location = std::stoul(layout->token);
} else if (layout->name == "Binding") {
binding = std::stoul(layout->token);
} else if (layout->name == "Set") {
set = std::stoul(layout->token);
}
}
} else if (child->name == "Qualifier") {
qualifier = child->token;
} else if (child->name == "Type") {
type = child->token;
} else if (child->name == "Name") {
name = child->token;
}else if (child->name == "ArraySize") {
array_size = std::stoul(child->token);
}
}
if(has_layout && type != "sampler2D")
{
*out << "layout(location = " << location << ") ";
}
*out << qualifier << " " << type << " " << name;
if(array_size)
*out << "[" << array_size << "]";
*out << ";";
} else if (node->name == "ConstArray") {
std::string type;
std::string name;
int array_size = 0;
std::vector<std::shared_ptr<peg::Ast>>* array;
for (std::shared_ptr<peg::Ast> &child : node->nodes) {
if (child->name == "Type") {
type = child->token;
} else if (child->name == "Name") {
name = child->token;
} else if (child->name == "ArraySize") {
array_size = std::stoul(child->token);
} else if (child->name == "Array") {
array = &child->nodes;
}
}
*out << type << " " << name;
if(array_size)
*out << "[" << array_size << "]";
*out << " = " << type;
if(array_size)
*out << "[" << array_size << "]";
*out << "(";
for (std::shared_ptr<peg::Ast> &item : *array) {
if(array_size)
*out << type << "(";
*out << item->token;
if(array_size)
*out << ")";
if(item != array->back())
*out << ", ";
}
*out << ");";
} else if (node->name == "Stage") {
std::string stage = node->token;
std::transform(stage.begin(), stage.end(), stage.begin(), ::toupper);
if(stage == "VERTEX")
out = &vs;
else
out = &ps;
} else if (node->name == "Indent"){
*out << node->token;
} else if (node->name == "Line"){
*out << node->token << std::endl;
} else {
std::cout << "Unexcpected node " << node->name << std::endl;
}
}
{
std::ofstream fs(vs_out_fn);
fs << common.str();
fs << vs.str();
}
{
std::ofstream fs(ps_out_fn);
fs << common.str();
fs << ps.str();
}
return 0;
}