diff options
| author | Dustin Graves <dustin@lunarg.com> | 2016-04-26 15:37:10 -0600 |
|---|---|---|
| committer | Dustin Graves <dustin@lunarg.com> | 2016-04-28 17:24:42 -0600 |
| commit | d33465e2c8a578a4e1bbd15e76d5e0f674aa7364 (patch) | |
| tree | b06eedc0c87de76650c68c31607bb3cea07aebb8 /generator.py | |
| parent | 298e942df7ae24098c8338a98163556566afed1e (diff) | |
| download | usermoji-d33465e2c8a578a4e1bbd15e76d5e0f674aa7364.tar.xz | |
layers: Add VkFlags parameter validation
Add parameter validation for VkFlags derived types to the
parameter_validation layer's code generation scripts. The following
validation checks are performed:
- If a VkFlags parameter is not marked as optional in the XML, a message
is generated when the parameter is 0.
- If a VkFlags parameter is not 0, a message is generated if it combines
bits that are not defined by its associated flag bits enumeration.
- If a VkFlags parameter does not have an associated flag bits
enumeration it is treated as a reserved value that must be 0.
Change-Id: I6daed360cde46e2a27c84deda1e0798621f92d50
Diffstat (limited to 'generator.py')
| -rw-r--r-- | generator.py | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/generator.py b/generator.py index 249313d6..7b4516f9 100644 --- a/generator.py +++ b/generator.py @@ -2850,6 +2850,8 @@ class ParamCheckerOutputGenerator(OutputGenerator): self.structMembers = [] # List of StructMemberData records for all Vulkan structs self.validatedStructs = dict() # Map of structs type names to generated validation code for that struct type self.enumRanges = dict() # Map of enum name to BEGIN/END range values + self.flags = dict() # Map of flags typenames to a Boolean value indicating that validation code is generated for a value of this type + self.flagBits = dict() # Map of flag bits typename to list of values # Named tuples to store struct and command data self.StructType = namedtuple('StructType', ['name', 'value']) self.CommandParam = namedtuple('CommandParam', ['type', 'name', 'ispointer', 'isstaticarray', 'isbool', 'israngedenum', @@ -2922,6 +2924,8 @@ class ParamCheckerOutputGenerator(OutputGenerator): self.structMembers = [] self.validatedStructs = dict() self.enumRanges = dict() + self.flags = dict() + self.flagBits = dict() def endFeature(self): # C-specific # Actually write the interface to the output file. @@ -2936,6 +2940,18 @@ class ParamCheckerOutputGenerator(OutputGenerator): self.processStructMemberData() # Generate the command parameter checking code from the captured data self.processCmdData() + # Write the declarations for the VkFlags values combining all flag bits + for flag in sorted(self.flags): + if self.flags[flag]: + flagBits = flag.replace('Flags', 'FlagBits') + bits = self.flagBits[flagBits] + decl = 'const {} All{} = {}'.format(flag, flagBits, bits[0]) + for bit in bits[1:]: + decl += '|' + bit + decl += ';' + write(decl, file=self.outFile) + self.newline() + # Write the parameter validation code to the file if (self.sections['command']): if (self.genOpts.protectProto): write(self.genOpts.protectProto, @@ -2965,6 +2981,8 @@ class ParamCheckerOutputGenerator(OutputGenerator): self.genStruct(typeinfo, name) elif (category == 'handle'): self.handleTypes.add(name) + elif (category == 'bitmask'): + self.flags[name] = False # # Struct parameter check generation. # This is a special case of the <type> tag where the contents are @@ -3057,6 +3075,12 @@ class ParamCheckerOutputGenerator(OutputGenerator): if groupName == 'VkStructureType': for elem in groupElem.findall('enum'): self.stypes.append(elem.get('name')) + elif 'FlagBits' in groupName: + bits = [] + for elem in groupElem.findall('enum'): + bits.append(elem.get('name')) + if bits: + self.flagBits[groupName] = bits else: # Determine if begin/end ranges are needed (we don't do this for VkStructureType, which has a more finely grained check) expandName = re.sub(r'([0-9a-z_])([A-Z0-9][^A-Z0-9]?)',r'\1_\2',groupName).upper() @@ -3311,22 +3335,34 @@ class ParamCheckerOutputGenerator(OutputGenerator): funcPrintName, valuePrintName, prefix, valueRequired, vn=value.name, sv=stype.value)) return checkExpr # - # Generate the sType check string + # Generate the handle check string def makeHandleCheck(self, prefix, value, lenValue, valueRequired, lenValueRequired, funcPrintName, lenPrintName, valuePrintName): checkExpr = [] if lenValue: - # This is assumed to be an output array with a pointer to a count value if lenValue.ispointer: + # This is assumed to be an output array with a pointer to a count value raise('Unsupported parameter validation case: Output handle array elements are not NULL checked') - # This is an array with an integer count value else: + # This is an array with an integer count value checkExpr.append('skipCall |= validate_handle_array(report_data, "{}", "{ldn}", "{dn}", {pf}{ln}, {pf}{vn}, {}, {});\n'.format( funcPrintName, lenValueRequired, valueRequired, ln=lenValue.name, ldn=lenPrintName, dn=valuePrintName, vn=value.name, pf=prefix)) - # This is assumed to be an output handle pointer else: + # This is assumed to be an output handle pointer raise('Unsupported parameter validation case: Output handles are not NULL checked') return checkExpr # + # Generate check string for an array of VkFlags values + def makeFlagsArrayCheck(self, prefix, value, lenValue, valueRequired, lenValueRequired, funcPrintName, lenPrintName, valuePrintName): + checkExpr = [] + flagBitsName = value.type.replace('Flags', 'FlagBits') + if not flagBitsName in self.flagBits: + raise('Unsupported parameter validation case: array of reserved VkFlags') + else: + allFlags = 'All' + flagBitsName + checkExpr.append('skipCall |= validate_flags_array(report_data, "{}", "{}", "{}", "{}", {}, {pf}{}, {pf}{}, {}, {});\n'.format(funcPrintName, lenPrintName, valuePrintName, flagBitsName, allFlags, lenValue.name, value.name, lenValueRequired, valueRequired, pf=prefix)) + self.flags[value.type] = True + return checkExpr + # # Generate pNext check string def makeStructNextCheck(self, prefix, value, funcPrintName, valuePrintName): checkExpr = [] @@ -3472,6 +3508,8 @@ class ParamCheckerOutputGenerator(OutputGenerator): # If this is an input handle array that is not allowed to contain NULL handles, verify that none of the handles are VK_NULL_HANDLE elif value.type in self.handleTypes and value.isconst and not self.isHandleOptional(value, lenParam): usedLines += self.makeHandleCheck(valuePrefix, value, lenParam, req, cvReq, funcName, lenDisplayName, valueDisplayName) + elif value.type in self.flags and value.isconst: + usedLines += self.makeFlagsArrayCheck(valuePrefix, value, lenParam, req, cvReq, funcName, lenDisplayName, valueDisplayName) elif value.isbool and value.isconst: usedLines.append('skipCall |= validate_bool32_array(report_data, "{}", "{}", "{}", {pf}{}, {pf}{}, {}, {});\n'.format(funcName, lenDisplayName, valueDisplayName, lenParam.name, value.name, cvReq, req, pf=valuePrefix)) elif value.israngedenum and value.isconst: @@ -3500,6 +3538,15 @@ class ParamCheckerOutputGenerator(OutputGenerator): elif value.type in self.handleTypes: if not self.isHandleOptional(value, None): usedLines.append('skipCall |= validate_required_handle(report_data, "{}", "{}", {}{});\n'.format(funcName, valueDisplayName, valuePrefix, value.name)) + elif value.type in self.flags: + flagBitsName = value.type.replace('Flags', 'FlagBits') + if not flagBitsName in self.flagBits: + usedLines.append('skipCall |= validate_reserved(report_data, "{}", "{}", {pf}{});\n'.format(funcName, valueDisplayName, value.name, pf=valuePrefix)) + else: + flagsRequired = 'false' if value.isoptional else 'true' + allFlagsName = 'All' + flagBitsName + usedLines.append('skipCall |= validate_flags(report_data, "{}", "{}", "{}", {}, {pf}{}, {});\n'.format(funcName, valueDisplayName, flagBitsName, allFlagsName, value.name, flagsRequired, pf=valuePrefix)) + self.flags[value.type] = True elif value.isbool: usedLines.append('skipCall |= validate_bool32(report_data, "{}", "{}", {}{});\n'.format(funcName, valueDisplayName, valuePrefix, value.name)) elif value.israngedenum: |
