Home | History | Annotate | Download | only in Test
      1 #!/bin/bash
      2 
      3 # This script validates shaders (if successfully compiled) using spirv-val.
      4 # It is not meant to preclude the possible addition of the validator to
      5 # glslang.
      6 
      7 declare -r EXE='../build/install/bin/glslangValidator'
      8 
      9 # search common locations for spirv-tools: keep first one
     10 for toolsdir in '../External/spirv-tools/build/tools' '../../SPIRV-Tools/build/tools/bin' '/usr/local/bin'; do
     11     [[ -z "$VAL" && -x "${toolsdir}/spirv-val" ]] && declare -r VAL="${toolsdir}/spirv-val"
     12     [[ -z "$DIS" && -x "${toolsdir}/spirv-dis" ]] && declare -r DIS="${toolsdir}/spirv-dis"
     13 done
     14 
     15 declare -r gtests='../gtests/Hlsl.FromFile.cpp ../gtests/Spv.FromFile.cpp'
     16 
     17 declare -r targetenv='vulkan1.0'
     18 
     19 function fatal() { echo "ERROR: $@"; exit 5; }
     20 
     21 function usage
     22 {
     23     echo
     24     echo "Usage: $(basename $0) [options...] shaders..."
     25     echo
     26     echo "   Validates shaders (if successfully compiled) through spirv-val."
     27     echo
     28     echo "General options:"
     29     echo "   --help          prints this text"
     30     echo "   --no-color      disables output colorization"
     31     echo "   --dump-asm      dumps all successfully compiled shader assemblies"
     32     echo "   --dump-val      dumps all validation results"
     33     echo "   --dump-comp     dumps all compilation logs"
     34     echo "Spam reduction options:"
     35     echo "   --no-summary    disables result summaries"
     36     echo "   --skip-ok       do not print successful validations"
     37     echo "   --skip-comperr  do not print compilation errors"
     38     echo "   --skip-valerr   do not print validation errors"
     39     echo "   --quiet         synonym for --skip-ok --skip-comperr --skip-valerr --no-summary"
     40     echo "   --terse         print terse single line progress summary"
     41     echo "Disassembly options:"
     42     echo "   --raw-id        uses raw ids for disassembly"
     43     echo
     44     echo "Usage examples.  Note most non-hlsl tests fail to compile for expected reasons."
     45     echo "   Exercise all hlsl.* files:"
     46     echo "       $(basename $0) hlsl.*"
     47     echo "   Exercise all hlsl.* files, tersely:"
     48     echo "       $(basename $0) --terse hlsl.*"
     49     echo "   Print validator output for myfile.frag:"
     50     echo "       $(basename $0) --quiet --dump-val myfile.frag"
     51     echo "   Exercise hlsl.* files, only printing validation errors:"
     52     echo "       $(basename $0) --skip-ok --skip-comperr hlsl.*"
     53 
     54     exit 5
     55 }
     56 
     57 function status()
     58 {
     59     printf "%-40s: %b\n" "$1" "$2"
     60 }
     61 
     62 # make sure we can find glslang
     63 [[ -x "$EXE" ]] || fatal "Unable to locate $(basename "$EXE") executable"
     64 [[ -x "$VAL" ]] || fatal "Unable to locate spirv-val executable"
     65 [[ -x "$DIS" ]] || fatal "Unable to locate spirv-dis executable"
     66 
     67 for gtest in $gtests; do
     68     [[ -r "$gtest" ]] || fatal "Unable to locate source file: $(basename $gtest)"
     69 done
     70 
     71 # temp files
     72 declare -r spvfile='out.spv' \
     73         complog='comp.out' \
     74         vallog='val.out' \
     75         dislog='dis.out' \
     76 
     77 # options
     78 declare opt_vallog=false \
     79         opt_complog=false \
     80         opt_dislog=false \
     81         opt_summary=true \
     82         opt_stat_comperr=true \
     83         opt_stat_ok=true \
     84         opt_stat_valerr=true \
     85         opt_color=true \
     86         opt_raw_id=false \
     87         opt_quiet=false \
     88         opt_terse=false
     89 
     90 # clean up on exit
     91 trap "rm -f ${spvfile} ${complog} ${vallog} ${dislog}" EXIT
     92 
     93 # Language guesser: there is no fixed mapping from filenames to language,
     94 # so this examines the file and return one of:
     95 #     hlsl
     96 #     glsl
     97 #     bin
     98 #     unknown
     99 # This is easier WRT future expansion than a big explicit list.
    100 function FindLanguage()
    101 {
    102     local test="$1"
    103 
    104     # If it starts with hlsl, assume it's hlsl.
    105     if [[ "$test" == *hlsl.* ]]; then
    106         echo hlsl
    107         return
    108     fi
    109 
    110     if [[ "$test" == *.spv ]]; then
    111         echo bin
    112         return;
    113     fi
    114 
    115     # If it doesn't start with spv., assume it's GLSL.
    116     if [[ ! "$test" == spv.* && ! "$test" == remap.* ]]; then
    117         echo glsl
    118         return
    119     fi
    120 
    121     # Otherwise, attempt to guess from shader contents, since there's no
    122     # fixed mapping of filenames to languages.
    123     local contents="$(cat "$test")"
    124 
    125     if [[ "$contents" == *#version* ]]; then
    126         echo glsl
    127         return
    128     fi
    129 
    130     if [[ "$contents" == *SamplerState* ||
    131           "$contents" == *cbuffer* ||
    132           "$contents" == *SV_* ]]; then
    133         echo hlsl
    134         return
    135     fi
    136 
    137     echo unknown
    138 }
    139 
    140 # Attempt to discover entry point
    141 function FindEntryPoint()
    142 {
    143     local test="$1"
    144 
    145     # if it's not hlsl, always use main
    146     if [[ "$language" != 'hlsl' ]]; then
    147         echo 'main'
    148         return
    149     fi
    150 
    151     # Try to find it in test sources
    152     awk -F '[ (){",]+' -e "\$2 == \"${test}\" { print \$3; found=1; } END { if (found==0) print \"main\"; } " $gtests
    153 }
    154 
    155 # command line options
    156 while [ $# -gt 0 ]
    157 do
    158     case "$1" in
    159         # -c) glslang="$2"; shift 2;;
    160         --help|-?)      usage;;
    161         --no-color)     opt_color=false;        shift;;
    162         --no-summary)   opt_summary=false;      shift;;
    163         --skip-ok)      opt_stat_ok=false;      shift;;
    164         --skip-comperr) opt_stat_comperr=false; shift;;
    165         --skip-valerr)  opt_stat_valerr=false;  shift;;
    166         --dump-asm)     opt_dislog=true;        shift;;
    167         --dump-val)     opt_vallog=true;        shift;;
    168         --dump-comp)    opt_complog=true;       shift;;
    169         --raw-id)       opt_raw_id=true;        shift;;
    170         --quiet)        opt_quiet=true;         shift;;
    171         --terse)        opt_quiet=true
    172                         opt_terse=true
    173                         shift;;
    174         --*)            fatal "Unknown command line option: $1";;
    175         *) break;;
    176     esac
    177 done
    178 
    179 # this is what quiet means
    180 if $opt_quiet; then
    181     opt_stat_ok=false
    182     opt_stat_comperr=false
    183     opt_stat_valerr=false
    184     $opt_terse || opt_summary=false
    185 fi
    186 
    187 if $opt_color; then
    188     declare -r white="\e[1;37m" cyan="\e[1;36m" red="\e[0;31m" no_color="\e[0m"
    189 else
    190     declare -r white="" cyan="" red="" no_color=""
    191 fi
    192 
    193 # stats
    194 declare -i count_ok=0 count_err=0 count_nocomp=0 count_total=0
    195 
    196 declare -r dashsep='------------------------------------------------------------------------'
    197 
    198 testfiles=(${@})
    199 # if no shaders given, look for everything in current directory
    200 [[ ${#testfiles[*]} == 0 ]] && testfiles=(*.frag *.vert *.tesc *.tese *.geom *.comp)
    201 
    202 $opt_summary && printf "\nValidating: ${#testfiles[*]} shaders\n\n"
    203 
    204 # Loop through the shaders we were given, compiling them if we can.
    205 for test in ${testfiles[*]}
    206 do
    207     if [[ ! -r "$test" ]]; then
    208         $opt_quiet || status "$test" "${red}FILE NOT FOUND${no_color}"
    209         continue
    210     fi
    211 
    212     ((++count_total))
    213 
    214     $opt_terse && printf "\r[%-3d/%-3d : ${white}comperr=%-3d ${red}valerr=%-3d ${cyan}ok=%-3d${no_color}]" \
    215                          ${count_total} ${#testfiles[*]} ${count_nocomp} ${count_err} ${count_ok}
    216 
    217     language="$(FindLanguage $test)"
    218     entry="$(FindEntryPoint $test)"
    219     langops=''
    220 
    221     case "$language" in
    222         hlsl) langops='-D --hlsl-iomap --hlsl-offsets';;
    223         glsl) ;;
    224         bin) continue;;   # skip binaries
    225         *) $opt_quiet || status "$test" "${red}UNKNOWN LANGUAGE${no_color}"; continue;;
    226     esac
    227 
    228     # compile the test file
    229     if compout=$("$EXE" -e "$entry" $langops -V -o "$spvfile" "$test" 2>&1)
    230     then
    231         # successful compilation: validate
    232         if valout=$("$VAL" --target-env ${targetenv} "$spvfile" 2>&1)
    233         then
    234             # validated OK
    235             $opt_stat_ok && status "$test" "${cyan}OK${no_color}"
    236             ((++count_ok))
    237         else
    238             # validation failure
    239             $opt_stat_valerr && status "$test" "${red}VAL ERROR${no_color}"
    240             printf "%s\n%s:\n%s\n" "$dashsep" "$test" "$valout" >> "$vallog"
    241             ((++count_err))
    242         fi
    243 
    244         if $opt_dislog; then
    245             printf "%s\n%s:\n" "$dashsep" "$test" >> "$dislog"
    246             $opt_raw_id && id_opt=--raw-id
    247             "$DIS" ${id_opt} "$spvfile" >> "$dislog"
    248         fi
    249     else
    250         # compile failure
    251         $opt_stat_comperr && status "$test" "${white}COMP ERROR${no_color}"
    252         printf "%s\n%s\n" "$dashsep" "$compout" >> "$complog"
    253         ((++count_nocomp))
    254     fi
    255 done
    256 
    257 $opt_terse && echo
    258 
    259 # summarize
    260 $opt_summary && printf "\nSummary: ${white}${count_nocomp} compile errors${no_color}, ${red}${count_err} validation errors${no_color}, ${cyan}${count_ok} successes${no_color}\n"
    261 
    262 # dump logs
    263 $opt_vallog  && [[ -r $vallog ]]  && cat "$vallog"
    264 $opt_complog && [[ -r $complog ]] && cat "$complog"
    265 $opt_dislog  && [[ -r $dislog ]]  && cat "$dislog"
    266 
    267 # exit code
    268 [[ ${count_err} -gt 0 ]] && exit 1
    269 exit 0
    270