You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
333 lines
8.0 KiB
333 lines
8.0 KiB
use String::CRC32; |
|
BEGIN {use File::Basename; push @INC, dirname($0); } |
|
require "valve_perl_helpers.pl"; |
|
|
|
sub BuildDefineOptions |
|
{ |
|
local( $output ); |
|
local( $combo ) = shift; |
|
local( $i ); |
|
for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) |
|
{ |
|
local( $val ) = ( $combo % ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) ) + $dynamicDefineMin[$i]; |
|
$output .= "/D$dynamicDefineNames[$i]=$val "; |
|
$combo = $combo / ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ); |
|
} |
|
for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) |
|
{ |
|
local( $val ) = ( $combo % ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) ) + $staticDefineMin[$i]; |
|
$output .= "/D$staticDefineNames[$i]=$val "; |
|
$combo = $combo / ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ); |
|
} |
|
return $output; |
|
} |
|
|
|
sub CalcNumCombos |
|
{ |
|
local( $i, $numCombos ); |
|
$numCombos = 1; |
|
for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) |
|
{ |
|
$numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; |
|
} |
|
for( $i = 0; $i < scalar( @staticDefineNames ); $i++ ) |
|
{ |
|
$numCombos *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1; |
|
} |
|
return $numCombos; |
|
} |
|
|
|
sub CalcNumDynamicCombos |
|
{ |
|
local( $i, $numCombos ); |
|
$numCombos = 1; |
|
for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ ) |
|
{ |
|
$numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1; |
|
} |
|
return $numCombos; |
|
} |
|
|
|
$g_dx9 = 1; |
|
|
|
while( 1 ) |
|
{ |
|
$psh_filename = shift; |
|
|
|
if( $psh_filename =~ m/-source/ ) |
|
{ |
|
$g_SourceDir = shift; |
|
} |
|
elsif( $psh_filename =~ m/-x360/ ) |
|
{ |
|
$g_x360 = 1; |
|
} |
|
else |
|
{ |
|
last; |
|
} |
|
} |
|
|
|
$psh_filename =~ s/-----.*$//; |
|
|
|
|
|
# Get the shader binary version number from a header file. |
|
open FILE, "<$g_SourceDir\\public\\materialsystem\\shader_vcs_version.h" || die; |
|
while( $line = <FILE> ) |
|
{ |
|
if( $line =~ m/^\#define\s+SHADER_VCS_VERSION_NUMBER\s+(\d+)\s*$/ ) |
|
{ |
|
$shaderVersion = $1; |
|
last; |
|
} |
|
} |
|
if( !defined $shaderVersion ) |
|
{ |
|
die "couldn't get shader version from shader_vcs_version.h"; |
|
} |
|
close FILE; |
|
|
|
|
|
|
|
local( @staticDefineNames ); |
|
local( @staticDefineMin ); |
|
local( @staticDefineMax ); |
|
local( @dynamicDefineNames ); |
|
local( @dynamicDefineMin ); |
|
local( @dynamicDefineMax ); |
|
|
|
# Parse the combos. |
|
open PSH, "<$psh_filename"; |
|
while( <PSH> ) |
|
{ |
|
last if( !m,^;, ); |
|
s,^;\s*,,; |
|
if( m/\s*STATIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ ) |
|
{ |
|
local( $name, $min, $max ); |
|
$name = $1; |
|
$min = $2; |
|
$max = $3; |
|
# print "\"STATIC: $name\" \"$min..$max\"\n"; |
|
if (/\[(.*)\]/) |
|
{ |
|
$platforms=$1; |
|
next if ( ($g_x360) && (!($platforms=~/XBOX/i)) ); |
|
next if ( (!$g_x360) && (!($platforms=~/PC/i)) ); |
|
} |
|
push @staticDefineNames, $name; |
|
push @staticDefineMin, $min; |
|
push @staticDefineMax, $max; |
|
} |
|
elsif( m/\s*DYNAMIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ ) |
|
{ |
|
local( $name, $min, $max ); |
|
$name = $1; |
|
$min = $2; |
|
$max = $3; |
|
# print "\"DYNAMIC: $name\" \"$min..$max\"\n"; |
|
if (/\[(.*)\]/) |
|
{ |
|
$platforms=$1; |
|
next if ( ($g_x360) && (!($platforms=~/XBOX/i)) ); |
|
next if ( (!$g_x360) && (!($platforms=~/PC/i)) ); |
|
} |
|
push @dynamicDefineNames, $name; |
|
push @dynamicDefineMin, $min; |
|
push @dynamicDefineMax, $max; |
|
} |
|
} |
|
close PSH; |
|
|
|
$numCombos = &CalcNumCombos(); |
|
$numDynamicCombos = &CalcNumDynamicCombos(); |
|
print "$psh_filename\n"; |
|
#print "$numCombos combos\n"; |
|
#print "$numDynamicCombos dynamic combos\n"; |
|
|
|
if( $g_x360 ) |
|
{ |
|
$pshtmp = "pshtmp9_360"; |
|
} |
|
elsif( $g_dx9 ) |
|
{ |
|
$pshtmp = "pshtmp9"; |
|
} |
|
else |
|
{ |
|
$pshtmp = "pshtmp8"; |
|
} |
|
$basename = $psh_filename; |
|
$basename =~ s/\.psh$//i; |
|
|
|
for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ ) |
|
{ |
|
my $tempFilename = "shader$shaderCombo.o"; |
|
unlink $tempFilename; |
|
|
|
if( $g_x360 ) |
|
{ |
|
$cmd = "$g_SourceDir\\x360xdk\\bin\\win32\\psa /D_X360=1 /Foshader$shaderCombo.o /nologo " . &BuildDefineOptions( $shaderCombo ) . "$psh_filename > NIL"; |
|
} |
|
else |
|
{ |
|
$cmd = "$g_SourceDir\\dx9sdk\\utilities\\psa /Foshader$shaderCombo.o /nologo " . &BuildDefineOptions( $shaderCombo ) . "$psh_filename > NIL"; |
|
} |
|
|
|
if( !stat $pshtmp ) |
|
{ |
|
mkdir $pshtmp, 0777 || die $!; |
|
} |
|
|
|
# print $cmd . "\n"; |
|
system $cmd || die $!; |
|
|
|
# Make sure a file got generated because sometimes the die above won't happen on compile errors. |
|
my $filesize = (stat $tempFilename)[7]; |
|
if ( !$filesize ) |
|
{ |
|
die "Error compiling shader$shaderCombo.o"; |
|
} |
|
|
|
push @outputHeader, @hdr; |
|
} |
|
|
|
$basename =~ s/\.fxc//gi; |
|
push @outputHeader, "static PrecompiledShaderByteCode_t " . $basename . "_pixel_shaders[" . $numCombos . "] = \n"; |
|
push @outputHeader, "{\n"; |
|
local( $j ); |
|
for( $j = 0; $j < $numCombos; $j++ ) |
|
{ |
|
local( $thing ) = "pixelShader_" . $basename . "_" . $j; |
|
push @outputHeader, "\t{ " . "$thing, sizeof( $thing ) },\n"; |
|
} |
|
push @outputHeader, "};\n"; |
|
|
|
push @outputHeader, "struct $basename" . "PixelShader_t : public PrecompiledShader_t\n"; |
|
push @outputHeader, "{\n"; |
|
push @outputHeader, "\t$basename" . "PixelShader_t()\n"; |
|
push @outputHeader, "\t{\n"; |
|
push @outputHeader, "\t\tm_nFlags = 0;\n"; |
|
push @outputHeader, "\t\tm_pByteCode = " . $basename . "_pixel_shaders;\n"; |
|
push @outputHeader, "\t\tm_nShaderCount = $numCombos;\n"; |
|
#push @outputHeader, "\t\tm_nDynamicCombos = m_nShaderCount;\n"; |
|
push @outputHeader, "\t\t// NOTE!!! psh_prep.pl shaders are always static combos!\n"; |
|
push @outputHeader, "\t\tm_nDynamicCombos = 1;\n"; |
|
push @outputHeader, "\t\tm_pName = \"$basename\";\n"; |
|
if( $basename =~ /vs\d\d/ ) # hack |
|
{ |
|
push @outputHeader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_VERTEX_SHADER, this );\n"; |
|
} |
|
else |
|
{ |
|
push @outputHeader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_PIXEL_SHADER, this );\n"; |
|
} |
|
push @outputHeader, "\t}\n"; |
|
push @outputHeader, "\tvirtual const PrecompiledShaderByteCode_t &GetByteCode( int shaderID )\n"; |
|
push @outputHeader, "\t{\n"; |
|
push @outputHeader, "\t\treturn m_pByteCode[shaderID];\n"; |
|
push @outputHeader, "\t}\n"; |
|
push @outputHeader, "};\n"; |
|
|
|
push @outputHeader, "static $basename" . "PixelShader_t $basename" . "_PixelShaderInstance;\n"; |
|
|
|
|
|
&MakeDirHier( "shaders/psh" ); |
|
|
|
my $vcsName = ""; |
|
if( $g_x360 ) |
|
{ |
|
$vcsName = $basename . ".360.vcs"; |
|
} |
|
else |
|
{ |
|
$vcsName = $basename . ".vcs"; |
|
} |
|
|
|
open COMPILEDSHADER, ">shaders/psh/$vcsName" || die; |
|
binmode( COMPILEDSHADER ); |
|
|
|
# |
|
# Write out the part of the header that we know. . we'll write the rest after writing the object code. |
|
# |
|
|
|
#print $numCombos . "\n"; |
|
|
|
# Pack arguments |
|
my $sInt = "i"; |
|
my $uInt = "I"; |
|
if ( $g_x360 ) |
|
{ |
|
# Change arguments to "big endian long" |
|
$sInt = "N"; |
|
$uInt = "N"; |
|
} |
|
|
|
open PSH, "<$psh_filename"; |
|
my $crc = crc32( *PSH ); |
|
close PSH; |
|
#print STDERR "crc for $psh_filename: $crc\n"; |
|
|
|
# version |
|
print COMPILEDSHADER pack $sInt, 4; |
|
# totalCombos |
|
print COMPILEDSHADER pack $sInt, $numCombos; |
|
# dynamic combos |
|
print COMPILEDSHADER pack $sInt, $numDynamicCombos; |
|
# flags |
|
print COMPILEDSHADER pack $uInt, 0x0; # nothing here for now. |
|
# centroid mask |
|
print COMPILEDSHADER pack $uInt, 0; |
|
# reference size for diffs |
|
print COMPILEDSHADER pack $uInt, 0; |
|
# crc32 of the source code |
|
print COMPILEDSHADER pack $uInt, $crc; |
|
|
|
my $beginningOfDir = tell COMPILEDSHADER; |
|
|
|
# Write out a blank directionary. . we'll fill it in later. |
|
for( $i = 0; $i < $numCombos; $i++ ) |
|
{ |
|
# offset from beginning of file. |
|
print COMPILEDSHADER pack $sInt, 0; |
|
# size |
|
print COMPILEDSHADER pack $sInt, 0; |
|
} |
|
|
|
my $startByteCode = tell COMPILEDSHADER; |
|
my @byteCodeStart; |
|
my @byteCodeSize; |
|
|
|
# Write out the shader object code. |
|
for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ ) |
|
{ |
|
my $filename = "shader$shaderCombo\.o"; |
|
my $filesize = (stat $filename)[7]; |
|
|
|
$byteCodeStart[$shaderCombo] = tell COMPILEDSHADER; |
|
$byteCodeSize[$shaderCombo] = $filesize; |
|
open SHADERBYTECODE, "<$filename"; |
|
binmode SHADERBYTECODE; |
|
|
|
my $bin; |
|
my $numread = read SHADERBYTECODE, $bin, $filesize; |
|
# print "filename: $filename numread: $numread filesize: $filesize\n"; |
|
close SHADERBYTECODE; |
|
unlink $filename; |
|
|
|
print COMPILEDSHADER $bin; |
|
} |
|
|
|
# Seek back to the directory and write it out. |
|
seek COMPILEDSHADER, $beginningOfDir, 0; |
|
for( $i = 0; $i < $numCombos; $i++ ) |
|
{ |
|
# offset from beginning of file. |
|
print COMPILEDSHADER pack $sInt, $byteCodeStart[$i]; |
|
# size |
|
print COMPILEDSHADER pack $sInt, $byteCodeSize[$i]; |
|
} |
|
|
|
close COMPILEDSHADER; |
|
|
|
|
|
|