Skip to content
Snippets Groups Projects
Commit 9e5ecbea authored by Paul McCarthy's avatar Paul McCarthy
Browse files

arbp/parse module has two separate functions - parseARBP returns

information about declared variables (in a similar vein to parseGLSL),
and fillARBP replaces variable declarations with arb code.
parent 370874cf
No related branches found
No related tags found
No related merge requests found
......@@ -6,63 +6,189 @@
#
import jinja2
import re
import jinja2 as j2
import jinja2.meta as j2meta
#
# {{ params.paramName }} -> program.local[X]
# {{ param_paramName }} -> program.local[X]
#
# Or, if 'paramName' has length > 1
#
# {{ params.paramName }} -> { program.local[x], program.local[x + 1], ... }
# {{ param4_paramName }} -> { program.local[x], program.local[x + 1], ... }
# {{ attrs.attName }} -> vertex.texcoord[N]
# {{ attr_attName }} -> vertex.texcoord[N]
#
# {{ textures.texName }} -> texture[N]
# {{ texture_texName }} -> texture[N]
# Maybe this too? In vertex program:
# {{ varying.outputName }} -> result.texcoord[N]
# {{ varying_outputName }} -> result.texcoord[N]
#
# In fragment program:
# {{ varying.outputName }} -> fragment.texcoord[N]
def parseARBP(source,
vert,
paramMap=None,
textureMap=None,
attrMap=None,
varyingMap=None):
if paramMap is None: paramMap = {}
if textureMap is None: textureMap = {}
if attrMap is None: attrMap = {}
if varyingMap is None: varyingMap = {}
params = {}
textures = {}
attrs = {}
varyings = {}
for name, num in paramMap .items(): params[ name] = _param( num)
for name, num in textureMap.items(): textures[name] = _texture(num)
for name, num in attrMap .items(): attrs[ name] = _attr( num)
for name, num in varyingMap.items(): varyings[name] = _varying(num, vert)
template = jinja2.Template(source)
parsedSrc = template.render(param=params,
texture=textures,
attr=attrs,
varying=varyings)
return parsedSrc
# {{ varying_outputName }} -> fragment.texcoord[N]
def parseARBP(vertSrc, fragSrc):
"""Parses the given ``ARB_vertex_program`` and ``ARB_fragment_program``
code, and returns information about all declared variables.
"""
vParams, vTextures, vAttrs, vVaryings = _findDeclaredVariables(vertSrc)
fParams, fTextures, fAttrs, fVaryings = _findDeclaredVariables(fragSrc)
_checkVariableValidity((vParams, vTextures, vAttrs, vVaryings),
(fParams, fTextures, fAttrs, fVaryings),
{}, {}, {}, {})
return {'vertParam' : vParams,
'fragParam' : fParams,
'attr' : vAttrs,
'texture' : fTextures,
'varying' : vVaryings}
def fillARBP(vertSrc, fragSrc, vertParams, fragParams, textures, attrs):
if vertParams is None: vertParams = {}
if fragParams is None: fragParams = {}
if textures is None: textures = {}
if attrs is None: attrs = {}
vertVars = _findDeclaredVariables(vertSrc)
fragVars = _findDeclaredVariables(fragSrc)
_checkVariableValidity(
vertVars, fragVars, vertParams, fragParams, textures, attrs)
for name, (number, length) in vertParams.items():
if length == 1: name = 'param_{}' .format(name)
else: name = 'param{}_{}'.format(name, length)
vertParams[name] = _param(number, length)
for name, (number, length) in fragParams.items():
if length == 1: name = 'param_{}' .format(name)
else: name = 'param{}_{}'.format(name, length)
fragParams[name] = _param(number, length)
textures = {'texture_{}'.format(n) : _texture(v)
for n, v in textures.items()}
attrs = {'attr_{}'.format(n) : _attr(v) for n, v in attrs.items()}
varyings = _makeVaryingMap(vertVars[3], fragVars[3])
vertVaryings = {}
fragVaryings = {}
for name, num in varyings.items():
vertVaryings['varying_{}'.format(name)] = _varying(num, True)
fragVaryings['varying_{}'.format(name)] = _varying(num, False)
vertTemplate = j2.Template(vertSrc)
fragTemplate = j2.Template(fragSrc)
vertVars = dict(vertParams .items() +
textures .items() +
attrs .items() +
vertVaryings.items())
fragVars = dict(fragParams .items() +
textures .items() +
fragVaryings.items())
vertSrc = vertTemplate.render(**vertVars)
fragSrc = fragTemplate.render(**fragVars)
return vertSrc, fragSrc
def _findDeclaredVariables(source):
def _param(number):
env = j2.Environment()
ast = env.parse(source)
svars = j2meta.find_undeclared_variables(ast)
try: number, length = number
except: number, length = number, 1
pExpr = re.compile('^param([1-9]*)_(.+)$')
tExpr = re.compile('^texture_(.+)$')
aExpr = re.compile('^attr_(.+)$')
vExpr = re.compile('^varying_(.+)$')
params = []
textures = []
attrs = []
varyings = []
for v in svars:
for expr, namelist in zip([pExpr, tExpr, aExpr, vExpr],
[params, textures, attrs, varyings]):
match = expr.match(v)
if match is None:
continue
if expr is pExpr:
length = match.group(1)
name = match.group(2)
if length == '': length = 1
else: length = int(length)
namelist.append((name, length))
else:
name = match.group(1)
namelist.append(name)
return map(sorted, (params, textures, attrs, varyings))
def _checkVariableValidity(vertVars,
fragVars,
vertParamMap,
fragParamMap,
textureMap,
attrMap):
vParams, vTextures, vAttrs, vVaryings = vertVars
fParams, fTextures, fAttrs, fVaryings = fragVars
vParams = [vp[0] for vp in vParams]
fParams = [fp[0] for fp in fParams]
# TODO Custom error type, and more useful error messages.
if len(vTextures) != 0:
raise ValueError('Texture access in vertex program')
if len(fAttrs) != 0:
raise ValueError('Attribute access in fragment program')
if vVaryings != fVaryings:
raise ValueError('Fragment/vertex varyings do not match')
if any([n not in vParams for n in vertParamMap]):
raise ValueError('Unknown variable in vertex parameter map.')
if any([n not in fParams for n in fragParamMap]):
raise ValueError('Unknown variable in fragment parameter map.')
if any([n not in fTextures for n in textureMap]):
raise ValueError('Unknown variable in texture parameter map.')
if any([n not in vAttrs for n in attrMap]):
raise ValueError('Unknown variable in attribute parameter map.')
def _makeVaryingMap(vertVaryings, fragVaryings):
indices = range(len(vertVaryings))
varyingMap = dict(zip(vertVaryings, indices))
return varyingMap
def _param(number, length):
if length == 1:
return 'program.local[{}]'.format(number)
else:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment