| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- # Copyright (C) Microsoft Corporation. All rights reserved.
- # This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details.
- """hcttest-system-values.py - Test all system values with each signature point through fxc.
- Builds csv tables for the results for each shader model from 4.0 through 5.1.
- """
- import re
- SignaturePoints = [
- # sig point, stage, tessfactors already present
- ('VSIn', 'vs', False),
- ('VSOut', 'vs', False),
- ('PCIn', 'hs', False),
- ('HSIn', 'hs', False),
- ('HSCPIn', 'hs', False),
- ('HSCPOut', 'hs', False),
- ('PCOut', 'hs', True ),
- ('DSIn', 'ds', True ),
- ('DSCPIn', 'ds', False),
- ('DSOut', 'ds', False),
- ('GSVIn', 'gs', False),
- ('GSIn', 'gs', False),
- ('GSOut', 'gs', False),
- ('PSIn', 'ps', False),
- ('PSOut', 'ps', False),
- ('CSIn', 'cs', False),
- ]
- SysValues = """
- VertexID
- InstanceID
- Position
- RenderTargetArrayIndex
- ViewportArrayIndex
- ClipDistance
- CullDistance
- OutputControlPointID
- DomainLocation
- PrimitiveID
- GSInstanceID
- SampleIndex
- IsFrontFace
- Coverage
- InnerCoverage
- Target
- Depth
- DepthLessEqual
- DepthGreaterEqual
- StencilRef
- DispatchThreadID
- GroupID
- GroupIndex
- GroupThreadID
- TessFactor
- InsideTessFactor
- """.split()
- def run(cmd, output_filename=None):
- import os
- print(cmd)
- if output_filename:
- if os.path.isfile(output_filename):
- os.unlink(output_filename)
- with file(output_filename, 'wt') as f:
- f.write('%s\n\n' % cmd)
- ret = os.system(cmd + ' >> "%s" 2>&1' % output_filename)
- output = ''
- if os.path.isfile(output_filename):
- with open(output_filename, 'rt') as f:
- output = f.read()
- return ret, output
- else:
- ret = os.system(cmd)
- return ret, None
- sig_examples = """
- // Patch Constant signature:
- //
- // Name Index Mask Register SysValue Format Used
- // -------------------- ----- ------ -------- -------- ------- ------
- // Arb 0 x 0 NONE float x
- // SV_TessFactor 0 x 1 QUADEDGE float x
- // SV_TessFactor 1 x 2 QUADEDGE float x
- // SV_TessFactor 2 x 3 QUADEDGE float x
- // SV_TessFactor 3 x 4 QUADEDGE float x
- // SV_InsideTessFactor 0 x 5 QUADINT float x
- // SV_InsideTessFactor 1 x 6 QUADINT float x
- //
- //
- // Input signature:
- //
- // Name Index Mask Register SysValue Format Used
- // -------------------- ----- ------ -------- -------- ------- ------
- // Arb 0 x 0 NONE float
- //
- //
- // Output signature:
- //
- // Name Index Mask Register SysValue Format Used
- // -------------------- ----- ------ -------- -------- ------- ------
- // Arb 0 x 0 NONE float x
- """
- rxSigBegin = re.compile(r'^// (Input|Output|Patch Constant) signature:\s*$')
- rxSigElementsBegin = re.compile(r'^// -------------------- ----- ------ -------- -------- ------- ------\s*$')
- # // SV_Target 1 xyzw 1 TARGET float xyzw
- rxSigElement = re.compile(r'^// ([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s*([^\s]+)?\s*$')
- # Name, Index, Mask, Register, SysValue, Format, Used = m.groups()
- # For now, ParseSigs just looks for a matching semantic name and reports whether it uses
- # a separate register (unpacked) and whether it's treated as arbitrary.
- def ParseSigs(text, semantic):
- "return separate_reg, as_arb for matching semantic"
- it = iter(text.splitlines())
- sigtype = None
- try:
- while True:
- line = it.next()
- m = rxSigBegin.match(line)
- if m:
- sigtype = m.group(1)
- continue
- m = rxSigElementsBegin.match(line)
- if m:
- while True:
- line = it.next()
- m = rxSigElement.match(line)
- if m:
- Name, Index, Mask, Register, SysValue, Format, Used = m.groups()
- if Name.lower() == semantic.lower():
- try:
- regnum = int(Register)
- reg = False
- except:
- reg = True
- arb = SysValue == 'NONE'
- return reg, arb
- except StopIteration:
- pass
- return None
- # Internal error or validation error:
- rxInternalError = re.compile(r"^(internal error:.*|error X8000:.*)$")
- # error X4502: invalid ps input semantic 'Foo'
- # error X4502: SV_Coverage input not supported on ps_4_0
- # error X4502: SV_SampleIndex isn't supported on ps_4_0
- # error X3514: SV_GSInstanceID is an invalid input semantic for geometry shader primitives, it must be its own parameter.
- # error X3514: 'GSMain': input parameter 'tfactor' must have a geometry specifier
- # also errors for unsupported shader models
- # error X3660: cs_4_0 does not support interlocked operations
- rxSemanticErrors = [
- re.compile(r".*?\.hlsl.*?: error X4502: invalid .*? semantic '(\w+)'"),
- re.compile(r".*?\.hlsl.*?: error X4502: (\w+) .*? supported on \w+"),
- re.compile(r".*?\.hlsl.*?: error X3514: (\w+) is an invalid input semantic for geometry shader primitives, it must be its own parameter\."),
- re.compile(r".*?\.hlsl.*?: error X3514: 'GSMain': input parameter '\w+' must have a geometry specifier"),
- ]
- def map_gen(fn, *sequences):
- "generator style map"
- iters = map(iter, sequences)
- while True:
- yield fn(*map(next, iters))
- def firstTrue(iterable):
- "returns first non-False element, or None."
- for it in iterable:
- if it:
- return it
- def ParseSVError(text, semantic):
- "return true if error is about illegal use of matching semantic"
- for line in text.splitlines():
- m = firstTrue(map_gen(lambda rx: rx.match(line), rxSemanticErrors))
- if m:
- if len(m.groups()) < 1 or m.group(1).lower() == semantic.lower():
- return True
- else:
- m = rxInternalError.match(line)
- if m:
- print('#### Internal error detected!')
- print(m.group(1))
- return 'InternalError'
- return False
- # TODO: Fill in the correct error pattern
- # error X4576: Non system-generated input signature parameter (Arb) cannot appear after a system generated value.
- rxMustBeLastError = re.compile(r".*?\.hlsl.*?: error X4576: Non system-generated input signature parameter \(\w+\) cannot appear after a system generated value.")
- def ParseSGVError(text, semantic):
- "return true if error is about matching semantic having to be declared last"
- for line in text.splitlines():
- m = rxMustBeLastError.match(line)
- if m:
- return True
- else:
- m = rxInternalError.match(line)
- if m:
- print('#### Internal error detected!')
- print(m.group(1))
- return 'InternalError'
- return False
- hlsl_filename = os.abspath(os.path.join()
- os.environ['HLSL_SRC_DIR'],
- r'tools\clang\test\HLSL',
- 'system-values.hlsl'))
- def main():
- do('5_1')
- do('5_0')
- do('4_1')
- do('4_0')
- def do(sm):
- import os, sys
- # set up table:
- table = [[None] * len(SignaturePoints) for sv in SysValues]
- null_filename = 'output\\test_sv_null.txt'
- for col, (sigpoint, stage, tfpresent) in enumerate(SignaturePoints):
- entry = stage.upper() + 'Main'
- target = stage + '_%s' % sm
- # test arb support:
- ret, output = run('fxc %s /E %s /T %s /D%s_Defs=Def_Arb(float,Arb1,Arb1)' %
- (hlsl_filename, entry, target, sigpoint),
- null_filename)
- arb_supported = ret == 0
- # iterate all system values
- sysvalues = tfpresent and SysValues[:-2] or SysValues
- for row, sv in enumerate(sysvalues):
- output_filename = 'output\\test_sv_output_%s_%s_%s.txt' % (sm, sv, sigpoint)
- separate_reg, as_arb, def_last, result = False, False, False, 'NotInSig'
- ret, output = run('fxc %s /E %s /T %s /D%s_Defs=Def_%s' %
- (hlsl_filename, entry, target, sigpoint, sv),
- output_filename)
- if ret:
- # Failed, look for expected error message:
- found = ParseSVError(output, 'SV_'+sv)
- if found == 'InternalError':
- table[row][col] = 'InternalError'
- print('#### Internal error from ParseSVError - see "%s"' % output_filename)
- elif not found:
- table[row][col] = 'ParseSVError'
- print('#### Error from ParseSVError - see "%s"' % output_filename)
- else:
- table[row][col] = 'NA'
- if os.path.isfile(output_filename):
- os.unlink(output_filename)
- continue
- parse_result = ParseSigs(output, 'SV_'+sv)
- if parse_result:
- separate_reg, as_arb = parse_result
- if as_arb:
- if separate_reg:
- table[row][col] = 'Error: both as_arb and separate_reg set!'
- print('#### Error from ParseSigs, both as_arb and separate_reg set - see "%s"' % output_filename)
- continue
- result = 'Arb'
- else:
- if separate_reg:
- result = 'NotPacked'
- else:
- result = 'SV'
- if os.path.isfile(output_filename):
- os.unlink(output_filename)
- else:
- print('## Not in signature? See "%s"' % output_filename)
- if arb_supported and not as_arb and not separate_reg:
- output_filename = 'output\\test_sv_output_last_%s_%s_%s.txt' % (sm, sv, sigpoint)
- # must system value be declared last? test by adding arb last if arb support
- ret, output = run('fxc %s /E %s /T %s /D%s_Defs="Def_%s Def_Arb(float,Arb1,Arb1)"' %
- (hlsl_filename, entry, target, sigpoint, sv),
- output_filename)
- if ret:
- found = ParseSGVError(output, 'SV_'+sv)
- if found == 'InternalError':
- result += ' | InternalError found with ParseSGVError'
- print('#### Internal error from ParseSGVError - see "%s"' % output_filename)
- elif not found:
- result += ' | ParseSGVError'
- print('#### Error from ParseSGVError - see "%s"' % output_filename)
- elif result == 'SV':
- result = 'SGV'
- if os.path.isfile(output_filename):
- os.unlink(output_filename)
- else:
- result += ' | Error: last required detected, but not SV?'
- print('#### Error: last required detected, but not SV? - see "%s"' % output_filename)
- else:
- if os.path.isfile(output_filename):
- os.unlink(output_filename)
- table[row][col] = result
- for row in range(row+1, len(SysValues)):
- table[row][col] = 'TessFactor'
- def WriteTable(writefn, table):
- writefn('Semantic,' + ','.join([sigpoint for sigpoint, stage, tfpresent in SignaturePoints]) + '\n')
- for n, row in enumerate(table):
- writefn((SysValues[n]) + ','.join(row) + '\n')
- WriteTable(sys.stdout.write, table)
- with open('fxc_sig_packing_table_%s.csv' % sm, 'wt') as f:
- WriteTable(f.write, table)
- if __name__ == '__main__':
- main()
|