1e5c31af7Sopenharmony_ci#!/usr/bin/python3 -i 2e5c31af7Sopenharmony_ci# 3e5c31af7Sopenharmony_ci# Copyright 2013-2024 The Khronos Group Inc. 4e5c31af7Sopenharmony_ci# 5e5c31af7Sopenharmony_ci# SPDX-License-Identifier: Apache-2.0 6e5c31af7Sopenharmony_ci 7e5c31af7Sopenharmony_cifrom generator import OutputGenerator, write 8e5c31af7Sopenharmony_ciimport os 9e5c31af7Sopenharmony_ci 10e5c31af7Sopenharmony_ciqueueTypeToQueueFlags = { 11e5c31af7Sopenharmony_ci 'graphics' : 'VK_QUEUE_GRAPHICS_BIT', 12e5c31af7Sopenharmony_ci 'compute' : 'VK_QUEUE_COMPUTE_BIT', 13e5c31af7Sopenharmony_ci 'transfer' : 'VK_QUEUE_TRANSFER_BIT', 14e5c31af7Sopenharmony_ci 'sparse_binding' : 'VK_QUEUE_SPARSE_BINDING_BIT', 15e5c31af7Sopenharmony_ci 'decode' : 'VK_QUEUE_VIDEO_DECODE_BIT_KHR', 16e5c31af7Sopenharmony_ci 'encode' : 'VK_QUEUE_VIDEO_ENCODE_BIT_KHR', 17e5c31af7Sopenharmony_ci 'opticalflow' : 'VK_QUEUE_OPTICAL_FLOW_BIT_NV', 18e5c31af7Sopenharmony_ci} 19e5c31af7Sopenharmony_ci 20e5c31af7Sopenharmony_ciclass SyncOutputGenerator(OutputGenerator): 21e5c31af7Sopenharmony_ci """SyncOutputGenerator - subclass of OutputGenerator. 22e5c31af7Sopenharmony_ci Generates AsciiDoc includes of the table for the Synchronization chapters 23e5c31af7Sopenharmony_ci of the API specification. 24e5c31af7Sopenharmony_ci 25e5c31af7Sopenharmony_ci ---- methods ---- 26e5c31af7Sopenharmony_ci SyncOutputGenerator(errFile, warnFile, diagFile) - args as for 27e5c31af7Sopenharmony_ci OutputGenerator. Defines additional internal state. 28e5c31af7Sopenharmony_ci ---- methods overriding base class ---- 29e5c31af7Sopenharmony_ci """ 30e5c31af7Sopenharmony_ci 31e5c31af7Sopenharmony_ci def __init__(self, *args, **kwargs): 32e5c31af7Sopenharmony_ci super().__init__(*args, **kwargs) 33e5c31af7Sopenharmony_ci 34e5c31af7Sopenharmony_ci # List of all elements 35e5c31af7Sopenharmony_ci self.pipeline_stages = [] 36e5c31af7Sopenharmony_ci self.access_flags = [] 37e5c31af7Sopenharmony_ci 38e5c31af7Sopenharmony_ci # <Pipeline Stage, condition as asciidoc string> 39e5c31af7Sopenharmony_ci self.pipeline_stage_condition = dict() 40e5c31af7Sopenharmony_ci # <success flag, condition as asciidoc string> 41e5c31af7Sopenharmony_ci self.access_flag_condition = dict() 42e5c31af7Sopenharmony_ci 43e5c31af7Sopenharmony_ci # <Pipeline Stage, [equivalent pipeline stages]> 44e5c31af7Sopenharmony_ci self.pipeline_stage_equivalent = dict() 45e5c31af7Sopenharmony_ci # <Pipeline Stage, [queue support]> 46e5c31af7Sopenharmony_ci self.pipeline_stage_queue_support = dict() 47e5c31af7Sopenharmony_ci 48e5c31af7Sopenharmony_ci # <Access Flag, [equivalent access flaga]> 49e5c31af7Sopenharmony_ci self.access_flag_equivalent = dict() 50e5c31af7Sopenharmony_ci # <Access Flag, [pipeline stage support]> 51e5c31af7Sopenharmony_ci self.access_flag_stage_support = dict() 52e5c31af7Sopenharmony_ci 53e5c31af7Sopenharmony_ci self.pipeline_order_info = [] 54e5c31af7Sopenharmony_ci 55e5c31af7Sopenharmony_ci def endFile(self): 56e5c31af7Sopenharmony_ci self.writeFlagDefinitions() 57e5c31af7Sopenharmony_ci self.supportedPipelineStages() 58e5c31af7Sopenharmony_ci self.supportedAccessTypes() 59e5c31af7Sopenharmony_ci self.pipelineOrdering() 60e5c31af7Sopenharmony_ci OutputGenerator.endFile(self) 61e5c31af7Sopenharmony_ci 62e5c31af7Sopenharmony_ci def writeBlock(self, basename, contents): 63e5c31af7Sopenharmony_ci """Generate an include file. 64e5c31af7Sopenharmony_ci 65e5c31af7Sopenharmony_ci - directory - subdirectory to put file in 66e5c31af7Sopenharmony_ci - basename - base name of the file 67e5c31af7Sopenharmony_ci - contents - contents of the file (Asciidoc boilerplate aside)""" 68e5c31af7Sopenharmony_ci 69e5c31af7Sopenharmony_ci filename = self.genOpts.directory + '/' + basename 70e5c31af7Sopenharmony_ci self.logMsg('diag', '# Generating include file:', filename) 71e5c31af7Sopenharmony_ci dirname = os.path.dirname(filename) 72e5c31af7Sopenharmony_ci if not os.path.exists(dirname): 73e5c31af7Sopenharmony_ci os.makedirs(dirname) 74e5c31af7Sopenharmony_ci with open(filename, 'w', encoding='utf-8') as fp: 75e5c31af7Sopenharmony_ci write(self.genOpts.conventions.warning_comment, file=fp) 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_ci if len(contents) > 0: 78e5c31af7Sopenharmony_ci for str in contents: 79e5c31af7Sopenharmony_ci write(str, file=fp) 80e5c31af7Sopenharmony_ci else: 81e5c31af7Sopenharmony_ci self.logMsg('diag', '# No contents for:', filename) 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_ci def genSyncStage(self, stageinfo): 84e5c31af7Sopenharmony_ci OutputGenerator.genSyncStage(self, stageinfo) 85e5c31af7Sopenharmony_ci name = stageinfo.elem.get('name') 86e5c31af7Sopenharmony_ci self.pipeline_stages.append(name) 87e5c31af7Sopenharmony_ci 88e5c31af7Sopenharmony_ci if stageinfo.condition is not None: 89e5c31af7Sopenharmony_ci self.pipeline_stage_condition[name] = stageinfo.condition 90e5c31af7Sopenharmony_ci 91e5c31af7Sopenharmony_ci syncsupport = stageinfo.elem.find('syncsupport') 92e5c31af7Sopenharmony_ci if syncsupport is not None: 93e5c31af7Sopenharmony_ci self.pipeline_stage_queue_support[name] = syncsupport.get('queues').split(',') 94e5c31af7Sopenharmony_ci 95e5c31af7Sopenharmony_ci syncequivalent = stageinfo.elem.find('syncequivalent') 96e5c31af7Sopenharmony_ci if syncequivalent is not None: 97e5c31af7Sopenharmony_ci self.pipeline_stage_equivalent[name] = syncequivalent.get('stage').split(',') 98e5c31af7Sopenharmony_ci 99e5c31af7Sopenharmony_ci def genSyncAccess(self, accessinfo): 100e5c31af7Sopenharmony_ci OutputGenerator.genSyncStage(self, accessinfo) 101e5c31af7Sopenharmony_ci name = accessinfo.elem.get('name') 102e5c31af7Sopenharmony_ci self.access_flags.append(name) 103e5c31af7Sopenharmony_ci 104e5c31af7Sopenharmony_ci if accessinfo.condition is not None: 105e5c31af7Sopenharmony_ci self.access_flag_condition[name] = accessinfo.condition 106e5c31af7Sopenharmony_ci 107e5c31af7Sopenharmony_ci syncsupport = accessinfo.elem.find('syncsupport') 108e5c31af7Sopenharmony_ci if syncsupport is not None: 109e5c31af7Sopenharmony_ci self.access_flag_stage_support[name] = syncsupport.get('stage').split(',') 110e5c31af7Sopenharmony_ci 111e5c31af7Sopenharmony_ci syncequivalent = accessinfo.elem.find('syncequivalent') 112e5c31af7Sopenharmony_ci if syncequivalent is not None: 113e5c31af7Sopenharmony_ci self.access_flag_equivalent[name] = syncequivalent.get('access').split(',') 114e5c31af7Sopenharmony_ci 115e5c31af7Sopenharmony_ci def genSyncPipeline(self, pipelineinfo): 116e5c31af7Sopenharmony_ci OutputGenerator.genSyncStage(self, pipelineinfo) 117e5c31af7Sopenharmony_ci self.pipeline_order_info.append(pipelineinfo) 118e5c31af7Sopenharmony_ci 119e5c31af7Sopenharmony_ci def isSameConditionPipeline(self, condition, stage): 120e5c31af7Sopenharmony_ci if stage not in self.pipeline_stage_condition: 121e5c31af7Sopenharmony_ci return False 122e5c31af7Sopenharmony_ci if condition is None: 123e5c31af7Sopenharmony_ci return False 124e5c31af7Sopenharmony_ci return self.pipeline_stage_condition[stage] == condition 125e5c31af7Sopenharmony_ci 126e5c31af7Sopenharmony_ci def isSameConditionPipelineAccess(self, stage, flag): 127e5c31af7Sopenharmony_ci if stage not in self.pipeline_stage_condition: 128e5c31af7Sopenharmony_ci return False 129e5c31af7Sopenharmony_ci if flag not in self.access_flag_condition: 130e5c31af7Sopenharmony_ci return False 131e5c31af7Sopenharmony_ci return self.pipeline_stage_condition[stage] == self.access_flag_condition[flag] 132e5c31af7Sopenharmony_ci 133e5c31af7Sopenharmony_ci def writePipelineIfdef(self, stage, list): 134e5c31af7Sopenharmony_ci condition = self.pipeline_stage_condition[stage] if stage in self.pipeline_stage_condition else None 135e5c31af7Sopenharmony_ci if condition is not None: 136e5c31af7Sopenharmony_ci list.append('ifdef::{}[]'.format(condition)) 137e5c31af7Sopenharmony_ci 138e5c31af7Sopenharmony_ci def writePipelineEndif(self, stage, list): 139e5c31af7Sopenharmony_ci condition = self.pipeline_stage_condition[stage] if stage in self.pipeline_stage_condition else None 140e5c31af7Sopenharmony_ci if condition is not None: 141e5c31af7Sopenharmony_ci list.append('endif::{}[]'.format(condition)) 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci def writeAccessIfdef(self, flag, list): 144e5c31af7Sopenharmony_ci condition = self.access_flag_condition[flag] if flag in self.access_flag_condition else None 145e5c31af7Sopenharmony_ci if condition is not None: 146e5c31af7Sopenharmony_ci list.append('ifdef::{}[]'.format(condition)) 147e5c31af7Sopenharmony_ci 148e5c31af7Sopenharmony_ci def writeAccessEndif(self, flag, list): 149e5c31af7Sopenharmony_ci condition = self.access_flag_condition[flag] if flag in self.access_flag_condition else None 150e5c31af7Sopenharmony_ci if condition is not None: 151e5c31af7Sopenharmony_ci list.append('endif::{}[]'.format(condition)) 152e5c31af7Sopenharmony_ci 153e5c31af7Sopenharmony_ci def writeFlagDefinitions(self): 154e5c31af7Sopenharmony_ci for name, stages in self.pipeline_stage_equivalent.items(): 155e5c31af7Sopenharmony_ci output = [] 156e5c31af7Sopenharmony_ci for stage in stages: 157e5c31af7Sopenharmony_ci self.writePipelineIfdef(stage, output) 158e5c31af7Sopenharmony_ci output.append(' ** ename:{}'.format(stage)) 159e5c31af7Sopenharmony_ci self.writePipelineEndif(stage, output) 160e5c31af7Sopenharmony_ci 161e5c31af7Sopenharmony_ci self.writeBlock(f'flagDefinitions/{name}{self.file_suffix}', output) 162e5c31af7Sopenharmony_ci 163e5c31af7Sopenharmony_ci for name, flags in self.access_flag_equivalent.items(): 164e5c31af7Sopenharmony_ci output = [] 165e5c31af7Sopenharmony_ci for flag in flags: 166e5c31af7Sopenharmony_ci self.writeAccessIfdef(flag, output) 167e5c31af7Sopenharmony_ci output.append(' ** ename:{}'.format(flag)) 168e5c31af7Sopenharmony_ci self.writeAccessEndif(flag, output) 169e5c31af7Sopenharmony_ci 170e5c31af7Sopenharmony_ci self.writeBlock(f'flagDefinitions/{name}{self.file_suffix}', output) 171e5c31af7Sopenharmony_ci 172e5c31af7Sopenharmony_ci def supportedPipelineStages(self): 173e5c31af7Sopenharmony_ci output = [] 174e5c31af7Sopenharmony_ci for stage in self.pipeline_stages: 175e5c31af7Sopenharmony_ci self.writePipelineIfdef(stage, output) 176e5c31af7Sopenharmony_ci queue_support = '' 177e5c31af7Sopenharmony_ci if stage not in self.pipeline_stage_queue_support: 178e5c31af7Sopenharmony_ci queue_support = 'None required' 179e5c31af7Sopenharmony_ci else: 180e5c31af7Sopenharmony_ci for queue in self.pipeline_stage_queue_support[stage]: 181e5c31af7Sopenharmony_ci ename = 'ename:{}'.format(queueTypeToQueueFlags[queue]) 182e5c31af7Sopenharmony_ci if queue_support != '': 183e5c31af7Sopenharmony_ci queue_support += ' or ' 184e5c31af7Sopenharmony_ci queue_support += ename 185e5c31af7Sopenharmony_ci 186e5c31af7Sopenharmony_ci output.append('|ename:{} | {}'.format(stage, queue_support)) 187e5c31af7Sopenharmony_ci 188e5c31af7Sopenharmony_ci self.writePipelineEndif(stage, output) 189e5c31af7Sopenharmony_ci 190e5c31af7Sopenharmony_ci self.writeBlock(f'supportedPipelineStages{self.file_suffix}', output) 191e5c31af7Sopenharmony_ci 192e5c31af7Sopenharmony_ci def supportedAccessTypes(self): 193e5c31af7Sopenharmony_ci output = [] 194e5c31af7Sopenharmony_ci for flag in self.access_flags: 195e5c31af7Sopenharmony_ci self.writeAccessIfdef(flag, output) 196e5c31af7Sopenharmony_ci output.append('|ename:{} |'.format(flag)) 197e5c31af7Sopenharmony_ci 198e5c31af7Sopenharmony_ci if flag not in self.access_flag_stage_support: 199e5c31af7Sopenharmony_ci output.append('\tAny') 200e5c31af7Sopenharmony_ci else: 201e5c31af7Sopenharmony_ci stages = self.access_flag_stage_support[flag] 202e5c31af7Sopenharmony_ci for index, stage in enumerate(stages): 203e5c31af7Sopenharmony_ci end_symbol = '' 204e5c31af7Sopenharmony_ci if index != (len(stages) - 1) and len(stages) > 1: 205e5c31af7Sopenharmony_ci end_symbol = ',' 206e5c31af7Sopenharmony_ci 207e5c31af7Sopenharmony_ci if not self.isSameConditionPipelineAccess(stage, flag): 208e5c31af7Sopenharmony_ci self.writePipelineIfdef(stage, output) 209e5c31af7Sopenharmony_ci output.append('\tename:{}{}'.format(stage, end_symbol)) 210e5c31af7Sopenharmony_ci if not self.isSameConditionPipelineAccess(stage, flag): 211e5c31af7Sopenharmony_ci self.writePipelineEndif(stage, output) 212e5c31af7Sopenharmony_ci 213e5c31af7Sopenharmony_ci self.writeAccessEndif(flag, output) 214e5c31af7Sopenharmony_ci 215e5c31af7Sopenharmony_ci self.writeBlock(f'supportedAccessTypes{self.file_suffix}', output) 216e5c31af7Sopenharmony_ci 217e5c31af7Sopenharmony_ci def pipelineOrdering(self): 218e5c31af7Sopenharmony_ci for pipelineinfo in self.pipeline_order_info: 219e5c31af7Sopenharmony_ci output = [] 220e5c31af7Sopenharmony_ci name = pipelineinfo.elem.get('name') 221e5c31af7Sopenharmony_ci depends = pipelineinfo.elem.get('depends') 222e5c31af7Sopenharmony_ci syncPipelineStages = pipelineinfo.elem.findall('syncpipelinestage') 223e5c31af7Sopenharmony_ci 224e5c31af7Sopenharmony_ci for stageElem in syncPipelineStages: 225e5c31af7Sopenharmony_ci stage = stageElem.text 226e5c31af7Sopenharmony_ci order = stageElem.get('order') 227e5c31af7Sopenharmony_ci before = stageElem.get('before') 228e5c31af7Sopenharmony_ci after = stageElem.get('after') 229e5c31af7Sopenharmony_ci if order == 'None': 230e5c31af7Sopenharmony_ci continue 231e5c31af7Sopenharmony_ci 232e5c31af7Sopenharmony_ci if not self.isSameConditionPipeline(depends, stage): 233e5c31af7Sopenharmony_ci self.writePipelineIfdef(stage, output) 234e5c31af7Sopenharmony_ci 235e5c31af7Sopenharmony_ci output.append(' * ename:{}'.format(stage)) 236e5c31af7Sopenharmony_ci 237e5c31af7Sopenharmony_ci if not self.isSameConditionPipeline(depends, stage): 238e5c31af7Sopenharmony_ci self.writePipelineEndif(stage, output) 239e5c31af7Sopenharmony_ci 240e5c31af7Sopenharmony_ci file_name = name.replace(' ', '_') 241e5c31af7Sopenharmony_ci self.writeBlock(f'pipelineOrders/{file_name}{self.file_suffix}', output) 242