mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-03 11:30:21 +01:00
gfxstream: vulkan-Docs: import the cerealgenerator
This imports the cereal generator into the next gen Vulkan docs. Reviewed-by: Aaron Ruby <aruby@blackberry.com> Acked-by: Yonggang Luo <luoyonggang@gmail.com> Acked-by: Adam Jackson <ajax@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27246>
This commit is contained in:
parent
c10d78e61e
commit
82ff5f769f
25 changed files with 12078 additions and 0 deletions
20
src/gfxstream/codegen/scripts/cereal/__init__.py
Normal file
20
src/gfxstream/codegen/scripts/cereal/__init__.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
from .common import *
|
||||
from .decoder import *
|
||||
from .encoder import *
|
||||
from .extensionstructs import *
|
||||
from .frontend import *
|
||||
from .functable import *
|
||||
from .marshaling import *
|
||||
from .reservedmarshaling import *
|
||||
from .counting import *
|
||||
from .testing import *
|
||||
from .transform import *
|
||||
from .deepcopy import *
|
||||
from .handlemap import *
|
||||
from .dispatch import *
|
||||
from .unbox import *
|
||||
from .decodersnapshot import *
|
||||
from .subdecode import *
|
||||
from .api_log_decoder import *
|
||||
from .vkextensionstructuretype import VulkanGfxstreamStructureType, \
|
||||
VulkanAndroidNativeBufferStructureType
|
||||
338
src/gfxstream/codegen/scripts/cereal/api_log_decoder.py
Normal file
338
src/gfxstream/codegen/scripts/cereal/api_log_decoder.py
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
import os
|
||||
from typing import List, Set, Dict, Optional
|
||||
|
||||
from . import VulkanType, VulkanCompoundType
|
||||
from .wrapperdefs import VulkanWrapperGenerator
|
||||
|
||||
|
||||
class ApiLogDecoder(VulkanWrapperGenerator):
|
||||
"""
|
||||
This class generates decoding logic for the graphics API logs captured by
|
||||
[GfxApiLogger](http://source/play-internal/battlestar/aosp/device/generic/vulkan-cereal/base/GfxApiLogger.h)
|
||||
|
||||
This allows developers to see a pretty-printed version of the API log data when using
|
||||
print_gfx_logs.py
|
||||
"""
|
||||
|
||||
# List of Vulkan APIs that we will generate decoding logic for
|
||||
generated_apis = [
|
||||
"vkAcquireImageANDROID",
|
||||
"vkAllocateMemory",
|
||||
"vkBeginCommandBufferAsyncGOOGLE",
|
||||
"vkBindBufferMemory",
|
||||
"vkBindImageMemory",
|
||||
"vkCmdBeginRenderPass",
|
||||
"vkCmdBindDescriptorSets",
|
||||
"vkCmdBindIndexBuffer",
|
||||
"vkCmdBindPipeline",
|
||||
"vkCmdBindVertexBuffers",
|
||||
"vkCmdClearAttachments",
|
||||
"vkCmdClearColorImage",
|
||||
"vkCmdCopyBufferToImage",
|
||||
"vkCmdCopyImageToBuffer",
|
||||
"vkCmdDraw",
|
||||
"vkCmdDrawIndexed",
|
||||
"vkCmdEndRenderPass",
|
||||
"vkCmdPipelineBarrier",
|
||||
"vkCmdSetScissor",
|
||||
"vkCmdSetViewport",
|
||||
"vkCollectDescriptorPoolIdsGOOGLE",
|
||||
"vkCreateBufferWithRequirementsGOOGLE",
|
||||
"vkCreateDescriptorPool",
|
||||
"vkCreateDescriptorSetLayout",
|
||||
"vkCreateFence",
|
||||
"vkCreateFramebuffer",
|
||||
"vkCreateGraphicsPipelines",
|
||||
"vkCreateImageView",
|
||||
"vkCreateImageWithRequirementsGOOGLE",
|
||||
"vkCreatePipelineCache",
|
||||
"vkCreateRenderPass",
|
||||
"vkCreateSampler",
|
||||
"vkCreateSemaphore",
|
||||
"vkCreateShaderModule",
|
||||
"vkDestroyBuffer",
|
||||
"vkDestroyCommandPool",
|
||||
"vkDestroyDescriptorPool",
|
||||
"vkDestroyDescriptorSetLayout",
|
||||
"vkDestroyDevice",
|
||||
"vkDestroyFence",
|
||||
"vkDestroyFramebuffer",
|
||||
"vkDestroyImage",
|
||||
"vkDestroyImageView",
|
||||
"vkDestroyInstance",
|
||||
"vkDestroyPipeline",
|
||||
"vkDestroyPipelineCache",
|
||||
"vkDestroyPipelineLayout",
|
||||
"vkDestroyRenderPass",
|
||||
"vkDestroySemaphore",
|
||||
"vkDestroyShaderModule",
|
||||
"vkEndCommandBufferAsyncGOOGLE",
|
||||
"vkFreeCommandBuffers",
|
||||
"vkFreeMemory",
|
||||
"vkFreeMemorySyncGOOGLE",
|
||||
"vkGetFenceStatus",
|
||||
"vkGetMemoryHostAddressInfoGOOGLE",
|
||||
"vkGetBlobGOOGLE",
|
||||
"vkGetPhysicalDeviceFormatProperties",
|
||||
"vkGetPhysicalDeviceProperties2KHR",
|
||||
"vkGetPipelineCacheData",
|
||||
"vkGetSwapchainGrallocUsageANDROID",
|
||||
"vkQueueCommitDescriptorSetUpdatesGOOGLE",
|
||||
"vkQueueFlushCommandsGOOGLE",
|
||||
"vkQueueSignalReleaseImageANDROIDAsyncGOOGLE",
|
||||
"vkQueueSubmitAsyncGOOGLE",
|
||||
"vkQueueWaitIdle",
|
||||
"vkResetFences",
|
||||
"vkWaitForFences",
|
||||
]
|
||||
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
self.typeInfo = typeInfo
|
||||
|
||||
# Set of Vulkan structs that we need to write decoding logic for
|
||||
self.structs: Set[str] = set()
|
||||
|
||||
# Maps enum group names to the list of enums in the group, for all enum groups in the spec
|
||||
# E.g.: "VkResult": ["VK_SUCCESS", "VK_NOT_READY", "VK_TIMEOUT", etc...]
|
||||
self.all_enums: Dict[str, List[str]] = {}
|
||||
|
||||
# Set of Vulkan enums that we need to write decoding logic for
|
||||
self.needed_enums: Set[str] = {"VkStructureType"}
|
||||
|
||||
def onBegin(self):
|
||||
self.module.append("""
|
||||
#####################################################################################################
|
||||
# Pretty-printer functions for Vulkan data structures
|
||||
# THIS FILE IS AUTO-GENERATED - DO NOT EDIT
|
||||
#
|
||||
# To re-generate this file, run generate-vulkan-sources.sh
|
||||
#####################################################################################################
|
||||
|
||||
""".lstrip())
|
||||
|
||||
def onGenGroup(self, groupinfo, groupName, alias=None):
|
||||
"""Called for each enum group in the spec"""
|
||||
for enum in groupinfo.elem.findall("enum"):
|
||||
self.all_enums[groupName] = self.all_enums.get(groupName, []) + [enum.get('name')]
|
||||
|
||||
def onEnd(self):
|
||||
for api_name in sorted(self.generated_apis):
|
||||
self.process_api(api_name)
|
||||
self.process_structs()
|
||||
self.process_enums()
|
||||
|
||||
def process_api(self, api_name):
|
||||
"""Main entry point to generate decoding logic for each Vulkan API"""
|
||||
api = self.typeInfo.apis[api_name]
|
||||
self.module.append('def OP_{}(printer, indent: int):\n'.format(api_name))
|
||||
|
||||
# Decode the sequence number. All commands have sequence numbers, except those handled
|
||||
# by VkSubdecoder.cpp. The logic here is a bit of a hack since it's based on the command
|
||||
# name. Ideally, we would detect whether a particular command is part of a subdecode block
|
||||
# in the decoding script.
|
||||
if not api_name.startswith("vkCmd") and api_name != "vkBeginCommandBufferAsyncGOOGLE":
|
||||
self.module.append(' printer.write_int("seqno: ", 4, indent)\n')
|
||||
|
||||
for param in api.parameters:
|
||||
# Add any structs that this API uses to the list of structs to write decoding logic for
|
||||
if self.typeInfo.isCompoundType(param.typeName):
|
||||
self.structs.add(param.typeName)
|
||||
|
||||
# Don't try to print the pData field of vkQueueFlushCommandsGOOGLE, those are the
|
||||
# commands processed as part of the subdecode pass
|
||||
if api.name == "vkQueueFlushCommandsGOOGLE" and param.paramName == "pData":
|
||||
continue
|
||||
|
||||
# Write out decoding logic for that parameter
|
||||
self.process_type(param)
|
||||
|
||||
# Finally, add a return statement. This is needed in case the API has no parameters.
|
||||
self.module.append(' return\n\n')
|
||||
|
||||
def process_structs(self):
|
||||
"""Writes decoding logic for all the structs that we use"""
|
||||
|
||||
# self.structs now contains all the structs used directly by the Vulkan APIs we use.
|
||||
# Recursively expand this set to add all the structs used by these structs.
|
||||
copy = self.structs.copy()
|
||||
self.structs.clear()
|
||||
for struct_name in copy:
|
||||
self.expand_needed_structs(struct_name)
|
||||
|
||||
# Now we have the full list of structs that we need to write decoding logic for.
|
||||
# Write a decoder for each of them
|
||||
for struct_name in sorted(self.structs):
|
||||
struct = self.typeInfo.structs[struct_name]
|
||||
self.module.append('def struct_{}(printer, indent: int):\n'.format(struct_name))
|
||||
for member in self.get_members(struct):
|
||||
self.process_type(member)
|
||||
self.module.append('\n')
|
||||
|
||||
def expand_needed_structs(self, struct_name: str):
|
||||
"""
|
||||
Recursively adds all the structs used by a given struct to the list of structs to process
|
||||
"""
|
||||
if struct_name in self.structs:
|
||||
return
|
||||
self.structs.add(struct_name)
|
||||
struct = self.typeInfo.structs[struct_name]
|
||||
for member in self.get_members(struct):
|
||||
if self.typeInfo.isCompoundType(member.typeName):
|
||||
self.expand_needed_structs(member.typeName)
|
||||
|
||||
def get_members(self, struct: VulkanCompoundType):
|
||||
"""
|
||||
Returns the members of a struct/union that we need to process.
|
||||
For structs, returns the list of all members
|
||||
For unions, returns a list with just the first member.
|
||||
"""
|
||||
return struct.members[0:1] if struct.isUnion else struct.members
|
||||
|
||||
def process_type(self, type: VulkanType):
|
||||
"""
|
||||
Writes decoding logic for a single Vulkan type. This could be the parameter in a Vulkan API,
|
||||
or a struct member.
|
||||
"""
|
||||
if type.typeName == "VkStructureType":
|
||||
self.module.append(
|
||||
' printer.write_stype_and_pnext("{}", indent)\n'.format(
|
||||
type.parent.structEnumExpr))
|
||||
return
|
||||
|
||||
if type.isNextPointer():
|
||||
return
|
||||
|
||||
if type.paramName == "commandBuffer":
|
||||
if type.parent.name != "vkQueueFlushCommandsGOOGLE":
|
||||
return
|
||||
|
||||
# Enums
|
||||
if type.isEnum(self.typeInfo):
|
||||
self.needed_enums.add(type.typeName)
|
||||
self.module.append(
|
||||
' printer.write_enum("{}", {}, indent)\n'.format(
|
||||
type.paramName, type.typeName))
|
||||
return
|
||||
|
||||
# Bitmasks
|
||||
if type.isBitmask(self.typeInfo):
|
||||
enum_type = self.typeInfo.bitmasks.get(type.typeName)
|
||||
if enum_type:
|
||||
self.needed_enums.add(enum_type)
|
||||
self.module.append(
|
||||
' printer.write_flags("{}", {}, indent)\n'.format(
|
||||
type.paramName, enum_type))
|
||||
return
|
||||
# else, fall through and let the primitive type logic handle it
|
||||
|
||||
# Structs or unions
|
||||
if self.typeInfo.isCompoundType(type.typeName):
|
||||
self.module.append(
|
||||
' printer.write_struct("{name}", struct_{type}, {optional}, {count}, indent)\n'
|
||||
.format(name=type.paramName,
|
||||
type=type.typeName,
|
||||
optional=type.isOptionalPointer(),
|
||||
count=self.get_length_expression(type)))
|
||||
return
|
||||
|
||||
# Null-terminated strings
|
||||
if type.isString():
|
||||
self.module.append(' printer.write_string("{}", None, indent)\n'.format(
|
||||
type.paramName))
|
||||
return
|
||||
|
||||
# Arrays of primitive types
|
||||
if type.staticArrExpr and type.primitiveEncodingSize and type.primitiveEncodingSize <= 8:
|
||||
# Array sizes are specified either as a number, or as an enum value
|
||||
array_size = int(type.staticArrExpr) if type.staticArrExpr.isdigit() \
|
||||
else self.typeInfo.enumValues.get(type.staticArrExpr)
|
||||
assert array_size is not None, type.staticArrExpr
|
||||
|
||||
if type.typeName == "char":
|
||||
self.module.append(
|
||||
' printer.write_string("{}", {}, indent)\n'.format(
|
||||
type.paramName, array_size))
|
||||
elif type.typeName == "float":
|
||||
self.module.append(
|
||||
' printer.write_float("{}", indent, count={})\n'
|
||||
.format(type.paramName, array_size))
|
||||
else:
|
||||
self.module.append(
|
||||
' printer.write_int("{name}", {int_size}, indent, signed={signed}, count={array_size})\n'
|
||||
.format(name=type.paramName,
|
||||
array_size=array_size,
|
||||
int_size=type.primitiveEncodingSize,
|
||||
signed=type.isSigned()))
|
||||
return
|
||||
|
||||
# Pointers
|
||||
if type.pointerIndirectionLevels > 0:
|
||||
# Assume that all uint32* are always serialized directly rather than passed by pointers.
|
||||
# This is probably not always true (e.g. out params) - fix this as needed.
|
||||
size = 4 if type.primitiveEncodingSize == 4 else 8
|
||||
self.module.append(
|
||||
' {name} = printer.write_int("{name}", {size}, indent, optional={opt}, count={count}, big_endian={big_endian})\n'
|
||||
.format(name=type.paramName,
|
||||
size=size,
|
||||
opt=type.isOptionalPointer(),
|
||||
count=self.get_length_expression(type),
|
||||
big_endian=self.using_big_endian(type)))
|
||||
return
|
||||
|
||||
# Primitive types (ints, floats)
|
||||
if type.isSimpleValueType(self.typeInfo) and type.primitiveEncodingSize:
|
||||
if type.typeName == "float":
|
||||
self.module.append(
|
||||
' printer.write_float("{name}", indent)\n'.format(name=type.paramName))
|
||||
else:
|
||||
self.module.append(
|
||||
' {name} = printer.write_int("{name}", {size}, indent, signed={signed}, big_endian={big_endian})\n'.format(
|
||||
name=type.paramName,
|
||||
size=type.primitiveEncodingSize,
|
||||
signed=type.isSigned(),
|
||||
big_endian=self.using_big_endian(type))
|
||||
)
|
||||
return
|
||||
|
||||
raise NotImplementedError(
|
||||
"No decoding logic for {} {}".format(type.typeName, type.paramName))
|
||||
|
||||
def using_big_endian(self, type: VulkanType):
|
||||
"""For some reason gfxstream serializes some types as big endian"""
|
||||
return type.typeName == "size_t"
|
||||
|
||||
def get_length_expression(self, type: VulkanType) -> Optional[str]:
|
||||
"""Returns the length expression for a given type"""
|
||||
if type.lenExpr is None:
|
||||
return None
|
||||
|
||||
if type.lenExpr.isalpha():
|
||||
return type.lenExpr
|
||||
|
||||
# There are a couple of instances in the spec where we use a math expression to express the
|
||||
# length (e.g. VkPipelineMultisampleStateCreateInfo). CodeGen().generalLengthAccess() has
|
||||
# logic o parse these expressions correctly, but for now,we just use a simple lookup table.
|
||||
known_expressions = {
|
||||
r"latexmath:[\lceil{\mathit{rasterizationSamples} \over 32}\rceil]":
|
||||
"int(rasterizationSamples / 32)",
|
||||
r"latexmath:[\textrm{codeSize} \over 4]": "int(codeSize / 4)",
|
||||
r"null-terminated": None
|
||||
}
|
||||
if type.lenExpr in known_expressions:
|
||||
return known_expressions[type.lenExpr]
|
||||
|
||||
raise NotImplementedError("Unknown length expression: " + type.lenExpr)
|
||||
|
||||
def process_enums(self):
|
||||
"""
|
||||
For each Vulkan enum that we use, write out a python dictionary mapping the enum values back
|
||||
to the enum name as a string
|
||||
"""
|
||||
for enum_name in sorted(self.needed_enums):
|
||||
self.module.append('{} = {{\n'.format(enum_name))
|
||||
for identifier in self.all_enums[enum_name]:
|
||||
value = self.typeInfo.enumValues.get(identifier)
|
||||
if value is not None and isinstance(value, int):
|
||||
self.module.append(' {}: "{}",\n'.format(value, identifier))
|
||||
self.module.append('}\n\n')
|
||||
2
src/gfxstream/codegen/scripts/cereal/common/__init__.py
Normal file
2
src/gfxstream/codegen/scripts/cereal/common/__init__.py
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
from .vulkantypes import *
|
||||
from .codegen import *
|
||||
1074
src/gfxstream/codegen/scripts/cereal/common/codegen.py
Normal file
1074
src/gfxstream/codegen/scripts/cereal/common/codegen.py
Normal file
File diff suppressed because it is too large
Load diff
1324
src/gfxstream/codegen/scripts/cereal/common/vulkantypes.py
Normal file
1324
src/gfxstream/codegen/scripts/cereal/common/vulkantypes.py
Normal file
File diff suppressed because it is too large
Load diff
696
src/gfxstream/codegen/scripts/cereal/counting.py
Normal file
696
src/gfxstream/codegen/scripts/cereal/counting.py
Normal file
|
|
@ -0,0 +1,696 @@
|
|||
# Copyright (c) 2018 The Android Open Source Project
|
||||
# Copyright (c) 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from copy import copy
|
||||
|
||||
from .common.codegen import CodeGen
|
||||
from .common.vulkantypes import \
|
||||
VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator, Atom, FuncExpr, FuncExprVal, FuncLambda
|
||||
|
||||
from .wrapperdefs import VulkanWrapperGenerator
|
||||
from .wrapperdefs import ROOT_TYPE_VAR_NAME, ROOT_TYPE_PARAM
|
||||
from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME
|
||||
|
||||
class VulkanCountingCodegen(VulkanTypeIterator):
|
||||
def __init__(self, cgen, featureBitsVar, toCountVar, countVar, rootTypeVar, prefix, forApiOutput=False, mapHandles=True, handleMapOverwrites=False, doFiltering=True):
|
||||
self.cgen = cgen
|
||||
self.featureBitsVar = featureBitsVar
|
||||
self.toCountVar = toCountVar
|
||||
self.rootTypeVar = rootTypeVar
|
||||
self.countVar = countVar
|
||||
self.prefix = prefix
|
||||
self.forApiOutput = forApiOutput
|
||||
|
||||
self.exprAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.toCountVar, asPtr = True)
|
||||
self.exprValueAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.toCountVar, asPtr = False)
|
||||
self.exprPrimitiveValueAccessor = lambda t: self.cgen.generalAccess(t, parentVarName = self.toCountVar, asPtr = False)
|
||||
|
||||
self.lenAccessor = lambda t: self.cgen.generalLengthAccess(t, parentVarName = self.toCountVar)
|
||||
self.lenAccessorGuard = lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName = self.toCountVar)
|
||||
self.filterVarAccessor = lambda t: self.cgen.filterVarAccess(t, parentVarName = self.toCountVar)
|
||||
|
||||
self.checked = False
|
||||
|
||||
self.mapHandles = mapHandles
|
||||
self.handleMapOverwrites = handleMapOverwrites
|
||||
self.doFiltering = doFiltering
|
||||
|
||||
def getTypeForStreaming(self, vulkanType):
|
||||
res = copy(vulkanType)
|
||||
|
||||
if not vulkanType.accessibleAsPointer():
|
||||
res = res.getForAddressAccess()
|
||||
|
||||
if vulkanType.staticArrExpr:
|
||||
res = res.getForAddressAccess()
|
||||
|
||||
return res
|
||||
|
||||
def makeCastExpr(self, vulkanType):
|
||||
return "(%s)" % (
|
||||
self.cgen.makeCTypeDecl(vulkanType, useParamName=False))
|
||||
|
||||
def genCount(self, sizeExpr):
|
||||
self.cgen.stmt("*%s += %s" % (self.countVar, sizeExpr))
|
||||
|
||||
def genPrimitiveStreamCall(self, vulkanType):
|
||||
self.genCount(str(self.cgen.countPrimitive(
|
||||
self.typeInfo,
|
||||
vulkanType)))
|
||||
|
||||
def genHandleMappingCall(self, vulkanType, access, lenAccess):
|
||||
|
||||
if lenAccess is None:
|
||||
lenAccess = "1"
|
||||
handle64Bytes = "8"
|
||||
else:
|
||||
handle64Bytes = "%s * 8" % lenAccess
|
||||
|
||||
handle64Var = self.cgen.var()
|
||||
if lenAccess != "1":
|
||||
self.cgen.beginIf(lenAccess)
|
||||
# self.cgen.stmt("uint64_t* %s" % handle64Var)
|
||||
# self.cgen.stmt(
|
||||
# "%s->alloc((void**)&%s, %s * 8)" % \
|
||||
# (self.streamVarName, handle64Var, lenAccess))
|
||||
handle64VarAccess = handle64Var
|
||||
handle64VarType = \
|
||||
makeVulkanTypeSimple(False, "uint64_t", 1, paramName=handle64Var)
|
||||
else:
|
||||
self.cgen.stmt("uint64_t %s" % handle64Var)
|
||||
handle64VarAccess = "&%s" % handle64Var
|
||||
handle64VarType = \
|
||||
makeVulkanTypeSimple(False, "uint64_t", 0, paramName=handle64Var)
|
||||
|
||||
if self.handleMapOverwrites:
|
||||
# self.cgen.stmt(
|
||||
# "static_assert(8 == sizeof(%s), \"handle map overwrite requres %s to be 8 bytes long\")" % \
|
||||
# (vulkanType.typeName, vulkanType.typeName))
|
||||
# self.cgen.stmt(
|
||||
# "%s->handleMapping()->mapHandles_%s((%s*)%s, %s)" %
|
||||
# (self.streamVarName, vulkanType.typeName, vulkanType.typeName,
|
||||
# access, lenAccess))
|
||||
self.genCount("8 * %s" % lenAccess)
|
||||
else:
|
||||
# self.cgen.stmt(
|
||||
# "%s->handleMapping()->mapHandles_%s_u64(%s, %s, %s)" %
|
||||
# (self.streamVarName, vulkanType.typeName,
|
||||
# access,
|
||||
# handle64VarAccess, lenAccess))
|
||||
self.genCount(handle64Bytes)
|
||||
|
||||
if lenAccess != "1":
|
||||
self.cgen.endIf()
|
||||
|
||||
def doAllocSpace(self, vulkanType):
|
||||
pass
|
||||
|
||||
def getOptionalStringFeatureExpr(self, vulkanType):
|
||||
feature = vulkanType.getProtectStreamFeature()
|
||||
if feature is None:
|
||||
return None
|
||||
return "%s & %s" % (self.featureBitsVar, feature)
|
||||
|
||||
def onCheck(self, vulkanType):
|
||||
|
||||
if self.forApiOutput:
|
||||
return
|
||||
|
||||
featureExpr = self.getOptionalStringFeatureExpr(vulkanType);
|
||||
|
||||
self.checked = True
|
||||
|
||||
access = self.exprAccessor(vulkanType)
|
||||
|
||||
needConsistencyCheck = False
|
||||
|
||||
self.cgen.line("// WARNING PTR CHECK")
|
||||
checkAccess = self.exprAccessor(vulkanType)
|
||||
addrExpr = "&" + checkAccess
|
||||
sizeExpr = self.cgen.sizeofExpr(vulkanType)
|
||||
|
||||
if featureExpr is not None:
|
||||
self.cgen.beginIf(featureExpr)
|
||||
|
||||
self.genPrimitiveStreamCall(
|
||||
vulkanType)
|
||||
|
||||
if featureExpr is not None:
|
||||
self.cgen.endIf()
|
||||
|
||||
if featureExpr is not None:
|
||||
self.cgen.beginIf("(!(%s) || %s)" % (featureExpr, access))
|
||||
else:
|
||||
self.cgen.beginIf(access)
|
||||
|
||||
if needConsistencyCheck and featureExpr is None:
|
||||
self.cgen.beginIf("!(%s)" % checkName)
|
||||
self.cgen.stmt(
|
||||
"fprintf(stderr, \"fatal: %s inconsistent between guest and host\\n\")" % (access))
|
||||
self.cgen.endIf()
|
||||
|
||||
|
||||
def onCheckWithNullOptionalStringFeature(self, vulkanType):
|
||||
self.cgen.beginIf("%s & VULKAN_STREAM_FEATURE_NULL_OPTIONAL_STRINGS_BIT" % self.featureBitsVar)
|
||||
self.onCheck(vulkanType)
|
||||
|
||||
def endCheckWithNullOptionalStringFeature(self, vulkanType):
|
||||
self.endCheck(vulkanType)
|
||||
self.cgen.endIf()
|
||||
self.cgen.beginElse()
|
||||
|
||||
def finalCheckWithNullOptionalStringFeature(self, vulkanType):
|
||||
self.cgen.endElse()
|
||||
|
||||
def endCheck(self, vulkanType):
|
||||
|
||||
if self.checked:
|
||||
self.cgen.endIf()
|
||||
self.checked = False
|
||||
|
||||
def genFilterFunc(self, filterfunc, env):
|
||||
|
||||
def loop(expr, lambdaEnv={}):
|
||||
def do_func(expr):
|
||||
fnamestr = expr.name.name
|
||||
if "not" == fnamestr:
|
||||
return "!(%s)" % (loop(expr.args[0], lambdaEnv))
|
||||
if "eq" == fnamestr:
|
||||
return "(%s == %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
|
||||
if "and" == fnamestr:
|
||||
return "(%s && %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
|
||||
if "or" == fnamestr:
|
||||
return "(%s || %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
|
||||
if "bitwise_and" == fnamestr:
|
||||
return "(%s & %s)" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv))
|
||||
if "getfield" == fnamestr:
|
||||
ptrlevels = get_ptrlevels(expr.args[0].val.name)
|
||||
if ptrlevels == 0:
|
||||
return "%s.%s" % (loop(expr.args[0], lambdaEnv), expr.args[1].val)
|
||||
else:
|
||||
return "(%s(%s)).%s" % ("*" * ptrlevels, loop(expr.args[0], lambdaEnv), expr.args[1].val)
|
||||
|
||||
if "if" == fnamestr:
|
||||
return "((%s) ? (%s) : (%s))" % (loop(expr.args[0], lambdaEnv), loop(expr.args[1], lambdaEnv), loop(expr.args[2], lambdaEnv))
|
||||
|
||||
return "%s(%s)" % (fnamestr, ", ".join(map(lambda e: loop(e, lambdaEnv), expr.args)))
|
||||
|
||||
def do_expratom(atomname, lambdaEnv= {}):
|
||||
if lambdaEnv.get(atomname, None) is not None:
|
||||
return atomname
|
||||
|
||||
enventry = env.get(atomname, None)
|
||||
if None != enventry:
|
||||
return self.getEnvAccessExpr(atomname)
|
||||
return atomname
|
||||
|
||||
def get_ptrlevels(atomname, lambdaEnv= {}):
|
||||
if lambdaEnv.get(atomname, None) is not None:
|
||||
return 0
|
||||
|
||||
enventry = env.get(atomname, None)
|
||||
if None != enventry:
|
||||
return self.getPointerIndirectionLevels(atomname)
|
||||
|
||||
return 0
|
||||
|
||||
def do_exprval(expr, lambdaEnv= {}):
|
||||
expratom = expr.val
|
||||
|
||||
if Atom == type(expratom):
|
||||
return do_expratom(expratom.name, lambdaEnv)
|
||||
|
||||
return "%s" % expratom
|
||||
|
||||
def do_lambda(expr, lambdaEnv= {}):
|
||||
params = expr.vs
|
||||
body = expr.body
|
||||
newEnv = {}
|
||||
|
||||
for (k, v) in lambdaEnv.items():
|
||||
newEnv[k] = v
|
||||
|
||||
for p in params:
|
||||
newEnv[p.name] = p.typ
|
||||
|
||||
return "[](%s) { return %s; }" % (", ".join(list(map(lambda p: "%s %s" % (p.typ, p.name), params))), loop(body, lambdaEnv=newEnv))
|
||||
|
||||
if FuncExpr == type(expr):
|
||||
return do_func(expr)
|
||||
if FuncLambda == type(expr):
|
||||
return do_lambda(expr)
|
||||
elif FuncExprVal == type(expr):
|
||||
return do_exprval(expr)
|
||||
|
||||
return loop(filterfunc)
|
||||
|
||||
def beginFilterGuard(self, vulkanType):
|
||||
if vulkanType.filterVar == None:
|
||||
return
|
||||
|
||||
if self.doFiltering == False:
|
||||
return
|
||||
|
||||
filterVarAccess = self.getEnvAccessExpr(vulkanType.filterVar)
|
||||
|
||||
filterValsExpr = None
|
||||
filterFuncExpr = None
|
||||
filterExpr = None
|
||||
|
||||
filterFeature = "%s & VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT" % self.featureBitsVar
|
||||
|
||||
if None != vulkanType.filterVals:
|
||||
filterValsExpr = " || ".join(map(lambda filterval: "(%s == %s)" % (filterval, filterVarAccess), vulkanType.filterVals))
|
||||
|
||||
if None != vulkanType.filterFunc:
|
||||
filterFuncExpr = self.genFilterFunc(vulkanType.filterFunc, self.currentStructInfo.environment)
|
||||
|
||||
if None != filterValsExpr and None != filterFuncExpr:
|
||||
filterExpr = "%s || %s" % (filterValsExpr, filterFuncExpr)
|
||||
elif None == filterValsExpr and None == filterFuncExpr:
|
||||
# Assume is bool
|
||||
self.cgen.beginIf(filterVarAccess)
|
||||
elif None != filterValsExpr:
|
||||
self.cgen.beginIf("(!(%s) || (%s))" % (filterFeature, filterValsExpr))
|
||||
elif None != filterFuncExpr:
|
||||
self.cgen.beginIf("(!(%s) || (%s))" % (filterFeature, filterFuncExpr))
|
||||
|
||||
def endFilterGuard(self, vulkanType, cleanupExpr=None):
|
||||
if vulkanType.filterVar == None:
|
||||
return
|
||||
|
||||
if self.doFiltering == False:
|
||||
return
|
||||
|
||||
if cleanupExpr == None:
|
||||
self.cgen.endIf()
|
||||
else:
|
||||
self.cgen.endIf()
|
||||
self.cgen.beginElse()
|
||||
self.cgen.stmt(cleanupExpr)
|
||||
self.cgen.endElse()
|
||||
|
||||
def getEnvAccessExpr(self, varName):
|
||||
parentEnvEntry = self.currentStructInfo.environment.get(varName, None)
|
||||
|
||||
if parentEnvEntry != None:
|
||||
isParentMember = parentEnvEntry["structmember"]
|
||||
|
||||
if isParentMember:
|
||||
envAccess = self.exprValueAccessor(list(filter(lambda member: member.paramName == varName, self.currentStructInfo.members))[0])
|
||||
else:
|
||||
envAccess = varName
|
||||
return envAccess
|
||||
|
||||
return None
|
||||
|
||||
def getPointerIndirectionLevels(self, varName):
|
||||
parentEnvEntry = self.currentStructInfo.environment.get(varName, None)
|
||||
|
||||
if parentEnvEntry != None:
|
||||
isParentMember = parentEnvEntry["structmember"]
|
||||
|
||||
if isParentMember:
|
||||
return list(filter(lambda member: member.paramName == varName, self.currentStructInfo.members))[0].pointerIndirectionLevels
|
||||
else:
|
||||
return 0
|
||||
return 0
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def onCompoundType(self, vulkanType):
|
||||
|
||||
access = self.exprAccessor(vulkanType)
|
||||
lenAccess = self.lenAccessor(vulkanType)
|
||||
lenAccessGuard = self.lenAccessorGuard(vulkanType)
|
||||
|
||||
self.beginFilterGuard(vulkanType)
|
||||
|
||||
if vulkanType.pointerIndirectionLevels > 0:
|
||||
self.doAllocSpace(vulkanType)
|
||||
|
||||
if lenAccess is not None:
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.beginIf(lenAccessGuard)
|
||||
loopVar = "i"
|
||||
access = "%s + %s" % (access, loopVar)
|
||||
forInit = "uint32_t %s = 0" % loopVar
|
||||
forCond = "%s < (uint32_t)%s" % (loopVar, lenAccess)
|
||||
forIncr = "++%s" % loopVar
|
||||
self.cgen.beginFor(forInit, forCond, forIncr)
|
||||
|
||||
accessWithCast = "%s(%s)" % (self.makeCastExpr(
|
||||
self.getTypeForStreaming(vulkanType)), access)
|
||||
|
||||
callParams = [self.featureBitsVar,
|
||||
self.rootTypeVar, accessWithCast, self.countVar]
|
||||
|
||||
for (bindName, localName) in vulkanType.binds.items():
|
||||
callParams.append(self.getEnvAccessExpr(localName))
|
||||
|
||||
self.cgen.funcCall(None, self.prefix + vulkanType.typeName,
|
||||
callParams)
|
||||
|
||||
if lenAccess is not None:
|
||||
self.cgen.endFor()
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.endIf()
|
||||
|
||||
self.endFilterGuard(vulkanType)
|
||||
|
||||
def onString(self, vulkanType):
|
||||
access = self.exprAccessor(vulkanType)
|
||||
self.genCount("sizeof(uint32_t) + (%s ? strlen(%s) : 0)" % (access, access))
|
||||
|
||||
def onStringArray(self, vulkanType):
|
||||
access = self.exprAccessor(vulkanType)
|
||||
lenAccess = self.lenAccessor(vulkanType)
|
||||
lenAccessGuard = self.lenAccessorGuard(vulkanType)
|
||||
|
||||
self.genCount("sizeof(uint32_t)")
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.beginIf(lenAccessGuard)
|
||||
self.cgen.beginFor("uint32_t i = 0", "i < %s" % lenAccess, "++i")
|
||||
self.cgen.stmt("size_t l = %s[i] ? strlen(%s[i]) : 0" % (access, access))
|
||||
self.genCount("sizeof(uint32_t) + (%s[i] ? strlen(%s[i]) : 0)" % (access, access))
|
||||
self.cgen.endFor()
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.endIf()
|
||||
|
||||
def onStaticArr(self, vulkanType):
|
||||
access = self.exprValueAccessor(vulkanType)
|
||||
lenAccess = self.lenAccessor(vulkanType)
|
||||
lenAccessGuard = self.lenAccessorGuard(vulkanType)
|
||||
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.beginIf(lenAccessGuard)
|
||||
finalLenExpr = "%s * %s" % (lenAccess, self.cgen.sizeofExpr(vulkanType))
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.endIf()
|
||||
self.genCount(finalLenExpr)
|
||||
|
||||
def onStructExtension(self, vulkanType):
|
||||
sTypeParam = copy(vulkanType)
|
||||
sTypeParam.paramName = "sType"
|
||||
|
||||
access = self.exprAccessor(vulkanType)
|
||||
sizeVar = "%s_size" % vulkanType.paramName
|
||||
|
||||
castedAccessExpr = access
|
||||
|
||||
sTypeAccess = self.exprAccessor(sTypeParam)
|
||||
self.cgen.beginIf("%s == VK_STRUCTURE_TYPE_MAX_ENUM" %
|
||||
self.rootTypeVar)
|
||||
self.cgen.stmt("%s = %s" % (self.rootTypeVar, sTypeAccess))
|
||||
self.cgen.endIf()
|
||||
|
||||
self.cgen.funcCall(None, self.prefix + "extension_struct",
|
||||
[self.featureBitsVar, self.rootTypeVar, castedAccessExpr, self.countVar])
|
||||
|
||||
|
||||
def onPointer(self, vulkanType):
|
||||
access = self.exprAccessor(vulkanType)
|
||||
|
||||
lenAccess = self.lenAccessor(vulkanType)
|
||||
lenAccessGuard = self.lenAccessorGuard(vulkanType)
|
||||
|
||||
self.beginFilterGuard(vulkanType)
|
||||
self.doAllocSpace(vulkanType)
|
||||
|
||||
if vulkanType.filterVar != None:
|
||||
print("onPointer Needs filter: %s filterVar %s" % (access, vulkanType.filterVar))
|
||||
|
||||
if vulkanType.isHandleType() and self.mapHandles:
|
||||
self.genHandleMappingCall(vulkanType, access, lenAccess)
|
||||
else:
|
||||
if self.typeInfo.isNonAbiPortableType(vulkanType.typeName):
|
||||
if lenAccess is not None:
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.beginIf(lenAccessGuard)
|
||||
self.cgen.beginFor("uint32_t i = 0", "i < (uint32_t)%s" % lenAccess, "++i")
|
||||
self.genPrimitiveStreamCall(vulkanType.getForValueAccess())
|
||||
self.cgen.endFor()
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.endIf()
|
||||
else:
|
||||
self.genPrimitiveStreamCall(vulkanType.getForValueAccess())
|
||||
else:
|
||||
if lenAccess is not None:
|
||||
needLenAccessGuard = True
|
||||
finalLenExpr = "%s * %s" % (
|
||||
lenAccess, self.cgen.sizeofExpr(vulkanType.getForValueAccess()))
|
||||
else:
|
||||
needLenAccessGuard = False
|
||||
finalLenExpr = "%s" % (
|
||||
self.cgen.sizeofExpr(vulkanType.getForValueAccess()))
|
||||
if needLenAccessGuard and lenAccessGuard is not None:
|
||||
self.cgen.beginIf(lenAccessGuard)
|
||||
self.genCount(finalLenExpr)
|
||||
if needLenAccessGuard and lenAccessGuard is not None:
|
||||
self.cgen.endIf()
|
||||
|
||||
self.endFilterGuard(vulkanType)
|
||||
|
||||
def onValue(self, vulkanType):
|
||||
self.beginFilterGuard(vulkanType)
|
||||
|
||||
if vulkanType.isHandleType() and self.mapHandles:
|
||||
access = self.exprAccessor(vulkanType)
|
||||
if vulkanType.filterVar != None:
|
||||
print("onValue Needs filter: %s filterVar %s" % (access, vulkanType.filterVar))
|
||||
self.genHandleMappingCall(
|
||||
vulkanType.getForAddressAccess(), access, "1")
|
||||
elif self.typeInfo.isNonAbiPortableType(vulkanType.typeName):
|
||||
access = self.exprPrimitiveValueAccessor(vulkanType)
|
||||
self.genPrimitiveStreamCall(vulkanType)
|
||||
else:
|
||||
access = self.exprAccessor(vulkanType)
|
||||
self.genCount(self.cgen.sizeofExpr(vulkanType))
|
||||
|
||||
self.endFilterGuard(vulkanType)
|
||||
|
||||
def streamLetParameter(self, structInfo, letParamInfo):
|
||||
filterFeature = "%s & VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT" % (self.featureBitsVar)
|
||||
self.cgen.stmt("%s %s = 1" % (letParamInfo.typeName, letParamInfo.paramName))
|
||||
|
||||
self.cgen.beginIf(filterFeature)
|
||||
|
||||
bodyExpr = self.currentStructInfo.environment[letParamInfo.paramName]["body"]
|
||||
self.cgen.stmt("%s = %s" % (letParamInfo.paramName, self.genFilterFunc(bodyExpr, self.currentStructInfo.environment)))
|
||||
|
||||
self.genPrimitiveStreamCall(letParamInfo)
|
||||
|
||||
self.cgen.endIf()
|
||||
|
||||
class VulkanCounting(VulkanWrapperGenerator):
|
||||
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
|
||||
self.codegen = CodeGen()
|
||||
|
||||
self.featureBitsVar = "featureBits"
|
||||
self.featureBitsVarType = makeVulkanTypeSimple(False, "uint32_t", 0, self.featureBitsVar)
|
||||
self.countingPrefix = "count_"
|
||||
self.countVars = ["toCount", "count"]
|
||||
self.countVarType = makeVulkanTypeSimple(False, "size_t", 1, self.countVars[1])
|
||||
self.voidType = makeVulkanTypeSimple(False, "void", 0)
|
||||
self.rootTypeVar = ROOT_TYPE_VAR_NAME
|
||||
|
||||
self.countingCodegen = \
|
||||
VulkanCountingCodegen(
|
||||
self.codegen,
|
||||
self.featureBitsVar,
|
||||
self.countVars[0],
|
||||
self.countVars[1],
|
||||
self.rootTypeVar,
|
||||
self.countingPrefix)
|
||||
|
||||
self.knownDefs = {}
|
||||
|
||||
self.extensionCountingPrototype = \
|
||||
VulkanAPI(self.countingPrefix + "extension_struct",
|
||||
self.voidType,
|
||||
[self.featureBitsVarType,
|
||||
ROOT_TYPE_PARAM,
|
||||
STRUCT_EXTENSION_PARAM,
|
||||
self.countVarType])
|
||||
|
||||
def onBegin(self,):
|
||||
VulkanWrapperGenerator.onBegin(self)
|
||||
self.module.appendImpl(self.codegen.makeFuncDecl(
|
||||
self.extensionCountingPrototype))
|
||||
|
||||
def onGenType(self, typeXml, name, alias):
|
||||
VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
|
||||
|
||||
if name in self.knownDefs:
|
||||
return
|
||||
|
||||
category = self.typeInfo.categoryOf(name)
|
||||
|
||||
if category in ["struct", "union"] and alias:
|
||||
# TODO(liyl): might not work if freeParams != []
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncAlias(self.countingPrefix + name,
|
||||
self.countingPrefix + alias))
|
||||
|
||||
if category in ["struct", "union"] and not alias:
|
||||
|
||||
structInfo = self.typeInfo.structs[name]
|
||||
|
||||
freeParams = []
|
||||
letParams = []
|
||||
|
||||
for (envname, bindingInfo) in list(sorted(structInfo.environment.items(), key = lambda kv: kv[0])):
|
||||
if None == bindingInfo["binding"]:
|
||||
freeParams.append(makeVulkanTypeSimple(True, bindingInfo["type"], 0, envname))
|
||||
else:
|
||||
if not bindingInfo["structmember"]:
|
||||
letParams.append(makeVulkanTypeSimple(True, bindingInfo["type"], 0, envname))
|
||||
|
||||
typeFromName = \
|
||||
lambda varname: \
|
||||
makeVulkanTypeSimple(True, name, 1, varname)
|
||||
|
||||
countingParams = \
|
||||
[makeVulkanTypeSimple(False, "uint32_t", 0, self.featureBitsVar),
|
||||
ROOT_TYPE_PARAM,
|
||||
typeFromName(self.countVars[0]),
|
||||
makeVulkanTypeSimple(False, "size_t", 1, self.countVars[1])]
|
||||
|
||||
countingPrototype = \
|
||||
VulkanAPI(self.countingPrefix + name,
|
||||
self.voidType,
|
||||
countingParams + freeParams)
|
||||
|
||||
countingPrototypeNoFilter = \
|
||||
VulkanAPI(self.countingPrefix + name,
|
||||
self.voidType,
|
||||
countingParams)
|
||||
|
||||
def structCountingDef(cgen):
|
||||
self.countingCodegen.cgen = cgen
|
||||
self.countingCodegen.currentStructInfo = structInfo
|
||||
cgen.stmt("(void)%s" % self.featureBitsVar);
|
||||
cgen.stmt("(void)%s" % self.rootTypeVar);
|
||||
cgen.stmt("(void)%s" % self.countVars[0]);
|
||||
cgen.stmt("(void)%s" % self.countVars[1]);
|
||||
|
||||
if category == "struct":
|
||||
# marshal 'let' parameters first
|
||||
for letp in letParams:
|
||||
self.countingCodegen.streamLetParameter(self.typeInfo, letp)
|
||||
|
||||
for member in structInfo.members:
|
||||
iterateVulkanType(self.typeInfo, member, self.countingCodegen)
|
||||
if category == "union":
|
||||
iterateVulkanType(self.typeInfo, structInfo.members[0], self.countingCodegen)
|
||||
|
||||
def structCountingDefNoFilter(cgen):
|
||||
self.countingCodegen.cgen = cgen
|
||||
self.countingCodegen.currentStructInfo = structInfo
|
||||
self.countingCodegen.doFiltering = False
|
||||
cgen.stmt("(void)%s" % self.featureBitsVar);
|
||||
cgen.stmt("(void)%s" % self.rootTypeVar);
|
||||
cgen.stmt("(void)%s" % self.countVars[0]);
|
||||
cgen.stmt("(void)%s" % self.countVars[1]);
|
||||
|
||||
if category == "struct":
|
||||
# marshal 'let' parameters first
|
||||
for letp in letParams:
|
||||
self.countingCodegen.streamLetParameter(self.typeInfo, letp)
|
||||
|
||||
for member in structInfo.members:
|
||||
iterateVulkanType(self.typeInfo, member, self.countingCodegen)
|
||||
if category == "union":
|
||||
iterateVulkanType(self.typeInfo, structInfo.members[0], self.countingCodegen)
|
||||
|
||||
self.countingCodegen.doFiltering = True
|
||||
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncDecl(countingPrototype))
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(countingPrototype, structCountingDef))
|
||||
|
||||
if freeParams != []:
|
||||
self.module.appendHeader(
|
||||
self.cgenHeader.makeFuncDecl(countingPrototypeNoFilter))
|
||||
self.module.appendImpl(
|
||||
self.cgenImpl.makeFuncImpl(
|
||||
countingPrototypeNoFilter, structCountingDefNoFilter))
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
|
||||
|
||||
def doExtensionStructCountCodegen(self, cgen, extParam, forEach, funcproto):
|
||||
accessVar = "structAccess"
|
||||
sizeVar = "currExtSize"
|
||||
cgen.stmt("VkInstanceCreateInfo* %s = (VkInstanceCreateInfo*)(%s)" % (accessVar, extParam.paramName))
|
||||
cgen.stmt("size_t %s = %s(%s, %s, %s)" % (sizeVar, EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME,
|
||||
self.featureBitsVar, ROOT_TYPE_VAR_NAME, extParam.paramName))
|
||||
|
||||
cgen.beginIf("!%s && %s" % (sizeVar, extParam.paramName))
|
||||
|
||||
cgen.line("// unknown struct extension; skip and call on its pNext field");
|
||||
cgen.funcCall(None, funcproto.name, [
|
||||
self.featureBitsVar, ROOT_TYPE_VAR_NAME, "(void*)%s->pNext" % accessVar, self.countVars[1]])
|
||||
cgen.stmt("return")
|
||||
|
||||
cgen.endIf()
|
||||
cgen.beginElse()
|
||||
|
||||
cgen.line("// known or null extension struct")
|
||||
|
||||
cgen.stmt("*%s += sizeof(uint32_t)" % self.countVars[1])
|
||||
|
||||
cgen.beginIf("!%s" % (sizeVar))
|
||||
cgen.line("// exit if this was a null extension struct (size == 0 in this branch)")
|
||||
cgen.stmt("return")
|
||||
cgen.endIf()
|
||||
|
||||
cgen.endIf()
|
||||
|
||||
cgen.stmt("*%s += sizeof(VkStructureType)" % self.countVars[1])
|
||||
|
||||
def fatalDefault(cgen):
|
||||
cgen.line("// fatal; the switch is only taken if the extension struct is known");
|
||||
cgen.stmt("abort()")
|
||||
pass
|
||||
|
||||
self.emitForEachStructExtension(
|
||||
cgen,
|
||||
makeVulkanTypeSimple(False, "void", 0, "void"),
|
||||
extParam,
|
||||
forEach,
|
||||
defaultEmit=fatalDefault,
|
||||
rootTypeVar=ROOT_TYPE_PARAM)
|
||||
|
||||
def onEnd(self,):
|
||||
VulkanWrapperGenerator.onEnd(self)
|
||||
|
||||
def forEachExtensionCounting(ext, castedAccess, cgen):
|
||||
cgen.funcCall(None, self.countingPrefix + ext.name,
|
||||
[self.featureBitsVar, self.rootTypeVar, castedAccess, self.countVars[1]])
|
||||
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(
|
||||
self.extensionCountingPrototype,
|
||||
lambda cgen: self.doExtensionStructCountCodegen(
|
||||
cgen,
|
||||
STRUCT_EXTENSION_PARAM,
|
||||
forEachExtensionCounting,
|
||||
self.extensionCountingPrototype)))
|
||||
946
src/gfxstream/codegen/scripts/cereal/decoder.py
Normal file
946
src/gfxstream/codegen/scripts/cereal/decoder.py
Normal file
|
|
@ -0,0 +1,946 @@
|
|||
from .common.codegen import CodeGen, VulkanWrapperGenerator
|
||||
from .common.vulkantypes import VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeInfo,\
|
||||
VulkanType
|
||||
|
||||
from .marshaling import VulkanMarshalingCodegen
|
||||
from .reservedmarshaling import VulkanReservedMarshalingCodegen
|
||||
from .transform import TransformCodegen
|
||||
|
||||
from .wrapperdefs import API_PREFIX_MARSHAL
|
||||
from .wrapperdefs import API_PREFIX_RESERVEDUNMARSHAL
|
||||
from .wrapperdefs import MAX_PACKET_LENGTH
|
||||
from .wrapperdefs import VULKAN_STREAM_TYPE
|
||||
from .wrapperdefs import ROOT_TYPE_DEFAULT_VALUE
|
||||
from .wrapperdefs import RELAXED_APIS
|
||||
|
||||
|
||||
SKIPPED_DECODER_DELETES = [
|
||||
"vkFreeDescriptorSets",
|
||||
]
|
||||
|
||||
DELAYED_DECODER_DELETES = [
|
||||
"vkDestroyPipelineLayout",
|
||||
]
|
||||
|
||||
global_state_prefix = "m_state->on_"
|
||||
|
||||
decoder_decl_preamble = """
|
||||
|
||||
namespace gfxstream {
|
||||
class IOStream;
|
||||
class ProcessResources;
|
||||
} // namespace gfxstream
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
class VkDecoder {
|
||||
public:
|
||||
VkDecoder();
|
||||
~VkDecoder();
|
||||
void setForSnapshotLoad(bool forSnapshotLoad);
|
||||
size_t decode(void* buf, size_t bufsize, IOStream* stream,
|
||||
const ProcessResources* processResources, const VkDecoderContext&);
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> mImpl;
|
||||
};
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
|
||||
"""
|
||||
|
||||
decoder_impl_preamble ="""
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
using android::base::MetricEventBadPacketLength;
|
||||
using android::base::MetricEventDuplicateSequenceNum;
|
||||
|
||||
class VkDecoder::Impl {
|
||||
public:
|
||||
Impl() : m_logCalls(android::base::getEnvironmentVariable("ANDROID_EMU_VK_LOG_CALLS") == "1"),
|
||||
m_vk(vkDispatch()),
|
||||
m_state(VkDecoderGlobalState::get()),
|
||||
m_boxedHandleUnwrapMapping(m_state),
|
||||
m_boxedHandleCreateMapping(m_state),
|
||||
m_boxedHandleDestroyMapping(m_state),
|
||||
m_boxedHandleUnwrapAndDeleteMapping(m_state),
|
||||
m_boxedHandleUnwrapAndDeletePreserveBoxedMapping(m_state),
|
||||
m_prevSeqno(std::nullopt) {}
|
||||
%s* stream() { return &m_vkStream; }
|
||||
VulkanMemReadingStream* readStream() { return &m_vkMemReadingStream; }
|
||||
|
||||
void setForSnapshotLoad(bool forSnapshotLoad) {
|
||||
m_forSnapshotLoad = forSnapshotLoad;
|
||||
}
|
||||
|
||||
size_t decode(void* buf, size_t bufsize, IOStream* stream,
|
||||
const ProcessResources* processResources, const VkDecoderContext&);
|
||||
|
||||
private:
|
||||
bool m_logCalls;
|
||||
bool m_forSnapshotLoad = false;
|
||||
VulkanDispatch* m_vk;
|
||||
VkDecoderGlobalState* m_state;
|
||||
%s m_vkStream { nullptr };
|
||||
VulkanMemReadingStream m_vkMemReadingStream { nullptr };
|
||||
BoxedHandleUnwrapMapping m_boxedHandleUnwrapMapping;
|
||||
BoxedHandleCreateMapping m_boxedHandleCreateMapping;
|
||||
BoxedHandleDestroyMapping m_boxedHandleDestroyMapping;
|
||||
BoxedHandleUnwrapAndDeleteMapping m_boxedHandleUnwrapAndDeleteMapping;
|
||||
android::base::BumpPool m_pool;
|
||||
BoxedHandleUnwrapAndDeletePreserveBoxedMapping m_boxedHandleUnwrapAndDeletePreserveBoxedMapping;
|
||||
std::optional<uint32_t> m_prevSeqno;
|
||||
};
|
||||
|
||||
VkDecoder::VkDecoder() :
|
||||
mImpl(new VkDecoder::Impl()) { }
|
||||
|
||||
VkDecoder::~VkDecoder() = default;
|
||||
|
||||
void VkDecoder::setForSnapshotLoad(bool forSnapshotLoad) {
|
||||
mImpl->setForSnapshotLoad(forSnapshotLoad);
|
||||
}
|
||||
|
||||
size_t VkDecoder::decode(void* buf, size_t bufsize, IOStream* stream,
|
||||
const ProcessResources* processResources,
|
||||
const VkDecoderContext& context) {
|
||||
return mImpl->decode(buf, bufsize, stream, processResources, context);
|
||||
}
|
||||
|
||||
// VkDecoder::Impl::decode to follow
|
||||
""" % (VULKAN_STREAM_TYPE, VULKAN_STREAM_TYPE)
|
||||
|
||||
decoder_impl_postamble = """
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
|
||||
"""
|
||||
|
||||
READ_STREAM = "vkReadStream"
|
||||
WRITE_STREAM = "vkStream"
|
||||
|
||||
# Driver workarounds for APIs that don't work well multithreaded
|
||||
driver_workarounds_global_lock_apis = [ \
|
||||
"vkCreatePipelineLayout",
|
||||
"vkDestroyPipelineLayout",
|
||||
]
|
||||
|
||||
def emit_param_decl_for_reading(param, cgen):
|
||||
if param.staticArrExpr:
|
||||
cgen.stmt(
|
||||
cgen.makeRichCTypeDecl(param.getForNonConstAccess()))
|
||||
else:
|
||||
cgen.stmt(
|
||||
cgen.makeRichCTypeDecl(param))
|
||||
|
||||
def emit_unmarshal(typeInfo, param, cgen, output = False, destroy = False, noUnbox = False):
|
||||
if destroy:
|
||||
iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen(
|
||||
cgen,
|
||||
"host",
|
||||
READ_STREAM,
|
||||
ROOT_TYPE_DEFAULT_VALUE,
|
||||
param.paramName,
|
||||
"readStreamPtrPtr",
|
||||
API_PREFIX_RESERVEDUNMARSHAL,
|
||||
"",
|
||||
direction="read",
|
||||
dynAlloc=True))
|
||||
lenAccess = cgen.generalLengthAccess(param)
|
||||
lenAccessGuard = cgen.generalLengthAccessGuard(param)
|
||||
if None == lenAccess or "1" == lenAccess:
|
||||
cgen.stmt("boxed_%s_preserve = %s" % (param.paramName, param.paramName))
|
||||
cgen.stmt("%s = unbox_%s(%s)" % (param.paramName, param.typeName, param.paramName))
|
||||
else:
|
||||
if lenAccessGuard is not None:
|
||||
cgen.beginIf(lenAccessGuard)
|
||||
cgen.beginFor("uint32_t i = 0", "i < %s" % lenAccess, "++i")
|
||||
cgen.stmt("boxed_%s_preserve[i] = %s[i]" % (param.paramName, param.paramName))
|
||||
cgen.stmt("((%s*)(%s))[i] = unbox_%s(%s[i])" % (param.typeName, param.paramName, param.typeName, param.paramName))
|
||||
cgen.endFor()
|
||||
if lenAccessGuard is not None:
|
||||
cgen.endIf()
|
||||
else:
|
||||
if noUnbox:
|
||||
cgen.line("// No unbox for %s" % (param.paramName))
|
||||
iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen(
|
||||
cgen,
|
||||
"host",
|
||||
READ_STREAM,
|
||||
ROOT_TYPE_DEFAULT_VALUE,
|
||||
param.paramName,
|
||||
"readStreamPtrPtr",
|
||||
API_PREFIX_RESERVEDUNMARSHAL,
|
||||
"" if (output or noUnbox) else "unbox_",
|
||||
direction="read",
|
||||
dynAlloc=True))
|
||||
|
||||
|
||||
def emit_dispatch_unmarshal(typeInfo: VulkanTypeInfo, param: VulkanType, cgen, globalWrapped):
|
||||
cgen.stmt("// Begin {} wrapped dispatchable handle unboxing for {}".format(
|
||||
"global" if globalWrapped else "non",
|
||||
param.paramName))
|
||||
|
||||
iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen(
|
||||
cgen,
|
||||
"host",
|
||||
READ_STREAM,
|
||||
ROOT_TYPE_DEFAULT_VALUE,
|
||||
param.paramName,
|
||||
"readStreamPtrPtr",
|
||||
API_PREFIX_RESERVEDUNMARSHAL,
|
||||
"",
|
||||
direction="read",
|
||||
dynAlloc=True))
|
||||
|
||||
if not globalWrapped:
|
||||
cgen.stmt("auto unboxed_%s = unbox_%s(%s)" %
|
||||
(param.paramName, param.typeName, param.paramName))
|
||||
cgen.stmt("auto vk = dispatch_%s(%s)" %
|
||||
(param.typeName, param.paramName))
|
||||
cgen.stmt("// End manual dispatchable handle unboxing for %s" % param.paramName)
|
||||
|
||||
|
||||
def emit_transform(typeInfo, param, cgen, variant="tohost"):
|
||||
res = iterateVulkanType(typeInfo, param, TransformCodegen(
|
||||
cgen, param.paramName, "m_state", "transform_%s_" % variant, variant))
|
||||
if not res:
|
||||
cgen.stmt("(void)%s" % param.paramName)
|
||||
|
||||
|
||||
def emit_marshal(typeInfo, param, cgen, handleMapOverwrites=False):
|
||||
iterateVulkanType(typeInfo, param, VulkanMarshalingCodegen(
|
||||
cgen,
|
||||
WRITE_STREAM,
|
||||
ROOT_TYPE_DEFAULT_VALUE,
|
||||
param.paramName,
|
||||
API_PREFIX_MARSHAL,
|
||||
direction="write",
|
||||
handleMapOverwrites=handleMapOverwrites))
|
||||
|
||||
|
||||
class DecodingParameters(object):
|
||||
def __init__(self, api: VulkanAPI):
|
||||
self.params: list[VulkanType] = []
|
||||
self.toRead: list[VulkanType] = []
|
||||
self.toWrite: list[VulkanType] = []
|
||||
|
||||
for i, param in enumerate(api.parameters):
|
||||
if i == 0 and param.isDispatchableHandleType():
|
||||
param.dispatchHandle = True
|
||||
|
||||
if param.isNonDispatchableHandleType() and param.isCreatedBy(api):
|
||||
param.nonDispatchableHandleCreate = True
|
||||
|
||||
if param.isNonDispatchableHandleType() and param.isDestroyedBy(api):
|
||||
param.nonDispatchableHandleDestroy = True
|
||||
|
||||
if param.isDispatchableHandleType() and param.isCreatedBy(api):
|
||||
param.dispatchableHandleCreate = True
|
||||
|
||||
if param.isDispatchableHandleType() and param.isDestroyedBy(api):
|
||||
param.dispatchableHandleDestroy = True
|
||||
|
||||
self.toRead.append(param)
|
||||
|
||||
if param.possiblyOutput():
|
||||
self.toWrite.append(param)
|
||||
|
||||
self.params.append(param)
|
||||
|
||||
|
||||
def emit_call_log(api, cgen):
|
||||
decodingParams = DecodingParameters(api)
|
||||
paramsToRead = decodingParams.toRead
|
||||
|
||||
cgen.beginIf("m_logCalls")
|
||||
paramLogFormat = ""
|
||||
paramLogArgs = []
|
||||
for p in paramsToRead:
|
||||
paramLogFormat += "0x%llx "
|
||||
for p in paramsToRead:
|
||||
paramLogArgs.append("(unsigned long long)%s" % (p.paramName))
|
||||
cgen.stmt("fprintf(stderr, \"stream %%p: call %s %s\\n\", ioStream, %s)" % (api.name, paramLogFormat, ", ".join(paramLogArgs)))
|
||||
cgen.endIf()
|
||||
|
||||
def emit_decode_parameters(typeInfo: VulkanTypeInfo, api: VulkanAPI, cgen, globalWrapped=False):
|
||||
decodingParams = DecodingParameters(api)
|
||||
|
||||
paramsToRead = decodingParams.toRead
|
||||
|
||||
for p in paramsToRead:
|
||||
emit_param_decl_for_reading(p, cgen)
|
||||
|
||||
for i, p in enumerate(paramsToRead):
|
||||
lenAccess = cgen.generalLengthAccess(p)
|
||||
|
||||
if p.dispatchHandle:
|
||||
emit_dispatch_unmarshal(typeInfo, p, cgen, globalWrapped)
|
||||
else:
|
||||
destroy = p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy
|
||||
noUnbox = api.name in ["vkQueueFlushCommandsGOOGLE", "vkQueueFlushCommandsFromAuxMemoryGOOGLE"] and p.paramName == "commandBuffer"
|
||||
|
||||
if p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy:
|
||||
destroy = True
|
||||
cgen.stmt("// Begin manual non dispatchable handle destroy unboxing for %s" % p.paramName)
|
||||
if None == lenAccess or "1" == lenAccess:
|
||||
cgen.stmt("%s boxed_%s_preserve" % (p.typeName, p.paramName))
|
||||
else:
|
||||
cgen.stmt("%s* boxed_%s_preserve; %s->alloc((void**)&boxed_%s_preserve, %s * sizeof(%s))" % (p.typeName, p.paramName, READ_STREAM, p.paramName, lenAccess, p.typeName))
|
||||
|
||||
if p.possiblyOutput():
|
||||
cgen.stmt("// Begin manual dispatchable handle unboxing for %s" % p.paramName)
|
||||
cgen.stmt("%s->unsetHandleMapping()" % READ_STREAM)
|
||||
|
||||
emit_unmarshal(typeInfo, p, cgen, output = p.possiblyOutput(), destroy = destroy, noUnbox = noUnbox)
|
||||
|
||||
for p in paramsToRead:
|
||||
emit_transform(typeInfo, p, cgen, variant="tohost")
|
||||
|
||||
emit_call_log(api, cgen)
|
||||
|
||||
def emit_dispatch_call(api, cgen):
|
||||
|
||||
decodingParams = DecodingParameters(api)
|
||||
|
||||
customParams = []
|
||||
|
||||
delay = api.name in DELAYED_DECODER_DELETES
|
||||
|
||||
for i, p in enumerate(api.parameters):
|
||||
customParam = p.paramName
|
||||
if decodingParams.params[i].dispatchHandle:
|
||||
customParam = "unboxed_%s" % p.paramName
|
||||
customParams.append(customParam)
|
||||
|
||||
if delay:
|
||||
cgen.line("std::function<void()> delayed_remove_callback = [vk, %s]() {" % ", ".join(customParams))
|
||||
|
||||
if api.name in driver_workarounds_global_lock_apis:
|
||||
if delay:
|
||||
cgen.stmt("auto state = VkDecoderGlobalState::get()")
|
||||
cgen.stmt("// state already locked")
|
||||
else:
|
||||
cgen.stmt("m_state->lock()")
|
||||
|
||||
cgen.vkApiCall(api, customPrefix="vk->", customParameters=customParams, \
|
||||
globalStatePrefix=global_state_prefix, checkForDeviceLost=True,
|
||||
checkForOutOfMemory=True)
|
||||
|
||||
if api.name in driver_workarounds_global_lock_apis:
|
||||
if not delay:
|
||||
cgen.stmt("m_state->unlock()")
|
||||
# for delayed remove, state is already locked, so we do not need to
|
||||
# unlock
|
||||
|
||||
if delay:
|
||||
cgen.line("};")
|
||||
|
||||
def emit_global_state_wrapped_call(api, cgen, context):
|
||||
if api.name in DELAYED_DECODER_DELETES:
|
||||
print("Error: Cannot generate a global state wrapped call that is also a delayed delete (yet)");
|
||||
raise
|
||||
|
||||
customParams = ["&m_pool"] + list(map(lambda p: p.paramName, api.parameters))
|
||||
if context:
|
||||
customParams += ["context"]
|
||||
cgen.vkApiCall(api, customPrefix=global_state_prefix, \
|
||||
customParameters=customParams, globalStatePrefix=global_state_prefix, \
|
||||
checkForDeviceLost=True, checkForOutOfMemory=True)
|
||||
|
||||
def emit_decode_parameters_writeback(typeInfo, api, cgen, autobox=True):
|
||||
decodingParams = DecodingParameters(api)
|
||||
|
||||
paramsToWrite = decodingParams.toWrite
|
||||
|
||||
cgen.stmt("%s->unsetHandleMapping()" % WRITE_STREAM)
|
||||
|
||||
handleMapOverwrites = False
|
||||
|
||||
for p in paramsToWrite:
|
||||
emit_transform(typeInfo, p, cgen, variant="fromhost")
|
||||
|
||||
handleMapOverwrites = False
|
||||
|
||||
if p.nonDispatchableHandleCreate or p.dispatchableHandleCreate:
|
||||
handleMapOverwrites = True
|
||||
|
||||
if autobox and p.nonDispatchableHandleCreate:
|
||||
cgen.stmt("// Begin auto non dispatchable handle create for %s" % p.paramName)
|
||||
cgen.stmt("if (%s == VK_SUCCESS) %s->setHandleMapping(&m_boxedHandleCreateMapping)" % \
|
||||
(api.getRetVarExpr(), WRITE_STREAM))
|
||||
|
||||
if (not autobox) and p.nonDispatchableHandleCreate:
|
||||
cgen.stmt("// Begin manual non dispatchable handle create for %s" % p.paramName)
|
||||
cgen.stmt("%s->unsetHandleMapping()" % WRITE_STREAM)
|
||||
|
||||
emit_marshal(typeInfo, p, cgen, handleMapOverwrites=handleMapOverwrites)
|
||||
|
||||
if autobox and p.nonDispatchableHandleCreate:
|
||||
cgen.stmt("// Begin auto non dispatchable handle create for %s" % p.paramName)
|
||||
cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % WRITE_STREAM)
|
||||
|
||||
if (not autobox) and p.nonDispatchableHandleCreate:
|
||||
cgen.stmt("// Begin manual non dispatchable handle create for %s" % p.paramName)
|
||||
cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % WRITE_STREAM)
|
||||
|
||||
def emit_decode_return_writeback(api, cgen):
|
||||
retTypeName = api.getRetTypeExpr()
|
||||
if retTypeName != "void":
|
||||
retVar = api.getRetVarExpr()
|
||||
cgen.stmt("%s->write(&%s, %s)" %
|
||||
(WRITE_STREAM, retVar, cgen.sizeofExpr(api.retType)))
|
||||
|
||||
def emit_decode_finish(api, cgen):
|
||||
decodingParams = DecodingParameters(api)
|
||||
retTypeName = api.getRetTypeExpr()
|
||||
paramsToWrite = decodingParams.toWrite
|
||||
|
||||
if retTypeName != "void" or len(paramsToWrite) != 0:
|
||||
cgen.stmt("%s->commitWrite()" % WRITE_STREAM)
|
||||
|
||||
def emit_destroyed_handle_cleanup(api, cgen):
|
||||
decodingParams = DecodingParameters(api)
|
||||
paramsToRead = decodingParams.toRead
|
||||
|
||||
skipDelete = api.name in SKIPPED_DECODER_DELETES
|
||||
|
||||
if skipDelete:
|
||||
cgen.line("// Skipping handle cleanup for %s" % api.name)
|
||||
return
|
||||
|
||||
for p in paramsToRead:
|
||||
if p.dispatchHandle:
|
||||
pass
|
||||
else:
|
||||
lenAccess = cgen.generalLengthAccess(p)
|
||||
lenAccessGuard = cgen.generalLengthAccess(p)
|
||||
destroy = p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy
|
||||
if destroy:
|
||||
if None == lenAccess or "1" == lenAccess:
|
||||
if api.name in DELAYED_DECODER_DELETES:
|
||||
cgen.stmt("delayed_delete_%s(boxed_%s_preserve, unboxed_device, delayed_remove_callback)" % (p.typeName, p.paramName))
|
||||
else:
|
||||
cgen.stmt("delete_%s(boxed_%s_preserve)" % (p.typeName, p.paramName))
|
||||
else:
|
||||
if lenAccessGuard is not None:
|
||||
cgen.beginIf(lenAccessGuard)
|
||||
cgen.beginFor("uint32_t i = 0", "i < %s" % lenAccess, "++i")
|
||||
if api.name in DELAYED_DECODER_DELETES:
|
||||
cgen.stmt("delayed_delete_%s(boxed_%s_preserve[i], unboxed_device, delayed_remove_callback)" % (p.typeName, p.paramName))
|
||||
else:
|
||||
cgen.stmt("delete_%s(boxed_%s_preserve[i])" % (p.typeName, p.paramName))
|
||||
cgen.endFor()
|
||||
if lenAccessGuard is not None:
|
||||
cgen.endIf()
|
||||
|
||||
def emit_pool_free(cgen):
|
||||
cgen.stmt("%s->clearPool()" % READ_STREAM)
|
||||
|
||||
def emit_seqno_incr(api, cgen):
|
||||
cgen.stmt("if (queueSubmitWithCommandsEnabled) seqnoPtr->fetch_add(1, std::memory_order_seq_cst)")
|
||||
|
||||
def emit_snapshot(typeInfo, api, cgen):
|
||||
|
||||
cgen.stmt("%s->setReadPos((uintptr_t)(*readStreamPtrPtr) - (uintptr_t)snapshotTraceBegin)" % READ_STREAM)
|
||||
cgen.stmt("size_t snapshotTraceBytes = %s->endTrace()" % READ_STREAM)
|
||||
|
||||
additionalParams = [ \
|
||||
makeVulkanTypeSimple(True, "uint8_t", 1, "snapshotTraceBegin"),
|
||||
makeVulkanTypeSimple(False, "size_t", 0, "snapshotTraceBytes"),
|
||||
makeVulkanTypeSimple(False, "android::base::BumpPool", 1, "&m_pool"),
|
||||
]
|
||||
|
||||
retTypeName = api.getRetTypeExpr()
|
||||
if retTypeName != "void":
|
||||
retVar = api.getRetVarExpr()
|
||||
additionalParams.append(makeVulkanTypeSimple(False, retTypeName, 0, retVar))
|
||||
|
||||
paramsForSnapshot = []
|
||||
|
||||
decodingParams = DecodingParameters(api)
|
||||
|
||||
for p in decodingParams.toRead:
|
||||
if p.nonDispatchableHandleDestroy or (not p.dispatchHandle and p.dispatchableHandleDestroy):
|
||||
paramsForSnapshot.append(p.withModifiedName("boxed_%s_preserve" % p.paramName))
|
||||
else:
|
||||
paramsForSnapshot.append(p)
|
||||
|
||||
customParams = additionalParams + paramsForSnapshot
|
||||
|
||||
apiForSnapshot = \
|
||||
api.withCustomReturnType(makeVulkanTypeSimple(False, "void", 0, "void")). \
|
||||
withCustomParameters(customParams)
|
||||
|
||||
cgen.beginIf("m_state->snapshotsEnabled()")
|
||||
cgen.vkApiCall(apiForSnapshot, customPrefix="m_state->snapshot()->")
|
||||
cgen.endIf()
|
||||
|
||||
def emit_decoding(typeInfo, api, cgen, globalWrapped=False, context=False):
|
||||
isAcquire = api.name in RELAXED_APIS
|
||||
emit_decode_parameters(typeInfo, api, cgen, globalWrapped)
|
||||
|
||||
if isAcquire:
|
||||
emit_seqno_incr(api, cgen)
|
||||
|
||||
if globalWrapped:
|
||||
emit_global_state_wrapped_call(api, cgen, context)
|
||||
else:
|
||||
emit_dispatch_call(api, cgen)
|
||||
|
||||
emit_decode_parameters_writeback(typeInfo, api, cgen, autobox=not globalWrapped)
|
||||
emit_decode_return_writeback(api, cgen)
|
||||
emit_decode_finish(api, cgen)
|
||||
emit_snapshot(typeInfo, api, cgen)
|
||||
emit_destroyed_handle_cleanup(api, cgen)
|
||||
emit_pool_free(cgen)
|
||||
|
||||
if not isAcquire:
|
||||
emit_seqno_incr(api, cgen)
|
||||
|
||||
def emit_default_decoding(typeInfo, api, cgen):
|
||||
emit_decoding(typeInfo, api, cgen)
|
||||
|
||||
def emit_global_state_wrapped_decoding(typeInfo, api, cgen):
|
||||
emit_decoding(typeInfo, api, cgen, globalWrapped=True)
|
||||
|
||||
def emit_global_state_wrapped_decoding_with_context(typeInfo, api, cgen):
|
||||
emit_decoding(typeInfo, api, cgen, globalWrapped=True, context=True)
|
||||
|
||||
## Custom decoding definitions##################################################
|
||||
def decode_vkFlushMappedMemoryRanges(typeInfo: VulkanTypeInfo, api, cgen):
|
||||
emit_decode_parameters(typeInfo, api, cgen)
|
||||
|
||||
cgen.beginIf("!m_state->usingDirectMapping()")
|
||||
cgen.stmt("// This is to deal with a deficiency in the encoder,");
|
||||
cgen.stmt("// where usingDirectMapping fails to set the proper packet size,");
|
||||
cgen.stmt("// meaning we can read off the end of the packet.");
|
||||
cgen.stmt("uint64_t sizeLeft = end - *readStreamPtrPtr")
|
||||
cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i")
|
||||
cgen.beginIf("sizeLeft < sizeof(uint64_t)")
|
||||
cgen.beginIf("m_prevSeqno")
|
||||
cgen.stmt("m_prevSeqno = m_prevSeqno.value() - 1")
|
||||
cgen.endIf()
|
||||
cgen.stmt("return ptr - (unsigned char*)buf;")
|
||||
cgen.endIf()
|
||||
cgen.stmt("auto range = pMemoryRanges[i]")
|
||||
cgen.stmt("auto memory = pMemoryRanges[i].memory")
|
||||
cgen.stmt("auto size = pMemoryRanges[i].size")
|
||||
cgen.stmt("auto offset = pMemoryRanges[i].offset")
|
||||
cgen.stmt("uint64_t readStream = 0")
|
||||
cgen.stmt("memcpy(&readStream, *readStreamPtrPtr, sizeof(uint64_t)); *readStreamPtrPtr += sizeof(uint64_t)")
|
||||
cgen.stmt("sizeLeft -= sizeof(uint64_t)")
|
||||
cgen.stmt("auto hostPtr = m_state->getMappedHostPointer(memory)")
|
||||
cgen.stmt("if (!hostPtr && readStream > 0) GFXSTREAM_ABORT(::emugl::FatalError(::emugl::ABORT_REASON_OTHER))")
|
||||
cgen.stmt("if (!hostPtr) continue")
|
||||
cgen.beginIf("sizeLeft < readStream")
|
||||
cgen.beginIf("m_prevSeqno")
|
||||
cgen.stmt("m_prevSeqno = m_prevSeqno.value() - 1")
|
||||
cgen.endIf()
|
||||
cgen.stmt("return ptr - (unsigned char*)buf;")
|
||||
cgen.endIf()
|
||||
cgen.stmt("sizeLeft -= readStream")
|
||||
cgen.stmt("uint8_t* targetRange = hostPtr + offset")
|
||||
cgen.stmt("memcpy(targetRange, *readStreamPtrPtr, readStream); *readStreamPtrPtr += readStream")
|
||||
cgen.stmt("packetLen += 8 + readStream")
|
||||
cgen.endFor()
|
||||
cgen.endIf()
|
||||
|
||||
emit_dispatch_call(api, cgen)
|
||||
emit_decode_parameters_writeback(typeInfo, api, cgen)
|
||||
emit_decode_return_writeback(api, cgen)
|
||||
emit_decode_finish(api, cgen)
|
||||
emit_snapshot(typeInfo, api, cgen);
|
||||
emit_pool_free(cgen)
|
||||
emit_seqno_incr(api, cgen)
|
||||
|
||||
def decode_vkInvalidateMappedMemoryRanges(typeInfo, api, cgen):
|
||||
emit_decode_parameters(typeInfo, api, cgen)
|
||||
emit_dispatch_call(api, cgen)
|
||||
emit_decode_parameters_writeback(typeInfo, api, cgen)
|
||||
emit_decode_return_writeback(api, cgen)
|
||||
|
||||
cgen.beginIf("!m_state->usingDirectMapping()")
|
||||
cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i")
|
||||
cgen.stmt("auto range = pMemoryRanges[i]")
|
||||
cgen.stmt("auto memory = range.memory")
|
||||
cgen.stmt("auto size = range.size")
|
||||
cgen.stmt("auto offset = range.offset")
|
||||
cgen.stmt("auto hostPtr = m_state->getMappedHostPointer(memory)")
|
||||
cgen.stmt("auto actualSize = size == VK_WHOLE_SIZE ? m_state->getDeviceMemorySize(memory) : size")
|
||||
cgen.stmt("uint64_t writeStream = 0")
|
||||
cgen.stmt("if (!hostPtr) { %s->write(&writeStream, sizeof(uint64_t)); continue; }" % WRITE_STREAM)
|
||||
cgen.stmt("uint8_t* targetRange = hostPtr + offset")
|
||||
cgen.stmt("writeStream = actualSize")
|
||||
cgen.stmt("%s->write(&writeStream, sizeof(uint64_t))" % WRITE_STREAM)
|
||||
cgen.stmt("%s->write(targetRange, actualSize)" % WRITE_STREAM)
|
||||
cgen.endFor()
|
||||
cgen.endIf()
|
||||
|
||||
emit_decode_finish(api, cgen)
|
||||
emit_snapshot(typeInfo, api, cgen);
|
||||
emit_pool_free(cgen)
|
||||
emit_seqno_incr(api, cgen)
|
||||
|
||||
def decode_unsupported_api(typeInfo, api, cgen):
|
||||
cgen.line(f"// Decoding {api.name} is not supported. This should not run.")
|
||||
cgen.stmt(f"fprintf(stderr, \"stream %p: fatal: decoding unsupported API {api.name}\\n\", ioStream)");
|
||||
cgen.stmt("__builtin_trap()")
|
||||
|
||||
custom_decodes = {
|
||||
"vkEnumerateInstanceVersion" : emit_global_state_wrapped_decoding,
|
||||
"vkCreateInstance" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyInstance" : emit_global_state_wrapped_decoding,
|
||||
"vkEnumeratePhysicalDevices" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkGetPhysicalDeviceFeatures" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceFeatures2" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceFeatures2KHR" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceFormatProperties" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceFormatProperties2" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceFormatProperties2KHR" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceImageFormatProperties" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceImageFormatProperties2" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceImageFormatProperties2KHR" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceProperties" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceProperties2" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceProperties2KHR" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkGetPhysicalDeviceMemoryProperties" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceMemoryProperties2" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceMemoryProperties2KHR" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkGetPhysicalDeviceExternalSemaphoreProperties" : emit_global_state_wrapped_decoding,
|
||||
"vkGetPhysicalDeviceExternalSemaphorePropertiesKHR" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkEnumerateDeviceExtensionProperties" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkCreateBuffer" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyBuffer" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkBindBufferMemory" : emit_global_state_wrapped_decoding,
|
||||
"vkBindBufferMemory2" : emit_global_state_wrapped_decoding,
|
||||
"vkBindBufferMemory2KHR" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkCreateDevice" : emit_global_state_wrapped_decoding,
|
||||
"vkGetDeviceQueue" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyDevice" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkGetDeviceQueue2" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkBindImageMemory" : emit_global_state_wrapped_decoding,
|
||||
"vkBindImageMemory2" : emit_global_state_wrapped_decoding,
|
||||
"vkBindImageMemory2KHR" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkCreateImage" : emit_global_state_wrapped_decoding,
|
||||
"vkCreateImageView" : emit_global_state_wrapped_decoding,
|
||||
"vkCreateSampler" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyImage" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyImageView" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroySampler" : emit_global_state_wrapped_decoding,
|
||||
"vkCmdCopyBufferToImage" : emit_global_state_wrapped_decoding_with_context,
|
||||
"vkCmdCopyImage" : emit_global_state_wrapped_decoding,
|
||||
"vkCmdCopyImageToBuffer" : emit_global_state_wrapped_decoding,
|
||||
"vkCmdCopyBufferToImage2" : emit_global_state_wrapped_decoding_with_context,
|
||||
"vkCmdCopyImage2" : emit_global_state_wrapped_decoding,
|
||||
"vkCmdCopyImageToBuffer2" : emit_global_state_wrapped_decoding,
|
||||
"vkGetImageMemoryRequirements" : emit_global_state_wrapped_decoding,
|
||||
"vkGetImageMemoryRequirements2" : emit_global_state_wrapped_decoding,
|
||||
"vkGetImageMemoryRequirements2KHR" : emit_global_state_wrapped_decoding,
|
||||
"vkGetBufferMemoryRequirements" : emit_global_state_wrapped_decoding,
|
||||
"vkGetBufferMemoryRequirements2": emit_global_state_wrapped_decoding,
|
||||
"vkGetBufferMemoryRequirements2KHR": emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkCreateDescriptorSetLayout" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyDescriptorSetLayout" : emit_global_state_wrapped_decoding,
|
||||
"vkCreateDescriptorPool" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyDescriptorPool" : emit_global_state_wrapped_decoding,
|
||||
"vkResetDescriptorPool" : emit_global_state_wrapped_decoding,
|
||||
"vkAllocateDescriptorSets" : emit_global_state_wrapped_decoding,
|
||||
"vkFreeDescriptorSets" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkUpdateDescriptorSets" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkCreateShaderModule": emit_global_state_wrapped_decoding,
|
||||
"vkDestroyShaderModule": emit_global_state_wrapped_decoding,
|
||||
"vkCreatePipelineCache": emit_global_state_wrapped_decoding,
|
||||
"vkDestroyPipelineCache": emit_global_state_wrapped_decoding,
|
||||
"vkCreateGraphicsPipelines": emit_global_state_wrapped_decoding,
|
||||
"vkDestroyPipeline": emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkAllocateMemory" : emit_global_state_wrapped_decoding,
|
||||
"vkFreeMemory" : emit_global_state_wrapped_decoding,
|
||||
"vkMapMemory" : emit_global_state_wrapped_decoding,
|
||||
"vkUnmapMemory" : emit_global_state_wrapped_decoding,
|
||||
"vkFlushMappedMemoryRanges" : decode_vkFlushMappedMemoryRanges,
|
||||
"vkInvalidateMappedMemoryRanges" : decode_vkInvalidateMappedMemoryRanges,
|
||||
|
||||
"vkAllocateCommandBuffers" : emit_global_state_wrapped_decoding,
|
||||
"vkCmdExecuteCommands" : emit_global_state_wrapped_decoding,
|
||||
"vkQueueSubmit" : emit_global_state_wrapped_decoding,
|
||||
"vkQueueSubmit2" : emit_global_state_wrapped_decoding,
|
||||
"vkQueueWaitIdle" : emit_global_state_wrapped_decoding,
|
||||
"vkBeginCommandBuffer" : emit_global_state_wrapped_decoding_with_context,
|
||||
"vkEndCommandBuffer" : emit_global_state_wrapped_decoding_with_context,
|
||||
"vkResetCommandBuffer" : emit_global_state_wrapped_decoding,
|
||||
"vkFreeCommandBuffers" : emit_global_state_wrapped_decoding,
|
||||
"vkCreateCommandPool" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyCommandPool" : emit_global_state_wrapped_decoding,
|
||||
"vkResetCommandPool" : emit_global_state_wrapped_decoding,
|
||||
"vkCmdPipelineBarrier" : emit_global_state_wrapped_decoding,
|
||||
"vkCmdBindPipeline" : emit_global_state_wrapped_decoding,
|
||||
"vkCmdBindDescriptorSets" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkCreateRenderPass" : emit_global_state_wrapped_decoding,
|
||||
"vkCreateRenderPass2" : emit_global_state_wrapped_decoding,
|
||||
"vkCreateRenderPass2KHR" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyRenderPass" : emit_global_state_wrapped_decoding,
|
||||
"vkCreateFramebuffer" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyFramebuffer" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkCreateSamplerYcbcrConversion": emit_global_state_wrapped_decoding,
|
||||
"vkDestroySamplerYcbcrConversion": emit_global_state_wrapped_decoding,
|
||||
|
||||
# VK_ANDROID_native_buffer
|
||||
"vkGetSwapchainGrallocUsageANDROID" : emit_global_state_wrapped_decoding,
|
||||
"vkGetSwapchainGrallocUsage2ANDROID" : emit_global_state_wrapped_decoding,
|
||||
"vkAcquireImageANDROID" : emit_global_state_wrapped_decoding,
|
||||
"vkQueueSignalReleaseImageANDROID" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkCreateSemaphore" : emit_global_state_wrapped_decoding,
|
||||
"vkGetSemaphoreFdKHR" : emit_global_state_wrapped_decoding,
|
||||
"vkImportSemaphoreFdKHR" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroySemaphore" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkCreateFence" : emit_global_state_wrapped_decoding,
|
||||
"vkResetFences" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyFence" : emit_global_state_wrapped_decoding,
|
||||
|
||||
# VK_GOOGLE_gfxstream
|
||||
"vkFreeMemorySyncGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkMapMemoryIntoAddressSpaceGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkGetMemoryHostAddressInfoGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkGetBlobGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
|
||||
# Descriptor update templates
|
||||
"vkCreateDescriptorUpdateTemplate" : emit_global_state_wrapped_decoding,
|
||||
"vkCreateDescriptorUpdateTemplateKHR" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyDescriptorUpdateTemplate" : emit_global_state_wrapped_decoding,
|
||||
"vkDestroyDescriptorUpdateTemplateKHR" : emit_global_state_wrapped_decoding,
|
||||
"vkUpdateDescriptorSetWithTemplateSizedGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkUpdateDescriptorSetWithTemplateSized2GOOGLE" : emit_global_state_wrapped_decoding,
|
||||
|
||||
# VK_GOOGLE_gfxstream
|
||||
"vkBeginCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding_with_context,
|
||||
"vkEndCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding_with_context,
|
||||
"vkResetCommandBufferAsyncGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkCommandBufferHostSyncGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkCreateImageWithRequirementsGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkCreateBufferWithRequirementsGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkQueueHostSyncGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkQueueSubmitAsyncGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkQueueSubmitAsync2GOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkQueueWaitIdleAsyncGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkQueueBindSparseAsyncGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkGetLinearImageLayoutGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkGetLinearImageLayout2GOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkQueueFlushCommandsGOOGLE" : emit_global_state_wrapped_decoding_with_context,
|
||||
"vkQueueFlushCommandsFromAuxMemoryGOOGLE" : emit_global_state_wrapped_decoding_with_context,
|
||||
"vkQueueCommitDescriptorSetUpdatesGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkCollectDescriptorPoolIdsGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
"vkQueueSignalReleaseImageANDROIDAsyncGOOGLE" : emit_global_state_wrapped_decoding,
|
||||
|
||||
"vkQueueBindSparse" : emit_global_state_wrapped_decoding,
|
||||
|
||||
# VK_KHR_xcb_surface
|
||||
"vkCreateXcbSurfaceKHR": decode_unsupported_api,
|
||||
"vkGetPhysicalDeviceXcbPresentationSupportKHR": decode_unsupported_api,
|
||||
|
||||
# VK_EXT_metal_surface
|
||||
"vkCreateMetalSurfaceEXT": decode_unsupported_api,
|
||||
|
||||
# VK_KHR_sampler_ycbcr_conversion
|
||||
"vkCreateSamplerYcbcrConversionKHR": emit_global_state_wrapped_decoding,
|
||||
"vkDestroySamplerYcbcrConversionKHR": emit_global_state_wrapped_decoding,
|
||||
|
||||
#VK_KHR_copy_commands2
|
||||
"vkCmdCopyBufferToImage2KHR" : emit_global_state_wrapped_decoding_with_context,
|
||||
"vkCmdCopyImage2KHR" : emit_global_state_wrapped_decoding,
|
||||
"vkCmdCopyImageToBuffer2KHR" : emit_global_state_wrapped_decoding,
|
||||
}
|
||||
|
||||
class VulkanDecoder(VulkanWrapperGenerator):
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
self.typeInfo: VulkanTypeInfo = typeInfo
|
||||
self.cgen = CodeGen()
|
||||
|
||||
def onBegin(self,):
|
||||
self.module.appendImpl(
|
||||
"#define MAX_PACKET_LENGTH %s\n" % MAX_PACKET_LENGTH)
|
||||
self.module.appendHeader(decoder_decl_preamble)
|
||||
self.module.appendImpl(decoder_impl_preamble)
|
||||
|
||||
self.module.appendImpl(
|
||||
"""
|
||||
size_t VkDecoder::Impl::decode(void* buf, size_t len, IOStream* ioStream,
|
||||
const ProcessResources* processResources,
|
||||
const VkDecoderContext& context)
|
||||
""")
|
||||
|
||||
self.cgen.beginBlock() # function body
|
||||
|
||||
self.cgen.stmt("const char* processName = context.processName")
|
||||
self.cgen.stmt("auto& gfx_logger = *context.gfxApiLogger")
|
||||
self.cgen.stmt("auto* healthMonitor = context.healthMonitor")
|
||||
self.cgen.stmt("auto& metricsLogger = *context.metricsLogger")
|
||||
self.cgen.stmt("if (len < 8) return 0")
|
||||
self.cgen.stmt("bool queueSubmitWithCommandsEnabled = feature_is_enabled(kFeature_VulkanQueueSubmitWithCommands)")
|
||||
self.cgen.stmt("unsigned char *ptr = (unsigned char *)buf")
|
||||
self.cgen.stmt("const unsigned char* const end = (const unsigned char*)buf + len")
|
||||
|
||||
self.cgen.beginIf("m_forSnapshotLoad")
|
||||
self.cgen.stmt("ptr += m_state->setCreatedHandlesForSnapshotLoad(ptr)");
|
||||
self.cgen.endIf()
|
||||
self.cgen.line("while (end - ptr >= 8)")
|
||||
self.cgen.beginBlock() # while loop
|
||||
|
||||
self.cgen.stmt("uint32_t opcode = *(uint32_t *)ptr")
|
||||
self.cgen.stmt("uint32_t packetLen = *(uint32_t *)(ptr + 4)")
|
||||
self.cgen.line("""
|
||||
// packetLen should be at least 8 (op code and packet length) and should not be excessively large
|
||||
if (packetLen < 8 || packetLen > MAX_PACKET_LENGTH) {
|
||||
WARN("Bad packet length %d detected, decode may fail", packetLen);
|
||||
metricsLogger.logMetricEvent(MetricEventBadPacketLength{ .len = packetLen });
|
||||
}
|
||||
""")
|
||||
self.cgen.stmt("if (end - ptr < packetLen) return ptr - (unsigned char*)buf")
|
||||
self.cgen.stmt("gfx_logger.record(ptr, std::min(size_t(packetLen + 8), size_t(end - ptr)))")
|
||||
|
||||
self.cgen.stmt("stream()->setStream(ioStream)")
|
||||
self.cgen.stmt("VulkanStream* %s = stream()" % WRITE_STREAM)
|
||||
self.cgen.stmt("VulkanMemReadingStream* %s = readStream()" % READ_STREAM)
|
||||
self.cgen.stmt("%s->setBuf((uint8_t*)(ptr + 8))" % READ_STREAM)
|
||||
self.cgen.stmt("uint8_t* readStreamPtr = %s->getBuf(); uint8_t** readStreamPtrPtr = &readStreamPtr" % READ_STREAM)
|
||||
self.cgen.stmt("uint8_t* snapshotTraceBegin = %s->beginTrace()" % READ_STREAM)
|
||||
self.cgen.stmt("%s->setHandleMapping(&m_boxedHandleUnwrapMapping)" % READ_STREAM)
|
||||
self.cgen.line("""
|
||||
std::unique_ptr<EventHangMetadata::HangAnnotations> executionData =
|
||||
std::make_unique<EventHangMetadata::HangAnnotations>();
|
||||
if (healthMonitor) {
|
||||
executionData->insert(
|
||||
{{"packet_length", std::to_string(packetLen)},
|
||||
{"opcode", std::to_string(opcode)}});
|
||||
if (processName) {
|
||||
executionData->insert(
|
||||
{{"renderthread_guest_process", std::string(processName)}});
|
||||
}
|
||||
if (m_prevSeqno) {
|
||||
executionData->insert({{"previous_seqno", std::to_string(m_prevSeqno.value())}});
|
||||
}
|
||||
}
|
||||
|
||||
std::atomic<uint32_t>* seqnoPtr = processResources ?
|
||||
processResources->getSequenceNumberPtr() : nullptr;
|
||||
|
||||
if (queueSubmitWithCommandsEnabled && ((opcode >= OP_vkFirst && opcode < OP_vkLast) || (opcode >= OP_vkFirst_old && opcode < OP_vkLast_old))) {
|
||||
uint32_t seqno;
|
||||
memcpy(&seqno, *readStreamPtrPtr, sizeof(uint32_t)); *readStreamPtrPtr += sizeof(uint32_t);
|
||||
if (healthMonitor) executionData->insert({{"seqno", std::to_string(seqno)}});
|
||||
if (m_prevSeqno && seqno == m_prevSeqno.value()) {
|
||||
WARN(
|
||||
"Seqno %d is the same as previously processed on thread %d. It might be a "
|
||||
"duplicate command.",
|
||||
seqno, getCurrentThreadId());
|
||||
metricsLogger.logMetricEvent(MetricEventDuplicateSequenceNum{ .opcode = opcode });
|
||||
}
|
||||
if (seqnoPtr && !m_forSnapshotLoad) {
|
||||
{
|
||||
auto seqnoWatchdog =
|
||||
WATCHDOG_BUILDER(healthMonitor,
|
||||
"RenderThread seqno loop")
|
||||
.setHangType(EventHangMetadata::HangType::kRenderThread)
|
||||
.setAnnotations(std::make_unique<EventHangMetadata::HangAnnotations>(*executionData))
|
||||
/* Data gathered if this hangs*/
|
||||
.setOnHangCallback([=]() {
|
||||
auto annotations = std::make_unique<EventHangMetadata::HangAnnotations>();
|
||||
annotations->insert({{"seqnoPtr", std::to_string(seqnoPtr->load(std::memory_order_seq_cst))}});
|
||||
return annotations;
|
||||
})
|
||||
.build();
|
||||
while ((seqno - seqnoPtr->load(std::memory_order_seq_cst) != 1)) {
|
||||
#if (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)))
|
||||
_mm_pause();
|
||||
#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
|
||||
__asm__ __volatile__("pause;");
|
||||
#endif
|
||||
}
|
||||
m_prevSeqno = seqno;
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
self.cgen.line("""
|
||||
gfx_logger.recordCommandExecution();
|
||||
""")
|
||||
|
||||
self.cgen.line("""
|
||||
auto executionWatchdog =
|
||||
WATCHDOG_BUILDER(healthMonitor, "RenderThread VkDecoder command execution")
|
||||
.setHangType(EventHangMetadata::HangType::kRenderThread)
|
||||
.setAnnotations(std::move(executionData))
|
||||
.build();
|
||||
""")
|
||||
|
||||
self.cgen.stmt("auto vk = m_vk")
|
||||
|
||||
self.cgen.line("switch (opcode)")
|
||||
self.cgen.beginBlock() # switch stmt
|
||||
|
||||
self.module.appendImpl(self.cgen.swapCode())
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
typeInfo = self.typeInfo
|
||||
cgen = self.cgen
|
||||
api: VulkanAPI = typeInfo.apis[name]
|
||||
|
||||
cgen.line("case OP_%s:" % name)
|
||||
cgen.beginBlock()
|
||||
cgen.stmt("android::base::beginTrace(\"%s decode\")" % name)
|
||||
|
||||
if api.name in custom_decodes.keys():
|
||||
custom_decodes[api.name](typeInfo, api, cgen)
|
||||
else:
|
||||
emit_default_decoding(typeInfo, api, cgen)
|
||||
|
||||
cgen.stmt("android::base::endTrace()")
|
||||
cgen.stmt("break")
|
||||
cgen.endBlock()
|
||||
self.module.appendImpl(self.cgen.swapCode())
|
||||
|
||||
def onEnd(self,):
|
||||
self.cgen.line("default:")
|
||||
self.cgen.beginBlock()
|
||||
self.cgen.stmt("m_pool.freeAll()")
|
||||
self.cgen.stmt("return ptr - (unsigned char *)buf")
|
||||
self.cgen.endBlock()
|
||||
|
||||
self.cgen.endBlock() # switch stmt
|
||||
|
||||
self.cgen.stmt("ptr += packetLen")
|
||||
self.cgen.endBlock() # while loop
|
||||
|
||||
self.cgen.beginIf("m_forSnapshotLoad")
|
||||
self.cgen.stmt("m_state->clearCreatedHandlesForSnapshotLoad()");
|
||||
self.cgen.endIf()
|
||||
|
||||
self.cgen.stmt("m_pool.freeAll()")
|
||||
self.cgen.stmt("return ptr - (unsigned char*)buf;")
|
||||
self.cgen.endBlock() # function body
|
||||
self.module.appendImpl(self.cgen.swapCode())
|
||||
self.module.appendImpl(decoder_impl_postamble)
|
||||
267
src/gfxstream/codegen/scripts/cereal/decodersnapshot.py
Normal file
267
src/gfxstream/codegen/scripts/cereal/decodersnapshot.py
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
from .common.codegen import CodeGen, VulkanWrapperGenerator, VulkanAPIWrapper
|
||||
from .common.vulkantypes import \
|
||||
VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, DISPATCHABLE_HANDLE_TYPES, NON_DISPATCHABLE_HANDLE_TYPES
|
||||
|
||||
from .transform import TransformCodegen, genTransformsForVulkanType
|
||||
|
||||
from .wrapperdefs import API_PREFIX_MARSHAL
|
||||
from .wrapperdefs import API_PREFIX_UNMARSHAL
|
||||
from .wrapperdefs import VULKAN_STREAM_TYPE
|
||||
|
||||
from copy import copy
|
||||
|
||||
decoder_snapshot_decl_preamble = """
|
||||
|
||||
namespace android {
|
||||
namespace base {
|
||||
class BumpPool;
|
||||
class Stream;
|
||||
} // namespace base {
|
||||
} // namespace android {
|
||||
|
||||
class VkDecoderSnapshot {
|
||||
public:
|
||||
VkDecoderSnapshot();
|
||||
~VkDecoderSnapshot();
|
||||
|
||||
void save(android::base::Stream* stream);
|
||||
void load(android::base::Stream* stream, emugl::GfxApiLogger& gfx_logger,
|
||||
emugl::HealthMonitor<>* healthMonitor);
|
||||
"""
|
||||
|
||||
decoder_snapshot_decl_postamble = """
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> mImpl;
|
||||
|
||||
};
|
||||
"""
|
||||
|
||||
decoder_snapshot_impl_preamble ="""
|
||||
|
||||
using namespace gfxstream::vk;
|
||||
using emugl::GfxApiLogger;
|
||||
using emugl::HealthMonitor;
|
||||
|
||||
class VkDecoderSnapshot::Impl {
|
||||
public:
|
||||
Impl() { }
|
||||
|
||||
void save(android::base::Stream* stream) {
|
||||
mReconstruction.save(stream);
|
||||
}
|
||||
|
||||
void load(android::base::Stream* stream, GfxApiLogger& gfx_logger,
|
||||
HealthMonitor<>* healthMonitor) {
|
||||
mReconstruction.load(stream, gfx_logger, healthMonitor);
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
decoder_snapshot_impl_postamble = """
|
||||
private:
|
||||
android::base::Lock mLock;
|
||||
VkReconstruction mReconstruction;
|
||||
};
|
||||
|
||||
VkDecoderSnapshot::VkDecoderSnapshot() :
|
||||
mImpl(new VkDecoderSnapshot::Impl()) { }
|
||||
|
||||
void VkDecoderSnapshot::save(android::base::Stream* stream) {
|
||||
mImpl->save(stream);
|
||||
}
|
||||
|
||||
void VkDecoderSnapshot::load(android::base::Stream* stream, GfxApiLogger& gfx_logger,
|
||||
HealthMonitor<>* healthMonitor) {
|
||||
mImpl->load(stream, gfx_logger, healthMonitor);
|
||||
}
|
||||
|
||||
VkDecoderSnapshot::~VkDecoderSnapshot() = default;
|
||||
"""
|
||||
|
||||
AUXILIARY_SNAPSHOT_API_BASE_PARAM_COUNT = 3
|
||||
|
||||
AUXILIARY_SNAPSHOT_API_PARAM_NAMES = [
|
||||
"input_result",
|
||||
]
|
||||
|
||||
# Vulkan handle dependencies.
|
||||
# (a, b): a depends on b
|
||||
SNAPSHOT_HANDLE_DEPENDENCIES = [
|
||||
# Dispatchable handle types
|
||||
("VkCommandBuffer", "VkCommandPool"),
|
||||
("VkCommandPool", "VkDevice"),
|
||||
("VkQueue", "VkDevice"),
|
||||
("VkDevice", "VkPhysicalDevice"),
|
||||
("VkPhysicalDevice", "VkInstance")] + \
|
||||
list(map(lambda handleType : (handleType, "VkDevice"), NON_DISPATCHABLE_HANDLE_TYPES))
|
||||
|
||||
handleDependenciesDict = dict(SNAPSHOT_HANDLE_DEPENDENCIES)
|
||||
|
||||
def extract_deps_vkAllocateCommandBuffers(param, access, lenExpr, api, cgen):
|
||||
cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \
|
||||
(access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkCommandPool(pAllocateInfo->commandPool)"))
|
||||
|
||||
specialCaseDependencyExtractors = {
|
||||
"vkAllocateCommandBuffers" : extract_deps_vkAllocateCommandBuffers,
|
||||
}
|
||||
|
||||
apiSequences = {
|
||||
"vkAllocateMemory" : ["vkAllocateMemory", "vkMapMemoryIntoAddressSpaceGOOGLE"]
|
||||
}
|
||||
|
||||
apiModifies = {
|
||||
"vkMapMemoryIntoAddressSpaceGOOGLE" : ["memory"],
|
||||
}
|
||||
|
||||
def is_modify_operation(api, param):
|
||||
if api.name in apiModifies:
|
||||
if param.paramName in apiModifies[api.name]:
|
||||
return True
|
||||
return False
|
||||
|
||||
def emit_impl(typeInfo, api, cgen):
|
||||
|
||||
cgen.line("// TODO: Implement")
|
||||
|
||||
for p in api.parameters:
|
||||
if not (p.isHandleType):
|
||||
continue
|
||||
|
||||
lenExpr = cgen.generalLengthAccess(p)
|
||||
lenAccessGuard = cgen.generalLengthAccessGuard(p)
|
||||
|
||||
if lenExpr is None:
|
||||
lenExpr = "1"
|
||||
|
||||
if p.pointerIndirectionLevels > 0:
|
||||
access = p.paramName
|
||||
else:
|
||||
access = "(&%s)" % p.paramName
|
||||
|
||||
if p.isCreatedBy(api):
|
||||
cgen.stmt("android::base::AutoLock lock(mLock)")
|
||||
cgen.line("// %s create" % p.paramName)
|
||||
cgen.stmt("mReconstruction.addHandles((const uint64_t*)%s, %s)" % (access, lenExpr));
|
||||
|
||||
if p.typeName in handleDependenciesDict:
|
||||
dependsOnType = handleDependenciesDict[p.typeName];
|
||||
for p2 in api.parameters:
|
||||
if p2.typeName == dependsOnType:
|
||||
cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % (access, lenExpr, p2.paramName))
|
||||
if api.name in specialCaseDependencyExtractors:
|
||||
specialCaseDependencyExtractors[api.name](p, access, lenExpr, api, cgen)
|
||||
|
||||
cgen.stmt("if (!%s) return" % access)
|
||||
cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()")
|
||||
cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)")
|
||||
cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name)
|
||||
if lenAccessGuard is not None:
|
||||
cgen.beginIf(lenAccessGuard)
|
||||
cgen.stmt("mReconstruction.forEachHandleAddApi((const uint64_t*)%s, %s, apiHandle)" % (access, lenExpr))
|
||||
cgen.stmt("mReconstruction.setCreatedHandlesForApi(apiHandle, (const uint64_t*)%s, %s)" % (access, lenExpr))
|
||||
if lenAccessGuard is not None:
|
||||
cgen.endIf()
|
||||
|
||||
if p.isDestroyedBy(api):
|
||||
cgen.stmt("android::base::AutoLock lock(mLock)")
|
||||
cgen.line("// %s destroy" % p.paramName)
|
||||
if lenAccessGuard is not None:
|
||||
cgen.beginIf(lenAccessGuard)
|
||||
cgen.stmt("mReconstruction.removeHandles((const uint64_t*)%s, %s)" % (access, lenExpr));
|
||||
if lenAccessGuard is not None:
|
||||
cgen.endIf()
|
||||
|
||||
if is_modify_operation(api, p):
|
||||
cgen.stmt("android::base::AutoLock lock(mLock)")
|
||||
cgen.line("// %s modify" % p.paramName)
|
||||
cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()")
|
||||
cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)")
|
||||
cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name)
|
||||
if lenAccessGuard is not None:
|
||||
cgen.beginIf(lenAccessGuard)
|
||||
cgen.beginFor("uint32_t i = 0", "i < %s" % lenExpr, "++i")
|
||||
if p.isNonDispatchableHandleType():
|
||||
cgen.stmt("%s boxed = unboxed_to_boxed_non_dispatchable_%s(%s[i])" % (p.typeName, p.typeName, access))
|
||||
else:
|
||||
cgen.stmt("%s boxed = unboxed_to_boxed_%s(%s[i])" % (p.typeName, p.typeName, access))
|
||||
cgen.stmt("mReconstruction.forEachHandleAddModifyApi((const uint64_t*)(&boxed), 1, apiHandle)")
|
||||
cgen.endFor()
|
||||
if lenAccessGuard is not None:
|
||||
cgen.endIf()
|
||||
|
||||
def emit_passthrough_to_impl(typeInfo, api, cgen):
|
||||
cgen.vkApiCall(api, customPrefix = "mImpl->")
|
||||
|
||||
class VulkanDecoderSnapshot(VulkanWrapperGenerator):
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
|
||||
self.typeInfo = typeInfo
|
||||
|
||||
self.cgenHeader = CodeGen()
|
||||
self.cgenHeader.incrIndent()
|
||||
|
||||
self.cgenImpl = CodeGen()
|
||||
|
||||
self.currentFeature = None
|
||||
|
||||
self.feature_apis = []
|
||||
|
||||
def onBegin(self,):
|
||||
self.module.appendHeader(decoder_snapshot_decl_preamble)
|
||||
self.module.appendImpl(decoder_snapshot_impl_preamble)
|
||||
|
||||
def onBeginFeature(self, featureName, featureType):
|
||||
VulkanWrapperGenerator.onBeginFeature(self, featureName, featureType)
|
||||
self.currentFeature = featureName
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
|
||||
|
||||
api = self.typeInfo.apis[name]
|
||||
|
||||
additionalParams = [ \
|
||||
makeVulkanTypeSimple(True, "uint8_t", 1, "snapshotTraceBegin"),
|
||||
makeVulkanTypeSimple(False, "size_t", 0, "snapshotTraceBytes"),
|
||||
makeVulkanTypeSimple(False, "android::base::BumpPool", 1, "pool"),]
|
||||
|
||||
if api.retType.typeName != "void":
|
||||
additionalParams.append( \
|
||||
makeVulkanTypeSimple(False, api.retType.typeName, 0, "input_result"))
|
||||
|
||||
apiForSnapshot = \
|
||||
api.withCustomParameters( \
|
||||
additionalParams + \
|
||||
api.parameters).withCustomReturnType( \
|
||||
makeVulkanTypeSimple(False, "void", 0, "void"))
|
||||
|
||||
self.feature_apis.append((self.currentFeature, apiForSnapshot))
|
||||
|
||||
self.cgenHeader.stmt(self.cgenHeader.makeFuncProto(apiForSnapshot))
|
||||
self.module.appendHeader(self.cgenHeader.swapCode())
|
||||
|
||||
self.cgenImpl.emitFuncImpl( \
|
||||
apiForSnapshot, lambda cgen: emit_impl(self.typeInfo, apiForSnapshot, cgen))
|
||||
self.module.appendImpl(self.cgenImpl.swapCode())
|
||||
|
||||
def onEnd(self,):
|
||||
self.module.appendHeader(decoder_snapshot_decl_postamble)
|
||||
self.module.appendImpl(decoder_snapshot_impl_postamble)
|
||||
self.cgenHeader.decrIndent()
|
||||
|
||||
for feature, api in self.feature_apis:
|
||||
if feature is not None:
|
||||
self.cgenImpl.line("#ifdef %s" % feature)
|
||||
|
||||
apiImplShell = \
|
||||
api.withModifiedName("VkDecoderSnapshot::" + api.name)
|
||||
|
||||
self.cgenImpl.emitFuncImpl( \
|
||||
apiImplShell, lambda cgen: emit_passthrough_to_impl(self.typeInfo, api, cgen))
|
||||
|
||||
if feature is not None:
|
||||
self.cgenImpl.line("#endif")
|
||||
|
||||
self.module.appendImpl(self.cgenImpl.swapCode())
|
||||
|
||||
383
src/gfxstream/codegen/scripts/cereal/deepcopy.py
Normal file
383
src/gfxstream/codegen/scripts/cereal/deepcopy.py
Normal file
|
|
@ -0,0 +1,383 @@
|
|||
# Copyright (c) 2018 The Android Open Source Project
|
||||
# Copyright (c) 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from .common.codegen import CodeGen
|
||||
from .common.vulkantypes import \
|
||||
VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator
|
||||
|
||||
from .wrapperdefs import VulkanWrapperGenerator
|
||||
from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE, EXTENSION_SIZE_API_NAME
|
||||
|
||||
class DeepcopyCodegen(VulkanTypeIterator):
|
||||
def __init__(self, cgen, inputVars, poolVarName, rootVarName, prefix, skipValues=False):
|
||||
self.cgen = cgen
|
||||
self.inputVars = inputVars
|
||||
self.prefix = prefix
|
||||
self.poolVarName = poolVarName
|
||||
self.rootVarName = rootVarName
|
||||
self.skipValues = skipValues
|
||||
|
||||
def makeAccess(varName, asPtr = True):
|
||||
return lambda t: self.cgen.generalAccess(t, parentVarName = varName, asPtr = asPtr)
|
||||
|
||||
def makeLengthAccess(varName):
|
||||
return lambda t: self.cgen.generalLengthAccess(t, parentVarName = varName)
|
||||
|
||||
def makeLengthAccessGuard(varName):
|
||||
return lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName=varName)
|
||||
|
||||
self.exprAccessorLhs = makeAccess(self.inputVars[0])
|
||||
self.exprAccessorRhs = makeAccess(self.inputVars[1])
|
||||
|
||||
self.exprAccessorValueLhs = makeAccess(self.inputVars[0], asPtr = False)
|
||||
self.exprAccessorValueRhs = makeAccess(self.inputVars[1], asPtr = False)
|
||||
|
||||
self.lenAccessorLhs = makeLengthAccess(self.inputVars[0])
|
||||
self.lenAccessorRhs = makeLengthAccess(self.inputVars[1])
|
||||
|
||||
self.lenAccessorGuardLhs = makeLengthAccessGuard(self.inputVars[0])
|
||||
self.lenAccessorGuardRhs = makeLengthAccessGuard(self.inputVars[1])
|
||||
|
||||
self.checked = False
|
||||
|
||||
def needSkip(self, vulkanType):
|
||||
return False
|
||||
|
||||
def makeCastExpr(self, vulkanType):
|
||||
return "(%s)" % (
|
||||
self.cgen.makeCTypeDecl(vulkanType, useParamName=False))
|
||||
|
||||
def makeNonConstCastForCopy(self, access, vulkanType):
|
||||
if vulkanType.staticArrExpr:
|
||||
casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
|
||||
elif vulkanType.accessibleAsPointer():
|
||||
casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForNonConstAccess()), access)
|
||||
else:
|
||||
casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
|
||||
return casted
|
||||
|
||||
def makeAllocBytesExpr(self, lenAccess, vulkanType):
|
||||
sizeof = self.cgen.sizeofExpr( \
|
||||
vulkanType.getForValueAccess())
|
||||
if lenAccess:
|
||||
bytesExpr = "%s * %s" % (lenAccess, sizeof)
|
||||
else:
|
||||
bytesExpr = sizeof
|
||||
|
||||
return bytesExpr
|
||||
|
||||
def onCheck(self, vulkanType):
|
||||
pass
|
||||
|
||||
def endCheck(self, vulkanType):
|
||||
pass
|
||||
|
||||
def onCompoundType(self, vulkanType):
|
||||
|
||||
if self.needSkip(vulkanType):
|
||||
self.cgen.line("// TODO: Unsupported : %s" %
|
||||
self.cgen.makeCTypeDecl(vulkanType))
|
||||
return
|
||||
|
||||
accessLhs = self.exprAccessorLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
lenAccessLhs = self.lenAccessorLhs(vulkanType)
|
||||
lenAccessRhs = self.lenAccessorRhs(vulkanType)
|
||||
|
||||
lenAccessorGuardLhs = self.lenAccessorGuardLhs(vulkanType)
|
||||
lenAccessorGuardRhs = self.lenAccessorGuardRhs(vulkanType)
|
||||
|
||||
isPtr = vulkanType.pointerIndirectionLevels > 0
|
||||
|
||||
if lenAccessorGuardLhs is not None:
|
||||
self.cgen.beginIf(lenAccessorGuardLhs)
|
||||
|
||||
if isPtr:
|
||||
self.cgen.stmt("%s = nullptr" % accessRhs)
|
||||
self.cgen.beginIf(accessLhs)
|
||||
|
||||
self.cgen.stmt( \
|
||||
"%s = %s%s->alloc(%s)" % \
|
||||
(accessRhs, self.makeCastExpr(vulkanType.getForNonConstAccess()),
|
||||
self.poolVarName, self.makeAllocBytesExpr(lenAccessLhs, vulkanType)))
|
||||
|
||||
if lenAccessLhs is not None:
|
||||
|
||||
loopVar = "i"
|
||||
accessLhs = "%s + %s" % (accessLhs, loopVar)
|
||||
forInit = "uint32_t %s = 0" % loopVar
|
||||
forCond = "%s < (uint32_t)%s" % (loopVar, lenAccessLhs)
|
||||
forIncr = "++%s" % loopVar
|
||||
|
||||
if isPtr:
|
||||
# Avoid generating a self-assign.
|
||||
if lenAccessRhs != lenAccessLhs:
|
||||
self.cgen.stmt("%s = %s" % (lenAccessRhs, lenAccessLhs))
|
||||
|
||||
accessRhs = "%s + %s" % (accessRhs, loopVar)
|
||||
self.cgen.beginFor(forInit, forCond, forIncr)
|
||||
|
||||
|
||||
accessRhsCasted = self.makeNonConstCastForCopy(accessRhs, vulkanType)
|
||||
|
||||
self.cgen.funcCall(None, self.prefix + vulkanType.typeName,
|
||||
[self.poolVarName, self.rootVarName, accessLhs, accessRhsCasted])
|
||||
|
||||
if lenAccessLhs is not None:
|
||||
self.cgen.endFor()
|
||||
|
||||
if isPtr:
|
||||
self.cgen.endIf()
|
||||
|
||||
if lenAccessorGuardLhs is not None:
|
||||
self.cgen.endIf()
|
||||
|
||||
def onString(self, vulkanType):
|
||||
accessLhs = self.exprAccessorLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
self.cgen.stmt("%s = nullptr" % accessRhs)
|
||||
self.cgen.beginIf(accessLhs)
|
||||
|
||||
self.cgen.stmt( \
|
||||
"%s = %s->strDup(%s)" % \
|
||||
(accessRhs,
|
||||
self.poolVarName,
|
||||
accessLhs))
|
||||
|
||||
self.cgen.endIf()
|
||||
|
||||
def onStringArray(self, vulkanType):
|
||||
accessLhs = self.exprAccessorLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
lenAccessLhs = self.lenAccessorLhs(vulkanType)
|
||||
|
||||
self.cgen.stmt("%s = nullptr" % accessRhs)
|
||||
self.cgen.beginIf("%s && %s" % (accessLhs, lenAccessLhs))
|
||||
|
||||
self.cgen.stmt( \
|
||||
"%s = %s->strDupArray(%s, %s)" % \
|
||||
(accessRhs,
|
||||
self.poolVarName,
|
||||
accessLhs,
|
||||
lenAccessLhs))
|
||||
|
||||
self.cgen.endIf()
|
||||
|
||||
def onStaticArr(self, vulkanType):
|
||||
accessLhs = self.exprAccessorValueLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorValueRhs(vulkanType)
|
||||
|
||||
lenAccessLhs = self.lenAccessorLhs(vulkanType)
|
||||
|
||||
bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType)
|
||||
self.cgen.stmt("memcpy(%s, %s, %s)" % (accessRhs, accessLhs, bytesExpr))
|
||||
|
||||
def onStructExtension(self, vulkanType):
|
||||
|
||||
lhs = self.exprAccessorLhs(vulkanType)
|
||||
rhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
rhsExpr = "(%s)(%s)" % ("void*", rhs)
|
||||
|
||||
nextVar = "from_%s" % vulkanType.paramName
|
||||
sizeVar = "%s_size" % vulkanType.paramName
|
||||
|
||||
self.cgen.beginIf("%s == VK_STRUCTURE_TYPE_MAX_ENUM" %
|
||||
self.rootVarName)
|
||||
self.cgen.stmt("%s = from->sType" % self.rootVarName)
|
||||
self.cgen.endIf()
|
||||
|
||||
self.cgen.stmt("const void* %s = %s" % (nextVar, self.inputVars[0]))
|
||||
self.cgen.stmt("size_t %s = 0u" % sizeVar)
|
||||
self.cgen.beginWhile("!%s && %s" % (sizeVar, nextVar))
|
||||
self.cgen.stmt("%s = static_cast<const vk_struct_common*>(%s)->%s" % (
|
||||
nextVar, nextVar, vulkanType.paramName
|
||||
))
|
||||
self.cgen.stmt("%s = %s(%s, %s)" % (
|
||||
sizeVar, EXTENSION_SIZE_API_NAME, self.rootVarName, nextVar))
|
||||
self.cgen.endWhile()
|
||||
|
||||
self.cgen.stmt("%s = nullptr" % rhs)
|
||||
|
||||
self.cgen.beginIf(sizeVar)
|
||||
|
||||
self.cgen.stmt( \
|
||||
"%s = %s%s->alloc(%s)" % \
|
||||
(rhs, self.makeCastExpr(vulkanType.getForNonConstAccess()), self.poolVarName, sizeVar))
|
||||
|
||||
self.cgen.funcCall(None, self.prefix + "extension_struct",
|
||||
[self.poolVarName, self.rootVarName, nextVar, rhsExpr])
|
||||
|
||||
self.cgen.endIf()
|
||||
|
||||
def onPointer(self, vulkanType):
|
||||
|
||||
accessLhs = self.exprAccessorLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
if self.needSkip(vulkanType):
|
||||
self.cgen.stmt("%s = nullptr" % accessRhs)
|
||||
return
|
||||
|
||||
lenAccessLhs = self.lenAccessorLhs(vulkanType)
|
||||
|
||||
self.cgen.stmt("%s = nullptr" % accessRhs)
|
||||
self.cgen.beginIf(accessLhs)
|
||||
|
||||
bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType)
|
||||
|
||||
self.cgen.stmt( \
|
||||
"%s = %s%s->dupArray(%s, %s)" % \
|
||||
(accessRhs,
|
||||
self.makeCastExpr(vulkanType.getForNonConstAccess()),
|
||||
self.poolVarName,
|
||||
accessLhs,
|
||||
bytesExpr))
|
||||
|
||||
self.cgen.endIf()
|
||||
|
||||
def onValue(self, vulkanType):
|
||||
if self.skipValues:
|
||||
return
|
||||
|
||||
accessLhs = self.exprAccessorValueLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorValueRhs(vulkanType)
|
||||
|
||||
self.cgen.stmt("%s = %s" % (accessRhs, accessLhs))
|
||||
|
||||
class VulkanDeepcopy(VulkanWrapperGenerator):
|
||||
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
|
||||
self.codegen = CodeGen()
|
||||
|
||||
self.deepcopyPrefix = "deepcopy_"
|
||||
self.deepcopyVars = ["from", "to"]
|
||||
self.deepcopyAllocatorVarName = "alloc"
|
||||
self.deepcopyAllocatorParam = \
|
||||
makeVulkanTypeSimple(False, "Allocator", 1,
|
||||
self.deepcopyAllocatorVarName)
|
||||
self.deepcopyRootVarName = "rootType"
|
||||
self.deepcopyRootParam = \
|
||||
makeVulkanTypeSimple(False, "VkStructureType",
|
||||
0, self.deepcopyRootVarName)
|
||||
self.voidType = makeVulkanTypeSimple(False, "void", 0)
|
||||
|
||||
self.deepcopyCodegen = \
|
||||
DeepcopyCodegen(
|
||||
None,
|
||||
self.deepcopyVars,
|
||||
self.deepcopyAllocatorVarName,
|
||||
self.deepcopyRootVarName,
|
||||
self.deepcopyPrefix,
|
||||
skipValues=True)
|
||||
|
||||
self.knownDefs = {}
|
||||
|
||||
self.extensionDeepcopyPrototype = \
|
||||
VulkanAPI(self.deepcopyPrefix + "extension_struct",
|
||||
self.voidType,
|
||||
[self.deepcopyAllocatorParam,
|
||||
self.deepcopyRootParam,
|
||||
STRUCT_EXTENSION_PARAM,
|
||||
STRUCT_EXTENSION_PARAM_FOR_WRITE])
|
||||
|
||||
def onBegin(self,):
|
||||
VulkanWrapperGenerator.onBegin(self)
|
||||
self.module.appendImpl(self.codegen.makeFuncDecl(
|
||||
self.extensionDeepcopyPrototype))
|
||||
|
||||
def onGenType(self, typeXml, name, alias):
|
||||
VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
|
||||
|
||||
if name in self.knownDefs:
|
||||
return
|
||||
|
||||
category = self.typeInfo.categoryOf(name)
|
||||
|
||||
if category in ["struct", "union"] and alias:
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncAlias(self.deepcopyPrefix + name,
|
||||
self.deepcopyPrefix + alias))
|
||||
|
||||
if category in ["struct", "union"] and not alias:
|
||||
|
||||
structInfo = self.typeInfo.structs[name]
|
||||
|
||||
typeFromName = \
|
||||
lambda varname: \
|
||||
makeVulkanTypeSimple(varname == "from", name, 1, varname)
|
||||
|
||||
deepcopyParams = \
|
||||
[self.deepcopyAllocatorParam, self.deepcopyRootParam] + \
|
||||
list(map(typeFromName, self.deepcopyVars))
|
||||
|
||||
deepcopyPrototype = \
|
||||
VulkanAPI(self.deepcopyPrefix + name,
|
||||
self.voidType,
|
||||
deepcopyParams)
|
||||
|
||||
def structDeepcopyDef(cgen):
|
||||
self.deepcopyCodegen.cgen = cgen
|
||||
canSimplyAssign = True
|
||||
for member in structInfo.members:
|
||||
if not member.isSimpleValueType(self.typeInfo):
|
||||
canSimplyAssign = False
|
||||
|
||||
cgen.stmt("(void)%s" % self.deepcopyAllocatorVarName)
|
||||
cgen.stmt("(void)%s" % self.deepcopyRootVarName)
|
||||
cgen.stmt("*to = *from")
|
||||
if canSimplyAssign:
|
||||
pass
|
||||
else:
|
||||
for member in structInfo.members:
|
||||
iterateVulkanType(self.typeInfo, member,
|
||||
self.deepcopyCodegen)
|
||||
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncDecl(deepcopyPrototype))
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(deepcopyPrototype, structDeepcopyDef))
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
|
||||
|
||||
def onEnd(self,):
|
||||
VulkanWrapperGenerator.onEnd(self)
|
||||
|
||||
def deepcopyDstExpr(cgen, typeName):
|
||||
return cgen.makeReinterpretCast( \
|
||||
STRUCT_EXTENSION_PARAM_FOR_WRITE.paramName,
|
||||
typeName, const=False)
|
||||
|
||||
def forEachExtensionDeepcopy(ext, castedAccess, cgen):
|
||||
cgen.funcCall(None, self.deepcopyPrefix + ext.name,
|
||||
[self.deepcopyAllocatorVarName,
|
||||
self.deepcopyRootVarName,
|
||||
castedAccess, deepcopyDstExpr(cgen, ext.name)])
|
||||
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(
|
||||
self.extensionDeepcopyPrototype,
|
||||
lambda cgen: self.emitForEachStructExtension(
|
||||
cgen,
|
||||
self.voidType,
|
||||
STRUCT_EXTENSION_PARAM,
|
||||
forEachExtensionDeepcopy,
|
||||
rootTypeVar=self.deepcopyRootParam)))
|
||||
501
src/gfxstream/codegen/scripts/cereal/dispatch.py
Normal file
501
src/gfxstream/codegen/scripts/cereal/dispatch.py
Normal file
|
|
@ -0,0 +1,501 @@
|
|||
# Copyright (c) 2018 The Android Open Source Project
|
||||
# Copyright (c) 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from .common.codegen import CodeGen
|
||||
from .common.vulkantypes import \
|
||||
VulkanAPI, makeVulkanTypeSimple, iterateVulkanType
|
||||
|
||||
from .wrapperdefs import VulkanWrapperGenerator
|
||||
|
||||
# No real good way to automatically infer the most important Vulkan API
|
||||
# functions as it relates to which getProcAddress function to use, plus
|
||||
# we might want to control which function to use depending on our
|
||||
# performance needs.
|
||||
|
||||
# This is based on the minimum set of functions needed to be directly
|
||||
# queried with dlsym and not returning null.
|
||||
getProcAddrFuncs = [
|
||||
"vkGetInstanceProcAddr",
|
||||
"vkDestroyInstance",
|
||||
"vkEnumeratePhysicalDevices",
|
||||
"vkGetPhysicalDeviceFeatures",
|
||||
"vkGetPhysicalDeviceFormatProperties",
|
||||
"vkGetPhysicalDeviceImageFormatProperties",
|
||||
"vkGetPhysicalDeviceProperties",
|
||||
"vkGetPhysicalDeviceQueueFamilyProperties",
|
||||
"vkGetPhysicalDeviceMemoryProperties",
|
||||
"vkCreateDevice",
|
||||
"vkDestroyDevice",
|
||||
"vkEnumerateDeviceExtensionProperties",
|
||||
"vkEnumerateDeviceLayerProperties",
|
||||
]
|
||||
|
||||
# Some methods can only be found using dlsym() while we cannot get the function
|
||||
# address using vkGetInstProcAddr() or vkGetDeviceProcAddr(). These function
|
||||
# pointers should only be initialized when setting up the dispatch from system
|
||||
# loader.
|
||||
getProcAddrOnlyFuncs = [
|
||||
"vkGetMTLDeviceMVK",
|
||||
"vkSetMTLTextureMVK",
|
||||
"vkGetMTLTextureMVK",
|
||||
"vkGetMTLBufferMVK",
|
||||
"vkUseIOSurfaceMVK",
|
||||
"vkGetIOSurfaceMVK",
|
||||
]
|
||||
|
||||
getInstanceProcAddrNoInstanceFuncs = [
|
||||
"vkCreateInstance",
|
||||
"vkEnumerateInstanceExtensionProperties",
|
||||
"vkEnumerateInstanceLayerProperties",
|
||||
]
|
||||
|
||||
getInstanceProcAddrFuncs = [
|
||||
"vkGetDeviceProcAddr",
|
||||
"vkCreateSwapchainKHR",
|
||||
"vkDestroySwapchainKHR",
|
||||
"vkGetSwapchainImagesKHR",
|
||||
"vkAcquireNextImageKHR",
|
||||
"vkQueuePresentKHR",
|
||||
"vkCreateMacOSSurfaceMVK",
|
||||
"vkCreateWin32SurfaceKHR",
|
||||
"vkGetPhysicalDeviceWin32PresentationSupportKHR",
|
||||
"vkCreateXlibSurfaceKHR",
|
||||
"vkGetPhysicalDeviceXlibPresentationSupportKHR",
|
||||
"vkCreateXcbSurfaceKHR",
|
||||
"vkGetPhysicalDeviceXcbPresentationSupportKHR",
|
||||
"vkGetPhysicalDeviceSparseImageFormatProperties",
|
||||
"vkEnumerateInstanceVersion",
|
||||
"vkEnumeratePhysicalDeviceGroups",
|
||||
"vkGetPhysicalDeviceFeatures2",
|
||||
"vkGetPhysicalDeviceProperties2",
|
||||
"vkGetPhysicalDeviceFormatProperties2",
|
||||
"vkGetPhysicalDeviceImageFormatProperties2",
|
||||
"vkGetPhysicalDeviceQueueFamilyProperties2",
|
||||
"vkGetPhysicalDeviceMemoryProperties2",
|
||||
"vkGetPhysicalDeviceSparseImageFormatProperties2",
|
||||
"vkGetPhysicalDeviceExternalBufferProperties",
|
||||
"vkGetPhysicalDeviceExternalFenceProperties",
|
||||
"vkGetPhysicalDeviceExternalSemaphoreProperties",
|
||||
]
|
||||
|
||||
# Implicitly, everything else is going to be obtained
|
||||
# with vkGetDeviceProcAddr,
|
||||
# unless it has instance in the arg.
|
||||
|
||||
def isGetProcAddressAPI(vulkanApi):
|
||||
return vulkanApi.name in getProcAddrFuncs
|
||||
|
||||
def isGetProcAddressOnlyAPI(vulkanApi):
|
||||
return vulkanApi.name in getProcAddrOnlyFuncs
|
||||
|
||||
def isGetInstanceProcAddressNoInstanceAPI(vulkanApi):
|
||||
return vulkanApi.name in getInstanceProcAddrNoInstanceFuncs
|
||||
|
||||
def isGetInstanceProcAddressAPI(vulkanApi):
|
||||
if vulkanApi.name in getInstanceProcAddrFuncs:
|
||||
return True
|
||||
|
||||
if vulkanApi.parameters[0].typeName == "VkInstance":
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def isGetDeviceProcAddressAPI(vulkanApi):
|
||||
if isGetProcAddressAPI(vulkanApi):
|
||||
return False
|
||||
|
||||
if isGetProcAddressOnlyAPI(vulkanApi):
|
||||
return False
|
||||
|
||||
if isGetInstanceProcAddressAPI(vulkanApi):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def inferProcAddressFuncType(vulkanApi):
|
||||
if isGetProcAddressAPI(vulkanApi):
|
||||
return "global"
|
||||
if isGetProcAddressOnlyAPI(vulkanApi):
|
||||
return "global-only"
|
||||
if isGetInstanceProcAddressNoInstanceAPI(vulkanApi):
|
||||
return "global-instance"
|
||||
if isGetInstanceProcAddressAPI(vulkanApi):
|
||||
return "instance"
|
||||
return "device"
|
||||
|
||||
# VulkanDispatch defines a struct, VulkanDispatch,
|
||||
# that is populated by function pointers from the Vulkan
|
||||
# loader. No attempt is made to do something different
|
||||
# for instance vs device functions.
|
||||
class VulkanDispatch(VulkanWrapperGenerator):
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
|
||||
self.apisToGet = {}
|
||||
|
||||
self.cgenHeader = CodeGen()
|
||||
self.cgenImpl = CodeGen()
|
||||
self.typeInfo = typeInfo
|
||||
|
||||
self.currentFeature = ""
|
||||
self.featureForCodegen = ""
|
||||
|
||||
def onBegin(self):
|
||||
|
||||
# The first way is to use just the loader to get symbols. This doesn't
|
||||
# necessarily work with extensions because at that point the dispatch
|
||||
# table needs to be specific to a particular Vulkan instance or device.
|
||||
|
||||
self.cgenHeader.line("""
|
||||
void init_vulkan_dispatch_from_system_loader(
|
||||
DlOpenFunc dlOpenFunc,
|
||||
DlSymFunc dlSymFunc,
|
||||
VulkanDispatch* dispatch_out);
|
||||
""")
|
||||
|
||||
# The second way is to initialize the table from a given Vulkan
|
||||
# instance or device. Provided the instance or device was created with
|
||||
# the right extensions, we can obtain function pointers to extension
|
||||
# functions this way.
|
||||
|
||||
self.cgenHeader.line("""
|
||||
void init_vulkan_dispatch_from_instance(
|
||||
VulkanDispatch* vk,
|
||||
VkInstance instance,
|
||||
VulkanDispatch* dispatch_out);
|
||||
""")
|
||||
self.cgenHeader.line("""
|
||||
void init_vulkan_dispatch_from_device(
|
||||
VulkanDispatch* vk,
|
||||
VkDevice device,
|
||||
VulkanDispatch* dispatch_out);
|
||||
""")
|
||||
|
||||
# After populating a VulkanDispatch with the above methods,
|
||||
# it can be useful to check whether the Vulkan 1.0 or 1.1 methods
|
||||
# are all there.
|
||||
def emit_feature_check_decl(cgen, tag, featureToCheck):
|
||||
cgen.line("""
|
||||
bool vulkan_dispatch_check_%s_%s(
|
||||
const VulkanDispatch* vk);
|
||||
""" % (tag, featureToCheck))
|
||||
|
||||
emit_feature_check_decl(self.cgenHeader, "instance", "VK_VERSION_1_0")
|
||||
emit_feature_check_decl(self.cgenHeader, "instance", "VK_VERSION_1_1")
|
||||
emit_feature_check_decl(self.cgenHeader, "device", "VK_VERSION_1_0")
|
||||
emit_feature_check_decl(self.cgenHeader, "device", "VK_VERSION_1_1")
|
||||
|
||||
self.cgenHeader.line("struct VulkanDispatch {")
|
||||
self.module.appendHeader(self.cgenHeader.swapCode())
|
||||
|
||||
def syncFeatureQuiet(self, cgen, feature):
|
||||
if self.featureForCodegen != feature:
|
||||
if feature == "":
|
||||
self.featureForCodegen = feature
|
||||
return
|
||||
|
||||
self.featureForCodegen = feature
|
||||
|
||||
def syncFeature(self, cgen, feature):
|
||||
if self.featureForCodegen != feature:
|
||||
if feature == "":
|
||||
cgen.leftline("#endif")
|
||||
self.featureForCodegen = feature
|
||||
return
|
||||
|
||||
if self.featureForCodegen != "":
|
||||
cgen.leftline("#endif")
|
||||
|
||||
cgen.leftline("#ifdef %s" % feature)
|
||||
self.featureForCodegen = feature
|
||||
|
||||
def makeDlsymCall(self, cgen, apiname, typedecl):
|
||||
cgen.stmt( \
|
||||
"out->%s = (%s)dlSymFunc(lib, \"%s\")" % \
|
||||
(apiname, typedecl, apiname))
|
||||
|
||||
def makeGetInstanceProcAddrCall(self, cgen, dispatch, instance, apiname, typedecl):
|
||||
cgen.stmt( \
|
||||
"out->%s = (%s)%s->vkGetInstanceProcAddr(%s, \"%s\")" % \
|
||||
(apiname, typedecl, dispatch, instance, apiname))
|
||||
|
||||
def makeGetDeviceProcAddrCall(self, cgen, dispatch, device, apiname, typedecl):
|
||||
cgen.stmt( \
|
||||
"out->%s = (%s)%s->vkGetDeviceProcAddr(%s, \"%s\")" % \
|
||||
(apiname, typedecl, dispatch, device, apiname))
|
||||
|
||||
def onEnd(self):
|
||||
self.cgenHeader.line("};")
|
||||
self.module.appendHeader(self.cgenHeader.swapCode())
|
||||
|
||||
# Getting dispatch tables from the loader
|
||||
self.cgenImpl.line("""
|
||||
void init_vulkan_dispatch_from_system_loader(
|
||||
DlOpenFunc dlOpenFunc,
|
||||
DlSymFunc dlSymFunc,
|
||||
VulkanDispatch* out)""")
|
||||
|
||||
self.cgenImpl.beginBlock()
|
||||
|
||||
self.cgenImpl.stmt("memset(out, 0x0, sizeof(VulkanDispatch))")
|
||||
|
||||
self.cgenImpl.stmt("void* lib = dlOpenFunc()")
|
||||
self.cgenImpl.stmt("if (!lib) return")
|
||||
|
||||
apis = \
|
||||
self.apisToGet["global"] + \
|
||||
self.apisToGet["global-instance"] + \
|
||||
self.apisToGet["instance"] + \
|
||||
self.apisToGet["device"]
|
||||
|
||||
if "global-only" in self.apisToGet:
|
||||
apis = apis + self.apisToGet["global-only"]
|
||||
|
||||
for vulkanApi, typeDecl, feature in apis:
|
||||
self.syncFeature(self.cgenImpl, feature)
|
||||
self.makeDlsymCall(self.cgenImpl, vulkanApi.name, typeDecl)
|
||||
|
||||
self.syncFeature(self.cgenImpl, "")
|
||||
self.cgenImpl.endBlock()
|
||||
|
||||
# Getting instance dispatch tables
|
||||
self.cgenImpl.line("""
|
||||
void init_vulkan_dispatch_from_instance(
|
||||
VulkanDispatch* vk,
|
||||
VkInstance instance,
|
||||
VulkanDispatch* out)""")
|
||||
|
||||
self.cgenImpl.beginBlock()
|
||||
|
||||
self.cgenImpl.stmt("memset(out, 0x0, sizeof(VulkanDispatch))")
|
||||
|
||||
apis = \
|
||||
self.apisToGet["global"] + \
|
||||
self.apisToGet["global-instance"] + \
|
||||
self.apisToGet["instance"] + \
|
||||
self.apisToGet["device"]
|
||||
|
||||
for vulkanApi, typeDecl, feature in apis:
|
||||
self.syncFeature(self.cgenImpl, feature)
|
||||
self.makeGetInstanceProcAddrCall(
|
||||
self.cgenImpl, "vk", "instance", vulkanApi.name, typeDecl)
|
||||
|
||||
self.syncFeature(self.cgenImpl, "")
|
||||
self.cgenImpl.endBlock()
|
||||
|
||||
# Getting device dispatch tables
|
||||
self.cgenImpl.line("""
|
||||
void init_vulkan_dispatch_from_device(
|
||||
VulkanDispatch* vk,
|
||||
VkDevice device,
|
||||
VulkanDispatch* out)""")
|
||||
|
||||
self.cgenImpl.beginBlock()
|
||||
|
||||
self.cgenImpl.stmt("memset(out, 0x0, sizeof(VulkanDispatch))")
|
||||
|
||||
apis = \
|
||||
self.apisToGet["global"] + \
|
||||
self.apisToGet["global-instance"] + \
|
||||
self.apisToGet["instance"] + \
|
||||
self.apisToGet["device"]
|
||||
|
||||
for vulkanApi, typeDecl, feature in apis:
|
||||
self.syncFeature(self.cgenImpl, feature)
|
||||
self.makeGetDeviceProcAddrCall(
|
||||
self.cgenImpl, "vk", "device", vulkanApi.name, typeDecl)
|
||||
|
||||
self.syncFeature(self.cgenImpl, "")
|
||||
self.cgenImpl.endBlock()
|
||||
|
||||
# Check Vulkan 1.0 / 1.1 functions
|
||||
|
||||
def emit_check_impl(cgen, dispatchVar, feature, featureToCheck, apiName):
|
||||
if feature == featureToCheck:
|
||||
cgen.beginIf("!%s->%s" % (dispatchVar, apiName))
|
||||
cgen.stmt("fprintf(stderr, \"%s check failed: %s not found\\n\")" % (featureToCheck, apiName))
|
||||
cgen.stmt("good = false")
|
||||
cgen.endIf()
|
||||
|
||||
def emit_feature_check_impl(context, cgen, tag, featureToCheck, apis):
|
||||
cgen.line("""
|
||||
bool vulkan_dispatch_check_%s_%s(
|
||||
const VulkanDispatch* vk)
|
||||
""" % (tag, featureToCheck))
|
||||
|
||||
cgen.beginBlock()
|
||||
|
||||
cgen.stmt("bool good = true")
|
||||
|
||||
for vulkanApi, typeDecl, feature in apis:
|
||||
context.syncFeatureQuiet(self.cgenImpl, feature)
|
||||
emit_check_impl(cgen, "vk", feature, featureToCheck, vulkanApi.name)
|
||||
|
||||
context.syncFeatureQuiet(self.cgenImpl, "")
|
||||
|
||||
cgen.stmt("return good")
|
||||
cgen.endBlock()
|
||||
|
||||
instanceApis = self.apisToGet["global-instance"] + self.apisToGet["instance"]
|
||||
|
||||
emit_feature_check_impl(self, self.cgenImpl, "instance", "VK_VERSION_1_0", instanceApis)
|
||||
emit_feature_check_impl(self, self.cgenImpl, "instance", "VK_VERSION_1_1", instanceApis)
|
||||
emit_feature_check_impl(self, self.cgenImpl, "device", "VK_VERSION_1_0", self.apisToGet["device"])
|
||||
emit_feature_check_impl(self, self.cgenImpl, "device", "VK_VERSION_1_1", self.apisToGet["device"])
|
||||
|
||||
self.module.appendImpl(self.cgenImpl.swapCode())
|
||||
|
||||
def onBeginFeature(self, featureName, featureType):
|
||||
self.currentFeature = featureName
|
||||
|
||||
def onGenType(self, typeXml, name, alias):
|
||||
VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
|
||||
|
||||
vulkanApi = self.typeInfo.apis[name]
|
||||
|
||||
typeDecl = "PFN_%s" % name
|
||||
|
||||
procAddressType = inferProcAddressFuncType(vulkanApi)
|
||||
|
||||
self.cgenHeader.stmt("%s %s" % (typeDecl, name));
|
||||
self.module.appendHeader(self.cgenHeader.swapCode())
|
||||
|
||||
current = self.apisToGet.get(procAddressType, [])
|
||||
if current == []:
|
||||
self.apisToGet[procAddressType] = current
|
||||
current.append((vulkanApi, typeDecl, self.currentFeature))
|
||||
|
||||
# VulkanDispatchFast allows one to get the optimal function pointers
|
||||
# for a given Vulkan API call, in order to improve performance.
|
||||
#
|
||||
# We can optionally query VkDevices to get function pointers that are
|
||||
# closer to the ICD and have fewer levels of indirection from the loader
|
||||
# to get there.
|
||||
# See
|
||||
# https://github.com/KhronosGroup/Vulkan-Loader/blob/master/loader/LoaderAndLayerInterface.md
|
||||
# for more info.
|
||||
#
|
||||
# This requires the calling C++ code to provide functions to
|
||||
# generate the desired instances and devices, otherwise we won't know
|
||||
# which instance or device to pass to vkGet(Instance|Device)ProcAddr,
|
||||
# so it does push more complexity to the user.
|
||||
class VulkanDispatchFast(VulkanDispatch):
|
||||
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanDispatch.__init__(self, module, typeInfo)
|
||||
|
||||
def onBegin(self):
|
||||
self.cgenHeader.line("""
|
||||
void init_vulkan_dispatch_from_system_loader(
|
||||
DlOpenFunc dlOpenFunc,
|
||||
DlSymFunc dlSymFunc,
|
||||
InstanceGetter instanceGetter,
|
||||
DeviceGetter deviceGetter,
|
||||
VulkanDispatch* dispatch_out);
|
||||
""")
|
||||
|
||||
self.cgenHeader.line("struct VulkanDispatch {")
|
||||
self.cgenHeader.line("VkInstance instance;")
|
||||
self.cgenHeader.line("VkPhysicalDevice physicalDevice;")
|
||||
self.cgenHeader.line("uint32_t physicalDeviceQueueFamilyInfoCount;")
|
||||
self.cgenHeader.line("VkQueueFamilyProperties* physicalDeviceQueueFamilyInfos;")
|
||||
self.cgenHeader.line("VkDevice device;")
|
||||
self.cgenHeader.line("bool presentCapable;")
|
||||
self.module.appendHeader(self.cgenHeader.swapCode())
|
||||
|
||||
def makeGetProcAddr(self, cgen, dispatchLevel, dispatch, apiname, typedecl):
|
||||
if dispatchLevel == "instance":
|
||||
funcname = "vkGetInstanceProcAddr"
|
||||
elif dispatchLevel == "device":
|
||||
funcname = "vkGetDeviceProcAddr"
|
||||
else:
|
||||
raise
|
||||
|
||||
cgen.stmt( \
|
||||
"out->%s = (%s)out->%s(%s, \"%s\")" % \
|
||||
(apiname, typedecl, funcname, dispatch, apiname))
|
||||
|
||||
def onEnd(self):
|
||||
self.cgenHeader.line("};")
|
||||
self.module.appendHeader(self.cgenHeader.swapCode())
|
||||
|
||||
self.cgenImpl.line("""
|
||||
void init_vulkan_dispatch_from_system_loader(
|
||||
DlOpenFunc dlOpenFunc,
|
||||
DlSymFunc dlSymFunc,
|
||||
InstanceGetter instanceGetter,
|
||||
DeviceGetter deviceGetter,
|
||||
VulkanDispatch* out)""")
|
||||
|
||||
self.cgenImpl.beginBlock()
|
||||
|
||||
self.cgenImpl.stmt("out->instance = nullptr")
|
||||
self.cgenImpl.stmt("out->physicalDevice = nullptr")
|
||||
self.cgenImpl.stmt("out->physicalDeviceQueueFamilyInfoCount = 0")
|
||||
self.cgenImpl.stmt("out->physicalDeviceQueueFamilyInfos = nullptr")
|
||||
self.cgenImpl.stmt("out->device = nullptr")
|
||||
self.cgenImpl.stmt("out->presentCapable = false")
|
||||
|
||||
self.cgenImpl.stmt("void* lib = dlOpenFunc()")
|
||||
self.cgenImpl.stmt("if (!lib) return")
|
||||
|
||||
for vulkanApi, typeDecl, feature in self.apisToGet["global"]:
|
||||
self.syncFeature(self.cgenImpl, feature)
|
||||
self.makeDlsymCall(self.cgenImpl, vulkanApi.name, typeDecl)
|
||||
|
||||
self.syncFeature(self.cgenImpl, "")
|
||||
self.cgenImpl.stmt("if (!out->vkGetInstanceProcAddr) return")
|
||||
|
||||
for vulkanApi, typeDecl, feature in self.apisToGet["global-instance"]:
|
||||
self.syncFeature(self.cgenImpl, feature)
|
||||
self.makeGetProcAddr( \
|
||||
self.cgenImpl, "instance", "nullptr", vulkanApi.name, typeDecl);
|
||||
|
||||
self.syncFeature(self.cgenImpl, "")
|
||||
self.cgenImpl.stmt("if (!instanceGetter(out, &out->instance)) return")
|
||||
|
||||
for vulkanApi, typeDecl, feature in self.apisToGet["instance"]:
|
||||
self.syncFeature(self.cgenImpl, feature)
|
||||
self.makeGetProcAddr( \
|
||||
self.cgenImpl, "instance", "out->instance", vulkanApi.name, typeDecl);
|
||||
|
||||
self.syncFeature(self.cgenImpl, "")
|
||||
|
||||
self.cgenImpl.stmt("if (!deviceGetter(out, out->instance, &out->physicalDevice, &out->physicalDeviceQueueFamilyInfoCount, nullptr, &out->device, &out->presentCapable)) return")
|
||||
self.cgenImpl.stmt("out->physicalDeviceQueueFamilyInfos = (VkQueueFamilyProperties*)malloc(out->physicalDeviceQueueFamilyInfoCount * sizeof(VkQueueFamilyProperties))");
|
||||
self.cgenImpl.stmt("if (!deviceGetter(out, out->instance, &out->physicalDevice, &out->physicalDeviceQueueFamilyInfoCount, out->physicalDeviceQueueFamilyInfos, &out->device, &out->presentCapable)) return")
|
||||
|
||||
for vulkanApi, typeDecl, feature in self.apisToGet["device"]:
|
||||
self.syncFeature(self.cgenImpl, feature)
|
||||
self.makeGetProcAddr( \
|
||||
self.cgenImpl, "device", "out->device", vulkanApi.name, typeDecl);
|
||||
|
||||
self.syncFeature(self.cgenImpl, "")
|
||||
|
||||
self.cgenImpl.endBlock()
|
||||
|
||||
self.module.appendImpl(self.cgenImpl.swapCode())
|
||||
|
||||
def onBeginFeature(self, featureName, featureType):
|
||||
VulkanDispatch.onBeginFeature(self, featureName, featureType);
|
||||
|
||||
def onGenType(self, typeXml, name, alias):
|
||||
VulkanDispatch.onGenType(self, typeXml, name, alias);
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanDispatch.onGenCmd(self, cmdinfo, name, alias);
|
||||
723
src/gfxstream/codegen/scripts/cereal/encoder.py
Normal file
723
src/gfxstream/codegen/scripts/cereal/encoder.py
Normal file
|
|
@ -0,0 +1,723 @@
|
|||
import copy
|
||||
|
||||
from .common.codegen import CodeGen, VulkanWrapperGenerator
|
||||
from .common.vulkantypes import \
|
||||
VulkanAPI, makeVulkanTypeSimple, iterateVulkanType
|
||||
|
||||
from .marshaling import VulkanMarshalingCodegen
|
||||
from .reservedmarshaling import VulkanReservedMarshalingCodegen
|
||||
from .counting import VulkanCountingCodegen
|
||||
from .handlemap import HandleMapCodegen
|
||||
from .deepcopy import DeepcopyCodegen
|
||||
from .transform import TransformCodegen, genTransformsForVulkanType
|
||||
|
||||
from .wrapperdefs import API_PREFIX_RESERVEDMARSHAL
|
||||
from .wrapperdefs import API_PREFIX_MARSHAL
|
||||
from .wrapperdefs import API_PREFIX_UNMARSHAL
|
||||
from .wrapperdefs import ROOT_TYPE_DEFAULT_VALUE
|
||||
from .wrapperdefs import VULKAN_STREAM_TYPE_GUEST
|
||||
|
||||
encoder_decl_preamble = """
|
||||
|
||||
class VkEncoder {
|
||||
public:
|
||||
VkEncoder(gfxstream::guest::IOStream* stream, gfxstream::guest::HealthMonitor<>* healthMonitor = nullptr);
|
||||
~VkEncoder();
|
||||
|
||||
#include "VkEncoder.h.inl"
|
||||
"""
|
||||
|
||||
encoder_decl_postamble = """
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> mImpl;
|
||||
gfxstream::guest::HealthMonitor<>* mHealthMonitor;
|
||||
};
|
||||
"""
|
||||
|
||||
encoder_impl_preamble ="""
|
||||
|
||||
using namespace gfxstream::vk;
|
||||
|
||||
using gfxstream::guest::AutoLock;
|
||||
using gfxstream::guest::Lock;
|
||||
using gfxstream::guest::BumpPool;
|
||||
|
||||
#include "VkEncoder.cpp.inl"
|
||||
|
||||
#define VALIDATE_RET(retType, success, validate) \\
|
||||
retType goldfish_vk_validateResult = validate; \\
|
||||
if (goldfish_vk_validateResult != success) return goldfish_vk_validateResult; \\
|
||||
|
||||
#define VALIDATE_VOID(validate) \\
|
||||
VkResult goldfish_vk_validateResult = validate; \\
|
||||
if (goldfish_vk_validateResult != VK_SUCCESS) return; \\
|
||||
|
||||
"""
|
||||
|
||||
STREAM = "stream"
|
||||
RESOURCES = "sResourceTracker"
|
||||
POOL = "pool"
|
||||
|
||||
ENCODER_PREVALIDATED_APIS = [
|
||||
"vkFlushMappedMemoryRanges",
|
||||
"vkInvalidateMappedMemoryRanges",
|
||||
]
|
||||
|
||||
ENCODER_CUSTOM_RESOURCE_PREPROCESS = [
|
||||
"vkMapMemoryIntoAddressSpaceGOOGLE",
|
||||
"vkDestroyDevice",
|
||||
]
|
||||
|
||||
ENCODER_CUSTOM_RESOURCE_POSTPROCESS = [
|
||||
"vkCreateInstance",
|
||||
"vkCreateDevice",
|
||||
"vkMapMemoryIntoAddressSpaceGOOGLE",
|
||||
"vkGetPhysicalDeviceFeatures2",
|
||||
"vkGetPhysicalDeviceFeatures2KHR",
|
||||
"vkGetPhysicalDeviceProperties",
|
||||
"vkGetPhysicalDeviceProperties2",
|
||||
"vkGetPhysicalDeviceProperties2KHR",
|
||||
"vkCreateDescriptorUpdateTemplate",
|
||||
"vkCreateDescriptorUpdateTemplateKHR",
|
||||
"vkGetPhysicalDeviceExternalSemaphoreProperties",
|
||||
"vkGetPhysicalDeviceExternalSemaphorePropertiesKHR",
|
||||
"vkGetDeviceQueue",
|
||||
"vkGetDeviceQueue2",
|
||||
]
|
||||
|
||||
ENCODER_EXPLICIT_FLUSHED_APIS = [
|
||||
"vkEndCommandBufferAsyncGOOGLE",
|
||||
"vkQueueSubmitAsyncGOOGLE",
|
||||
"vkQueueBindSparseAsyncGOOGLE",
|
||||
"vkQueueWaitIdleAsyncGOOGLE",
|
||||
"vkQueueSignalReleaseImageANDROID",
|
||||
"vkDestroyDevice",
|
||||
]
|
||||
|
||||
SUCCESS_RET_TYPES = {
|
||||
"VkResult" : "VK_SUCCESS",
|
||||
"void" : None,
|
||||
# TODO: Put up success results for other return types here.
|
||||
}
|
||||
|
||||
ENCODER_THIS_PARAM = makeVulkanTypeSimple(False, "VkEncoder", 1, "this")
|
||||
|
||||
# Common components of encoding a Vulkan API call
|
||||
def make_event_handler_call(
|
||||
handler_access,
|
||||
api,
|
||||
context_param,
|
||||
input_result_param,
|
||||
cgen,
|
||||
suffix=""):
|
||||
extraParams = [context_param.paramName]
|
||||
if input_result_param:
|
||||
extraParams.append(input_result_param)
|
||||
return cgen.makeCallExpr( \
|
||||
"%s->on_%s%s" % (handler_access, api.name, suffix),
|
||||
extraParams + \
|
||||
[p.paramName for p in api.parameters[:-1]])
|
||||
|
||||
def emit_custom_pre_validate(typeInfo, api, cgen):
|
||||
if api.name in ENCODER_PREVALIDATED_APIS:
|
||||
callExpr = \
|
||||
make_event_handler_call( \
|
||||
"mImpl->validation()", api,
|
||||
ENCODER_THIS_PARAM,
|
||||
SUCCESS_RET_TYPES[api.getRetTypeExpr()],
|
||||
cgen)
|
||||
|
||||
if api.getRetTypeExpr() == "void":
|
||||
cgen.stmt("VALIDATE_VOID(%s)" % callExpr)
|
||||
else:
|
||||
cgen.stmt("VALIDATE_RET(%s, %s, %s)" % \
|
||||
(api.getRetTypeExpr(),
|
||||
SUCCESS_RET_TYPES[api.getRetTypeExpr()],
|
||||
callExpr))
|
||||
|
||||
def emit_custom_resource_preprocess(typeInfo, api, cgen):
|
||||
if api.name in ENCODER_CUSTOM_RESOURCE_PREPROCESS:
|
||||
cgen.stmt( \
|
||||
make_event_handler_call( \
|
||||
"sResourceTracker", api,
|
||||
ENCODER_THIS_PARAM,
|
||||
SUCCESS_RET_TYPES[api.getRetTypeExpr()],
|
||||
cgen, suffix="_pre"))
|
||||
|
||||
def emit_custom_resource_postprocess(typeInfo, api, cgen):
|
||||
if api.name in ENCODER_CUSTOM_RESOURCE_POSTPROCESS:
|
||||
cgen.stmt(make_event_handler_call( \
|
||||
"sResourceTracker",
|
||||
api,
|
||||
ENCODER_THIS_PARAM,
|
||||
api.getRetVarExpr(),
|
||||
cgen))
|
||||
|
||||
def emit_count_marshal(typeInfo, param, cgen):
|
||||
res = \
|
||||
iterateVulkanType(
|
||||
typeInfo, param,
|
||||
VulkanCountingCodegen( \
|
||||
cgen, "sFeatureBits", param.paramName, "countPtr", ROOT_TYPE_DEFAULT_VALUE,
|
||||
"count_"))
|
||||
if not res:
|
||||
cgen.stmt("(void)%s" % param.paramName)
|
||||
|
||||
def emit_marshal(typeInfo, param, cgen):
|
||||
forOutput = param.isHandleType() and ("out" in param.inout)
|
||||
if forOutput:
|
||||
cgen.stmt("/* is handle, possibly out */")
|
||||
|
||||
res = \
|
||||
iterateVulkanType(
|
||||
typeInfo, param,
|
||||
VulkanReservedMarshalingCodegen( \
|
||||
cgen, "guest", STREAM, ROOT_TYPE_DEFAULT_VALUE, param.paramName, "streamPtrPtr",
|
||||
API_PREFIX_RESERVEDMARSHAL,
|
||||
"" if forOutput else "get_host_u64_",
|
||||
direction="write"))
|
||||
if not res:
|
||||
cgen.stmt("(void)%s" % param.paramName)
|
||||
|
||||
if forOutput:
|
||||
cgen.stmt("/* is handle, possibly out */")
|
||||
|
||||
def emit_unmarshal(typeInfo, param, cgen):
|
||||
iterateVulkanType(
|
||||
typeInfo, param,
|
||||
VulkanMarshalingCodegen( \
|
||||
cgen, STREAM, ROOT_TYPE_DEFAULT_VALUE, param.paramName,
|
||||
API_PREFIX_UNMARSHAL, direction="read"))
|
||||
|
||||
def emit_deepcopy(typeInfo, param, cgen):
|
||||
res = \
|
||||
iterateVulkanType(typeInfo, param, DeepcopyCodegen(
|
||||
cgen, [param.paramName, "local_" + param.paramName], "pool", ROOT_TYPE_DEFAULT_VALUE, "deepcopy_"))
|
||||
if not res:
|
||||
cgen.stmt("(void)%s" % param.paramName)
|
||||
|
||||
def emit_transform(typeInfo, param, cgen, variant="tohost"):
|
||||
res = \
|
||||
iterateVulkanType(typeInfo, param, TransformCodegen( \
|
||||
cgen, param.paramName, "sResourceTracker", "transform_%s_" % variant, variant))
|
||||
if not res:
|
||||
cgen.stmt("(void)%s" % param.paramName)
|
||||
|
||||
def emit_handlemap_create(typeInfo, param, cgen):
|
||||
iterateVulkanType(typeInfo, param, HandleMapCodegen(
|
||||
cgen, None, "sResourceTracker", "handlemap_",
|
||||
lambda vtype: typeInfo.isHandleType(vtype.typeName)
|
||||
))
|
||||
|
||||
def custom_encoder_args(api):
|
||||
params = ["this"]
|
||||
if api.getRetVarExpr() is not None:
|
||||
params.append(api.getRetVarExpr())
|
||||
return params
|
||||
|
||||
def emit_handlemap_destroy(typeInfo, param, cgen):
|
||||
iterateVulkanType(typeInfo, param, HandleMapCodegen(
|
||||
cgen, None, "sResourceTracker->destroyMapping()", "handlemap_",
|
||||
lambda vtype: typeInfo.isHandleType(vtype.typeName)
|
||||
))
|
||||
|
||||
class EncodingParameters(object):
|
||||
def __init__(self, api):
|
||||
self.localCopied = []
|
||||
self.toWrite = []
|
||||
self.toRead = []
|
||||
self.toCreate = []
|
||||
self.toDestroy = []
|
||||
|
||||
for param in api.parameters:
|
||||
param.action = None
|
||||
param.inout = "in"
|
||||
|
||||
if param.paramName == "doLock":
|
||||
continue
|
||||
|
||||
if param.possiblyOutput():
|
||||
param.inout += "out"
|
||||
self.toWrite.append(param)
|
||||
self.toRead.append(param)
|
||||
if param.isCreatedBy(api):
|
||||
self.toCreate.append(param)
|
||||
param.action = "create"
|
||||
else:
|
||||
|
||||
if param.paramName == "doLock":
|
||||
continue
|
||||
|
||||
if param.isDestroyedBy(api):
|
||||
self.toDestroy.append(param)
|
||||
param.action = "destroy"
|
||||
localCopyParam = \
|
||||
param.getForNonConstAccess().withModifiedName( \
|
||||
"local_" + param.paramName)
|
||||
self.localCopied.append((param, localCopyParam))
|
||||
self.toWrite.append(localCopyParam)
|
||||
|
||||
def emit_parameter_encode_preamble_write(typeInfo, api, cgen):
|
||||
emit_custom_pre_validate(typeInfo, api, cgen);
|
||||
emit_custom_resource_preprocess(typeInfo, api, cgen);
|
||||
|
||||
cgen.stmt("auto %s = mImpl->stream()" % STREAM)
|
||||
cgen.stmt("auto %s = mImpl->pool()" % POOL)
|
||||
# cgen.stmt("%s->setHandleMapping(%s->unwrapMapping())" % (STREAM, RESOURCES))
|
||||
|
||||
encodingParams = EncodingParameters(api)
|
||||
for (_, localCopyParam) in encodingParams.localCopied:
|
||||
cgen.stmt(cgen.makeRichCTypeDecl(localCopyParam))
|
||||
|
||||
def emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen, customUnwrap=None):
|
||||
encodingParams = EncodingParameters(api)
|
||||
|
||||
for (origParam, localCopyParam) in encodingParams.localCopied:
|
||||
shouldCustomCopy = \
|
||||
customUnwrap and \
|
||||
origParam.paramName in customUnwrap and \
|
||||
"copyOp" in customUnwrap[origParam.paramName]
|
||||
|
||||
shouldCustomMap = \
|
||||
customUnwrap and \
|
||||
origParam.paramName in customUnwrap and \
|
||||
"mapOp" in customUnwrap[origParam.paramName]
|
||||
|
||||
if shouldCustomCopy:
|
||||
customUnwrap[origParam.paramName]["copyOp"](cgen, origParam, localCopyParam)
|
||||
else:
|
||||
# if this is a pointer type and we don't do custom copy nor unwrap,
|
||||
# and the transform doesn't end up doing anything,
|
||||
# don't deepcopy, just cast it.
|
||||
|
||||
avoidDeepcopy = False
|
||||
|
||||
if origParam.pointerIndirectionLevels > 0:
|
||||
testCgen = CodeGen()
|
||||
genTransformsForVulkanType("sResourceTracker", origParam, lambda p: testCgen.generalAccess(p, parentVarName = None, asPtr = True), lambda p: testCgen.generalLengthAccess(p, parentVarName = None), testCgen)
|
||||
emit_transform(typeInfo, origParam, testCgen, variant="tohost")
|
||||
if "" == testCgen.swapCode():
|
||||
avoidDeepcopy = True
|
||||
if avoidDeepcopy:
|
||||
cgen.line("// Avoiding deepcopy for %s" % origParam.paramName)
|
||||
cgen.stmt("%s = (%s%s)%s" % (localCopyParam.paramName, localCopyParam.typeName, "*" * origParam.pointerIndirectionLevels, origParam.paramName))
|
||||
else:
|
||||
emit_deepcopy(typeInfo, origParam, cgen)
|
||||
|
||||
for (origParam, localCopyParam) in encodingParams.localCopied:
|
||||
shouldCustomMap = \
|
||||
customUnwrap and \
|
||||
origParam.paramName in customUnwrap and \
|
||||
"mapOp" in customUnwrap[origParam.paramName]
|
||||
|
||||
if shouldCustomMap:
|
||||
customUnwrap[origParam.paramName]["mapOp"](cgen, origParam, localCopyParam)
|
||||
else:
|
||||
if localCopyParam.typeName == "VkAllocationCallbacks":
|
||||
cgen.stmt("%s = nullptr" % localCopyParam.paramName)
|
||||
|
||||
apiForTransform = \
|
||||
api.withCustomParameters( \
|
||||
map(lambda p: p[1], \
|
||||
encodingParams.localCopied))
|
||||
|
||||
# Apply transforms if applicable.
|
||||
# Apply transform to API itself:
|
||||
genTransformsForVulkanType(
|
||||
"sResourceTracker",
|
||||
apiForTransform,
|
||||
lambda p: cgen.generalAccess(p, parentVarName = None, asPtr = True),
|
||||
lambda p: cgen.generalLengthAccess(p, parentVarName = None),
|
||||
cgen)
|
||||
|
||||
# For all local copied parameters, run the transforms
|
||||
for localParam in apiForTransform.parameters:
|
||||
if "doLock" in localParam.paramName:
|
||||
continue
|
||||
emit_transform(typeInfo, localParam, cgen, variant="tohost")
|
||||
|
||||
cgen.stmt("size_t count = 0")
|
||||
cgen.stmt("size_t* countPtr = &count")
|
||||
cgen.beginBlock()
|
||||
|
||||
# Use counting stream to calculate the packet size.
|
||||
for p in encodingParams.toWrite:
|
||||
emit_count_marshal(typeInfo, p, cgen)
|
||||
|
||||
cgen.endBlock()
|
||||
|
||||
def is_cmdbuf_dispatch(api):
|
||||
return "VkCommandBuffer" == api.parameters[0].typeName
|
||||
|
||||
def emit_parameter_encode_write_packet_info(typeInfo, api, cgen):
|
||||
# Seqno and skipping dispatch serialize are for use with VULKAN_STREAM_FEATURE_QUEUE_SUBMIT_WITH_COMMANDS_BIT
|
||||
doSeqno = True
|
||||
doDispatchSerialize = True
|
||||
|
||||
if is_cmdbuf_dispatch(api):
|
||||
doSeqno = False
|
||||
doDispatchSerialize = False
|
||||
|
||||
if doSeqno:
|
||||
cgen.stmt("uint32_t packetSize_%s = 4 + 4 + (queueSubmitWithCommandsEnabled ? 4 : 0) + count" % (api.name))
|
||||
else:
|
||||
cgen.stmt("uint32_t packetSize_%s = 4 + 4 + count" % (api.name))
|
||||
cgen.stmt("healthMonitorAnnotation_packetSize = std::make_optional(packetSize_%s)" % (api.name))
|
||||
|
||||
if not doDispatchSerialize:
|
||||
cgen.stmt("if (queueSubmitWithCommandsEnabled) packetSize_%s -= 8" % api.name)
|
||||
|
||||
cgen.stmt("uint8_t* streamPtr = %s->reserve(packetSize_%s)" % (STREAM, api.name))
|
||||
cgen.stmt("uint8_t* packetBeginPtr = streamPtr")
|
||||
cgen.stmt("uint8_t** streamPtrPtr = &streamPtr")
|
||||
cgen.stmt("uint32_t opcode_%s = OP_%s" % (api.name, api.name))
|
||||
|
||||
if doSeqno:
|
||||
cgen.stmt("uint32_t seqno; if (queueSubmitWithCommandsEnabled) seqno = ResourceTracker::nextSeqno()")
|
||||
cgen.stmt("healthMonitorAnnotation_seqno = std::make_optional(seqno)")
|
||||
|
||||
cgen.stmt("memcpy(streamPtr, &opcode_%s, sizeof(uint32_t)); streamPtr += sizeof(uint32_t)" % api.name)
|
||||
cgen.stmt("memcpy(streamPtr, &packetSize_%s, sizeof(uint32_t)); streamPtr += sizeof(uint32_t)" % api.name)
|
||||
|
||||
if doSeqno:
|
||||
cgen.line("if (queueSubmitWithCommandsEnabled) { memcpy(streamPtr, &seqno, sizeof(uint32_t)); streamPtr += sizeof(uint32_t); }")
|
||||
|
||||
def emit_parameter_encode_do_parameter_write(typeInfo, api, cgen):
|
||||
encodingParams = EncodingParameters(api)
|
||||
|
||||
dispatchDone = False
|
||||
|
||||
for p in encodingParams.toWrite:
|
||||
if is_cmdbuf_dispatch(api) and not dispatchDone:
|
||||
cgen.beginIf("!queueSubmitWithCommandsEnabled")
|
||||
emit_marshal(typeInfo, p, cgen)
|
||||
cgen.endIf()
|
||||
else:
|
||||
emit_marshal(typeInfo, p, cgen)
|
||||
|
||||
dispatchDone = True
|
||||
|
||||
cgen.beginIf("watchdog")
|
||||
cgen.stmt("size_t watchdogBufSize = std::min<size_t>(static_cast<size_t>(packetSize_%s), kWatchdogBufferMax)" % (api.name))
|
||||
cgen.stmt("healthMonitorAnnotation_packetContents.resize(watchdogBufSize)")
|
||||
cgen.stmt("memcpy(&healthMonitorAnnotation_packetContents[0], packetBeginPtr, watchdogBufSize)")
|
||||
cgen.endIf()
|
||||
|
||||
def emit_parameter_encode_read(typeInfo, api, cgen):
|
||||
encodingParams = EncodingParameters(api)
|
||||
|
||||
for p in encodingParams.toRead:
|
||||
if p.action == "create":
|
||||
cgen.stmt(
|
||||
"%s->setHandleMapping(%s->createMapping())" % \
|
||||
(STREAM, RESOURCES))
|
||||
emit_unmarshal(typeInfo, p, cgen)
|
||||
if p.action == "create":
|
||||
cgen.stmt(
|
||||
"%s->unsetHandleMapping()" % STREAM)
|
||||
emit_transform(typeInfo, p, cgen, variant="fromhost")
|
||||
|
||||
def emit_post(typeInfo, api, cgen):
|
||||
encodingParams = EncodingParameters(api)
|
||||
|
||||
emit_custom_resource_postprocess(typeInfo, api, cgen)
|
||||
|
||||
for p in encodingParams.toDestroy:
|
||||
emit_handlemap_destroy(typeInfo, p, cgen)
|
||||
|
||||
doSeqno = True
|
||||
if is_cmdbuf_dispatch(api):
|
||||
doSeqno = False
|
||||
|
||||
retType = api.getRetTypeExpr()
|
||||
|
||||
if api.name in ENCODER_EXPLICIT_FLUSHED_APIS:
|
||||
cgen.stmt("stream->flush()");
|
||||
return
|
||||
|
||||
if doSeqno:
|
||||
if retType == "void":
|
||||
encodingParams = EncodingParameters(api)
|
||||
if 0 == len(encodingParams.toRead):
|
||||
cgen.stmt("stream->flush()");
|
||||
|
||||
def emit_pool_free(cgen):
|
||||
cgen.stmt("++encodeCount;")
|
||||
cgen.beginIf("0 == encodeCount % POOL_CLEAR_INTERVAL")
|
||||
cgen.stmt("pool->freeAll()")
|
||||
cgen.stmt("%s->clearPool()" % STREAM)
|
||||
cgen.endIf()
|
||||
|
||||
def emit_return_unmarshal(typeInfo, api, cgen):
|
||||
|
||||
retType = api.getRetTypeExpr()
|
||||
|
||||
if retType == "void":
|
||||
return
|
||||
|
||||
retVar = api.getRetVarExpr()
|
||||
cgen.stmt("%s %s = (%s)0" % (retType, retVar, retType))
|
||||
cgen.stmt("%s->read(&%s, %s)" % \
|
||||
(STREAM, retVar, cgen.sizeofExpr(api.retType)))
|
||||
|
||||
def emit_return(typeInfo, api, cgen):
|
||||
if api.getRetTypeExpr() == "void":
|
||||
return
|
||||
|
||||
retVar = api.getRetVarExpr()
|
||||
cgen.stmt("return %s" % retVar)
|
||||
|
||||
def emit_lock(cgen):
|
||||
cgen.stmt("(void)doLock");
|
||||
cgen.stmt("bool queueSubmitWithCommandsEnabled = sFeatureBits & VULKAN_STREAM_FEATURE_QUEUE_SUBMIT_WITH_COMMANDS_BIT")
|
||||
cgen.stmt("if (!queueSubmitWithCommandsEnabled && doLock) this->lock()")
|
||||
|
||||
def emit_unlock(cgen):
|
||||
cgen.stmt("if (!queueSubmitWithCommandsEnabled && doLock) this->unlock()")
|
||||
|
||||
def emit_debug_log(typeInfo, api, cgen):
|
||||
logFormat = []
|
||||
logVargs = []
|
||||
for param in api.parameters:
|
||||
if param.paramName == "doLock":
|
||||
continue
|
||||
|
||||
paramFormatSpecifier = param.getPrintFormatSpecifier()
|
||||
if not paramFormatSpecifier:
|
||||
continue
|
||||
|
||||
logFormat.append(param.paramName + ":" + paramFormatSpecifier)
|
||||
logVargs.append(param.paramName)
|
||||
|
||||
logFormatStr = ", ".join(logFormat)
|
||||
logVargsStr = ", ".join(logVargs)
|
||||
|
||||
cgen.stmt("ENCODER_DEBUG_LOG(\"%s(%s)\", %s)" % (api.name, logFormatStr, logVargsStr))
|
||||
|
||||
def emit_health_watchdog(api, cgen):
|
||||
cgen.stmt("std::optional<uint32_t> healthMonitorAnnotation_seqno = std::nullopt")
|
||||
cgen.stmt("std::optional<uint32_t> healthMonitorAnnotation_packetSize = std::nullopt")
|
||||
cgen.stmt("std::vector<uint8_t> healthMonitorAnnotation_packetContents")
|
||||
cgen.line("""
|
||||
auto watchdog = WATCHDOG_BUILDER(mHealthMonitor, \"%s in VkEncoder\")
|
||||
.setOnHangCallback([&]() {
|
||||
auto annotations = std::make_unique<EventHangMetadata::HangAnnotations>();
|
||||
if (healthMonitorAnnotation_seqno) {
|
||||
annotations->insert({{"seqno", std::to_string(healthMonitorAnnotation_seqno.value())}});
|
||||
}
|
||||
if (healthMonitorAnnotation_packetSize) {
|
||||
annotations->insert({{"packetSize", std::to_string(healthMonitorAnnotation_packetSize.value())}});
|
||||
}
|
||||
if (!healthMonitorAnnotation_packetContents.empty()) {
|
||||
annotations->insert(
|
||||
{{"packetContents", getPacketContents(
|
||||
&healthMonitorAnnotation_packetContents[0], healthMonitorAnnotation_packetContents.size())}});
|
||||
}
|
||||
return std::move(annotations);
|
||||
})
|
||||
.build();
|
||||
"""% (api.name)
|
||||
)
|
||||
|
||||
def emit_default_encoding(typeInfo, api, cgen):
|
||||
emit_debug_log(typeInfo, api, cgen)
|
||||
emit_lock(cgen)
|
||||
emit_parameter_encode_preamble_write(typeInfo, api, cgen)
|
||||
emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen)
|
||||
emit_parameter_encode_write_packet_info(typeInfo, api, cgen)
|
||||
emit_parameter_encode_do_parameter_write(typeInfo, api, cgen)
|
||||
emit_parameter_encode_read(typeInfo, api, cgen)
|
||||
emit_return_unmarshal(typeInfo, api, cgen)
|
||||
emit_post(typeInfo, api, cgen)
|
||||
emit_pool_free(cgen)
|
||||
emit_unlock(cgen)
|
||||
emit_return(typeInfo, api, cgen)
|
||||
|
||||
## Custom encoding definitions##################################################
|
||||
|
||||
def emit_only_goldfish_custom(typeInfo, api, cgen):
|
||||
emit_lock(cgen)
|
||||
cgen.vkApiCall( \
|
||||
api,
|
||||
customPrefix="sResourceTracker->on_",
|
||||
customParameters=custom_encoder_args(api) + \
|
||||
[p.paramName for p in api.parameters[:-1]])
|
||||
emit_unlock(cgen)
|
||||
emit_return(typeInfo, api, cgen)
|
||||
|
||||
def emit_only_resource_event(typeInfo, api, cgen):
|
||||
cgen.stmt("(void)doLock");
|
||||
input_result = None
|
||||
retExpr = api.getRetVarExpr()
|
||||
|
||||
if retExpr:
|
||||
retType = api.getRetTypeExpr()
|
||||
input_result = SUCCESS_RET_TYPES[retType]
|
||||
cgen.stmt("%s %s = (%s)0" % (retType, retExpr, retType))
|
||||
|
||||
cgen.stmt(
|
||||
(("%s = " % retExpr) if retExpr else "") +
|
||||
make_event_handler_call(
|
||||
"sResourceTracker",
|
||||
api,
|
||||
ENCODER_THIS_PARAM,
|
||||
input_result, cgen))
|
||||
|
||||
if retExpr:
|
||||
emit_return(typeInfo, api, cgen)
|
||||
|
||||
def emit_with_custom_unwrap(custom):
|
||||
def call(typeInfo, api, cgen):
|
||||
emit_lock(cgen)
|
||||
emit_parameter_encode_preamble_write(typeInfo, api, cgen)
|
||||
emit_parameter_encode_copy_unwrap_count(
|
||||
typeInfo, api, cgen, customUnwrap=custom)
|
||||
emit_parameter_encode_write_packet_info(typeInfo, api, cgen)
|
||||
emit_parameter_encode_do_parameter_write(typeInfo, api, cgen)
|
||||
emit_parameter_encode_read(typeInfo, api, cgen)
|
||||
emit_return_unmarshal(typeInfo, api, cgen)
|
||||
emit_pool_free(cgen)
|
||||
emit_unlock(cgen)
|
||||
emit_return(typeInfo, api, cgen)
|
||||
return call
|
||||
|
||||
def encode_vkFlushMappedMemoryRanges(typeInfo, api, cgen):
|
||||
emit_lock(cgen)
|
||||
emit_parameter_encode_preamble_write(typeInfo, api, cgen)
|
||||
emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen)
|
||||
|
||||
def emit_flush_ranges(streamVar):
|
||||
cgen.beginIf("!sResourceTracker->usingDirectMapping()")
|
||||
cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i")
|
||||
cgen.stmt("auto range = pMemoryRanges[i]")
|
||||
cgen.stmt("auto memory = pMemoryRanges[i].memory")
|
||||
cgen.stmt("auto size = pMemoryRanges[i].size")
|
||||
cgen.stmt("auto offset = pMemoryRanges[i].offset")
|
||||
cgen.stmt("uint64_t streamSize = 0")
|
||||
cgen.stmt("if (!memory) { %s->write(&streamSize, sizeof(uint64_t)); continue; }" % streamVar)
|
||||
cgen.stmt("auto hostPtr = sResourceTracker->getMappedPointer(memory)")
|
||||
cgen.stmt("auto actualSize = size == VK_WHOLE_SIZE ? sResourceTracker->getMappedSize(memory) : size")
|
||||
cgen.stmt("if (!hostPtr) { %s->write(&streamSize, sizeof(uint64_t)); continue; }" % streamVar)
|
||||
cgen.stmt("streamSize = actualSize")
|
||||
cgen.stmt("%s->write(&streamSize, sizeof(uint64_t))" % streamVar)
|
||||
cgen.stmt("uint8_t* targetRange = hostPtr + offset")
|
||||
cgen.stmt("%s->write(targetRange, actualSize)" % streamVar)
|
||||
cgen.endFor()
|
||||
cgen.endIf()
|
||||
|
||||
emit_parameter_encode_write_packet_info(typeInfo, api, cgen)
|
||||
emit_parameter_encode_do_parameter_write(typeInfo, api, cgen)
|
||||
|
||||
emit_flush_ranges(STREAM)
|
||||
|
||||
emit_parameter_encode_read(typeInfo, api, cgen)
|
||||
emit_return_unmarshal(typeInfo, api, cgen)
|
||||
emit_pool_free(cgen)
|
||||
emit_unlock(cgen)
|
||||
emit_return(typeInfo, api, cgen)
|
||||
|
||||
def encode_vkInvalidateMappedMemoryRanges(typeInfo, api, cgen):
|
||||
emit_lock(cgen)
|
||||
emit_parameter_encode_preamble_write(typeInfo, api, cgen)
|
||||
emit_parameter_encode_copy_unwrap_count(typeInfo, api, cgen)
|
||||
emit_parameter_encode_write_packet_info(typeInfo, api, cgen)
|
||||
emit_parameter_encode_do_parameter_write(typeInfo, api, cgen)
|
||||
emit_parameter_encode_read(typeInfo, api, cgen)
|
||||
emit_return_unmarshal(typeInfo, api, cgen)
|
||||
|
||||
def emit_invalidate_ranges(streamVar):
|
||||
cgen.beginIf("!sResourceTracker->usingDirectMapping()")
|
||||
cgen.beginFor("uint32_t i = 0", "i < memoryRangeCount", "++i")
|
||||
cgen.stmt("auto range = pMemoryRanges[i]")
|
||||
cgen.stmt("auto memory = pMemoryRanges[i].memory")
|
||||
cgen.stmt("auto size = pMemoryRanges[i].size")
|
||||
cgen.stmt("auto offset = pMemoryRanges[i].offset")
|
||||
cgen.stmt("uint64_t streamSize = 0")
|
||||
cgen.stmt("if (!memory) { %s->read(&streamSize, sizeof(uint64_t)); continue; }" % streamVar)
|
||||
cgen.stmt("auto hostPtr = sResourceTracker->getMappedPointer(memory)")
|
||||
cgen.stmt("auto actualSize = size == VK_WHOLE_SIZE ? sResourceTracker->getMappedSize(memory) : size")
|
||||
cgen.stmt("if (!hostPtr) { %s->read(&streamSize, sizeof(uint64_t)); continue; }" % streamVar)
|
||||
cgen.stmt("streamSize = actualSize")
|
||||
cgen.stmt("%s->read(&streamSize, sizeof(uint64_t))" % streamVar)
|
||||
cgen.stmt("uint8_t* targetRange = hostPtr + offset")
|
||||
cgen.stmt("%s->read(targetRange, actualSize)" % streamVar)
|
||||
cgen.endFor()
|
||||
cgen.endIf()
|
||||
|
||||
emit_invalidate_ranges(STREAM)
|
||||
emit_pool_free(cgen)
|
||||
emit_unlock(cgen)
|
||||
emit_return(typeInfo, api, cgen)
|
||||
|
||||
def emit_manual_inline(typeInfo, api, cgen):
|
||||
cgen.line("#include \"%s_encode_impl.cpp.inl\"" % api.name)
|
||||
|
||||
def unwrap_vkCreateImage_pCreateInfo():
|
||||
def mapOp(cgen, orig, local):
|
||||
cgen.stmt("sResourceTracker->unwrap_vkCreateImage_pCreateInfo(%s, %s)" %
|
||||
(orig.paramName, local.paramName))
|
||||
return { "pCreateInfo" : { "mapOp" : mapOp } }
|
||||
|
||||
def unwrap_vkBindImageMemory2_pBindInfos():
|
||||
def mapOp(cgen, orig, local):
|
||||
cgen.stmt("sResourceTracker->unwrap_VkBindImageMemory2_pBindInfos(bindInfoCount, %s, %s)" %
|
||||
(orig.paramName, local.paramName))
|
||||
return { "pBindInfos" : { "mapOp" : mapOp } }
|
||||
|
||||
def unwrap_vkAcquireImageANDROID_nativeFenceFd():
|
||||
def mapOp(cgen, orig, local):
|
||||
cgen.stmt("sResourceTracker->unwrap_vkAcquireImageANDROID_nativeFenceFd(%s, &%s)" %
|
||||
(orig.paramName, local.paramName))
|
||||
return { "nativeFenceFd" : { "mapOp" : mapOp } }
|
||||
|
||||
custom_encodes = {
|
||||
"vkMapMemory" : emit_only_resource_event,
|
||||
"vkUnmapMemory" : emit_only_resource_event,
|
||||
"vkFlushMappedMemoryRanges" : encode_vkFlushMappedMemoryRanges,
|
||||
"vkInvalidateMappedMemoryRanges" : encode_vkInvalidateMappedMemoryRanges,
|
||||
"vkCreateImage" : emit_with_custom_unwrap(unwrap_vkCreateImage_pCreateInfo()),
|
||||
"vkCreateImageWithRequirementsGOOGLE" : emit_with_custom_unwrap(unwrap_vkCreateImage_pCreateInfo()),
|
||||
"vkBindImageMemory2": emit_with_custom_unwrap(unwrap_vkBindImageMemory2_pBindInfos()),
|
||||
"vkAcquireImageANDROID" : emit_with_custom_unwrap(unwrap_vkAcquireImageANDROID_nativeFenceFd()),
|
||||
"vkQueueFlushCommandsGOOGLE" : emit_manual_inline,
|
||||
}
|
||||
|
||||
class VulkanEncoder(VulkanWrapperGenerator):
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
|
||||
self.typeInfo = typeInfo
|
||||
|
||||
self.cgenHeader = CodeGen()
|
||||
self.cgenHeader.incrIndent()
|
||||
|
||||
self.cgenImpl = CodeGen()
|
||||
|
||||
def onBegin(self,):
|
||||
self.module.appendHeader(encoder_decl_preamble)
|
||||
self.module.appendImpl(encoder_impl_preamble)
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
|
||||
|
||||
api = copy.deepcopy(self.typeInfo.apis[name])
|
||||
api.parameters.append(makeVulkanTypeSimple(False, "uint32_t", 0, "doLock"))
|
||||
|
||||
self.cgenHeader.stmt(self.cgenHeader.makeFuncProto(api))
|
||||
apiImpl = api.withModifiedName("VkEncoder::" + api.name)
|
||||
|
||||
self.module.appendHeader(self.cgenHeader.swapCode())
|
||||
|
||||
def emit_function_impl(cgen):
|
||||
emit_health_watchdog(api, cgen)
|
||||
if api.name in custom_encodes.keys():
|
||||
custom_encodes[api.name](self.typeInfo, api, cgen)
|
||||
else:
|
||||
emit_default_encoding(self.typeInfo, api, cgen)
|
||||
|
||||
self.module.appendImpl(self.cgenImpl.makeFuncImpl(apiImpl, emit_function_impl))
|
||||
|
||||
def onEnd(self,):
|
||||
self.module.appendHeader(encoder_decl_postamble)
|
||||
self.cgenHeader.decrIndent()
|
||||
124
src/gfxstream/codegen/scripts/cereal/extensionstructs.py
Normal file
124
src/gfxstream/codegen/scripts/cereal/extensionstructs.py
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
# Copyright (c) 2018 The Android Open Source Project
|
||||
# Copyright (c) 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from .common.codegen import CodeGen
|
||||
from .common.vulkantypes import \
|
||||
VulkanAPI, makeVulkanTypeSimple, iterateVulkanType
|
||||
|
||||
from .wrapperdefs import VulkanWrapperGenerator
|
||||
from .wrapperdefs import STRUCT_EXTENSION_PARAM
|
||||
from .wrapperdefs import STRUCT_EXTENSION_PARAM_FOR_WRITE
|
||||
from .wrapperdefs import EXTENSION_SIZE_API_NAME
|
||||
from .wrapperdefs import EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME
|
||||
from .wrapperdefs import STRUCT_TYPE_API_NAME
|
||||
|
||||
class VulkanExtensionStructs(VulkanWrapperGenerator):
|
||||
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
|
||||
self.codegen = CodeGen()
|
||||
|
||||
self.structTypeRetType = \
|
||||
makeVulkanTypeSimple(False, "uint32_t", 0)
|
||||
|
||||
self.rootTypeVarName = "rootType"
|
||||
self.rootTypeParam = \
|
||||
makeVulkanTypeSimple(False, "VkStructureType",
|
||||
0, self.rootTypeVarName)
|
||||
self.structTypePrototype = \
|
||||
VulkanAPI(STRUCT_TYPE_API_NAME,
|
||||
self.structTypeRetType,
|
||||
[STRUCT_EXTENSION_PARAM])
|
||||
|
||||
self.extensionStructSizeRetType = \
|
||||
makeVulkanTypeSimple(False, "size_t", 0)
|
||||
self.extensionStructSizePrototype = \
|
||||
VulkanAPI(EXTENSION_SIZE_API_NAME,
|
||||
self.extensionStructSizeRetType,
|
||||
[self.rootTypeParam, STRUCT_EXTENSION_PARAM])
|
||||
|
||||
self.streamFeaturesType = makeVulkanTypeSimple(False, "uint32_t", 0, "streamFeatures")
|
||||
|
||||
self.extensionStructSizeWithStreamFeaturesPrototype = \
|
||||
VulkanAPI(EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME,
|
||||
self.extensionStructSizeRetType,
|
||||
[self.streamFeaturesType, self.rootTypeParam, STRUCT_EXTENSION_PARAM])
|
||||
def onBegin(self,):
|
||||
VulkanWrapperGenerator.onBegin(self)
|
||||
self.module.appendHeader(self.codegen.makeFuncDecl(
|
||||
self.structTypePrototype))
|
||||
self.module.appendHeader(self.codegen.makeFuncDecl(
|
||||
self.extensionStructSizePrototype))
|
||||
self.module.appendHeader(self.codegen.makeFuncDecl(
|
||||
self.extensionStructSizeWithStreamFeaturesPrototype))
|
||||
|
||||
def onGenType(self, typeXml, name, alias):
|
||||
VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
|
||||
|
||||
def onEnd(self,):
|
||||
VulkanWrapperGenerator.onEnd(self)
|
||||
|
||||
def castAsStruct(varName, typeName, const=True):
|
||||
return "reinterpret_cast<%s%s*>(%s)" % \
|
||||
("const " if const else "", typeName, varName)
|
||||
|
||||
def structTypeImpl(cgen):
|
||||
cgen.stmt(
|
||||
"const uint32_t asStructType = *(%s)" %
|
||||
(castAsStruct(STRUCT_EXTENSION_PARAM.paramName, "uint32_t")))
|
||||
cgen.stmt("return asStructType")
|
||||
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(
|
||||
self.structTypePrototype, structTypeImpl))
|
||||
|
||||
def forEachExtensionReturnSize(ext, _, cgen):
|
||||
cgen.stmt("return sizeof(%s)" % ext.name)
|
||||
|
||||
def forEachExtensionReturnSizeProtectedByFeature(ext, _, cgen):
|
||||
streamFeature = ext.getProtectStreamFeature()
|
||||
if streamFeature is None:
|
||||
cgen.stmt("return sizeof(%s)" % ext.name)
|
||||
return
|
||||
cgen.beginIf("%s & %s" % ("streamFeatures", streamFeature))
|
||||
cgen.stmt("return sizeof(%s)" % ext.name)
|
||||
cgen.endIf()
|
||||
cgen.beginElse()
|
||||
cgen.stmt("return 0")
|
||||
cgen.endIf()
|
||||
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(
|
||||
self.extensionStructSizePrototype,
|
||||
lambda cgen: self.emitForEachStructExtension(
|
||||
cgen,
|
||||
self.extensionStructSizeRetType,
|
||||
STRUCT_EXTENSION_PARAM,
|
||||
forEachExtensionReturnSize, autoBreak=False,
|
||||
rootTypeVar=self.rootTypeParam)))
|
||||
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(
|
||||
self.extensionStructSizeWithStreamFeaturesPrototype,
|
||||
lambda cgen: self.emitForEachStructExtension(
|
||||
cgen,
|
||||
self.extensionStructSizeRetType,
|
||||
STRUCT_EXTENSION_PARAM,
|
||||
forEachExtensionReturnSizeProtectedByFeature, autoBreak=False,
|
||||
rootTypeVar=self.rootTypeParam)))
|
||||
102
src/gfxstream/codegen/scripts/cereal/frontend.py
Normal file
102
src/gfxstream/codegen/scripts/cereal/frontend.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
# Copyright (c) 2018 The Android Open Source Project
|
||||
# Copyright (c) 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from .common.codegen import CodeGen, VulkanAPIWrapper
|
||||
from .common.vulkantypes import \
|
||||
VulkanAPI, makeVulkanTypeSimple, iterateVulkanType
|
||||
|
||||
from .wrapperdefs import VulkanWrapperGenerator
|
||||
|
||||
from .wrapperdefs import API_PREFIX_VALIDATE
|
||||
from .wrapperdefs import PARAMETERS_VALIDATE
|
||||
from .wrapperdefs import VOID_TYPE
|
||||
from .wrapperdefs import VALIDATE_RESULT_TYPE
|
||||
from .wrapperdefs import VALIDATE_VAR_NAME
|
||||
from .wrapperdefs import VALIDATE_GOOD_RESULT
|
||||
|
||||
from .wrapperdefs import VULKAN_STREAM_TYPE
|
||||
from .wrapperdefs import VULKAN_STREAM_VAR_NAME
|
||||
|
||||
from .wrapperdefs import API_PREFIX_MARSHAL
|
||||
from .wrapperdefs import API_PREFIX_FRONTEND
|
||||
|
||||
# Frontend
|
||||
class VulkanFrontend(VulkanWrapperGenerator):
|
||||
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
|
||||
def validateDefFunc(_codegen, _api):
|
||||
# TODO
|
||||
pass
|
||||
|
||||
self.validateWrapper = \
|
||||
VulkanAPIWrapper(
|
||||
API_PREFIX_VALIDATE,
|
||||
PARAMETERS_VALIDATE,
|
||||
VOID_TYPE,
|
||||
validateDefFunc)
|
||||
|
||||
def frontendDefFunc(codegen, api):
|
||||
retTypeName = api.retType.typeName
|
||||
|
||||
codegen.stmt(
|
||||
"%s %s = %s" % (VALIDATE_RESULT_TYPE, VALIDATE_VAR_NAME,
|
||||
VALIDATE_GOOD_RESULT))
|
||||
codegen.funcCall(None, API_PREFIX_VALIDATE + api.origName,
|
||||
["&%s" % VALIDATE_VAR_NAME] + list(
|
||||
map(lambda p: p.paramName, api.parameters)))
|
||||
|
||||
codegen.beginIf(
|
||||
"%s != %s" % (VALIDATE_VAR_NAME, VALIDATE_GOOD_RESULT))
|
||||
if retTypeName == VALIDATE_RESULT_TYPE:
|
||||
codegen.stmt("return %s" % VALIDATE_VAR_NAME)
|
||||
elif retTypeName != "void":
|
||||
codegen.stmt("return (%s)0" % retTypeName)
|
||||
else:
|
||||
codegen.stmt("return")
|
||||
codegen.endIf()
|
||||
|
||||
codegen.stmt("// VULKAN_STREAM_GET()")
|
||||
codegen.stmt("%s* %s = nullptr" % (VULKAN_STREAM_TYPE,
|
||||
VULKAN_STREAM_VAR_NAME))
|
||||
|
||||
retLhs = None
|
||||
if retTypeName != "void":
|
||||
retLhs = retTypeName + " res"
|
||||
|
||||
codegen.funcCall(retLhs, API_PREFIX_MARSHAL + api.origName,
|
||||
[VULKAN_STREAM_VAR_NAME] + list(
|
||||
map(lambda p: p.paramName, api.parameters)))
|
||||
|
||||
if retTypeName != "void":
|
||||
codegen.stmt("return res")
|
||||
|
||||
self.frontendWrapper = \
|
||||
VulkanAPIWrapper(
|
||||
API_PREFIX_FRONTEND,
|
||||
[],
|
||||
None,
|
||||
frontendDefFunc)
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
|
||||
self.module.appendHeader(
|
||||
self.frontendWrapper.makeDecl(self.typeInfo, name))
|
||||
self.module.appendImpl(
|
||||
self.validateWrapper.makeDefinition(
|
||||
self.typeInfo, name, isStatic=True))
|
||||
self.module.appendImpl(
|
||||
self.frontendWrapper.makeDefinition(self.typeInfo, name))
|
||||
411
src/gfxstream/codegen/scripts/cereal/functable.py
Normal file
411
src/gfxstream/codegen/scripts/cereal/functable.py
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
from .common.codegen import CodeGen, VulkanWrapperGenerator
|
||||
from .common.vulkantypes import \
|
||||
VulkanAPI, makeVulkanTypeSimple, iterateVulkanType
|
||||
from .common.vulkantypes import EXCLUDED_APIS
|
||||
|
||||
RESOURCE_TRACKER_ENTRIES = [
|
||||
"vkEnumerateInstanceExtensionProperties",
|
||||
"vkEnumerateDeviceExtensionProperties",
|
||||
"vkEnumeratePhysicalDevices",
|
||||
"vkAllocateMemory",
|
||||
"vkFreeMemory",
|
||||
"vkCreateImage",
|
||||
"vkDestroyImage",
|
||||
"vkGetImageMemoryRequirements",
|
||||
"vkGetImageMemoryRequirements2",
|
||||
"vkGetImageMemoryRequirements2KHR",
|
||||
"vkBindImageMemory",
|
||||
"vkBindImageMemory2",
|
||||
"vkBindImageMemory2KHR",
|
||||
"vkCreateBuffer",
|
||||
"vkDestroyBuffer",
|
||||
"vkGetBufferMemoryRequirements",
|
||||
"vkGetBufferMemoryRequirements2",
|
||||
"vkGetBufferMemoryRequirements2KHR",
|
||||
"vkBindBufferMemory",
|
||||
"vkBindBufferMemory2",
|
||||
"vkBindBufferMemory2KHR",
|
||||
"vkCreateSemaphore",
|
||||
"vkDestroySemaphore",
|
||||
"vkQueueSubmit",
|
||||
"vkQueueSubmit2",
|
||||
"vkQueueWaitIdle",
|
||||
"vkImportSemaphoreFdKHR",
|
||||
"vkGetSemaphoreFdKHR",
|
||||
# Warning: These need to be defined in vk.xml (currently no-op) {
|
||||
"vkGetMemoryFuchsiaHandleKHR",
|
||||
"vkGetMemoryFuchsiaHandlePropertiesKHR",
|
||||
"vkGetSemaphoreFuchsiaHandleKHR",
|
||||
"vkImportSemaphoreFuchsiaHandleKHR",
|
||||
# } end Warning: These need to be defined in vk.xml (currently no-op)
|
||||
"vkGetAndroidHardwareBufferPropertiesANDROID",
|
||||
"vkGetMemoryAndroidHardwareBufferANDROID",
|
||||
"vkCreateSamplerYcbcrConversion",
|
||||
"vkDestroySamplerYcbcrConversion",
|
||||
"vkCreateSamplerYcbcrConversionKHR",
|
||||
"vkDestroySamplerYcbcrConversionKHR",
|
||||
"vkUpdateDescriptorSetWithTemplate",
|
||||
"vkGetPhysicalDeviceImageFormatProperties2",
|
||||
"vkGetPhysicalDeviceImageFormatProperties2KHR",
|
||||
"vkBeginCommandBuffer",
|
||||
"vkEndCommandBuffer",
|
||||
"vkResetCommandBuffer",
|
||||
"vkCreateImageView",
|
||||
"vkCreateSampler",
|
||||
"vkGetPhysicalDeviceExternalFenceProperties",
|
||||
"vkGetPhysicalDeviceExternalFencePropertiesKHR",
|
||||
"vkGetPhysicalDeviceExternalBufferProperties",
|
||||
"vkGetPhysicalDeviceExternalBufferPropertiesKHR",
|
||||
"vkCreateFence",
|
||||
"vkResetFences",
|
||||
"vkImportFenceFdKHR",
|
||||
"vkGetFenceFdKHR",
|
||||
"vkWaitForFences",
|
||||
"vkCreateDescriptorPool",
|
||||
"vkDestroyDescriptorPool",
|
||||
"vkResetDescriptorPool",
|
||||
"vkAllocateDescriptorSets",
|
||||
"vkFreeDescriptorSets",
|
||||
"vkCreateDescriptorSetLayout",
|
||||
"vkUpdateDescriptorSets",
|
||||
"vkCmdExecuteCommands",
|
||||
"vkCmdBindDescriptorSets",
|
||||
"vkDestroyDescriptorSetLayout",
|
||||
"vkAllocateCommandBuffers",
|
||||
"vkQueueSignalReleaseImageANDROID",
|
||||
"vkCmdPipelineBarrier",
|
||||
"vkCreateGraphicsPipelines",
|
||||
# Fuchsia
|
||||
"vkGetMemoryZirconHandleFUCHSIA",
|
||||
"vkGetMemoryZirconHandlePropertiesFUCHSIA",
|
||||
"vkGetSemaphoreZirconHandleFUCHSIA",
|
||||
"vkImportSemaphoreZirconHandleFUCHSIA",
|
||||
"vkCreateBufferCollectionFUCHSIA",
|
||||
"vkDestroyBufferCollectionFUCHSIA",
|
||||
"vkSetBufferCollectionImageConstraintsFUCHSIA",
|
||||
"vkSetBufferCollectionBufferConstraintsFUCHSIA",
|
||||
"vkGetBufferCollectionPropertiesFUCHSIA",
|
||||
]
|
||||
|
||||
SUCCESS_VAL = {
|
||||
"VkResult" : ["VK_SUCCESS"],
|
||||
}
|
||||
|
||||
POSTPROCESSES = {
|
||||
"vkResetCommandPool" : """if (vkResetCommandPool_VkResult_return == VK_SUCCESS) {
|
||||
ResourceTracker::get()->resetCommandPoolStagingInfo(commandPool);
|
||||
}""",
|
||||
"vkAllocateCommandBuffers" : """if (vkAllocateCommandBuffers_VkResult_return == VK_SUCCESS) {
|
||||
ResourceTracker::get()->addToCommandPool(pAllocateInfo->commandPool, pAllocateInfo->commandBufferCount, pCommandBuffers);
|
||||
}""",
|
||||
}
|
||||
|
||||
def is_cmdbuf_dispatch(api):
|
||||
return "VkCommandBuffer" == api.parameters[0].typeName
|
||||
|
||||
def is_queue_dispatch(api):
|
||||
return "VkQueue" == api.parameters[0].typeName
|
||||
|
||||
class VulkanFuncTable(VulkanWrapperGenerator):
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
self.typeInfo = typeInfo
|
||||
self.cgen = CodeGen()
|
||||
self.entries = []
|
||||
self.entryFeatures = []
|
||||
self.cmdToFeatureType = {}
|
||||
self.feature = None
|
||||
self.featureType = None
|
||||
|
||||
def onBegin(self,):
|
||||
cgen = self.cgen
|
||||
cgen.line("static void sOnInvalidDynamicallyCheckedCall(const char* apiname, const char* neededFeature)")
|
||||
cgen.beginBlock()
|
||||
cgen.stmt("ALOGE(\"invalid call to %s: %s not supported\", apiname, neededFeature)")
|
||||
cgen.stmt("abort()")
|
||||
cgen.endBlock()
|
||||
self.module.appendImpl(cgen.swapCode())
|
||||
pass
|
||||
|
||||
def onBeginFeature(self, featureName, featureType):
|
||||
self.feature = featureName
|
||||
self.featureType = featureType
|
||||
|
||||
def onEndFeature(self):
|
||||
self.feature = None
|
||||
self.featureType = None
|
||||
|
||||
def onFeatureNewCmd(self, name):
|
||||
self.cmdToFeatureType[name] = self.featureType
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
typeInfo = self.typeInfo
|
||||
cgen = self.cgen
|
||||
api = typeInfo.apis[name]
|
||||
self.entries.append(api)
|
||||
self.entryFeatures.append(self.feature)
|
||||
|
||||
def genEncoderOrResourceTrackerCall(cgen, api, declareResources=True):
|
||||
cgen.stmt("AEMU_SCOPED_TRACE(\"%s\")" % api.name)
|
||||
|
||||
if is_cmdbuf_dispatch(api):
|
||||
cgen.stmt("auto vkEnc = ResourceTracker::getCommandBufferEncoder(commandBuffer)")
|
||||
elif is_queue_dispatch(api):
|
||||
cgen.stmt("auto vkEnc = ResourceTracker::getQueueEncoder(queue)")
|
||||
else:
|
||||
cgen.stmt("auto vkEnc = ResourceTracker::getThreadLocalEncoder()")
|
||||
callLhs = None
|
||||
retTypeName = api.getRetTypeExpr()
|
||||
if retTypeName != "void":
|
||||
retVar = api.getRetVarExpr()
|
||||
cgen.stmt("%s %s = (%s)0" % (retTypeName, retVar, retTypeName))
|
||||
callLhs = retVar
|
||||
|
||||
if name in RESOURCE_TRACKER_ENTRIES:
|
||||
if declareResources:
|
||||
cgen.stmt("auto resources = ResourceTracker::get()")
|
||||
cgen.funcCall(
|
||||
callLhs, "resources->" + "on_" + api.name,
|
||||
["vkEnc"] + SUCCESS_VAL.get(retTypeName, []) + \
|
||||
[p.paramName for p in api.parameters])
|
||||
else:
|
||||
cgen.funcCall(
|
||||
callLhs, "vkEnc->" + api.name, [p.paramName for p in api.parameters] + ["true /* do lock */"])
|
||||
|
||||
if name in POSTPROCESSES:
|
||||
cgen.line(POSTPROCESSES[name])
|
||||
|
||||
if retTypeName != "void":
|
||||
cgen.stmt("return %s" % retVar)
|
||||
|
||||
|
||||
api_entry = api.withModifiedName("entry_" + api.name)
|
||||
|
||||
cgen.line("static " + self.cgen.makeFuncProto(api_entry))
|
||||
cgen.beginBlock()
|
||||
genEncoderOrResourceTrackerCall(cgen, api)
|
||||
cgen.endBlock()
|
||||
|
||||
if self.isDeviceDispatch(api) and self.feature != "VK_VERSION_1_0":
|
||||
api_entry_dyn_check = api.withModifiedName("dynCheck_entry_" + api.name)
|
||||
cgen.line("static " + self.cgen.makeFuncProto(api_entry_dyn_check))
|
||||
cgen.beginBlock()
|
||||
if self.feature == "VK_VERSION_1_3":
|
||||
cgen.stmt("auto resources = ResourceTracker::get()")
|
||||
if "VkCommandBuffer" == api.parameters[0].typeName:
|
||||
cgen.stmt("VkDevice device = resources->getDevice(commandBuffer)")
|
||||
cgen.beginIf("resources->getApiVersionFromDevice(device) < VK_API_VERSION_1_3")
|
||||
cgen.stmt("sOnInvalidDynamicallyCheckedCall(\"%s\", \"%s\")" % (api.name, self.feature))
|
||||
cgen.endIf()
|
||||
elif self.feature == "VK_VERSION_1_2":
|
||||
cgen.stmt("auto resources = ResourceTracker::get()")
|
||||
if "VkCommandBuffer" == api.parameters[0].typeName:
|
||||
cgen.stmt("VkDevice device = resources->getDevice(commandBuffer)")
|
||||
cgen.beginIf("resources->getApiVersionFromDevice(device) < VK_API_VERSION_1_2")
|
||||
cgen.stmt("sOnInvalidDynamicallyCheckedCall(\"%s\", \"%s\")" % (api.name, self.feature))
|
||||
cgen.endIf()
|
||||
elif self.feature == "VK_VERSION_1_1":
|
||||
cgen.stmt("auto resources = ResourceTracker::get()")
|
||||
if "VkCommandBuffer" == api.parameters[0].typeName:
|
||||
cgen.stmt("VkDevice device = resources->getDevice(commandBuffer)")
|
||||
cgen.beginIf("resources->getApiVersionFromDevice(device) < VK_API_VERSION_1_1")
|
||||
cgen.stmt("sOnInvalidDynamicallyCheckedCall(\"%s\", \"%s\")" % (api.name, self.feature))
|
||||
cgen.endIf()
|
||||
elif self.feature != "VK_VERSION_1_0":
|
||||
cgen.stmt("auto resources = ResourceTracker::get()")
|
||||
if "VkCommandBuffer" == api.parameters[0].typeName:
|
||||
cgen.stmt("VkDevice device = resources->getDevice(commandBuffer);")
|
||||
cgen.beginIf("!resources->hasDeviceExtension(device, \"%s\")" % self.feature)
|
||||
cgen.stmt("sOnInvalidDynamicallyCheckedCall(\"%s\", \"%s\")" % (api.name, self.feature))
|
||||
cgen.endIf()
|
||||
else:
|
||||
print("About to generate a frivolous api!: dynCheck entry: %s" % api.name)
|
||||
raise
|
||||
genEncoderOrResourceTrackerCall(cgen, api, declareResources = False)
|
||||
cgen.endBlock()
|
||||
|
||||
self.module.appendImpl(cgen.swapCode())
|
||||
|
||||
def onEnd(self,):
|
||||
getProcAddressDecl = "void* goldfish_vulkan_get_proc_address(const char* name)"
|
||||
self.module.appendHeader(getProcAddressDecl + ";\n")
|
||||
self.module.appendImpl(getProcAddressDecl)
|
||||
self.cgen.beginBlock()
|
||||
|
||||
prevFeature = None
|
||||
for e, f in zip(self.entries, self.entryFeatures):
|
||||
featureEndif = prevFeature is not None and (f != prevFeature)
|
||||
featureif = not featureEndif and (f != prevFeature)
|
||||
|
||||
if featureEndif:
|
||||
self.cgen.leftline("#endif")
|
||||
self.cgen.leftline("#ifdef %s" % f)
|
||||
|
||||
if featureif:
|
||||
self.cgen.leftline("#ifdef %s" % f)
|
||||
|
||||
self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name)
|
||||
if e.name in EXCLUDED_APIS:
|
||||
self.cgen.stmt("return nullptr")
|
||||
elif f == "VK_VERSION_1_3":
|
||||
self.cgen.stmt("return nullptr")
|
||||
elif f == "VK_VERSION_1_2":
|
||||
self.cgen.stmt("return nullptr")
|
||||
elif f == "VK_VERSION_1_1":
|
||||
self.cgen.stmt("return nullptr")
|
||||
elif f != "VK_VERSION_1_0":
|
||||
self.cgen.stmt("return nullptr")
|
||||
else:
|
||||
self.cgen.stmt("return (void*)%s" % ("entry_" + e.name))
|
||||
self.cgen.endIf()
|
||||
prevFeature = f
|
||||
|
||||
self.cgen.leftline("#endif")
|
||||
|
||||
self.cgen.stmt("return nullptr")
|
||||
self.cgen.endBlock()
|
||||
self.module.appendImpl(self.cgen.swapCode())
|
||||
|
||||
getInstanceProcAddressDecl = "void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name)"
|
||||
self.module.appendHeader(getInstanceProcAddressDecl + ";\n")
|
||||
self.module.appendImpl(getInstanceProcAddressDecl)
|
||||
self.cgen.beginBlock()
|
||||
|
||||
self.cgen.stmt(
|
||||
"auto resources = ResourceTracker::get()")
|
||||
self.cgen.stmt(
|
||||
"bool has1_1OrHigher = resources->getApiVersionFromInstance(instance) >= VK_API_VERSION_1_1")
|
||||
self.cgen.stmt(
|
||||
"bool has1_2OrHigher = resources->getApiVersionFromInstance(instance) >= VK_API_VERSION_1_2")
|
||||
self.cgen.stmt(
|
||||
"bool has1_3OrHigher = resources->getApiVersionFromInstance(instance) >= VK_API_VERSION_1_3")
|
||||
|
||||
prevFeature = None
|
||||
for e, f in zip(self.entries, self.entryFeatures):
|
||||
featureEndif = prevFeature is not None and (f != prevFeature)
|
||||
featureif = not featureEndif and (f != prevFeature)
|
||||
|
||||
if featureEndif:
|
||||
self.cgen.leftline("#endif")
|
||||
self.cgen.leftline("#ifdef %s" % f)
|
||||
|
||||
if featureif:
|
||||
self.cgen.leftline("#ifdef %s" % f)
|
||||
|
||||
self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name)
|
||||
|
||||
entryPointExpr = "(void*)%s" % ("entry_" + e.name)
|
||||
|
||||
if e.name in EXCLUDED_APIS:
|
||||
self.cgen.stmt("return nullptr")
|
||||
elif f == "VK_VERSION_1_3":
|
||||
if self.isDeviceDispatch(e):
|
||||
self.cgen.stmt("return (void*)dynCheck_entry_%s" % e.name)
|
||||
else:
|
||||
self.cgen.stmt( \
|
||||
"return has1_3OrHigher ? %s : nullptr" % \
|
||||
entryPointExpr)
|
||||
elif f == "VK_VERSION_1_2":
|
||||
if self.isDeviceDispatch(e):
|
||||
self.cgen.stmt("return (void*)dynCheck_entry_%s" % e.name)
|
||||
else:
|
||||
self.cgen.stmt( \
|
||||
"return has1_2OrHigher ? %s : nullptr" % \
|
||||
entryPointExpr)
|
||||
elif f == "VK_VERSION_1_1":
|
||||
if self.isDeviceDispatch(e):
|
||||
self.cgen.stmt("return (void*)dynCheck_entry_%s" % e.name)
|
||||
else:
|
||||
self.cgen.stmt( \
|
||||
"return has1_1OrHigher ? %s : nullptr" % \
|
||||
entryPointExpr)
|
||||
elif f != "VK_VERSION_1_0":
|
||||
entryNeedsInstanceExtensionCheck = self.cmdToFeatureType[e.name] == "instance"
|
||||
|
||||
entryPrefix = "dynCheck_" if self.isDeviceDispatch(e) else ""
|
||||
entryPointExpr = "(void*)%sentry_%s" % (entryPrefix, e.name)
|
||||
|
||||
if entryNeedsInstanceExtensionCheck:
|
||||
self.cgen.stmt("bool hasExt = resources->hasInstanceExtension(instance, \"%s\")" % f)
|
||||
self.cgen.stmt("return hasExt ? %s : nullptr" % entryPointExpr)
|
||||
else:
|
||||
# TODO(b/236246382): We need to check the device extension support here.
|
||||
self.cgen.stmt("// TODO(b/236246382): Check support for device extension");
|
||||
self.cgen.stmt("return %s" % entryPointExpr)
|
||||
|
||||
else:
|
||||
self.cgen.stmt("return %s" % entryPointExpr)
|
||||
self.cgen.endIf()
|
||||
prevFeature = f
|
||||
|
||||
self.cgen.leftline("#endif")
|
||||
|
||||
self.cgen.stmt("return nullptr")
|
||||
self.cgen.endBlock()
|
||||
self.module.appendImpl(self.cgen.swapCode())
|
||||
|
||||
getDeviceProcAddressDecl = "void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name)"
|
||||
self.module.appendHeader(getDeviceProcAddressDecl + ";\n")
|
||||
self.module.appendImpl(getDeviceProcAddressDecl)
|
||||
self.cgen.beginBlock()
|
||||
|
||||
self.cgen.stmt(
|
||||
"auto resources = ResourceTracker::get()")
|
||||
self.cgen.stmt(
|
||||
"bool has1_1OrHigher = resources->getApiVersionFromDevice(device) >= VK_API_VERSION_1_1")
|
||||
self.cgen.stmt(
|
||||
"bool has1_2OrHigher = resources->getApiVersionFromDevice(device) >= VK_API_VERSION_1_2")
|
||||
self.cgen.stmt(
|
||||
"bool has1_3OrHigher = resources->getApiVersionFromDevice(device) >= VK_API_VERSION_1_3")
|
||||
prevFeature = None
|
||||
for e, f in zip(self.entries, self.entryFeatures):
|
||||
featureEndif = prevFeature is not None and (f != prevFeature)
|
||||
featureif = not featureEndif and (f != prevFeature)
|
||||
|
||||
if featureEndif:
|
||||
self.cgen.leftline("#endif")
|
||||
self.cgen.leftline("#ifdef %s" % f)
|
||||
|
||||
if featureif:
|
||||
self.cgen.leftline("#ifdef %s" % f)
|
||||
|
||||
self.cgen.beginIf("!strcmp(name, \"%s\")" % e.name)
|
||||
|
||||
entryPointExpr = "(void*)%s" % ("entry_" + e.name)
|
||||
|
||||
if e.name in EXCLUDED_APIS:
|
||||
self.cgen.stmt("return nullptr")
|
||||
elif f == "VK_VERSION_1_3":
|
||||
self.cgen.stmt( \
|
||||
"return has1_3OrHigher ? %s : nullptr" % \
|
||||
entryPointExpr)
|
||||
elif f == "VK_VERSION_1_2":
|
||||
self.cgen.stmt( \
|
||||
"return has1_2OrHigher ? %s : nullptr" % \
|
||||
entryPointExpr)
|
||||
elif f == "VK_VERSION_1_1":
|
||||
self.cgen.stmt( \
|
||||
"return has1_1OrHigher ? %s : nullptr" % \
|
||||
entryPointExpr)
|
||||
elif f != "VK_VERSION_1_0":
|
||||
self.cgen.stmt( \
|
||||
"bool hasExt = resources->hasDeviceExtension(device, \"%s\")" % f)
|
||||
self.cgen.stmt("return hasExt ? %s : nullptr" % entryPointExpr)
|
||||
else:
|
||||
self.cgen.stmt("return %s" % entryPointExpr)
|
||||
self.cgen.endIf()
|
||||
prevFeature = f
|
||||
|
||||
self.cgen.leftline("#endif")
|
||||
|
||||
self.cgen.stmt("return nullptr")
|
||||
self.cgen.endBlock()
|
||||
|
||||
self.module.appendImpl(self.cgen.swapCode())
|
||||
|
||||
def isDeviceDispatch(self, api):
|
||||
# TODO(230793667): improve the heuristic and just use "cmdToFeatureType"
|
||||
return (len(api.parameters) > 0 and
|
||||
"VkDevice" == api.parameters[0].typeName) or (
|
||||
"VkCommandBuffer" == api.parameters[0].typeName and
|
||||
self.cmdToFeatureType.get(api.name, "") == "device")
|
||||
264
src/gfxstream/codegen/scripts/cereal/handlemap.py
Normal file
264
src/gfxstream/codegen/scripts/cereal/handlemap.py
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
# Copyright (c) 2018 The Android Open Source Project
|
||||
# Copyright (c) 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from .common.codegen import CodeGen
|
||||
from .common.vulkantypes import \
|
||||
VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator
|
||||
|
||||
from .wrapperdefs import VulkanWrapperGenerator
|
||||
from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE
|
||||
|
||||
class HandleMapCodegen(VulkanTypeIterator):
|
||||
def __init__(self, cgen, inputVar, handlemapVarName, prefix, isHandleFunc):
|
||||
self.cgen = cgen
|
||||
self.inputVar = inputVar
|
||||
self.prefix = prefix
|
||||
self.handlemapVarName = handlemapVarName
|
||||
|
||||
def makeAccess(varName, asPtr = True):
|
||||
return lambda t: self.cgen.generalAccess(t, parentVarName = varName, asPtr = asPtr)
|
||||
|
||||
def makeLengthAccess(varName):
|
||||
return lambda t: self.cgen.generalLengthAccess(t, parentVarName = varName)
|
||||
|
||||
def makeLengthAccessGuard(varName):
|
||||
return lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName=varName)
|
||||
|
||||
self.exprAccessor = makeAccess(self.inputVar)
|
||||
self.exprAccessorValue = makeAccess(self.inputVar, asPtr = False)
|
||||
self.lenAccessor = makeLengthAccess(self.inputVar)
|
||||
self.lenAccessorGuard = makeLengthAccessGuard(self.inputVar)
|
||||
|
||||
self.checked = False
|
||||
self.isHandleFunc = isHandleFunc
|
||||
|
||||
def needSkip(self, vulkanType):
|
||||
return False
|
||||
|
||||
def makeCastExpr(self, vulkanType):
|
||||
return "(%s)" % (
|
||||
self.cgen.makeCTypeDecl(vulkanType, useParamName=False))
|
||||
|
||||
def asNonConstCast(self, access, vulkanType):
|
||||
if vulkanType.staticArrExpr:
|
||||
casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
|
||||
elif vulkanType.accessibleAsPointer():
|
||||
casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForNonConstAccess()), access)
|
||||
else:
|
||||
casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
|
||||
return casted
|
||||
|
||||
def onCheck(self, vulkanType):
|
||||
pass
|
||||
|
||||
def endCheck(self, vulkanType):
|
||||
pass
|
||||
|
||||
def onCompoundType(self, vulkanType):
|
||||
|
||||
if self.needSkip(vulkanType):
|
||||
self.cgen.line("// TODO: Unsupported : %s" %
|
||||
self.cgen.makeCTypeDecl(vulkanType))
|
||||
return
|
||||
access = self.exprAccessor(vulkanType)
|
||||
lenAccess = self.lenAccessor(vulkanType)
|
||||
lenAccessGuard = self.lenAccessorGuard(vulkanType)
|
||||
|
||||
isPtr = vulkanType.pointerIndirectionLevels > 0
|
||||
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.beginIf(lenAccessGuard)
|
||||
|
||||
if isPtr:
|
||||
self.cgen.beginIf(access)
|
||||
|
||||
if lenAccess is not None:
|
||||
|
||||
loopVar = "i"
|
||||
access = "%s + %s" % (access, loopVar)
|
||||
forInit = "uint32_t %s = 0" % loopVar
|
||||
forCond = "%s < (uint32_t)%s" % (loopVar, lenAccess)
|
||||
forIncr = "++%s" % loopVar
|
||||
|
||||
self.cgen.beginFor(forInit, forCond, forIncr)
|
||||
|
||||
accessCasted = self.asNonConstCast(access, vulkanType)
|
||||
self.cgen.funcCall(None, self.prefix + vulkanType.typeName,
|
||||
[self.handlemapVarName, accessCasted])
|
||||
|
||||
if lenAccess is not None:
|
||||
self.cgen.endFor()
|
||||
|
||||
if isPtr:
|
||||
self.cgen.endIf()
|
||||
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.endIf()
|
||||
|
||||
def onString(self, vulkanType):
|
||||
pass
|
||||
|
||||
def onStringArray(self, vulkanType):
|
||||
pass
|
||||
|
||||
def onStaticArr(self, vulkanType):
|
||||
if not self.isHandleFunc(vulkanType):
|
||||
return
|
||||
|
||||
accessLhs = self.exprAccessor(vulkanType)
|
||||
lenAccess = self.lenAccessor(vulkanType)
|
||||
|
||||
self.cgen.stmt("%s->mapHandles_%s(%s%s, %s)" % \
|
||||
(self.handlemapVarName, vulkanType.typeName,
|
||||
self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()),
|
||||
accessLhs, lenAccess))
|
||||
|
||||
def onStructExtension(self, vulkanType):
|
||||
access = self.exprAccessor(vulkanType)
|
||||
|
||||
castedAccessExpr = "(%s)(%s)" % ("void*", access)
|
||||
self.cgen.beginIf(access)
|
||||
self.cgen.funcCall(None, self.prefix + "extension_struct",
|
||||
[self.handlemapVarName, castedAccessExpr])
|
||||
self.cgen.endIf()
|
||||
|
||||
def onPointer(self, vulkanType):
|
||||
if self.needSkip(vulkanType):
|
||||
return
|
||||
|
||||
if not self.isHandleFunc(vulkanType):
|
||||
return
|
||||
|
||||
access = self.exprAccessor(vulkanType)
|
||||
lenAccess = self.lenAccessor(vulkanType)
|
||||
lenAccess = "1" if lenAccess is None else lenAccess
|
||||
|
||||
self.cgen.beginIf(access)
|
||||
|
||||
self.cgen.stmt( \
|
||||
"%s->mapHandles_%s(%s%s, %s)" % \
|
||||
(self.handlemapVarName,
|
||||
vulkanType.typeName,
|
||||
self.makeCastExpr(vulkanType.getForNonConstAccess()),
|
||||
access,
|
||||
lenAccess))
|
||||
|
||||
self.cgen.endIf()
|
||||
|
||||
def onValue(self, vulkanType):
|
||||
if not self.isHandleFunc(vulkanType):
|
||||
return
|
||||
access = self.exprAccessor(vulkanType)
|
||||
self.cgen.stmt(
|
||||
"%s->mapHandles_%s(%s%s)" % \
|
||||
(self.handlemapVarName, vulkanType.typeName,
|
||||
self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()),
|
||||
access))
|
||||
|
||||
class VulkanHandleMap(VulkanWrapperGenerator):
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
|
||||
self.codegen = CodeGen()
|
||||
|
||||
self.handlemapPrefix = "handlemap_"
|
||||
self.toMapVar = "toMap"
|
||||
self.handlemapVarName = "handlemap"
|
||||
self.handlemapParam = \
|
||||
makeVulkanTypeSimple(False, "VulkanHandleMapping", 1,
|
||||
self.handlemapVarName)
|
||||
self.voidType = makeVulkanTypeSimple(False, "void", 0)
|
||||
|
||||
self.handlemapCodegen = \
|
||||
HandleMapCodegen(
|
||||
None,
|
||||
self.toMapVar,
|
||||
self.handlemapVarName,
|
||||
self.handlemapPrefix,
|
||||
lambda vtype : typeInfo.isHandleType(vtype.typeName))
|
||||
|
||||
self.knownDefs = {}
|
||||
|
||||
self.extensionHandlemapPrototype = \
|
||||
VulkanAPI(self.handlemapPrefix + "extension_struct",
|
||||
self.voidType,
|
||||
[self.handlemapParam, STRUCT_EXTENSION_PARAM_FOR_WRITE])
|
||||
|
||||
def onBegin(self,):
|
||||
VulkanWrapperGenerator.onBegin(self)
|
||||
self.module.appendImpl(self.codegen.makeFuncDecl(
|
||||
self.extensionHandlemapPrototype))
|
||||
|
||||
def onGenType(self, typeXml, name, alias):
|
||||
VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
|
||||
|
||||
if name in self.knownDefs:
|
||||
return
|
||||
|
||||
category = self.typeInfo.categoryOf(name)
|
||||
|
||||
if category in ["struct", "union"] and alias:
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncAlias(self.handlemapPrefix + name,
|
||||
self.handlemapPrefix + alias))
|
||||
|
||||
if category in ["struct", "union"] and not alias:
|
||||
|
||||
structInfo = self.typeInfo.structs[name]
|
||||
|
||||
typeFromName = \
|
||||
lambda varname: \
|
||||
makeVulkanTypeSimple(varname == "from", name, 1, varname)
|
||||
|
||||
handlemapParams = \
|
||||
[self.handlemapParam] + \
|
||||
list(map(typeFromName, [self.toMapVar]))
|
||||
|
||||
handlemapPrototype = \
|
||||
VulkanAPI(self.handlemapPrefix + name,
|
||||
self.voidType,
|
||||
handlemapParams)
|
||||
|
||||
def funcDefGenerator(cgen):
|
||||
self.handlemapCodegen.cgen = cgen
|
||||
for p in handlemapParams:
|
||||
cgen.stmt("(void)%s" % p.paramName)
|
||||
for member in structInfo.members:
|
||||
iterateVulkanType(self.typeInfo, member,
|
||||
self.handlemapCodegen)
|
||||
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncDecl(handlemapPrototype))
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(handlemapPrototype, funcDefGenerator))
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
|
||||
|
||||
def onEnd(self,):
|
||||
VulkanWrapperGenerator.onEnd(self)
|
||||
|
||||
def forEachExtensionHandlemap(ext, castedAccess, cgen):
|
||||
cgen.funcCall(None, self.handlemapPrefix + ext.name,
|
||||
[self.handlemapVarName, castedAccess])
|
||||
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(
|
||||
self.extensionHandlemapPrototype,
|
||||
lambda cgen: self.emitForEachStructExtension(
|
||||
cgen,
|
||||
self.voidType,
|
||||
STRUCT_EXTENSION_PARAM_FOR_WRITE,
|
||||
forEachExtensionHandlemap)))
|
||||
1035
src/gfxstream/codegen/scripts/cereal/marshaling.py
Normal file
1035
src/gfxstream/codegen/scripts/cereal/marshaling.py
Normal file
File diff suppressed because it is too large
Load diff
528
src/gfxstream/codegen/scripts/cereal/marshalingdefs.py
Normal file
528
src/gfxstream/codegen/scripts/cereal/marshalingdefs.py
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
# Copyright (c) 2021 The Android Open Source Project
|
||||
# Copyright (c) 2021 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
KNOWN_FUNCTION_OPCODES = {
|
||||
"vkCreateInstance": 20000,
|
||||
"vkDestroyInstance": 20001,
|
||||
"vkEnumeratePhysicalDevices": 20002,
|
||||
"vkGetPhysicalDeviceFeatures": 20003,
|
||||
"vkGetPhysicalDeviceFormatProperties": 20004,
|
||||
"vkGetPhysicalDeviceImageFormatProperties": 20005,
|
||||
"vkGetPhysicalDeviceProperties": 20006,
|
||||
"vkGetPhysicalDeviceQueueFamilyProperties": 20007,
|
||||
"vkGetPhysicalDeviceMemoryProperties": 20008,
|
||||
"vkGetInstanceProcAddr": 20009,
|
||||
"vkGetDeviceProcAddr": 20010,
|
||||
"vkCreateDevice": 20011,
|
||||
"vkDestroyDevice": 20012,
|
||||
"vkEnumerateInstanceExtensionProperties": 20013,
|
||||
"vkEnumerateDeviceExtensionProperties": 20014,
|
||||
"vkEnumerateInstanceLayerProperties": 20015,
|
||||
"vkEnumerateDeviceLayerProperties": 20016,
|
||||
"vkGetDeviceQueue": 20017,
|
||||
"vkQueueSubmit": 20018,
|
||||
"vkQueueWaitIdle": 20019,
|
||||
"vkDeviceWaitIdle": 20020,
|
||||
"vkAllocateMemory": 20021,
|
||||
"vkFreeMemory": 20022,
|
||||
"vkMapMemory": 20023,
|
||||
"vkUnmapMemory": 20024,
|
||||
"vkFlushMappedMemoryRanges": 20025,
|
||||
"vkInvalidateMappedMemoryRanges": 20026,
|
||||
"vkGetDeviceMemoryCommitment": 20027,
|
||||
"vkBindBufferMemory": 20028,
|
||||
"vkBindImageMemory": 20029,
|
||||
"vkGetBufferMemoryRequirements": 20030,
|
||||
"vkGetImageMemoryRequirements": 20031,
|
||||
"vkGetImageSparseMemoryRequirements": 20032,
|
||||
"vkGetPhysicalDeviceSparseImageFormatProperties": 20033,
|
||||
"vkQueueBindSparse": 20034,
|
||||
"vkCreateFence": 20035,
|
||||
"vkDestroyFence": 20036,
|
||||
"vkResetFences": 20037,
|
||||
"vkGetFenceStatus": 20038,
|
||||
"vkWaitForFences": 20039,
|
||||
"vkCreateSemaphore": 20040,
|
||||
"vkDestroySemaphore": 20041,
|
||||
"vkCreateEvent": 20042,
|
||||
"vkDestroyEvent": 20043,
|
||||
"vkGetEventStatus": 20044,
|
||||
"vkSetEvent": 20045,
|
||||
"vkResetEvent": 20046,
|
||||
"vkCreateQueryPool": 20047,
|
||||
"vkDestroyQueryPool": 20048,
|
||||
"vkGetQueryPoolResults": 20049,
|
||||
"vkCreateBuffer": 20050,
|
||||
"vkDestroyBuffer": 20051,
|
||||
"vkCreateBufferView": 20052,
|
||||
"vkDestroyBufferView": 20053,
|
||||
"vkCreateImage": 20054,
|
||||
"vkDestroyImage": 20055,
|
||||
"vkGetImageSubresourceLayout": 20056,
|
||||
"vkCreateImageView": 20057,
|
||||
"vkDestroyImageView": 20058,
|
||||
"vkCreateShaderModule": 20059,
|
||||
"vkDestroyShaderModule": 20060,
|
||||
"vkCreatePipelineCache": 20061,
|
||||
"vkDestroyPipelineCache": 20062,
|
||||
"vkGetPipelineCacheData": 20063,
|
||||
"vkMergePipelineCaches": 20064,
|
||||
"vkCreateGraphicsPipelines": 20065,
|
||||
"vkCreateComputePipelines": 20066,
|
||||
"vkDestroyPipeline": 20067,
|
||||
"vkCreatePipelineLayout": 20068,
|
||||
"vkDestroyPipelineLayout": 20069,
|
||||
"vkCreateSampler": 20070,
|
||||
"vkDestroySampler": 20071,
|
||||
"vkCreateDescriptorSetLayout": 20072,
|
||||
"vkDestroyDescriptorSetLayout": 20073,
|
||||
"vkCreateDescriptorPool": 20074,
|
||||
"vkDestroyDescriptorPool": 20075,
|
||||
"vkResetDescriptorPool": 20076,
|
||||
"vkAllocateDescriptorSets": 20077,
|
||||
"vkFreeDescriptorSets": 20078,
|
||||
"vkUpdateDescriptorSets": 20079,
|
||||
"vkCreateFramebuffer": 20080,
|
||||
"vkDestroyFramebuffer": 20081,
|
||||
"vkCreateRenderPass": 20082,
|
||||
"vkDestroyRenderPass": 20083,
|
||||
"vkGetRenderAreaGranularity": 20084,
|
||||
"vkCreateCommandPool": 20085,
|
||||
"vkDestroyCommandPool": 20086,
|
||||
"vkResetCommandPool": 20087,
|
||||
"vkAllocateCommandBuffers": 20088,
|
||||
"vkFreeCommandBuffers": 20089,
|
||||
"vkBeginCommandBuffer": 20090,
|
||||
"vkEndCommandBuffer": 20091,
|
||||
"vkResetCommandBuffer": 20092,
|
||||
"vkCmdBindPipeline": 20093,
|
||||
"vkCmdSetViewport": 20094,
|
||||
"vkCmdSetScissor": 20095,
|
||||
"vkCmdSetLineWidth": 20096,
|
||||
"vkCmdSetDepthBias": 20097,
|
||||
"vkCmdSetBlendConstants": 20098,
|
||||
"vkCmdSetDepthBounds": 20099,
|
||||
"vkCmdSetStencilCompareMask": 20100,
|
||||
"vkCmdSetStencilWriteMask": 20101,
|
||||
"vkCmdSetStencilReference": 20102,
|
||||
"vkCmdBindDescriptorSets": 20103,
|
||||
"vkCmdBindIndexBuffer": 20104,
|
||||
"vkCmdBindVertexBuffers": 20105,
|
||||
"vkCmdDraw": 20106,
|
||||
"vkCmdDrawIndexed": 20107,
|
||||
"vkCmdDrawIndirect": 20108,
|
||||
"vkCmdDrawIndexedIndirect": 20109,
|
||||
"vkCmdDispatch": 20110,
|
||||
"vkCmdDispatchIndirect": 20111,
|
||||
"vkCmdCopyBuffer": 20112,
|
||||
"vkCmdCopyImage": 20113,
|
||||
"vkCmdBlitImage": 20114,
|
||||
"vkCmdCopyBufferToImage": 20115,
|
||||
"vkCmdCopyImageToBuffer": 20116,
|
||||
"vkCmdUpdateBuffer": 20117,
|
||||
"vkCmdFillBuffer": 20118,
|
||||
"vkCmdClearColorImage": 20119,
|
||||
"vkCmdClearDepthStencilImage": 20120,
|
||||
"vkCmdClearAttachments": 20121,
|
||||
"vkCmdResolveImage": 20122,
|
||||
"vkCmdSetEvent": 20123,
|
||||
"vkCmdResetEvent": 20124,
|
||||
"vkCmdWaitEvents": 20125,
|
||||
"vkCmdPipelineBarrier": 20126,
|
||||
"vkCmdBeginQuery": 20127,
|
||||
"vkCmdEndQuery": 20128,
|
||||
"vkCmdResetQueryPool": 20129,
|
||||
"vkCmdWriteTimestamp": 20130,
|
||||
"vkCmdCopyQueryPoolResults": 20131,
|
||||
"vkCmdPushConstants": 20132,
|
||||
"vkCmdBeginRenderPass": 20133,
|
||||
"vkCmdNextSubpass": 20134,
|
||||
"vkCmdEndRenderPass": 20135,
|
||||
"vkCmdExecuteCommands": 20136,
|
||||
"vkEnumerateInstanceVersion": 20137,
|
||||
"vkBindBufferMemory2": 20138,
|
||||
"vkBindImageMemory2": 20139,
|
||||
"vkGetDeviceGroupPeerMemoryFeatures": 20140,
|
||||
"vkCmdSetDeviceMask": 20141,
|
||||
"vkCmdDispatchBase": 20142,
|
||||
"vkEnumeratePhysicalDeviceGroups": 20143,
|
||||
"vkGetImageMemoryRequirements2": 20144,
|
||||
"vkGetBufferMemoryRequirements2": 20145,
|
||||
"vkGetImageSparseMemoryRequirements2": 20146,
|
||||
"vkGetPhysicalDeviceFeatures2": 20147,
|
||||
"vkGetPhysicalDeviceProperties2": 20148,
|
||||
"vkGetPhysicalDeviceFormatProperties2": 20149,
|
||||
"vkGetPhysicalDeviceImageFormatProperties2": 20150,
|
||||
"vkGetPhysicalDeviceQueueFamilyProperties2": 20151,
|
||||
"vkGetPhysicalDeviceMemoryProperties2": 20152,
|
||||
"vkGetPhysicalDeviceSparseImageFormatProperties2": 20153,
|
||||
"vkTrimCommandPool": 20154,
|
||||
"vkGetDeviceQueue2": 20155,
|
||||
"vkCreateSamplerYcbcrConversion": 20156,
|
||||
"vkDestroySamplerYcbcrConversion": 20157,
|
||||
"vkCreateDescriptorUpdateTemplate": 20158,
|
||||
"vkDestroyDescriptorUpdateTemplate": 20159,
|
||||
"vkUpdateDescriptorSetWithTemplate": 20160,
|
||||
"vkGetPhysicalDeviceExternalBufferProperties": 20161,
|
||||
"vkGetPhysicalDeviceExternalFenceProperties": 20162,
|
||||
"vkGetPhysicalDeviceExternalSemaphoreProperties": 20163,
|
||||
"vkGetDescriptorSetLayoutSupport": 20164,
|
||||
"vkDestroySurfaceKHR": 20165,
|
||||
"vkGetPhysicalDeviceSurfaceSupportKHR": 20166,
|
||||
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR": 20167,
|
||||
"vkGetPhysicalDeviceSurfaceFormatsKHR": 20168,
|
||||
"vkGetPhysicalDeviceSurfacePresentModesKHR": 20169,
|
||||
"vkCreateSwapchainKHR": 20170,
|
||||
"vkDestroySwapchainKHR": 20171,
|
||||
"vkGetSwapchainImagesKHR": 20172,
|
||||
"vkAcquireNextImageKHR": 20173,
|
||||
"vkQueuePresentKHR": 20174,
|
||||
"vkGetDeviceGroupPresentCapabilitiesKHR": 20175,
|
||||
"vkGetDeviceGroupSurfacePresentModesKHR": 20176,
|
||||
"vkGetPhysicalDevicePresentRectanglesKHR": 20177,
|
||||
"vkAcquireNextImage2KHR": 20178,
|
||||
"vkGetPhysicalDeviceDisplayPropertiesKHR": 20179,
|
||||
"vkGetPhysicalDeviceDisplayPlanePropertiesKHR": 20180,
|
||||
"vkGetDisplayPlaneSupportedDisplaysKHR": 20181,
|
||||
"vkGetDisplayModePropertiesKHR": 20182,
|
||||
"vkCreateDisplayModeKHR": 20183,
|
||||
"vkGetDisplayPlaneCapabilitiesKHR": 20184,
|
||||
"vkCreateDisplayPlaneSurfaceKHR": 20185,
|
||||
"vkCreateSharedSwapchainsKHR": 20186,
|
||||
"vkCreateXlibSurfaceKHR": 20187,
|
||||
"vkGetPhysicalDeviceXlibPresentationSupportKHR": 20188,
|
||||
"vkCreateXcbSurfaceKHR": 20189,
|
||||
"vkGetPhysicalDeviceXcbPresentationSupportKHR": 20190,
|
||||
"vkCreateWaylandSurfaceKHR": 20191,
|
||||
"vkGetPhysicalDeviceWaylandPresentationSupportKHR": 20192,
|
||||
"vkCreateMirSurfaceKHR": 20193,
|
||||
"vkGetPhysicalDeviceMirPresentationSupportKHR": 20194,
|
||||
"vkCreateAndroidSurfaceKHR": 20195,
|
||||
"vkCreateWin32SurfaceKHR": 20196,
|
||||
"vkGetPhysicalDeviceWin32PresentationSupportKHR": 20197,
|
||||
"vkGetPhysicalDeviceFeatures2KHR": 20198,
|
||||
"vkGetPhysicalDeviceProperties2KHR": 20199,
|
||||
"vkGetPhysicalDeviceFormatProperties2KHR": 20200,
|
||||
"vkGetPhysicalDeviceImageFormatProperties2KHR": 20201,
|
||||
"vkGetPhysicalDeviceQueueFamilyProperties2KHR": 20202,
|
||||
"vkGetPhysicalDeviceMemoryProperties2KHR": 20203,
|
||||
"vkGetPhysicalDeviceSparseImageFormatProperties2KHR": 20204,
|
||||
"vkGetDeviceGroupPeerMemoryFeaturesKHR": 20205,
|
||||
"vkCmdSetDeviceMaskKHR": 20206,
|
||||
"vkCmdDispatchBaseKHR": 20207,
|
||||
"vkTrimCommandPoolKHR": 20208,
|
||||
"vkEnumeratePhysicalDeviceGroupsKHR": 20209,
|
||||
"vkGetPhysicalDeviceExternalBufferPropertiesKHR": 20210,
|
||||
"vkGetMemoryWin32HandleKHR": 20211,
|
||||
"vkGetMemoryWin32HandlePropertiesKHR": 20212,
|
||||
"vkGetMemoryFdKHR": 20213,
|
||||
"vkGetMemoryFdPropertiesKHR": 20214,
|
||||
"vkGetPhysicalDeviceExternalSemaphorePropertiesKHR": 20215,
|
||||
"vkImportSemaphoreWin32HandleKHR": 20216,
|
||||
"vkGetSemaphoreWin32HandleKHR": 20217,
|
||||
"vkImportSemaphoreFdKHR": 20218,
|
||||
"vkGetSemaphoreFdKHR": 20219,
|
||||
"vkCmdPushDescriptorSetKHR": 20220,
|
||||
"vkCmdPushDescriptorSetWithTemplateKHR": 20221,
|
||||
"vkCreateDescriptorUpdateTemplateKHR": 20222,
|
||||
"vkDestroyDescriptorUpdateTemplateKHR": 20223,
|
||||
"vkUpdateDescriptorSetWithTemplateKHR": 20224,
|
||||
"vkCreateRenderPass2KHR": 20225,
|
||||
"vkCmdBeginRenderPass2KHR": 20226,
|
||||
"vkCmdNextSubpass2KHR": 20227,
|
||||
"vkCmdEndRenderPass2KHR": 20228,
|
||||
"vkGetSwapchainStatusKHR": 20229,
|
||||
"vkGetPhysicalDeviceExternalFencePropertiesKHR": 20230,
|
||||
"vkImportFenceWin32HandleKHR": 20231,
|
||||
"vkGetFenceWin32HandleKHR": 20232,
|
||||
"vkImportFenceFdKHR": 20233,
|
||||
"vkGetFenceFdKHR": 20234,
|
||||
"vkGetPhysicalDeviceSurfaceCapabilities2KHR": 20235,
|
||||
"vkGetPhysicalDeviceSurfaceFormats2KHR": 20236,
|
||||
"vkGetPhysicalDeviceDisplayProperties2KHR": 20237,
|
||||
"vkGetPhysicalDeviceDisplayPlaneProperties2KHR": 20238,
|
||||
"vkGetDisplayModeProperties2KHR": 20239,
|
||||
"vkGetDisplayPlaneCapabilities2KHR": 20240,
|
||||
"vkGetImageMemoryRequirements2KHR": 20241,
|
||||
"vkGetBufferMemoryRequirements2KHR": 20242,
|
||||
"vkGetImageSparseMemoryRequirements2KHR": 20243,
|
||||
"vkCreateSamplerYcbcrConversionKHR": 20244,
|
||||
"vkDestroySamplerYcbcrConversionKHR": 20245,
|
||||
"vkBindBufferMemory2KHR": 20246,
|
||||
"vkBindImageMemory2KHR": 20247,
|
||||
"vkGetDescriptorSetLayoutSupportKHR": 20248,
|
||||
"vkCmdDrawIndirectCountKHR": 20249,
|
||||
"vkCmdDrawIndexedIndirectCountKHR": 20250,
|
||||
"vkGetSwapchainGrallocUsageANDROID": 20251,
|
||||
"vkAcquireImageANDROID": 20252,
|
||||
"vkQueueSignalReleaseImageANDROID": 20253,
|
||||
"vkCreateDebugReportCallbackEXT": 20254,
|
||||
"vkDestroyDebugReportCallbackEXT": 20255,
|
||||
"vkDebugReportMessageEXT": 20256,
|
||||
"vkDebugMarkerSetObjectTagEXT": 20257,
|
||||
"vkDebugMarkerSetObjectNameEXT": 20258,
|
||||
"vkCmdDebugMarkerBeginEXT": 20259,
|
||||
"vkCmdDebugMarkerEndEXT": 20260,
|
||||
"vkCmdDebugMarkerInsertEXT": 20261,
|
||||
"vkCmdDrawIndirectCountAMD": 20262,
|
||||
"vkCmdDrawIndexedIndirectCountAMD": 20263,
|
||||
"vkGetShaderInfoAMD": 20264,
|
||||
"vkGetPhysicalDeviceExternalImageFormatPropertiesNV": 20265,
|
||||
"vkGetMemoryWin32HandleNV": 20266,
|
||||
"vkCreateViSurfaceNN": 20267,
|
||||
"vkCmdBeginConditionalRenderingEXT": 20268,
|
||||
"vkCmdEndConditionalRenderingEXT": 20269,
|
||||
"vkCmdProcessCommandsNVX": 20270,
|
||||
"vkCmdReserveSpaceForCommandsNVX": 20271,
|
||||
"vkCreateIndirectCommandsLayoutNVX": 20272,
|
||||
"vkDestroyIndirectCommandsLayoutNVX": 20273,
|
||||
"vkCreateObjectTableNVX": 20274,
|
||||
"vkDestroyObjectTableNVX": 20275,
|
||||
"vkRegisterObjectsNVX": 20276,
|
||||
"vkUnregisterObjectsNVX": 20277,
|
||||
"vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX": 20278,
|
||||
"vkCmdSetViewportWScalingNV": 20279,
|
||||
"vkReleaseDisplayEXT": 20280,
|
||||
"vkAcquireXlibDisplayEXT": 20281,
|
||||
"vkGetRandROutputDisplayEXT": 20282,
|
||||
"vkGetPhysicalDeviceSurfaceCapabilities2EXT": 20283,
|
||||
"vkDisplayPowerControlEXT": 20284,
|
||||
"vkRegisterDeviceEventEXT": 20285,
|
||||
"vkRegisterDisplayEventEXT": 20286,
|
||||
"vkGetSwapchainCounterEXT": 20287,
|
||||
"vkGetRefreshCycleDurationGOOGLE": 20288,
|
||||
"vkGetPastPresentationTimingGOOGLE": 20289,
|
||||
"vkCmdSetDiscardRectangleEXT": 20290,
|
||||
"vkSetHdrMetadataEXT": 20291,
|
||||
"vkCreateIOSSurfaceMVK": 20292,
|
||||
"vkCreateMacOSSurfaceMVK": 20293,
|
||||
"vkSetDebugUtilsObjectNameEXT": 20294,
|
||||
"vkSetDebugUtilsObjectTagEXT": 20295,
|
||||
"vkQueueBeginDebugUtilsLabelEXT": 20296,
|
||||
"vkQueueEndDebugUtilsLabelEXT": 20297,
|
||||
"vkQueueInsertDebugUtilsLabelEXT": 20298,
|
||||
"vkCmdBeginDebugUtilsLabelEXT": 20299,
|
||||
"vkCmdEndDebugUtilsLabelEXT": 20300,
|
||||
"vkCmdInsertDebugUtilsLabelEXT": 20301,
|
||||
"vkCreateDebugUtilsMessengerEXT": 20302,
|
||||
"vkDestroyDebugUtilsMessengerEXT": 20303,
|
||||
"vkSubmitDebugUtilsMessageEXT": 20304,
|
||||
"vkGetAndroidHardwareBufferPropertiesANDROID": 20305,
|
||||
"vkGetMemoryAndroidHardwareBufferANDROID": 20306,
|
||||
"vkCmdSetSampleLocationsEXT": 20307,
|
||||
"vkGetPhysicalDeviceMultisamplePropertiesEXT": 20308,
|
||||
"vkCreateValidationCacheEXT": 20309,
|
||||
"vkDestroyValidationCacheEXT": 20310,
|
||||
"vkMergeValidationCachesEXT": 20311,
|
||||
"vkGetValidationCacheDataEXT": 20312,
|
||||
"vkGetMemoryHostPointerPropertiesEXT": 20313,
|
||||
"vkCmdWriteBufferMarkerAMD": 20314,
|
||||
"vkCmdSetCheckpointNV": 20315,
|
||||
"vkGetQueueCheckpointDataNV": 20316,
|
||||
"vkMapMemoryIntoAddressSpaceGOOGLE": 20317,
|
||||
"vkUpdateDescriptorSetWithTemplateSizedGOOGLE": 20320,
|
||||
"vkBeginCommandBufferAsyncGOOGLE": 20321,
|
||||
"vkEndCommandBufferAsyncGOOGLE": 20322,
|
||||
"vkResetCommandBufferAsyncGOOGLE": 20323,
|
||||
"vkCommandBufferHostSyncGOOGLE": 20324,
|
||||
"vkCreateImageWithRequirementsGOOGLE": 20325,
|
||||
"vkCreateBufferWithRequirementsGOOGLE": 20326,
|
||||
"vkGetMemoryHostAddressInfoGOOGLE": 20327,
|
||||
"vkFreeMemorySyncGOOGLE": 20328,
|
||||
"vkQueueHostSyncGOOGLE": 20329,
|
||||
"vkQueueSubmitAsyncGOOGLE": 20330,
|
||||
"vkQueueWaitIdleAsyncGOOGLE": 20331,
|
||||
"vkQueueBindSparseAsyncGOOGLE": 20332,
|
||||
"vkGetLinearImageLayoutGOOGLE": 20333,
|
||||
"vkGetMTLDeviceMVK": 20334,
|
||||
"vkSetMTLTextureMVK": 20335,
|
||||
"vkGetMTLTextureMVK": 20336,
|
||||
"vkGetMTLBufferMVK": 20337,
|
||||
"vkUseIOSurfaceMVK": 20338,
|
||||
"vkGetIOSurfaceMVK": 20339,
|
||||
"vkQueueFlushCommandsGOOGLE": 20340,
|
||||
"vkGetBlobGOOGLE": 20341,
|
||||
}
|
||||
|
||||
CUSTOM_MARSHAL_TYPES = {
|
||||
"VkAccelerationStructureInstanceKHR": {
|
||||
"common": """
|
||||
typedef struct VkAccelerationStructureInstanceKHRWithoutBitFields {
|
||||
VkTransformMatrixKHR transform;
|
||||
uint32_t dwords[2];
|
||||
uint64_t accelerationStructureReference;
|
||||
} VkAccelerationStructureInstanceKHRWithoutBitFields;
|
||||
""",
|
||||
"marshaling": """
|
||||
const VkAccelerationStructureInstanceKHRWithoutBitFields* {newInputVarName} = (const VkAccelerationStructureInstanceKHRWithoutBitFields*)({inputVarName});
|
||||
marshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transform));
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
{streamVarName}->write((uint32_t*)&({newInputVarName}->dwords[i]), sizeof(uint32_t));
|
||||
}}
|
||||
{streamVarName}->write((uint64_t*)&{newInputVarName}->accelerationStructureReference, sizeof(uint64_t));
|
||||
""",
|
||||
"unmarshaling": """
|
||||
VkAccelerationStructureInstanceKHRWithoutBitFields* {newInputVarName} = (VkAccelerationStructureInstanceKHRWithoutBitFields*)({inputVarName});
|
||||
unmarshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transform));
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
{streamVarName}->read((uint32_t*)&({newInputVarName}->dwords[i]), sizeof(uint32_t));
|
||||
}}
|
||||
{streamVarName}->read((uint64_t*)&{newInputVarName}->accelerationStructureReference, sizeof(uint64_t));
|
||||
""",
|
||||
"reservedmarshaling": """
|
||||
(void)vkStream;
|
||||
const VkAccelerationStructureInstanceKHRWithoutBitFields* {newInputVarName} = (const VkAccelerationStructureInstanceKHRWithoutBitFields*)({inputVarName});
|
||||
reservedmarshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transform), ptr);
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
memcpy(*ptr, (uint32_t*)&({newInputVarName}->dwords[i]), sizeof(uint32_t));
|
||||
*ptr += sizeof(uint32_t);
|
||||
}}
|
||||
memcpy(*ptr, (uint64_t*)&{newInputVarName}->accelerationStructureReference, sizeof(uint64_t));
|
||||
*ptr += sizeof(uint64_t);
|
||||
""",
|
||||
"reservedunmarshaling": """
|
||||
VkAccelerationStructureInstanceKHRWithoutBitFields* {newInputVarName} = (VkAccelerationStructureInstanceKHRWithoutBitFields*)({inputVarName});
|
||||
reservedunmarshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transform), ptr);
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
memcpy((uint32_t*)&({newInputVarName}->dwords[i]), *ptr, sizeof(uint32_t));
|
||||
*ptr += sizeof(uint32_t);
|
||||
}}
|
||||
memcpy((uint64_t*)&{newInputVarName}->accelerationStructureReference, *ptr, sizeof(uint64_t));
|
||||
*ptr += sizeof(uint64_t);
|
||||
""",
|
||||
},
|
||||
"VkAccelerationStructureMatrixMotionInstanceNV": {
|
||||
"common": """
|
||||
typedef struct VkAccelerationStructureMatrixMotionInstanceNVWithoutBitFields {
|
||||
VkTransformMatrixKHR transformT0;
|
||||
VkTransformMatrixKHR transformT1;
|
||||
uint32_t dwords[2];
|
||||
uint64_t accelerationStructureReference;
|
||||
} VkAccelerationStructureMatrixMotionInstanceNVWithoutBitFields;
|
||||
""",
|
||||
"marshaling": """
|
||||
const VkAccelerationStructureMatrixMotionInstanceNVWithoutBitFields* {newInputVarName} = (const VkAccelerationStructureMatrixMotionInstanceNVWithoutBitFields*)({inputVarName});
|
||||
marshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transformT0));
|
||||
marshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transformT1));
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
{streamVarName}->write((uint32_t*)&({newInputVarName}->dwords[i]), sizeof(uint32_t));
|
||||
}}
|
||||
{streamVarName}->write((uint64_t*)&{newInputVarName}->accelerationStructureReference, sizeof(uint64_t));
|
||||
""",
|
||||
"unmarshaling": """
|
||||
VkAccelerationStructureMatrixMotionInstanceNVWithoutBitFields* {newInputVarName} = (VkAccelerationStructureMatrixMotionInstanceNVWithoutBitFields*)({inputVarName});
|
||||
unmarshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transformT0));
|
||||
unmarshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transformT1));
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
{streamVarName}->read((uint32_t*)&({newInputVarName}->dwords[i]), sizeof(uint32_t));
|
||||
}}
|
||||
{streamVarName}->read((uint64_t*)&{newInputVarName}->accelerationStructureReference, sizeof(uint64_t));
|
||||
""",
|
||||
"reservedmarshaling": """
|
||||
(void)vkStream;
|
||||
const VkAccelerationStructureMatrixMotionInstanceNVWithoutBitFields* {newInputVarName} = (const VkAccelerationStructureMatrixMotionInstanceNVWithoutBitFields*)({inputVarName});
|
||||
reservedmarshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transformT0), ptr);
|
||||
reservedmarshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transformT1), ptr);
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
memcpy(*ptr, (uint32_t*)&({newInputVarName}->dwords[i]), sizeof(uint32_t));
|
||||
*ptr += sizeof(uint32_t);
|
||||
}}
|
||||
memcpy(*ptr, (uint64_t*)&{newInputVarName}->accelerationStructureReference, sizeof(uint64_t));
|
||||
*ptr += sizeof(uint64_t);
|
||||
""",
|
||||
"reservedunmarshaling": """
|
||||
VkAccelerationStructureMatrixMotionInstanceNVWithoutBitFields* {newInputVarName} = (VkAccelerationStructureMatrixMotionInstanceNVWithoutBitFields*)({inputVarName});
|
||||
reservedunmarshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transformT0), ptr);
|
||||
reservedunmarshal_VkTransformMatrixKHR({streamVarName}, {rootTypeVarName}, (VkTransformMatrixKHR*)(&{newInputVarName}->transformT1), ptr);
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
memcpy((uint32_t*)&({newInputVarName}->dwords[i]), *ptr, sizeof(uint32_t));
|
||||
*ptr += sizeof(uint32_t);
|
||||
}}
|
||||
memcpy((uint64_t*)&{newInputVarName}->accelerationStructureReference, *ptr, sizeof(uint64_t));
|
||||
*ptr += sizeof(uint64_t);
|
||||
""",
|
||||
},
|
||||
"VkAccelerationStructureSRTMotionInstanceNV": {
|
||||
"common": """
|
||||
typedef struct VkAccelerationStructureSRTMotionInstanceNVWithoutBitFields {
|
||||
VkSRTDataNV transformT0;
|
||||
VkSRTDataNV transformT1;
|
||||
uint32_t dwords[2];
|
||||
uint64_t accelerationStructureReference;
|
||||
} VkAccelerationStructureSRTMotionInstanceNVWithoutBitFields;
|
||||
""",
|
||||
"marshaling": """
|
||||
const VkAccelerationStructureSRTMotionInstanceNVWithoutBitFields* {newInputVarName} = (const VkAccelerationStructureSRTMotionInstanceNVWithoutBitFields*)({inputVarName});
|
||||
marshal_VkSRTDataNV({streamVarName}, {rootTypeVarName}, (VkSRTDataNV*)(&{newInputVarName}->transformT0));
|
||||
marshal_VkSRTDataNV({streamVarName}, {rootTypeVarName}, (VkSRTDataNV*)(&{newInputVarName}->transformT1));
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
{streamVarName}->write((uint32_t*)&({newInputVarName}->dwords[i]), sizeof(uint32_t));
|
||||
}}
|
||||
{streamVarName}->write((uint64_t*)&{newInputVarName}->accelerationStructureReference, sizeof(uint64_t));
|
||||
""",
|
||||
"unmarshaling": """
|
||||
VkAccelerationStructureSRTMotionInstanceNVWithoutBitFields* {newInputVarName} = (VkAccelerationStructureSRTMotionInstanceNVWithoutBitFields*)({inputVarName});
|
||||
unmarshal_VkSRTDataNV({streamVarName}, {rootTypeVarName}, (VkSRTDataNV*)(&{newInputVarName}->transformT0));
|
||||
unmarshal_VkSRTDataNV({streamVarName}, {rootTypeVarName}, (VkSRTDataNV*)(&{newInputVarName}->transformT1));
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
{streamVarName}->read((uint32_t*)&({newInputVarName}->dwords[i]), sizeof(uint32_t));
|
||||
}}
|
||||
{streamVarName}->read((uint64_t*)&{newInputVarName}->accelerationStructureReference, sizeof(uint64_t));
|
||||
""",
|
||||
"reservedmarshaling": """
|
||||
(void)vkStream;
|
||||
const VkAccelerationStructureSRTMotionInstanceNVWithoutBitFields* {newInputVarName} = (const VkAccelerationStructureSRTMotionInstanceNVWithoutBitFields*)({inputVarName});
|
||||
reservedmarshal_VkSRTDataNV({streamVarName}, {rootTypeVarName}, (VkSRTDataNV*)(&{newInputVarName}->transformT0), ptr);
|
||||
reservedmarshal_VkSRTDataNV({streamVarName}, {rootTypeVarName}, (VkSRTDataNV*)(&{newInputVarName}->transformT1), ptr);
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
memcpy(*ptr, (uint32_t*)&({newInputVarName}->dwords[i]), sizeof(uint32_t));
|
||||
*ptr += sizeof(uint32_t);
|
||||
}}
|
||||
memcpy(*ptr, (uint64_t*)&{newInputVarName}->accelerationStructureReference, sizeof(uint64_t));
|
||||
*ptr += sizeof(uint64_t);
|
||||
""",
|
||||
"reservedunmarshaling": """
|
||||
VkAccelerationStructureSRTMotionInstanceNVWithoutBitFields* {newInputVarName} = (VkAccelerationStructureSRTMotionInstanceNVWithoutBitFields*)({inputVarName});
|
||||
reservedunmarshal_VkSRTDataNV({streamVarName}, {rootTypeVarName}, (VkSRTDataNV*)(&{newInputVarName}->transformT0), ptr);
|
||||
reservedunmarshal_VkSRTDataNV({streamVarName}, {rootTypeVarName}, (VkSRTDataNV*)(&{newInputVarName}->transformT1), ptr);
|
||||
for (uint32_t i = 0; i < 2; i++) {{
|
||||
memcpy((uint32_t*)&({newInputVarName}->dwords[i]), *ptr, sizeof(uint32_t));
|
||||
*ptr += sizeof(uint32_t);
|
||||
}}
|
||||
memcpy((uint64_t*)&{newInputVarName}->accelerationStructureReference, *ptr, sizeof(uint64_t));
|
||||
*ptr += sizeof(uint64_t);
|
||||
""",
|
||||
},
|
||||
"VkXcbSurfaceCreateInfoKHR": {
|
||||
"common": """
|
||||
// This struct should never be marshaled / unmarshaled.
|
||||
__builtin_trap();
|
||||
""",
|
||||
"marshaling": "",
|
||||
"unmarshaling": "",
|
||||
"reservedmarshaling": "",
|
||||
"reservedunmarshaling": "",
|
||||
},
|
||||
"VkMetalSurfaceCreateInfoEXT": {
|
||||
"common": """
|
||||
// This struct should never be marshaled / unmarshaled.
|
||||
__builtin_trap();
|
||||
""",
|
||||
"marshaling": "",
|
||||
"unmarshaling": "",
|
||||
"reservedmarshaling": "",
|
||||
"reservedunmarshaling": "",
|
||||
},
|
||||
}
|
||||
1061
src/gfxstream/codegen/scripts/cereal/reservedmarshaling.py
Normal file
1061
src/gfxstream/codegen/scripts/cereal/reservedmarshaling.py
Normal file
File diff suppressed because it is too large
Load diff
405
src/gfxstream/codegen/scripts/cereal/subdecode.py
Normal file
405
src/gfxstream/codegen/scripts/cereal/subdecode.py
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
from .common.codegen import CodeGen, VulkanWrapperGenerator
|
||||
from .common.vulkantypes import VulkanAPI, iterateVulkanType, VulkanType
|
||||
|
||||
from .reservedmarshaling import VulkanReservedMarshalingCodegen
|
||||
from .transform import TransformCodegen
|
||||
|
||||
from .wrapperdefs import API_PREFIX_RESERVEDUNMARSHAL
|
||||
from .wrapperdefs import MAX_PACKET_LENGTH
|
||||
from .wrapperdefs import ROOT_TYPE_DEFAULT_VALUE
|
||||
|
||||
|
||||
decoder_decl_preamble = """
|
||||
"""
|
||||
|
||||
decoder_impl_preamble = """
|
||||
"""
|
||||
|
||||
global_state_prefix = "this->on_"
|
||||
|
||||
READ_STREAM = "readStream"
|
||||
WRITE_STREAM = "vkStream"
|
||||
|
||||
# Driver workarounds for APIs that don't work well multithreaded
|
||||
driver_workarounds_global_lock_apis = [
|
||||
"vkCreatePipelineLayout",
|
||||
"vkDestroyPipelineLayout",
|
||||
]
|
||||
|
||||
MAX_STACK_ITEMS = "16"
|
||||
|
||||
|
||||
def emit_param_decl_for_reading(param, cgen):
|
||||
if param.staticArrExpr:
|
||||
cgen.stmt(
|
||||
cgen.makeRichCTypeDecl(param.getForNonConstAccess()))
|
||||
else:
|
||||
cgen.stmt(
|
||||
cgen.makeRichCTypeDecl(param))
|
||||
|
||||
if param.pointerIndirectionLevels > 0:
|
||||
lenAccess = cgen.generalLengthAccess(param)
|
||||
if not lenAccess:
|
||||
lenAccess = "1"
|
||||
arrSize = "1" if "1" == lenAccess else "MAX_STACK_ITEMS"
|
||||
|
||||
typeHere = "uint8_t*" if "void" == param.typeName else param.typeName
|
||||
cgen.stmt("%s%s stack_%s[%s]" % (
|
||||
typeHere, "*" * (param.pointerIndirectionLevels - 1), param.paramName, arrSize))
|
||||
|
||||
|
||||
def emit_unmarshal(typeInfo, param, cgen, output=False, destroy=False, noUnbox=False):
|
||||
if destroy:
|
||||
iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen(
|
||||
cgen,
|
||||
"host",
|
||||
READ_STREAM,
|
||||
ROOT_TYPE_DEFAULT_VALUE,
|
||||
param.paramName,
|
||||
"readStreamPtrPtr",
|
||||
API_PREFIX_RESERVEDUNMARSHAL,
|
||||
"",
|
||||
direction="read",
|
||||
dynAlloc=True))
|
||||
lenAccess = cgen.generalLengthAccess(param)
|
||||
lenAccessGuard = cgen.generalLengthAccessGuard(param)
|
||||
if None == lenAccess or "1" == lenAccess:
|
||||
cgen.stmt("boxed_%s_preserve = %s" %
|
||||
(param.paramName, param.paramName))
|
||||
cgen.stmt("%s = unbox_%s(%s)" %
|
||||
(param.paramName, param.typeName, param.paramName))
|
||||
else:
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.beginIf(lenAccessGuard)
|
||||
cgen.beginFor("uint32_t i = 0", "i < %s" % lenAccess, "++i")
|
||||
cgen.stmt("boxed_%s_preserve[i] = %s[i]" %
|
||||
(param.paramName, param.paramName))
|
||||
cgen.stmt("((%s*)(%s))[i] = unbox_%s(%s[i])" % (param.typeName,
|
||||
param.paramName, param.typeName, param.paramName))
|
||||
cgen.endFor()
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.endIf()
|
||||
else:
|
||||
if noUnbox:
|
||||
cgen.line("// No unbox for %s" % (param.paramName))
|
||||
|
||||
lenAccess = cgen.generalLengthAccess(param)
|
||||
if not lenAccess:
|
||||
lenAccess = "1"
|
||||
arrSize = "1" if "1" == lenAccess else "MAX_STACK_ITEMS"
|
||||
|
||||
iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen(
|
||||
cgen,
|
||||
"host",
|
||||
READ_STREAM,
|
||||
ROOT_TYPE_DEFAULT_VALUE,
|
||||
param.paramName,
|
||||
"readStreamPtrPtr",
|
||||
API_PREFIX_RESERVEDUNMARSHAL,
|
||||
"" if (output or noUnbox) else "unbox_",
|
||||
direction="read",
|
||||
dynAlloc=True,
|
||||
stackVar="stack_%s" % param.paramName,
|
||||
stackArrSize=arrSize))
|
||||
|
||||
|
||||
def emit_dispatch_unmarshal(typeInfo, param, cgen, globalWrapped):
|
||||
if globalWrapped:
|
||||
cgen.stmt(
|
||||
"// Begin global wrapped dispatchable handle unboxing for %s" % param.paramName)
|
||||
iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen(
|
||||
cgen,
|
||||
"host",
|
||||
READ_STREAM,
|
||||
ROOT_TYPE_DEFAULT_VALUE,
|
||||
param.paramName,
|
||||
"readStreamPtrPtr",
|
||||
API_PREFIX_RESERVEDUNMARSHAL,
|
||||
"",
|
||||
direction="read",
|
||||
dynAlloc=True))
|
||||
else:
|
||||
cgen.stmt(
|
||||
"// Begin non wrapped dispatchable handle unboxing for %s" % param.paramName)
|
||||
# cgen.stmt("%s->unsetHandleMapping()" % READ_STREAM)
|
||||
iterateVulkanType(typeInfo, param, VulkanReservedMarshalingCodegen(
|
||||
cgen,
|
||||
"host",
|
||||
READ_STREAM,
|
||||
ROOT_TYPE_DEFAULT_VALUE,
|
||||
param.paramName,
|
||||
"readStreamPtrPtr",
|
||||
API_PREFIX_RESERVEDUNMARSHAL,
|
||||
"",
|
||||
direction="read",
|
||||
dynAlloc=True))
|
||||
cgen.stmt("auto unboxed_%s = unbox_%s(%s)" %
|
||||
(param.paramName, param.typeName, param.paramName))
|
||||
cgen.stmt("auto vk = dispatch_%s(%s)" %
|
||||
(param.typeName, param.paramName))
|
||||
cgen.stmt("// End manual dispatchable handle unboxing for %s" %
|
||||
param.paramName)
|
||||
|
||||
|
||||
def emit_transform(typeInfo, param, cgen, variant="tohost"):
|
||||
res = \
|
||||
iterateVulkanType(typeInfo, param, TransformCodegen(
|
||||
cgen, param.paramName, "globalstate", "transform_%s_" % variant, variant))
|
||||
if not res:
|
||||
cgen.stmt("(void)%s" % param.paramName)
|
||||
|
||||
# Everything here elides the initial arg
|
||||
|
||||
|
||||
class DecodingParameters(object):
|
||||
def __init__(self, api: VulkanAPI):
|
||||
self.params: list[VulkanType] = []
|
||||
self.toRead: list[VulkanType] = []
|
||||
self.toWrite: list[VulkanType] = []
|
||||
|
||||
for i, param in enumerate(api.parameters[1:]):
|
||||
if i == 0 and param.isDispatchableHandleType():
|
||||
param.dispatchHandle = True
|
||||
|
||||
if param.isNonDispatchableHandleType() and param.isCreatedBy(api):
|
||||
param.nonDispatchableHandleCreate = True
|
||||
|
||||
if param.isNonDispatchableHandleType() and param.isDestroyedBy(api):
|
||||
param.nonDispatchableHandleDestroy = True
|
||||
|
||||
if param.isDispatchableHandleType() and param.isCreatedBy(api):
|
||||
param.dispatchableHandleCreate = True
|
||||
|
||||
if param.isDispatchableHandleType() and param.isDestroyedBy(api):
|
||||
param.dispatchableHandleDestroy = True
|
||||
|
||||
self.toRead.append(param)
|
||||
|
||||
if param.possiblyOutput():
|
||||
self.toWrite.append(param)
|
||||
|
||||
self.params.append(param)
|
||||
|
||||
|
||||
def emit_call_log(api, cgen):
|
||||
decodingParams = DecodingParameters(api)
|
||||
paramsToRead = decodingParams.toRead
|
||||
|
||||
# cgen.beginIf("m_logCalls")
|
||||
paramLogFormat = "%p"
|
||||
paramLogArgs = ["(void*)boxed_dispatchHandle"]
|
||||
|
||||
for p in paramsToRead:
|
||||
paramLogFormat += "0x%llx "
|
||||
for p in paramsToRead:
|
||||
paramLogArgs.append("(unsigned long long)%s" % (p.paramName))
|
||||
# cgen.stmt("fprintf(stderr, \"substream %%p: call %s %s\\n\", readStream, %s)" % (api.name, paramLogFormat, ", ".join(paramLogArgs)))
|
||||
# cgen.endIf()
|
||||
|
||||
|
||||
def emit_decode_parameters(typeInfo, api, cgen, globalWrapped=False):
|
||||
|
||||
decodingParams = DecodingParameters(api)
|
||||
|
||||
paramsToRead = decodingParams.toRead
|
||||
|
||||
for p in paramsToRead:
|
||||
emit_param_decl_for_reading(p, cgen)
|
||||
|
||||
i = 0
|
||||
for p in paramsToRead:
|
||||
lenAccess = cgen.generalLengthAccess(p)
|
||||
|
||||
if p.dispatchHandle:
|
||||
emit_dispatch_unmarshal(typeInfo, p, cgen, globalWrapped)
|
||||
else:
|
||||
destroy = p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy
|
||||
noUnbox = False
|
||||
|
||||
if p.nonDispatchableHandleDestroy or p.dispatchableHandleDestroy:
|
||||
destroy = True
|
||||
cgen.stmt(
|
||||
"// Begin manual non dispatchable handle destroy unboxing for %s" % p.paramName)
|
||||
if None == lenAccess or "1" == lenAccess:
|
||||
cgen.stmt("%s boxed_%s_preserve" %
|
||||
(p.typeName, p.paramName))
|
||||
else:
|
||||
cgen.stmt("%s* boxed_%s_preserve; %s->alloc((void**)&boxed_%s_preserve, %s * sizeof(%s))" %
|
||||
(p.typeName, p.paramName, READ_STREAM, p.paramName, lenAccess, p.typeName))
|
||||
|
||||
if p.possiblyOutput():
|
||||
cgen.stmt(
|
||||
"// Begin manual dispatchable handle unboxing for %s" % p.paramName)
|
||||
cgen.stmt("%s->unsetHandleMapping()" % READ_STREAM)
|
||||
|
||||
emit_unmarshal(typeInfo, p, cgen, output=p.possiblyOutput(
|
||||
), destroy=destroy, noUnbox=noUnbox)
|
||||
i += 1
|
||||
|
||||
for p in paramsToRead:
|
||||
emit_transform(typeInfo, p, cgen, variant="tohost")
|
||||
|
||||
emit_call_log(api, cgen)
|
||||
|
||||
|
||||
def emit_dispatch_call(api, cgen):
|
||||
|
||||
decodingParams = DecodingParameters(api)
|
||||
|
||||
customParams = ["(VkCommandBuffer)dispatchHandle"]
|
||||
|
||||
for (i, p) in enumerate(api.parameters[1:]):
|
||||
customParam = p.paramName
|
||||
if decodingParams.params[i].dispatchHandle:
|
||||
customParam = "unboxed_%s" % p.paramName
|
||||
customParams.append(customParam)
|
||||
|
||||
if api.name in driver_workarounds_global_lock_apis:
|
||||
cgen.stmt("lock()")
|
||||
|
||||
cgen.vkApiCall(api, customPrefix="vk->", customParameters=customParams,
|
||||
checkForDeviceLost=True, globalStatePrefix=global_state_prefix,
|
||||
checkForOutOfMemory=True)
|
||||
|
||||
if api.name in driver_workarounds_global_lock_apis:
|
||||
cgen.stmt("unlock()")
|
||||
|
||||
|
||||
def emit_global_state_wrapped_call(api, cgen, context=False):
|
||||
customParams = ["pool", "(VkCommandBuffer)(boxed_dispatchHandle)"] + \
|
||||
list(map(lambda p: p.paramName, api.parameters[1:]))
|
||||
if context:
|
||||
customParams += ["context"];
|
||||
cgen.vkApiCall(api, customPrefix=global_state_prefix,
|
||||
customParameters=customParams, checkForDeviceLost=True,
|
||||
checkForOutOfMemory=True, globalStatePrefix=global_state_prefix)
|
||||
|
||||
|
||||
def emit_default_decoding(typeInfo, api, cgen):
|
||||
emit_decode_parameters(typeInfo, api, cgen)
|
||||
emit_dispatch_call(api, cgen)
|
||||
|
||||
|
||||
def emit_global_state_wrapped_decoding(typeInfo, api, cgen):
|
||||
emit_decode_parameters(typeInfo, api, cgen, globalWrapped=True)
|
||||
emit_global_state_wrapped_call(api, cgen)
|
||||
|
||||
def emit_global_state_wrapped_decoding_with_context(typeInfo, api, cgen):
|
||||
emit_decode_parameters(typeInfo, api, cgen, globalWrapped=True)
|
||||
emit_global_state_wrapped_call(api, cgen, context=True)
|
||||
|
||||
custom_decodes = {
|
||||
"vkCmdCopyBufferToImage": emit_global_state_wrapped_decoding_with_context,
|
||||
"vkCmdCopyImage": emit_global_state_wrapped_decoding,
|
||||
"vkCmdCopyImageToBuffer": emit_global_state_wrapped_decoding,
|
||||
"vkCmdCopyBufferToImage2": emit_global_state_wrapped_decoding_with_context,
|
||||
"vkCmdCopyImage2": emit_global_state_wrapped_decoding,
|
||||
"vkCmdCopyImageToBuffer2": emit_global_state_wrapped_decoding,
|
||||
"vkCmdCopyBufferToImage2KHR": emit_global_state_wrapped_decoding_with_context,
|
||||
"vkCmdCopyImage2KHR": emit_global_state_wrapped_decoding,
|
||||
"vkCmdCopyImageToBuffer2KHR": emit_global_state_wrapped_decoding,
|
||||
"vkCmdExecuteCommands": emit_global_state_wrapped_decoding,
|
||||
"vkBeginCommandBuffer": emit_global_state_wrapped_decoding_with_context,
|
||||
"vkEndCommandBuffer": emit_global_state_wrapped_decoding_with_context,
|
||||
"vkResetCommandBuffer": emit_global_state_wrapped_decoding,
|
||||
"vkCmdPipelineBarrier": emit_global_state_wrapped_decoding,
|
||||
"vkCmdBindPipeline": emit_global_state_wrapped_decoding,
|
||||
"vkCmdBindDescriptorSets": emit_global_state_wrapped_decoding,
|
||||
"vkCmdCopyQueryPoolResults": emit_global_state_wrapped_decoding,
|
||||
"vkBeginCommandBufferAsyncGOOGLE": emit_global_state_wrapped_decoding_with_context,
|
||||
"vkEndCommandBufferAsyncGOOGLE": emit_global_state_wrapped_decoding_with_context,
|
||||
"vkResetCommandBufferAsyncGOOGLE": emit_global_state_wrapped_decoding,
|
||||
"vkCommandBufferHostSyncGOOGLE": emit_global_state_wrapped_decoding,
|
||||
}
|
||||
|
||||
|
||||
class VulkanSubDecoder(VulkanWrapperGenerator):
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
self.typeInfo = typeInfo
|
||||
self.cgen = CodeGen()
|
||||
|
||||
def onBegin(self,):
|
||||
self.module.appendImpl(
|
||||
"#define MAX_STACK_ITEMS %s\n" % MAX_STACK_ITEMS)
|
||||
|
||||
self.module.appendImpl(
|
||||
"#define MAX_PACKET_LENGTH %s\n" % MAX_PACKET_LENGTH)
|
||||
|
||||
self.module.appendImpl(
|
||||
"size_t subDecode(VulkanMemReadingStream* readStream, VulkanDispatch* vk, void* boxed_dispatchHandle, void* dispatchHandle, VkDeviceSize dataSize, const void* pData, const VkDecoderContext& context)\n")
|
||||
|
||||
self.cgen.beginBlock() # function body
|
||||
|
||||
self.cgen.stmt("auto& metricsLogger = *context.metricsLogger")
|
||||
self.cgen.stmt("uint32_t count = 0")
|
||||
self.cgen.stmt("unsigned char *buf = (unsigned char *)pData")
|
||||
self.cgen.stmt("android::base::BumpPool* pool = readStream->pool()")
|
||||
self.cgen.stmt("unsigned char *ptr = (unsigned char *)pData")
|
||||
self.cgen.stmt(
|
||||
"const unsigned char* const end = (const unsigned char*)buf + dataSize")
|
||||
self.cgen.stmt(
|
||||
"VkDecoderGlobalState* globalstate = VkDecoderGlobalState::get()")
|
||||
|
||||
self.cgen.line("while (end - ptr >= 8)")
|
||||
self.cgen.beginBlock() # while loop
|
||||
|
||||
self.cgen.stmt("uint32_t opcode = *(uint32_t *)ptr")
|
||||
self.cgen.stmt("uint32_t packetLen = *(uint32_t *)(ptr + 4)")
|
||||
self.cgen.line("""
|
||||
// packetLen should be at least 8 (op code and packet length) and should not be excessively large
|
||||
if (packetLen < 8 || packetLen > MAX_PACKET_LENGTH) {
|
||||
WARN("Bad packet length %d detected, subdecode may fail", packetLen);
|
||||
metricsLogger.logMetricEvent(MetricEventBadPacketLength{ .len = packetLen });
|
||||
}
|
||||
""")
|
||||
self.cgen.stmt("if (end - ptr < packetLen) return ptr - (unsigned char*)buf")
|
||||
|
||||
|
||||
self.cgen.stmt("%s->setBuf((uint8_t*)(ptr + 8))" % READ_STREAM)
|
||||
self.cgen.stmt(
|
||||
"uint8_t* readStreamPtr = %s->getBuf(); uint8_t** readStreamPtrPtr = &readStreamPtr" % READ_STREAM)
|
||||
self.cgen.line("switch (opcode)")
|
||||
self.cgen.beginBlock() # switch stmt
|
||||
|
||||
self.module.appendImpl(self.cgen.swapCode())
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
typeInfo = self.typeInfo
|
||||
cgen = self.cgen
|
||||
api = typeInfo.apis[name]
|
||||
|
||||
if "commandBuffer" != api.parameters[0].paramName:
|
||||
return
|
||||
|
||||
cgen.line("case OP_%s:" % name)
|
||||
cgen.beginBlock()
|
||||
cgen.stmt("android::base::beginTrace(\"%s subdecode\")" % name)
|
||||
|
||||
if api.name in custom_decodes.keys():
|
||||
custom_decodes[api.name](typeInfo, api, cgen)
|
||||
else:
|
||||
emit_default_decoding(typeInfo, api, cgen)
|
||||
|
||||
cgen.stmt("android::base::endTrace()")
|
||||
cgen.stmt("break")
|
||||
cgen.endBlock()
|
||||
self.module.appendImpl(self.cgen.swapCode())
|
||||
|
||||
def onEnd(self,):
|
||||
self.cgen.line("default:")
|
||||
self.cgen.beginBlock()
|
||||
self.cgen.stmt(
|
||||
"GFXSTREAM_ABORT(::emugl::FatalError(::emugl::ABORT_REASON_OTHER)) << \"Unrecognized opcode \" << opcode")
|
||||
self.cgen.endBlock()
|
||||
|
||||
self.cgen.endBlock() # switch stmt
|
||||
|
||||
self.cgen.stmt("++count; if (count % 1000 == 0) { pool->freeAll(); }")
|
||||
self.cgen.stmt("ptr += packetLen")
|
||||
self.cgen.endBlock() # while loop
|
||||
|
||||
self.cgen.stmt("pool->freeAll()")
|
||||
self.cgen.stmt("return ptr - (unsigned char*)buf;")
|
||||
self.cgen.endBlock() # function body
|
||||
self.module.appendImpl(self.cgen.swapCode())
|
||||
399
src/gfxstream/codegen/scripts/cereal/testing.py
Normal file
399
src/gfxstream/codegen/scripts/cereal/testing.py
Normal file
|
|
@ -0,0 +1,399 @@
|
|||
# Copyright (c) 2018 The Android Open Source Project
|
||||
# Copyright (c) 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from copy import copy
|
||||
|
||||
from .common.codegen import CodeGen
|
||||
from .common.vulkantypes import \
|
||||
VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator
|
||||
|
||||
from .wrapperdefs import VulkanWrapperGenerator
|
||||
from .wrapperdefs import EQUALITY_VAR_NAMES
|
||||
from .wrapperdefs import EQUALITY_ON_FAIL_VAR
|
||||
from .wrapperdefs import EQUALITY_ON_FAIL_VAR_TYPE
|
||||
from .wrapperdefs import EQUALITY_RET_TYPE
|
||||
from .wrapperdefs import API_PREFIX_EQUALITY
|
||||
from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM2
|
||||
|
||||
class VulkanEqualityCodegen(VulkanTypeIterator):
|
||||
|
||||
def __init__(self, cgen, inputVars, onFailCompareVar, prefix):
|
||||
self.cgen = cgen
|
||||
self.inputVars = inputVars
|
||||
self.onFailCompareVar = onFailCompareVar
|
||||
self.prefix = prefix
|
||||
|
||||
def makeAccess(varName, asPtr = True):
|
||||
return lambda t: self.cgen.generalAccess(t, parentVarName = varName, asPtr = asPtr)
|
||||
|
||||
def makeLengthAccess(varName):
|
||||
return lambda t: self.cgen.generalLengthAccess(t, parentVarName = varName)
|
||||
|
||||
def makeLengthAccessGuard(varName):
|
||||
return lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName=varName)
|
||||
|
||||
self.exprAccessorLhs = makeAccess(self.inputVars[0])
|
||||
self.exprAccessorRhs = makeAccess(self.inputVars[1])
|
||||
|
||||
self.exprAccessorValueLhs = makeAccess(self.inputVars[0], asPtr = False)
|
||||
self.exprAccessorValueRhs = makeAccess(self.inputVars[1], asPtr = False)
|
||||
|
||||
self.lenAccessorLhs = makeLengthAccess(self.inputVars[0])
|
||||
self.lenAccessorRhs = makeLengthAccess(self.inputVars[1])
|
||||
|
||||
self.lenAccessGuardLhs = makeLengthAccessGuard(self.inputVars[0])
|
||||
self.lenAccessGuardRhs = makeLengthAccessGuard(self.inputVars[1])
|
||||
|
||||
self.checked = False
|
||||
|
||||
def getTypeForCompare(self, vulkanType):
|
||||
res = copy(vulkanType)
|
||||
|
||||
if not vulkanType.accessibleAsPointer():
|
||||
res = res.getForAddressAccess()
|
||||
|
||||
if vulkanType.staticArrExpr:
|
||||
res = res.getForAddressAccess()
|
||||
|
||||
return res
|
||||
|
||||
def makeCastExpr(self, vulkanType):
|
||||
return "(%s)" % (
|
||||
self.cgen.makeCTypeDecl(vulkanType, useParamName=False))
|
||||
|
||||
def makeEqualExpr(self, lhs, rhs):
|
||||
return "(%s) == (%s)" % (lhs, rhs)
|
||||
|
||||
def makeEqualBufExpr(self, lhs, rhs, size):
|
||||
return "(memcmp(%s, %s, %s) == 0)" % (lhs, rhs, size)
|
||||
|
||||
def makeEqualStringExpr(self, lhs, rhs):
|
||||
return "(strcmp(%s, %s) == 0)" % (lhs, rhs)
|
||||
|
||||
def makeBothNotNullExpr(self, lhs, rhs):
|
||||
return "(%s) && (%s)" % (lhs, rhs)
|
||||
|
||||
def makeBothNullExpr(self, lhs, rhs):
|
||||
return "!(%s) && !(%s)" % (lhs, rhs)
|
||||
|
||||
def compareWithConsequence(self, compareExpr, vulkanType, errMsg=""):
|
||||
self.cgen.stmt("if (!(%s)) { %s(\"%s (Error: %s)\"); }" %
|
||||
(compareExpr, self.onFailCompareVar,
|
||||
self.exprAccessorValueLhs(vulkanType), errMsg))
|
||||
|
||||
def onCheck(self, vulkanType):
|
||||
|
||||
self.checked = True
|
||||
|
||||
accessLhs = self.exprAccessorLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
bothNull = self.makeBothNullExpr(accessLhs, accessRhs)
|
||||
bothNotNull = self.makeBothNotNullExpr(accessLhs, accessRhs)
|
||||
nullMatchExpr = "(%s) || (%s)" % (bothNull, bothNotNull)
|
||||
|
||||
self.compareWithConsequence( \
|
||||
nullMatchExpr,
|
||||
vulkanType,
|
||||
"Mismatch in optional field")
|
||||
|
||||
skipStreamInternal = vulkanType.typeName == "void"
|
||||
|
||||
if skipStreamInternal:
|
||||
return
|
||||
|
||||
self.cgen.beginIf("%s && %s" % (accessLhs, accessRhs))
|
||||
|
||||
def endCheck(self, vulkanType):
|
||||
|
||||
skipStreamInternal = vulkanType.typeName == "void"
|
||||
if skipStreamInternal:
|
||||
return
|
||||
|
||||
if self.checked:
|
||||
self.cgen.endIf()
|
||||
self.checked = False
|
||||
|
||||
def onCompoundType(self, vulkanType):
|
||||
accessLhs = self.exprAccessorLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
lenAccessLhs = self.lenAccessorLhs(vulkanType)
|
||||
lenAccessRhs = self.lenAccessorRhs(vulkanType)
|
||||
|
||||
lenAccessGuardLhs = self.lenAccessGuardLhs(vulkanType)
|
||||
lenAccessGuardRhs = self.lenAccessGuardRhs(vulkanType)
|
||||
|
||||
needNullCheck = vulkanType.pointerIndirectionLevels > 0
|
||||
|
||||
if needNullCheck:
|
||||
bothNotNullExpr = self.makeBothNotNullExpr(accessLhs, accessRhs)
|
||||
self.cgen.beginIf(bothNotNullExpr)
|
||||
|
||||
if lenAccessLhs is not None:
|
||||
equalLenExpr = self.makeEqualExpr(lenAccessLhs, lenAccessRhs)
|
||||
|
||||
self.compareWithConsequence( \
|
||||
equalLenExpr,
|
||||
vulkanType, "Lengths not equal")
|
||||
|
||||
loopVar = "i"
|
||||
accessLhs = "%s + %s" % (accessLhs, loopVar)
|
||||
accessRhs = "%s + %s" % (accessRhs, loopVar)
|
||||
forInit = "uint32_t %s = 0" % loopVar
|
||||
forCond = "%s < (uint32_t)%s" % (loopVar, lenAccessLhs)
|
||||
forIncr = "++%s" % loopVar
|
||||
|
||||
if needNullCheck:
|
||||
self.cgen.beginIf(equalLenExpr)
|
||||
|
||||
if lenAccessGuardLhs is not None:
|
||||
self.cgen.beginIf(lenAccessGuardLhs)
|
||||
|
||||
self.cgen.beginFor(forInit, forCond, forIncr)
|
||||
|
||||
self.cgen.funcCall(None, self.prefix + vulkanType.typeName,
|
||||
[accessLhs, accessRhs, self.onFailCompareVar])
|
||||
|
||||
if lenAccessLhs is not None:
|
||||
self.cgen.endFor()
|
||||
if lenAccessGuardLhs is not None:
|
||||
self.cgen.endIf()
|
||||
if needNullCheck:
|
||||
self.cgen.endIf()
|
||||
|
||||
if needNullCheck:
|
||||
self.cgen.endIf()
|
||||
|
||||
def onString(self, vulkanType):
|
||||
accessLhs = self.exprAccessorLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
bothNullExpr = self.makeBothNullExpr(accessLhs, accessRhs)
|
||||
bothNotNullExpr = self.makeBothNotNullExpr(accessLhs, accessRhs)
|
||||
nullMatchExpr = "(%s) || (%s)" % (bothNullExpr, bothNotNullExpr)
|
||||
|
||||
self.compareWithConsequence( \
|
||||
nullMatchExpr,
|
||||
vulkanType,
|
||||
"Mismatch in string pointer nullness")
|
||||
|
||||
self.cgen.beginIf(bothNotNullExpr)
|
||||
|
||||
self.compareWithConsequence(
|
||||
self.makeEqualStringExpr(accessLhs, accessRhs),
|
||||
vulkanType, "Unequal strings")
|
||||
|
||||
self.cgen.endIf()
|
||||
|
||||
def onStringArray(self, vulkanType):
|
||||
accessLhs = self.exprAccessorLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
lenAccessLhs = self.lenAccessorLhs(vulkanType)
|
||||
lenAccessRhs = self.lenAccessorRhs(vulkanType)
|
||||
|
||||
lenAccessGuardLhs = self.lenAccessGuardLhs(vulkanType)
|
||||
lenAccessGuardRhs = self.lenAccessGuardRhs(vulkanType)
|
||||
|
||||
bothNullExpr = self.makeBothNullExpr(accessLhs, accessRhs)
|
||||
bothNotNullExpr = self.makeBothNotNullExpr(accessLhs, accessRhs)
|
||||
nullMatchExpr = "(%s) || (%s)" % (bothNullExpr, bothNotNullExpr)
|
||||
|
||||
self.compareWithConsequence( \
|
||||
nullMatchExpr,
|
||||
vulkanType,
|
||||
"Mismatch in string array pointer nullness")
|
||||
|
||||
equalLenExpr = self.makeEqualExpr(lenAccessLhs, lenAccessRhs)
|
||||
|
||||
self.compareWithConsequence( \
|
||||
equalLenExpr,
|
||||
vulkanType, "Lengths not equal in string array")
|
||||
|
||||
self.compareWithConsequence( \
|
||||
equalLenExpr,
|
||||
vulkanType, "Lengths not equal in string array")
|
||||
|
||||
self.cgen.beginIf("%s && %s" % (equalLenExpr, bothNotNullExpr))
|
||||
|
||||
loopVar = "i"
|
||||
accessLhs = "*(%s + %s)" % (accessLhs, loopVar)
|
||||
accessRhs = "*(%s + %s)" % (accessRhs, loopVar)
|
||||
forInit = "uint32_t %s = 0" % loopVar
|
||||
forCond = "%s < (uint32_t)%s" % (loopVar, lenAccessLhs)
|
||||
forIncr = "++%s" % loopVar
|
||||
|
||||
if lenAccessGuardLhs is not None:
|
||||
self.cgen.beginIf(lenAccessGuardLhs)
|
||||
|
||||
self.cgen.beginFor(forInit, forCond, forIncr)
|
||||
|
||||
self.compareWithConsequence(
|
||||
self.makeEqualStringExpr(accessLhs, accessRhs),
|
||||
vulkanType, "Unequal string in string array")
|
||||
|
||||
self.cgen.endFor()
|
||||
|
||||
if lenAccessGuardLhs is not None:
|
||||
self.cgen.endIf()
|
||||
|
||||
self.cgen.endIf()
|
||||
|
||||
def onStaticArr(self, vulkanType):
|
||||
accessLhs = self.exprAccessorLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
lenAccessLhs = self.lenAccessorLhs(vulkanType)
|
||||
|
||||
finalLenExpr = "%s * %s" % (lenAccessLhs,
|
||||
self.cgen.sizeofExpr(vulkanType))
|
||||
|
||||
self.compareWithConsequence(
|
||||
self.makeEqualBufExpr(accessLhs, accessRhs, finalLenExpr),
|
||||
vulkanType, "Unequal static array")
|
||||
|
||||
def onStructExtension(self, vulkanType):
|
||||
lhs = self.exprAccessorLhs(vulkanType)
|
||||
rhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
self.cgen.beginIf(lhs)
|
||||
self.cgen.funcCall(None, self.prefix + "extension_struct",
|
||||
[lhs, rhs, self.onFailCompareVar])
|
||||
self.cgen.endIf()
|
||||
|
||||
def onPointer(self, vulkanType):
|
||||
accessLhs = self.exprAccessorLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorRhs(vulkanType)
|
||||
|
||||
skipStreamInternal = vulkanType.typeName == "void"
|
||||
if skipStreamInternal:
|
||||
return
|
||||
|
||||
lenAccessLhs = self.lenAccessorLhs(vulkanType)
|
||||
lenAccessRhs = self.lenAccessorRhs(vulkanType)
|
||||
|
||||
if lenAccessLhs is not None:
|
||||
self.compareWithConsequence( \
|
||||
self.makeEqualExpr(lenAccessLhs, lenAccessRhs),
|
||||
vulkanType, "Lengths not equal")
|
||||
|
||||
finalLenExpr = "%s * %s" % (lenAccessLhs,
|
||||
self.cgen.sizeofExpr(
|
||||
vulkanType.getForValueAccess()))
|
||||
else:
|
||||
finalLenExpr = self.cgen.sizeofExpr(vulkanType.getForValueAccess())
|
||||
|
||||
self.compareWithConsequence(
|
||||
self.makeEqualBufExpr(accessLhs, accessRhs, finalLenExpr),
|
||||
vulkanType, "Unequal dyn array")
|
||||
|
||||
def onValue(self, vulkanType):
|
||||
accessLhs = self.exprAccessorValueLhs(vulkanType)
|
||||
accessRhs = self.exprAccessorValueRhs(vulkanType)
|
||||
self.compareWithConsequence(
|
||||
self.makeEqualExpr(accessLhs, accessRhs), vulkanType,
|
||||
"Value not equal")
|
||||
|
||||
|
||||
class VulkanTesting(VulkanWrapperGenerator):
|
||||
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
|
||||
self.codegen = CodeGen()
|
||||
|
||||
self.equalityCodegen = \
|
||||
VulkanEqualityCodegen(
|
||||
None,
|
||||
EQUALITY_VAR_NAMES,
|
||||
EQUALITY_ON_FAIL_VAR,
|
||||
API_PREFIX_EQUALITY)
|
||||
|
||||
self.knownDefs = {}
|
||||
|
||||
self.extensionTestingPrototype = \
|
||||
VulkanAPI(API_PREFIX_EQUALITY + "extension_struct",
|
||||
EQUALITY_RET_TYPE,
|
||||
[STRUCT_EXTENSION_PARAM,
|
||||
STRUCT_EXTENSION_PARAM2,
|
||||
EQUALITY_ON_FAIL_VAR_TYPE])
|
||||
|
||||
def onBegin(self,):
|
||||
VulkanWrapperGenerator.onBegin(self)
|
||||
self.module.appendImpl(self.codegen.makeFuncDecl(
|
||||
self.extensionTestingPrototype))
|
||||
|
||||
def onGenType(self, typeXml, name, alias):
|
||||
VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
|
||||
|
||||
if name in self.knownDefs:
|
||||
return
|
||||
|
||||
category = self.typeInfo.categoryOf(name)
|
||||
|
||||
if category in ["struct", "union"] and alias:
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncAlias(API_PREFIX_EQUALITY + name,
|
||||
API_PREFIX_EQUALITY + alias))
|
||||
|
||||
if category in ["struct", "union"] and not alias:
|
||||
|
||||
structInfo = self.typeInfo.structs[name]
|
||||
|
||||
typeFromName = \
|
||||
lambda varname: makeVulkanTypeSimple(True, name, 1, varname)
|
||||
|
||||
compareParams = \
|
||||
list(map(typeFromName, EQUALITY_VAR_NAMES)) + \
|
||||
[EQUALITY_ON_FAIL_VAR_TYPE]
|
||||
|
||||
comparePrototype = \
|
||||
VulkanAPI(API_PREFIX_EQUALITY + name,
|
||||
EQUALITY_RET_TYPE,
|
||||
compareParams)
|
||||
|
||||
def structCompareDef(cgen):
|
||||
self.equalityCodegen.cgen = cgen
|
||||
for member in structInfo.members:
|
||||
iterateVulkanType(self.typeInfo, member,
|
||||
self.equalityCodegen)
|
||||
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncDecl(comparePrototype))
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(comparePrototype, structCompareDef))
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
|
||||
|
||||
def onEnd(self,):
|
||||
VulkanWrapperGenerator.onEnd(self)
|
||||
|
||||
def forEachExtensionCompare(ext, castedAccess, cgen):
|
||||
cgen.funcCall(None, API_PREFIX_EQUALITY + ext.name,
|
||||
[castedAccess,
|
||||
cgen.makeReinterpretCast(
|
||||
STRUCT_EXTENSION_PARAM2.paramName, ext.name),
|
||||
EQUALITY_ON_FAIL_VAR])
|
||||
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(
|
||||
self.extensionTestingPrototype,
|
||||
lambda cgen: self.emitForEachStructExtension(
|
||||
cgen,
|
||||
EQUALITY_RET_TYPE,
|
||||
STRUCT_EXTENSION_PARAM,
|
||||
forEachExtensionCompare)))
|
||||
348
src/gfxstream/codegen/scripts/cereal/transform.py
Normal file
348
src/gfxstream/codegen/scripts/cereal/transform.py
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
# Copyright (c) 2018 The Android Open Source Project
|
||||
# Copyright (c) 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from .common.codegen import CodeGen
|
||||
from .common.vulkantypes import \
|
||||
VulkanCompoundType, VulkanAPI, makeVulkanTypeSimple, vulkanTypeNeedsTransform, vulkanTypeGetNeededTransformTypes, VulkanTypeIterator, iterateVulkanType, vulkanTypeforEachSubType, TRIVIAL_TRANSFORMED_TYPES, NON_TRIVIAL_TRANSFORMED_TYPES, TRANSFORMED_TYPES
|
||||
|
||||
from .wrapperdefs import VulkanWrapperGenerator
|
||||
from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE
|
||||
|
||||
def deviceMemoryTransform(resourceTrackerVarName, structOrApiInfo, getExpr, getLen, cgen, variant="tohost"):
|
||||
paramIndices = \
|
||||
structOrApiInfo.deviceMemoryInfoParameterIndices
|
||||
|
||||
for _, info in paramIndices.items():
|
||||
orderedKeys = [
|
||||
"handle",
|
||||
"offset",
|
||||
"size",
|
||||
"typeIndex",
|
||||
"typeBits",]
|
||||
|
||||
casts = {
|
||||
"handle" : "VkDeviceMemory*",
|
||||
"offset" : "VkDeviceSize*",
|
||||
"size" : "VkDeviceSize*",
|
||||
"typeIndex" : "uint32_t*",
|
||||
"typeBits" : "uint32_t*",
|
||||
}
|
||||
|
||||
accesses = {
|
||||
"handle" : "nullptr",
|
||||
"offset" : "nullptr",
|
||||
"size" : "nullptr",
|
||||
"typeIndex" : "nullptr",
|
||||
"typeBits" : "nullptr",
|
||||
}
|
||||
|
||||
lenAccesses = {
|
||||
"handle" : "0",
|
||||
"offset" : "0",
|
||||
"size" : "0",
|
||||
"typeIndex" : "0",
|
||||
"typeBits" : "0",
|
||||
}
|
||||
|
||||
def doParam(i, vulkanType):
|
||||
access = getExpr(vulkanType)
|
||||
lenAccess = getLen(vulkanType)
|
||||
|
||||
for k in orderedKeys:
|
||||
if i == info.__dict__[k]:
|
||||
accesses[k] = access
|
||||
if lenAccess is not None:
|
||||
lenAccesses[k] = lenAccess
|
||||
else:
|
||||
lenAccesses[k] = "1"
|
||||
|
||||
vulkanTypeforEachSubType(structOrApiInfo, doParam)
|
||||
|
||||
callParams = ", ".join( \
|
||||
["(%s)%s, %s" % (casts[k], accesses[k], lenAccesses[k]) \
|
||||
for k in orderedKeys])
|
||||
|
||||
if variant == "tohost":
|
||||
cgen.stmt("%s->deviceMemoryTransform_tohost(%s)" % \
|
||||
(resourceTrackerVarName, callParams))
|
||||
else:
|
||||
cgen.stmt("%s->deviceMemoryTransform_fromhost(%s)" % \
|
||||
(resourceTrackerVarName, callParams))
|
||||
|
||||
def directTransform(resourceTrackerVarName, vulkanType, getExpr, getLen, cgen, variant="tohost"):
|
||||
access = getExpr(vulkanType)
|
||||
lenAccess = getLen(vulkanType)
|
||||
|
||||
if lenAccess:
|
||||
finalLenAccess = lenAccess
|
||||
else:
|
||||
finalLenAccess = "1"
|
||||
|
||||
cgen.stmt("%s->transformImpl_%s_%s(%s, %s)" % (resourceTrackerVarName,
|
||||
vulkanType.typeName, variant, access, finalLenAccess))
|
||||
|
||||
def genTransformsForVulkanType(resourceTrackerVarName, structOrApiInfo, getExpr, getLen, cgen, variant="tohost"):
|
||||
for transform in vulkanTypeGetNeededTransformTypes(structOrApiInfo):
|
||||
if transform == "devicememory":
|
||||
deviceMemoryTransform( \
|
||||
resourceTrackerVarName,
|
||||
structOrApiInfo,
|
||||
getExpr, getLen, cgen, variant=variant)
|
||||
|
||||
class TransformCodegen(VulkanTypeIterator):
|
||||
def __init__(self, cgen, inputVar, resourceTrackerVarName, prefix, variant):
|
||||
self.cgen = cgen
|
||||
self.inputVar = inputVar
|
||||
self.prefix = prefix
|
||||
self.resourceTrackerVarName = resourceTrackerVarName
|
||||
|
||||
def makeAccess(varName, asPtr = True):
|
||||
return lambda t: self.cgen.generalAccess(t, parentVarName = varName, asPtr = asPtr)
|
||||
|
||||
def makeLengthAccess(varName):
|
||||
return lambda t: self.cgen.generalLengthAccess(t, parentVarName = varName)
|
||||
|
||||
def makeLengthAccessGuard(varName):
|
||||
return lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName=varName)
|
||||
|
||||
self.exprAccessor = makeAccess(self.inputVar)
|
||||
self.exprAccessorValue = makeAccess(self.inputVar, asPtr = False)
|
||||
self.lenAccessor = makeLengthAccess(self.inputVar)
|
||||
self.lenAccessorGuard = makeLengthAccessGuard(self.inputVar)
|
||||
|
||||
self.checked = False
|
||||
|
||||
self.variant = variant
|
||||
|
||||
def makeCastExpr(self, vulkanType):
|
||||
return "(%s)" % (
|
||||
self.cgen.makeCTypeDecl(vulkanType, useParamName=False))
|
||||
|
||||
def asNonConstCast(self, access, vulkanType):
|
||||
if vulkanType.staticArrExpr:
|
||||
casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
|
||||
elif vulkanType.accessibleAsPointer():
|
||||
casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForNonConstAccess()), access)
|
||||
else:
|
||||
casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
|
||||
return casted
|
||||
|
||||
def onCheck(self, vulkanType):
|
||||
pass
|
||||
|
||||
def endCheck(self, vulkanType):
|
||||
pass
|
||||
|
||||
def onCompoundType(self, vulkanType):
|
||||
|
||||
access = self.exprAccessor(vulkanType)
|
||||
lenAccess = self.lenAccessor(vulkanType)
|
||||
lenAccessGuard = self.lenAccessorGuard(vulkanType)
|
||||
|
||||
isPtr = vulkanType.pointerIndirectionLevels > 0
|
||||
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.beginIf(lenAccessGuard)
|
||||
|
||||
if isPtr:
|
||||
self.cgen.beginIf(access)
|
||||
|
||||
if lenAccess is not None:
|
||||
|
||||
loopVar = "i"
|
||||
access = "%s + %s" % (access, loopVar)
|
||||
forInit = "uint32_t %s = 0" % loopVar
|
||||
forCond = "%s < (uint32_t)%s" % (loopVar, lenAccess)
|
||||
forIncr = "++%s" % loopVar
|
||||
|
||||
self.cgen.beginFor(forInit, forCond, forIncr)
|
||||
|
||||
accessCasted = self.asNonConstCast(access, vulkanType)
|
||||
|
||||
if vulkanType.isTransformed:
|
||||
directTransform(self.resourceTrackerVarName, vulkanType, self.exprAccessor, self.lenAccessor, self.cgen, variant=self.variant)
|
||||
|
||||
self.cgen.funcCall(None, self.prefix + vulkanType.typeName,
|
||||
[self.resourceTrackerVarName, accessCasted])
|
||||
|
||||
if lenAccess is not None:
|
||||
self.cgen.endFor()
|
||||
|
||||
if isPtr:
|
||||
self.cgen.endIf()
|
||||
|
||||
if lenAccessGuard is not None:
|
||||
self.cgen.endIf()
|
||||
|
||||
def onString(self, vulkanType):
|
||||
pass
|
||||
|
||||
def onStringArray(self, vulkanType):
|
||||
pass
|
||||
|
||||
def onStaticArr(self, vulkanType):
|
||||
pass
|
||||
|
||||
def onStructExtension(self, vulkanType):
|
||||
access = self.exprAccessor(vulkanType)
|
||||
|
||||
castedAccessExpr = "(%s)(%s)" % ("void*", access)
|
||||
self.cgen.beginIf(access)
|
||||
self.cgen.funcCall(None, self.prefix + "extension_struct",
|
||||
[self.resourceTrackerVarName, castedAccessExpr])
|
||||
self.cgen.endIf()
|
||||
|
||||
def onPointer(self, vulkanType):
|
||||
pass
|
||||
|
||||
def onValue(self, vulkanType):
|
||||
pass
|
||||
|
||||
|
||||
class VulkanTransform(VulkanWrapperGenerator):
|
||||
def __init__(self, module, typeInfo, resourceTrackerTypeName="ResourceTracker", resourceTrackerVarName="resourceTracker"):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
|
||||
self.codegen = CodeGen()
|
||||
|
||||
self.transformPrefix = "transform_"
|
||||
|
||||
self.tohostpart = "tohost"
|
||||
self.fromhostpart = "fromhost"
|
||||
self.variants = [self.tohostpart, self.fromhostpart]
|
||||
|
||||
self.toTransformVar = "toTransform"
|
||||
self.resourceTrackerTypeName = resourceTrackerTypeName
|
||||
self.resourceTrackerVarName = resourceTrackerVarName
|
||||
self.transformParam = \
|
||||
makeVulkanTypeSimple(False, self.resourceTrackerTypeName, 1,
|
||||
self.resourceTrackerVarName)
|
||||
self.voidType = makeVulkanTypeSimple(False, "void", 0)
|
||||
|
||||
self.extensionTransformPrototypes = []
|
||||
|
||||
for variant in self.variants:
|
||||
self.extensionTransformPrototypes.append( \
|
||||
VulkanAPI(self.transformPrefix + variant + "_extension_struct",
|
||||
self.voidType,
|
||||
[self.transformParam, STRUCT_EXTENSION_PARAM_FOR_WRITE]))
|
||||
|
||||
self.knownStructs = {}
|
||||
self.needsTransform = set([])
|
||||
|
||||
def onBegin(self,):
|
||||
VulkanWrapperGenerator.onBegin(self)
|
||||
# Set up a convenience macro fro the transformed structs
|
||||
# and forward-declare the resource tracker class
|
||||
self.codegen.stmt("class %s" % self.resourceTrackerTypeName)
|
||||
self.codegen.line("#define LIST_TRIVIAL_TRANSFORMED_TYPES(f) \\")
|
||||
for name in TRIVIAL_TRANSFORMED_TYPES:
|
||||
self.codegen.line("f(%s) \\" % name)
|
||||
self.codegen.line("")
|
||||
|
||||
self.codegen.line("#define LIST_NON_TRIVIAL_TRANSFORMED_TYPES(f) \\")
|
||||
for name in NON_TRIVIAL_TRANSFORMED_TYPES:
|
||||
self.codegen.line("f(%s) \\" % name)
|
||||
self.codegen.line("")
|
||||
|
||||
self.codegen.line("#define LIST_TRANSFORMED_TYPES(f) \\")
|
||||
self.codegen.line("LIST_TRIVIAL_TRANSFORMED_TYPES(f) \\")
|
||||
self.codegen.line("LIST_NON_TRIVIAL_TRANSFORMED_TYPES(f) \\")
|
||||
self.codegen.line("")
|
||||
|
||||
self.module.appendHeader(self.codegen.swapCode())
|
||||
|
||||
for prototype in self.extensionTransformPrototypes:
|
||||
self.module.appendImpl(self.codegen.makeFuncDecl(
|
||||
prototype))
|
||||
|
||||
def onGenType(self, typeXml, name, alias):
|
||||
VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
|
||||
|
||||
if name in self.knownStructs:
|
||||
return
|
||||
|
||||
category = self.typeInfo.categoryOf(name)
|
||||
|
||||
if category in ["struct", "union"] and alias:
|
||||
for variant in self.variants:
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncAlias(self.transformPrefix + variant + "_" + name,
|
||||
self.transformPrefix + variant + "_" + alias))
|
||||
|
||||
if category in ["struct", "union"] and not alias:
|
||||
structInfo = self.typeInfo.structs[name]
|
||||
self.knownStructs[name] = structInfo
|
||||
|
||||
for variant in self.variants:
|
||||
api = VulkanAPI( \
|
||||
self.transformPrefix + variant + "_" + name,
|
||||
self.voidType,
|
||||
[self.transformParam] + \
|
||||
[makeVulkanTypeSimple( \
|
||||
False, name, 1, self.toTransformVar)])
|
||||
|
||||
transformer = TransformCodegen(
|
||||
None,
|
||||
self.toTransformVar,
|
||||
self.resourceTrackerVarName,
|
||||
self.transformPrefix + variant + "_",
|
||||
variant)
|
||||
|
||||
def funcDefGenerator(cgen):
|
||||
transformer.cgen = cgen
|
||||
for p in api.parameters:
|
||||
cgen.stmt("(void)%s" % p.paramName)
|
||||
|
||||
genTransformsForVulkanType(
|
||||
self.resourceTrackerVarName,
|
||||
structInfo,
|
||||
transformer.exprAccessor,
|
||||
transformer.lenAccessor,
|
||||
cgen,
|
||||
variant=variant)
|
||||
|
||||
for member in structInfo.members:
|
||||
iterateVulkanType(
|
||||
self.typeInfo, member,
|
||||
transformer)
|
||||
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncDecl(api))
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(api, funcDefGenerator))
|
||||
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
|
||||
|
||||
def onEnd(self,):
|
||||
VulkanWrapperGenerator.onEnd(self)
|
||||
|
||||
for (variant, prototype) in zip(self.variants, self.extensionTransformPrototypes):
|
||||
def forEachExtensionTransform(ext, castedAccess, cgen):
|
||||
if ext.isTransformed:
|
||||
directTransform(self.resourceTrackerVarName, ext, lambda _ : castedAccess, lambda _ : "1", cgen, variant);
|
||||
cgen.funcCall(None, self.transformPrefix + variant + "_" + ext.name,
|
||||
[self.resourceTrackerVarName, castedAccess])
|
||||
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(
|
||||
prototype,
|
||||
lambda cgen: self.emitForEachStructExtension(
|
||||
cgen,
|
||||
self.voidType,
|
||||
STRUCT_EXTENSION_PARAM_FOR_WRITE,
|
||||
forEachExtensionTransform)))
|
||||
81
src/gfxstream/codegen/scripts/cereal/unbox.py
Normal file
81
src/gfxstream/codegen/scripts/cereal/unbox.py
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Copyright (c) 2018 The Android Open Source Project
|
||||
# Copyright (c) 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from .common.codegen import CodeGen
|
||||
from .common.vulkantypes import \
|
||||
VulkanCompoundType, VulkanAPI, makeVulkanTypeSimple, vulkanTypeNeedsTransform, vulkanTypeGetNeededTransformTypes, VulkanTypeIterator, iterateVulkanType, vulkanTypeforEachSubType, TRANSFORMED_TYPES
|
||||
|
||||
from .wrapperdefs import VulkanWrapperGenerator
|
||||
from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE
|
||||
|
||||
# This is different from others; it operations solely in terms of deepcopy and handlemap
|
||||
class VulkanUnbox(VulkanWrapperGenerator):
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
|
||||
self.codegen = CodeGen()
|
||||
|
||||
self.unboxPrefix = "unbox"
|
||||
self.toUnboxVar = "toUnbox"
|
||||
self.poolParam = \
|
||||
makeVulkanTypeSimple(False, "BumpPool", 1, "pool")
|
||||
|
||||
self.knownStructs = {}
|
||||
self.needsTransform = set([])
|
||||
|
||||
def onBegin(self,):
|
||||
VulkanWrapperGenerator.onBegin(self)
|
||||
|
||||
def onGenType(self, typeXml, name, alias):
|
||||
VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
|
||||
|
||||
if name in self.knownStructs:
|
||||
return
|
||||
|
||||
category = self.typeInfo.categoryOf(name)
|
||||
|
||||
if category in ["struct", "union"] and alias:
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncAlias(self.unboxPrefix + "_" + name,
|
||||
self.unboxPrefix + "_" + alias))
|
||||
|
||||
if category in ["struct", "union"] and not alias:
|
||||
structInfo = self.typeInfo.structs[name]
|
||||
self.knownStructs[name] = structInfo
|
||||
|
||||
api = VulkanAPI( \
|
||||
self.unboxPrefix + "_" + name,
|
||||
makeVulkanTypeSimple(False, name, 1),
|
||||
[self.poolParam] + \
|
||||
[makeVulkanTypeSimple( \
|
||||
True, name, 1, self.toUnboxVar)])
|
||||
|
||||
def funcDefGenerator(cgen):
|
||||
cgen.stmt("BoxedHandleUnwrapMapping unboxMapping")
|
||||
cgen.stmt("%s* res = (%s*)pool->alloc(sizeof(const %s))" % (name, name, name))
|
||||
cgen.stmt("deepcopy_%s(pool, %s, %s)" % (name, self.toUnboxVar, "res"))
|
||||
cgen.stmt("handlemap_%s(%s, %s)" % (name, "&unboxMapping", "res"))
|
||||
cgen.stmt("return res")
|
||||
|
||||
self.module.appendHeader(
|
||||
self.codegen.makeFuncDecl(api))
|
||||
self.module.appendImpl(
|
||||
self.codegen.makeFuncImpl(api, funcDefGenerator))
|
||||
|
||||
def onGenCmd(self, cmdinfo, name, alias):
|
||||
VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
|
||||
|
||||
def onEnd(self,):
|
||||
VulkanWrapperGenerator.onEnd(self)
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# Copyright (c) 2022 The Android Open Source Project
|
||||
# Copyright (c) 2022 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from .wrapperdefs import VulkanWrapperGenerator
|
||||
|
||||
|
||||
class VulkanExtensionStructureType(VulkanWrapperGenerator):
|
||||
def __init__(self, extensionName: str, module, typeInfo):
|
||||
super().__init__(module, typeInfo)
|
||||
self._extensionName = extensionName
|
||||
|
||||
def onGenGroup(self, groupinfo, groupName, alias=None):
|
||||
super().onGenGroup(groupinfo, groupName, alias)
|
||||
elem = groupinfo.elem
|
||||
if (not elem.get('type') == 'enum'):
|
||||
return
|
||||
if (not elem.get('name') == 'VkStructureType'):
|
||||
return
|
||||
extensionEnumFactoryMacro = f'{self._extensionName.upper()}_ENUM'
|
||||
for enum in elem.findall(f"enum[@extname='{self._extensionName}']"):
|
||||
name = enum.get('name')
|
||||
offset = enum.get('offset')
|
||||
self.module.appendHeader(
|
||||
f"#define {name} {extensionEnumFactoryMacro}(VkStructureType, {offset})\n")
|
||||
|
||||
|
||||
class VulkanGfxstreamStructureType(VulkanExtensionStructureType):
|
||||
def __init__(self, module, typeInfo):
|
||||
super().__init__('VK_GOOGLE_gfxstream', module, typeInfo)
|
||||
|
||||
|
||||
class VulkanAndroidNativeBufferStructureType(VulkanExtensionStructureType):
|
||||
def __init__(self, module, typeInfo):
|
||||
super().__init__('VK_ANDROID_native_buffer', module, typeInfo)
|
||||
108
src/gfxstream/codegen/scripts/cereal/wrapperdefs.py
Normal file
108
src/gfxstream/codegen/scripts/cereal/wrapperdefs.py
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
# Copyright (c) 2018 The Android Open Source Project
|
||||
# Copyright (c) 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from .common.codegen import VulkanWrapperGenerator
|
||||
from .common.vulkantypes import makeVulkanTypeSimple
|
||||
|
||||
# Contains definitions for various Vulkan API wrappers. This information is
|
||||
# shared to make it easier for one kind of wrapper to know how to call
|
||||
# another one.
|
||||
|
||||
API_PREFIX_MARSHAL = "marshal_"
|
||||
API_PREFIX_UNMARSHAL = "unmarshal_"
|
||||
API_PREFIX_RESERVEDMARSHAL = "reservedmarshal_"
|
||||
API_PREFIX_RESERVEDUNMARSHAL = "reservedunmarshal_"
|
||||
|
||||
MARSHAL_INPUT_VAR_NAME = "forMarshaling"
|
||||
UNMARSHAL_INPUT_VAR_NAME = "forUnmarshaling"
|
||||
|
||||
API_PREFIX_VALIDATE = "validate_"
|
||||
API_PREFIX_FRONTEND = "goldfish_frontend_"
|
||||
|
||||
VULKAN_STREAM_TYPE = "VulkanStream"
|
||||
VULKAN_STREAM_TYPE_GUEST = "VulkanStreamGuest"
|
||||
VULKAN_STREAM_VAR_NAME = "vkStream"
|
||||
|
||||
VALIDATE_RESULT_TYPE = "VkResult"
|
||||
VALIDATE_VAR_NAME = "validateResult"
|
||||
VALIDATE_GOOD_RESULT = "VK_SUCCESS"
|
||||
|
||||
ROOT_TYPE_VAR_NAME = "rootType"
|
||||
ROOT_TYPE_DEFAULT_VALUE = "VK_STRUCTURE_TYPE_MAX_ENUM"
|
||||
ROOT_TYPE_TYPE = "VkStructureType"
|
||||
ROOT_TYPE_PARAM = makeVulkanTypeSimple(
|
||||
False, ROOT_TYPE_TYPE, 0, ROOT_TYPE_VAR_NAME)
|
||||
|
||||
PARAMETERS_MARSHALING = [
|
||||
makeVulkanTypeSimple(False, VULKAN_STREAM_TYPE, 1, VULKAN_STREAM_VAR_NAME),
|
||||
ROOT_TYPE_PARAM,
|
||||
]
|
||||
PARAMETERS_MARSHALING_GUEST = [
|
||||
makeVulkanTypeSimple(False, VULKAN_STREAM_TYPE_GUEST,
|
||||
1, VULKAN_STREAM_VAR_NAME),
|
||||
ROOT_TYPE_PARAM,
|
||||
]
|
||||
PARAMETERS_VALIDATE = [
|
||||
makeVulkanTypeSimple(False, VALIDATE_RESULT_TYPE, 1, VALIDATE_VAR_NAME)
|
||||
]
|
||||
PARAMETERS_COUNTING = [
|
||||
makeVulkanTypeSimple(False, "size_t", 1, VULKAN_STREAM_VAR_NAME)
|
||||
]
|
||||
|
||||
STRUCT_EXTENSION_PARAM = \
|
||||
makeVulkanTypeSimple(True, "void", 1, "structExtension")
|
||||
|
||||
STRUCT_EXTENSION_PARAM2 = \
|
||||
makeVulkanTypeSimple(True, "void", 1, "structExtension2")
|
||||
|
||||
STRUCT_EXTENSION_PARAM_FOR_WRITE = \
|
||||
makeVulkanTypeSimple(False, "void", 1, "structExtension_out")
|
||||
|
||||
STRUCT_TYPE_API_NAME = "goldfish_vk_struct_type"
|
||||
EXTENSION_SIZE_API_NAME = "goldfish_vk_extension_struct_size"
|
||||
EXTENSION_SIZE_WITH_STREAM_FEATURES_API_NAME = "goldfish_vk_extension_struct_size_with_stream_features"
|
||||
|
||||
VOID_TYPE = makeVulkanTypeSimple(False, "void", 0)
|
||||
STREAM_RET_TYPE = makeVulkanTypeSimple(False, "void", 0)
|
||||
|
||||
API_PREFIX_EQUALITY = "checkEqual_"
|
||||
EQUALITY_VAR_NAMES = ["a", "b"]
|
||||
EQUALITY_ON_FAIL_VAR = "onFail"
|
||||
EQUALITY_ON_FAIL_VAR_TYPE = makeVulkanTypeSimple(False, "OnFailCompareFunc", 0,
|
||||
EQUALITY_ON_FAIL_VAR)
|
||||
EQUALITY_RET_TYPE = makeVulkanTypeSimple(False, "void", 0)
|
||||
|
||||
RELAXED_APIS = [
|
||||
"vkWaitForFences",
|
||||
"vkWaitSemaphores",
|
||||
"vkWaitSemaphoresKHR",
|
||||
"vkQueueWaitIdle",
|
||||
"vkDeviceWaitIdle",
|
||||
"vkQueueFlushCommandsGOOGLE",
|
||||
]
|
||||
|
||||
STYPE_OVERRIDE = {
|
||||
"VkPhysicalDeviceFragmentDensityMapFeaturesEXT": "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT",
|
||||
"VkPhysicalDeviceFragmentDensityMapPropertiesEXT": "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT",
|
||||
"VkRenderPassFragmentDensityMapCreateInfoEXT": "VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT",
|
||||
"VkImportColorBufferGOOGLE": "VK_STRUCTURE_TYPE_IMPORT_COLOR_BUFFER_GOOGLE",
|
||||
"VkImportBufferGOOGLE": "VK_STRUCTURE_TYPE_IMPORT_BUFFER_GOOGLE",
|
||||
"VkCreateBlobGOOGLE": "VK_STRUCTURE_TYPE_CREATE_BLOB_GOOGLE",
|
||||
}
|
||||
|
||||
MAX_PACKET_LENGTH = "(400 * 1024 * 1024) // 400MB"
|
||||
|
||||
|
||||
|
||||
892
src/gfxstream/codegen/scripts/cerealgenerator.py
Normal file
892
src/gfxstream/codegen/scripts/cerealgenerator.py
Normal file
|
|
@ -0,0 +1,892 @@
|
|||
#!/usr/bin/python3 -i
|
||||
#
|
||||
# Copyright (c) 2013-2018 The Khronos Group Inc.
|
||||
# Copyright (c) 2013-2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os, re, sys
|
||||
from generator import *
|
||||
from pathlib import Path, PurePosixPath
|
||||
|
||||
import cereal
|
||||
from cereal.wrapperdefs import VULKAN_STREAM_TYPE
|
||||
from cereal.wrapperdefs import VULKAN_STREAM_TYPE_GUEST
|
||||
|
||||
# CerealGenerator - generates set of driver sources
|
||||
# while being agnostic to the stream implementation
|
||||
from reg import GroupInfo, TypeInfo, EnumInfo
|
||||
|
||||
SUPPORTED_FEATURES = [
|
||||
"VK_VERSION_1_0",
|
||||
"VK_VERSION_1_1",
|
||||
"VK_VERSION_1_2",
|
||||
"VK_VERSION_1_3",
|
||||
# Instance extensions
|
||||
"VK_KHR_get_physical_device_properties2",
|
||||
"VK_KHR_sampler_ycbcr_conversion",
|
||||
"VK_KHR_external_semaphore_capabilities",
|
||||
"VK_KHR_external_memory_capabilities",
|
||||
"VK_KHR_external_fence_capabilities",
|
||||
# Device extensions
|
||||
"VK_KHR_storage_buffer_storage_class",
|
||||
"VK_KHR_vulkan_memory_model",
|
||||
"VK_KHR_buffer_device_address",
|
||||
"VK_KHR_maintenance1",
|
||||
"VK_KHR_maintenance2",
|
||||
"VK_KHR_maintenance3",
|
||||
"VK_KHR_bind_memory2",
|
||||
"VK_KHR_dedicated_allocation",
|
||||
"VK_KHR_get_memory_requirements2",
|
||||
"VK_KHR_sampler_ycbcr_conversion",
|
||||
"VK_KHR_shader_float16_int8",
|
||||
"VK_AMD_gpu_shader_half_float",
|
||||
"VK_NV_shader_subgroup_partitioned",
|
||||
"VK_KHR_shader_subgroup_extended_types",
|
||||
"VK_EXT_provoking_vertex",
|
||||
"VK_EXT_line_rasterization",
|
||||
"VK_EXT_transform_feedback",
|
||||
"VK_EXT_primitive_topology_list_restart",
|
||||
"VK_EXT_index_type_uint8",
|
||||
"VK_EXT_load_store_op_none",
|
||||
"VK_EXT_swapchain_colorspace",
|
||||
"VK_EXT_custom_border_color",
|
||||
"VK_EXT_shader_stencil_export",
|
||||
"VK_KHR_image_format_list",
|
||||
"VK_KHR_incremental_present",
|
||||
"VK_KHR_pipeline_executable_properties",
|
||||
"VK_EXT_queue_family_foreign",
|
||||
"VK_KHR_external_semaphore",
|
||||
"VK_KHR_external_semaphore_fd",
|
||||
"VK_KHR_external_memory",
|
||||
"VK_KHR_external_fence",
|
||||
"VK_KHR_external_fence_fd",
|
||||
"VK_EXT_device_memory_report",
|
||||
"VK_KHR_create_renderpass2",
|
||||
"VK_KHR_imageless_framebuffer",
|
||||
"VK_KHR_descriptor_update_template",
|
||||
# see aosp/2736079 + b/268351352
|
||||
"VK_EXT_swapchain_maintenance1",
|
||||
"VK_EXT_image_compression_control",
|
||||
"VK_EXT_image_compression_control_swapchain",
|
||||
# VK1.3 extensions: see b/298704840
|
||||
"VK_KHR_copy_commands2",
|
||||
"VK_KHR_dynamic_rendering",
|
||||
"VK_KHR_format_feature_flags2",
|
||||
"VK_KHR_maintenance4",
|
||||
"VK_KHR_shader_integer_dot_product",
|
||||
"VK_KHR_shader_non_semantic_info",
|
||||
"VK_KHR_shader_terminate_invocation",
|
||||
"VK_KHR_synchronization2",
|
||||
"VK_KHR_zero_initialize_workgroup_memory",
|
||||
"VK_EXT_4444_formats",
|
||||
"VK_EXT_extended_dynamic_state",
|
||||
"VK_EXT_extended_dynamic_state2",
|
||||
"VK_EXT_image_robustness",
|
||||
"VK_EXT_inline_uniform_block",
|
||||
"VK_EXT_pipeline_creation_cache_control",
|
||||
"VK_EXT_pipeline_creation_feedback",
|
||||
"VK_EXT_private_data",
|
||||
"VK_EXT_shader_demote_to_helper_invocation",
|
||||
"VK_EXT_subgroup_size_control",
|
||||
"VK_EXT_texel_buffer_alignment",
|
||||
"VK_EXT_texture_compression_astc_hdr",
|
||||
"VK_EXT_tooling_info",
|
||||
"VK_EXT_ycbcr_2plane_444_formats",
|
||||
# Host dispatch
|
||||
"VK_EXT_debug_utils",
|
||||
"VK_KHR_surface",
|
||||
"VK_KHR_swapchain",
|
||||
"VK_KHR_xcb_surface",
|
||||
"VK_KHR_win32_surface",
|
||||
"VK_EXT_metal_surface",
|
||||
"VK_MVK_moltenvk",
|
||||
"VK_KHR_external_semaphore_win32",
|
||||
"VK_KHR_external_memory_win32",
|
||||
"VK_KHR_external_memory_fd",
|
||||
# Android
|
||||
"VK_ANDROID_native_buffer",
|
||||
"VK_ANDROID_external_memory_android_hardware_buffer",
|
||||
"VK_KHR_android_surface",
|
||||
# Custom
|
||||
"VK_GOOGLE_gfxstream",
|
||||
# Used in tests without proper support checks
|
||||
"VK_EXT_graphics_pipeline_library",
|
||||
]
|
||||
|
||||
# By default, the all wrappers are run all on all features. In certain cases,
|
||||
# we wish run only a subset of wrappers. For example, `VK_GOOGLE_gfxstream`
|
||||
# shouldn't generate a function table entry since it's an internal interface.
|
||||
SUPPORTED_WRAPPERS = {
|
||||
"VK_EXT_debug_utils": [cereal.VulkanDispatch],
|
||||
"VK_KHR_surface": [cereal.VulkanDispatch],
|
||||
"VK_KHR_xcb_surface": [cereal.VulkanDispatch],
|
||||
"VK_KHR_win32_surface": [cereal.VulkanDispatch],
|
||||
"VK_EXT_metal_surface": [cereal.VulkanDispatch],
|
||||
# VK_MVK_moltenvk doesn't generate a generate dispatch entry for some reason, but should. The
|
||||
# lack of this extension doesn't cause any build failtures though.
|
||||
"VK_MVK_moltenvk": [cereal.VulkanDispatch],
|
||||
"VK_KHR_external_semaphore_win32" : [cereal.VulkanDispatch],
|
||||
"VK_KHR_external_memory_win32" : [cereal.VulkanDispatch],
|
||||
"VK_KHR_external_memory_fd": [cereal.VulkanDispatch],
|
||||
"VK_ANDROID_external_memory_android_hardware_buffer": [cereal.VulkanFuncTable],
|
||||
"VK_KHR_android_surface": [cereal.VulkanFuncTable],
|
||||
}
|
||||
|
||||
copyrightHeader = """// Copyright (C) 2018 The Android Open Source Project
|
||||
// Copyright (C) 2018 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
"""
|
||||
|
||||
# We put the long generated commands in a separate paragraph, so that the formatter won't mess up
|
||||
# with other texts.
|
||||
autogeneratedHeaderTemplate = """
|
||||
// Autogenerated module %s
|
||||
//
|
||||
// %s
|
||||
//
|
||||
// Please do not modify directly;
|
||||
// re-run gfxstream-protocols/scripts/generate-vulkan-sources.sh,
|
||||
// or directly from Python by defining:
|
||||
// VULKAN_REGISTRY_XML_DIR : Directory containing vk.xml
|
||||
// VULKAN_REGISTRY_SCRIPTS_DIR : Directory containing genvk.py
|
||||
// CEREAL_OUTPUT_DIR: Where to put the generated sources.
|
||||
//
|
||||
// python3 $VULKAN_REGISTRY_SCRIPTS_DIR/genvk.py -registry $VULKAN_REGISTRY_XML_DIR/vk.xml cereal -o $CEREAL_OUTPUT_DIR
|
||||
//
|
||||
"""
|
||||
|
||||
autogeneratedMkTemplate = """
|
||||
# Autogenerated makefile
|
||||
# %s
|
||||
# Please do not modify directly;
|
||||
# re-run gfxstream-protocols/scripts/generate-vulkan-sources.sh,
|
||||
# or directly from Python by defining:
|
||||
# VULKAN_REGISTRY_XML_DIR : Directory containing vk.xml
|
||||
# VULKAN_REGISTRY_SCRIPTS_DIR : Directory containing genvk.py
|
||||
# CEREAL_OUTPUT_DIR: Where to put the generated sources.
|
||||
# python3 $VULKAN_REGISTRY_SCRIPTS_DIR/genvk.py -registry $VULKAN_REGISTRY_XML_DIR/vk.xml cereal -o $CEREAL_OUTPUT_DIR
|
||||
"""
|
||||
|
||||
namespaceBegin ="""
|
||||
namespace gfxstream {
|
||||
namespace vk {\n
|
||||
"""
|
||||
|
||||
namespaceEnd = """
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
"""
|
||||
|
||||
def banner_command(argv):
|
||||
"""Return sanitized command-line description.
|
||||
|argv| must be a list of command-line parameters, e.g. sys.argv.
|
||||
Return a string corresponding to the command, with platform-specific
|
||||
paths removed."""
|
||||
|
||||
def makePosixRelative(someArg):
|
||||
if os.path.exists(someArg):
|
||||
return str(PurePosixPath(Path(os.path.relpath(someArg))))
|
||||
return someArg
|
||||
|
||||
return ' '.join(map(makePosixRelative, argv))
|
||||
|
||||
def envGetOrDefault(key, default=None):
|
||||
if key in os.environ:
|
||||
return os.environ[key]
|
||||
print("envGetOrDefault: notfound: %s" % key)
|
||||
return default
|
||||
|
||||
# ---- methods overriding base class ----
|
||||
# beginFile(genOpts)
|
||||
# endFile()
|
||||
# beginFeature(interface, emit)
|
||||
# endFeature()
|
||||
# genType(typeinfo,name)
|
||||
# genStruct(typeinfo,name)
|
||||
# genGroup(groupinfo,name)
|
||||
# genEnum(enuminfo, name)
|
||||
# genCmd(cmdinfo)
|
||||
class CerealGenerator(OutputGenerator):
|
||||
|
||||
"""Generate serialization code"""
|
||||
def __init__(self, errFile = sys.stderr,
|
||||
warnFile = sys.stderr,
|
||||
diagFile = sys.stdout):
|
||||
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
|
||||
|
||||
self.typeInfo = cereal.VulkanTypeInfo(self)
|
||||
|
||||
self.modules = {}
|
||||
self.protos = {}
|
||||
self.moduleList = []
|
||||
self.protoList = []
|
||||
|
||||
self.wrappers = []
|
||||
|
||||
self.codegen = cereal.CodeGen()
|
||||
self.featureSupported = False
|
||||
self.supportedWrappers = None
|
||||
|
||||
self.guestBaseLibDirPrefix = \
|
||||
envGetOrDefault("VK_CEREAL_GUEST_BASELIB_PREFIX", "aemu/base")
|
||||
self.baseLibDirPrefix = \
|
||||
envGetOrDefault("VK_CEREAL_BASELIB_PREFIX", "aemu/base")
|
||||
self.baseLibLinkName = \
|
||||
envGetOrDefault("VK_CEREAL_BASELIB_LINKNAME", "android-emu-base")
|
||||
self.vulkanHeaderTargetName = envGetOrDefault("VK_CEREAL_VK_HEADER_TARGET", "")
|
||||
self.utilsHeader = envGetOrDefault("VK_CEREAL_UTILS_LINKNAME", "")
|
||||
self.utilsHeaderDirPrefix = envGetOrDefault("VK_CEREAL_UTILS_PREFIX", "utils")
|
||||
|
||||
# THe host always needs all possible guest struct definitions, while the guest only needs
|
||||
# platform sepcific headers.
|
||||
self.hostCommonExtraVulkanHeaders = '#include "vk_android_native_buffer.h"'
|
||||
self.host_cmake_generator = lambda cppFiles: f"""{autogeneratedMkTemplate % banner_command(sys.argv)}
|
||||
add_library(OpenglRender_vulkan_cereal {cppFiles})
|
||||
target_compile_definitions(OpenglRender_vulkan_cereal PRIVATE -DVK_GOOGLE_gfxstream)
|
||||
if (WIN32)
|
||||
target_compile_definitions(OpenglRender_vulkan_cereal PRIVATE -DVK_USE_PLATFORM_WIN32_KHR)
|
||||
endif()
|
||||
target_link_libraries(
|
||||
OpenglRender_vulkan_cereal
|
||||
PUBLIC
|
||||
{self.baseLibLinkName}
|
||||
{self.vulkanHeaderTargetName}
|
||||
PRIVATE
|
||||
{self.utilsHeader})
|
||||
|
||||
target_include_directories(OpenglRender_vulkan_cereal
|
||||
PUBLIC
|
||||
.
|
||||
PRIVATE
|
||||
..
|
||||
../..
|
||||
../../../include)
|
||||
"""
|
||||
|
||||
encoderInclude = f"""
|
||||
#include "{self.guestBaseLibDirPrefix}/AndroidHealthMonitor.h"
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
#include <memory>
|
||||
|
||||
namespace gfxstream {{
|
||||
namespace guest {{
|
||||
class IOStream;
|
||||
}} // namespace guest
|
||||
}} // namespace gfxstream
|
||||
"""
|
||||
encoderImplInclude = f"""
|
||||
#include "EncoderDebug.h"
|
||||
#include "IOStream.h"
|
||||
#include "Resources.h"
|
||||
#include "ResourceTracker.h"
|
||||
#include "Validation.h"
|
||||
#include "%s.h"
|
||||
|
||||
#include "{self.guestBaseLibDirPrefix}/AlignedBuf.h"
|
||||
#include "{self.guestBaseLibDirPrefix}/BumpPool.h"
|
||||
#include "{self.guestBaseLibDirPrefix}/synchronization/AndroidLock.h"
|
||||
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include "goldfish_vk_marshaling_guest.h"
|
||||
#include "goldfish_vk_reserved_marshaling_guest.h"
|
||||
#include "goldfish_vk_deepcopy_guest.h"
|
||||
#include "goldfish_vk_counting_guest.h"
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
#include "goldfish_vk_transform_guest.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
""" % VULKAN_STREAM_TYPE_GUEST
|
||||
|
||||
functableImplInclude = """
|
||||
#include "VkEncoder.h"
|
||||
#include "../OpenglSystemCommon/HostConnection.h"
|
||||
#include "ResourceTracker.h"
|
||||
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
|
||||
#include <log/log.h>
|
||||
#include <cstring>
|
||||
|
||||
// Stuff we are not going to use but if included,
|
||||
// will cause compile errors. These are Android Vulkan
|
||||
// required extensions, but the approach will be to
|
||||
// implement them completely on the guest side.
|
||||
#undef VK_KHR_android_surface
|
||||
#if defined(LINUX_GUEST_BUILD)
|
||||
#undef VK_ANDROID_native_buffer
|
||||
#endif
|
||||
"""
|
||||
marshalIncludeGuest = """
|
||||
#include "goldfish_vk_marshaling_guest.h"
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
#include "%s.h"
|
||||
|
||||
// Stuff we are not going to use but if included,
|
||||
// will cause compile errors. These are Android Vulkan
|
||||
// required extensions, but the approach will be to
|
||||
// implement them completely on the guest side.
|
||||
#undef VK_KHR_android_surface
|
||||
#undef VK_ANDROID_external_memory_android_hardware_buffer
|
||||
""" % VULKAN_STREAM_TYPE_GUEST
|
||||
|
||||
reservedmarshalIncludeGuest = """
|
||||
#include "goldfish_vk_marshaling_guest.h"
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
#include "%s.h"
|
||||
|
||||
// Stuff we are not going to use but if included,
|
||||
// will cause compile errors. These are Android Vulkan
|
||||
// required extensions, but the approach will be to
|
||||
// implement them completely on the guest side.
|
||||
#undef VK_KHR_android_surface
|
||||
#undef VK_ANDROID_external_memory_android_hardware_buffer
|
||||
""" % VULKAN_STREAM_TYPE_GUEST
|
||||
|
||||
reservedmarshalImplIncludeGuest = """
|
||||
#include "Resources.h"
|
||||
"""
|
||||
|
||||
vulkanStreamIncludeHost = f"""
|
||||
{self.hostCommonExtraVulkanHeaders}
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
|
||||
#include "%s.h"
|
||||
#include "{self.baseLibDirPrefix}/files/StreamSerializing.h"
|
||||
""" % VULKAN_STREAM_TYPE
|
||||
|
||||
poolInclude = f"""
|
||||
{self.hostCommonExtraVulkanHeaders}
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
#include "{self.baseLibDirPrefix}/BumpPool.h"
|
||||
using android::base::Allocator;
|
||||
using android::base::BumpPool;
|
||||
"""
|
||||
handleMapInclude = f"""
|
||||
{self.hostCommonExtraVulkanHeaders}
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
#include "VulkanHandleMapping.h"
|
||||
"""
|
||||
transformIncludeGuest = """
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
"""
|
||||
transformInclude = f"""
|
||||
{self.hostCommonExtraVulkanHeaders}
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
#include "goldfish_vk_extension_structs.h"
|
||||
"""
|
||||
transformImplIncludeGuest = """
|
||||
#include "ResourceTracker.h"
|
||||
"""
|
||||
transformImplInclude = """
|
||||
#include "VkDecoderGlobalState.h"
|
||||
"""
|
||||
deepcopyInclude = """
|
||||
#include "vk_util.h"
|
||||
"""
|
||||
poolIncludeGuest = f"""
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
#include "{self.guestBaseLibDirPrefix}/BumpPool.h"
|
||||
using gfxstream::guest::Allocator;
|
||||
using gfxstream::guest::BumpPool;
|
||||
// Stuff we are not going to use but if included,
|
||||
// will cause compile errors. These are Android Vulkan
|
||||
// required extensions, but the approach will be to
|
||||
// implement them completely on the guest side.
|
||||
#undef VK_KHR_android_surface
|
||||
#undef VK_ANDROID_external_memory_android_hardware_buffer
|
||||
"""
|
||||
dispatchHeaderDefs = f"""
|
||||
{self.hostCommonExtraVulkanHeaders}
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
namespace gfxstream {{
|
||||
namespace vk {{
|
||||
|
||||
struct VulkanDispatch;
|
||||
|
||||
}} // namespace vk
|
||||
}} // namespace gfxstream
|
||||
using DlOpenFunc = void* (void);
|
||||
using DlSymFunc = void* (void*, const char*);
|
||||
"""
|
||||
|
||||
extensionStructsInclude = f"""
|
||||
{self.hostCommonExtraVulkanHeaders}
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
"""
|
||||
|
||||
extensionStructsIncludeGuest = """
|
||||
#include "vk_platform_compat.h"
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
// Stuff we are not going to use but if included,
|
||||
// will cause compile errors. These are Android Vulkan
|
||||
// required extensions, but the approach will be to
|
||||
// implement them completely on the guest side.
|
||||
#undef VK_KHR_android_surface
|
||||
#undef VK_ANDROID_external_memory_android_hardware_buffer
|
||||
"""
|
||||
commonCerealImplIncludes = """
|
||||
#include "goldfish_vk_extension_structs.h"
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
#include <string.h>
|
||||
"""
|
||||
commonCerealIncludesGuest = """
|
||||
#include "vk_platform_compat.h"
|
||||
"""
|
||||
commonCerealImplIncludesGuest = """
|
||||
#include "goldfish_vk_extension_structs_guest.h"
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
|
||||
#include <cstring>
|
||||
"""
|
||||
countingIncludes = """
|
||||
#include "vk_platform_compat.h"
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
"""
|
||||
|
||||
dispatchImplIncludes = """
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
"""
|
||||
|
||||
decoderSnapshotHeaderIncludes = f"""
|
||||
#include <memory>
|
||||
#include "{self.utilsHeaderDirPrefix}/GfxApiLogger.h"
|
||||
#include "{self.baseLibDirPrefix}/HealthMonitor.h"
|
||||
#include "common/goldfish_vk_private_defs.h"
|
||||
"""
|
||||
decoderSnapshotImplIncludes = f"""
|
||||
#include "VulkanHandleMapping.h"
|
||||
#include "VkDecoderGlobalState.h"
|
||||
#include "VkReconstruction.h"
|
||||
|
||||
#include "{self.baseLibDirPrefix}/synchronization/Lock.h"
|
||||
"""
|
||||
|
||||
decoderHeaderIncludes = f"""
|
||||
#include "VkDecoderContext.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace android {{
|
||||
namespace base {{
|
||||
class BumpPool;
|
||||
}} // namespace android
|
||||
}} // namespace base
|
||||
|
||||
"""
|
||||
|
||||
decoderImplIncludes = f"""
|
||||
#include "common/goldfish_vk_marshaling.h"
|
||||
#include "common/goldfish_vk_reserved_marshaling.h"
|
||||
#include "common/goldfish_vk_private_defs.h"
|
||||
#include "common/goldfish_vk_transform.h"
|
||||
|
||||
#include "{self.baseLibDirPrefix}/BumpPool.h"
|
||||
#include "{self.baseLibDirPrefix}/system/System.h"
|
||||
#include "{self.baseLibDirPrefix}/Tracing.h"
|
||||
#include "{self.baseLibDirPrefix}/Metrics.h"
|
||||
#include "render-utils/IOStream.h"
|
||||
#include "host/FrameBuffer.h"
|
||||
#include "host-common/feature_control.h"
|
||||
#include "host-common/GfxstreamFatalError.h"
|
||||
#include "host-common/logging.h"
|
||||
|
||||
#include "VkDecoderGlobalState.h"
|
||||
#include "VkDecoderSnapshot.h"
|
||||
|
||||
#include "VulkanDispatch.h"
|
||||
#include "%s.h"
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
""" % VULKAN_STREAM_TYPE
|
||||
|
||||
def createVkExtensionStructureTypePreamble(extensionName: str) -> str:
|
||||
return f"""
|
||||
#define {extensionName}_ENUM(type,id) \
|
||||
((type)(1000000000 + (1000 * ({extensionName}_NUMBER - 1)) + (id)))
|
||||
"""
|
||||
self.guest_encoder_tag = "guest_encoder"
|
||||
self.host_tag = "host"
|
||||
|
||||
default_guest_abs_encoder_destination = \
|
||||
os.path.join(
|
||||
os.getcwd(),
|
||||
"..", "..",
|
||||
"device", "generic", "goldfish-opengl",
|
||||
"system", "vulkan_enc")
|
||||
self.guest_abs_encoder_destination = \
|
||||
envGetOrDefault("VK_CEREAL_GUEST_ENCODER_DIR",
|
||||
default_guest_abs_encoder_destination)
|
||||
|
||||
default_host_abs_decoder_destination = \
|
||||
os.path.join(
|
||||
os.getcwd(),
|
||||
"android", "android-emugl", "host",
|
||||
"libs", "libOpenglRender", "vulkan")
|
||||
self.host_abs_decoder_destination = \
|
||||
envGetOrDefault("VK_CEREAL_HOST_DECODER_DIR",
|
||||
default_host_abs_decoder_destination)
|
||||
self.host_script_destination = envGetOrDefault("VK_CEREAL_HOST_SCRIPTS_DIR")
|
||||
assert(self.host_script_destination is not None)
|
||||
|
||||
self.addGuestEncoderModule(
|
||||
"VkEncoder",
|
||||
extraHeader = encoderInclude,
|
||||
extraImpl = encoderImplInclude)
|
||||
|
||||
self.addGuestEncoderModule("goldfish_vk_extension_structs_guest",
|
||||
extraHeader=extensionStructsIncludeGuest)
|
||||
self.addGuestEncoderModule("goldfish_vk_marshaling_guest",
|
||||
extraHeader=commonCerealIncludesGuest + marshalIncludeGuest,
|
||||
extraImpl=commonCerealImplIncludesGuest)
|
||||
self.addGuestEncoderModule("goldfish_vk_reserved_marshaling_guest",
|
||||
extraHeader=commonCerealIncludesGuest + reservedmarshalIncludeGuest,
|
||||
extraImpl=commonCerealImplIncludesGuest + reservedmarshalImplIncludeGuest)
|
||||
self.addGuestEncoderModule("goldfish_vk_deepcopy_guest",
|
||||
extraHeader=commonCerealIncludesGuest + poolIncludeGuest,
|
||||
extraImpl=commonCerealImplIncludesGuest + deepcopyInclude)
|
||||
self.addGuestEncoderModule("goldfish_vk_counting_guest",
|
||||
extraHeader=countingIncludes,
|
||||
extraImpl=commonCerealImplIncludesGuest)
|
||||
self.addGuestEncoderModule("goldfish_vk_transform_guest",
|
||||
extraHeader=commonCerealIncludesGuest + transformIncludeGuest,
|
||||
extraImpl=commonCerealImplIncludesGuest + transformImplIncludeGuest)
|
||||
self.addGuestEncoderModule(
|
||||
"vulkan_gfxstream_structure_type", headerOnly=True, suppressFeatureGuards=True,
|
||||
moduleName="vulkan_gfxstream_structure_type_guest", useNamespace=False,
|
||||
suppressVulkanHeaders=True,
|
||||
extraHeader=createVkExtensionStructureTypePreamble('VK_GOOGLE_GFXSTREAM'))
|
||||
|
||||
self.addGuestEncoderModule("func_table", extraImpl=functableImplInclude)
|
||||
|
||||
self.addCppModule("common", "goldfish_vk_extension_structs",
|
||||
extraHeader=extensionStructsInclude)
|
||||
self.addCppModule("common", "goldfish_vk_marshaling",
|
||||
extraHeader=vulkanStreamIncludeHost,
|
||||
extraImpl=commonCerealImplIncludes)
|
||||
self.addCppModule("common", "goldfish_vk_reserved_marshaling",
|
||||
extraHeader=vulkanStreamIncludeHost,
|
||||
extraImpl=commonCerealImplIncludes)
|
||||
self.addCppModule("common", "goldfish_vk_deepcopy",
|
||||
extraHeader=poolInclude,
|
||||
extraImpl=commonCerealImplIncludes + deepcopyInclude)
|
||||
self.addCppModule("common", "goldfish_vk_handlemap",
|
||||
extraHeader=handleMapInclude,
|
||||
extraImpl=commonCerealImplIncludes)
|
||||
self.addCppModule("common", "goldfish_vk_dispatch",
|
||||
extraHeader=dispatchHeaderDefs,
|
||||
extraImpl=dispatchImplIncludes)
|
||||
self.addCppModule("common", "goldfish_vk_transform",
|
||||
extraHeader=transformInclude,
|
||||
extraImpl=transformImplInclude)
|
||||
self.addHostModule("VkDecoder",
|
||||
extraHeader=decoderHeaderIncludes,
|
||||
extraImpl=decoderImplIncludes,
|
||||
useNamespace=False)
|
||||
self.addHostModule("VkDecoderSnapshot",
|
||||
extraHeader=decoderSnapshotHeaderIncludes,
|
||||
extraImpl=decoderSnapshotImplIncludes,
|
||||
useNamespace=False)
|
||||
self.addHostModule("VkSubDecoder",
|
||||
extraHeader="",
|
||||
extraImpl="",
|
||||
useNamespace=False,
|
||||
implOnly=True)
|
||||
|
||||
self.addModule(cereal.PyScript(self.host_tag, "vulkan_printer", customAbsDir=Path(
|
||||
self.host_script_destination) / "print_gfx_logs"), moduleName="ApiLogDecoder")
|
||||
self.addHostModule(
|
||||
"vulkan_gfxstream_structure_type", headerOnly=True, suppressFeatureGuards=True,
|
||||
moduleName="vulkan_gfxstream_structure_type_host", useNamespace=False,
|
||||
suppressVulkanHeaders=True,
|
||||
extraHeader=createVkExtensionStructureTypePreamble('VK_GOOGLE_GFXSTREAM'))
|
||||
self.addHostModule(
|
||||
"vk_android_native_buffer_structure_type", headerOnly=True, suppressFeatureGuards=True,
|
||||
useNamespace=False, suppressVulkanHeaders=True,
|
||||
extraHeader=createVkExtensionStructureTypePreamble('VK_ANDROID_NATIVE_BUFFER'))
|
||||
|
||||
self.addWrapper(cereal.VulkanEncoder, "VkEncoder")
|
||||
self.addWrapper(cereal.VulkanExtensionStructs, "goldfish_vk_extension_structs_guest")
|
||||
self.addWrapper(cereal.VulkanMarshaling, "goldfish_vk_marshaling_guest", variant = "guest")
|
||||
self.addWrapper(cereal.VulkanReservedMarshaling, "goldfish_vk_reserved_marshaling_guest", variant = "guest")
|
||||
self.addWrapper(cereal.VulkanDeepcopy, "goldfish_vk_deepcopy_guest")
|
||||
self.addWrapper(cereal.VulkanCounting, "goldfish_vk_counting_guest")
|
||||
self.addWrapper(cereal.VulkanTransform, "goldfish_vk_transform_guest")
|
||||
self.addWrapper(cereal.VulkanFuncTable, "func_table")
|
||||
self.addWrapper(cereal.VulkanExtensionStructs, "goldfish_vk_extension_structs")
|
||||
self.addWrapper(cereal.VulkanMarshaling, "goldfish_vk_marshaling")
|
||||
self.addWrapper(cereal.VulkanReservedMarshaling, "goldfish_vk_reserved_marshaling", variant = "host")
|
||||
self.addWrapper(cereal.VulkanDeepcopy, "goldfish_vk_deepcopy")
|
||||
self.addWrapper(cereal.VulkanHandleMap, "goldfish_vk_handlemap")
|
||||
self.addWrapper(cereal.VulkanDispatch, "goldfish_vk_dispatch")
|
||||
self.addWrapper(cereal.VulkanTransform, "goldfish_vk_transform", resourceTrackerTypeName="VkDecoderGlobalState")
|
||||
self.addWrapper(cereal.VulkanDecoder, "VkDecoder")
|
||||
self.addWrapper(cereal.VulkanDecoderSnapshot, "VkDecoderSnapshot")
|
||||
self.addWrapper(cereal.VulkanSubDecoder, "VkSubDecoder")
|
||||
self.addWrapper(cereal.ApiLogDecoder, "ApiLogDecoder")
|
||||
self.addWrapper(cereal.VulkanGfxstreamStructureType,
|
||||
"vulkan_gfxstream_structure_type_guest")
|
||||
self.addWrapper(cereal.VulkanGfxstreamStructureType, "vulkan_gfxstream_structure_type_host")
|
||||
self.addWrapper(cereal.VulkanAndroidNativeBufferStructureType,
|
||||
"vk_android_native_buffer_structure_type")
|
||||
|
||||
self.guestAndroidMkCppFiles = ""
|
||||
self.hostCMakeCppFiles = ""
|
||||
self.hostDecoderCMakeCppFiles = ""
|
||||
|
||||
def addSrcEntry(m):
|
||||
mkSrcEntry = m.getMakefileSrcEntry()
|
||||
cmakeSrcEntry = m.getCMakeSrcEntry()
|
||||
if m.directory == self.guest_encoder_tag:
|
||||
self.guestAndroidMkCppFiles += mkSrcEntry
|
||||
elif m.directory == self.host_tag:
|
||||
self.hostDecoderCMakeCppFiles += cmakeSrcEntry
|
||||
else:
|
||||
self.hostCMakeCppFiles += cmakeSrcEntry
|
||||
|
||||
self.forEachModule(addSrcEntry)
|
||||
|
||||
def addGuestEncoderModule(
|
||||
self, basename, extraHeader="", extraImpl="", useNamespace=True, headerOnly=False,
|
||||
suppressFeatureGuards=False, moduleName=None, suppressVulkanHeaders=False):
|
||||
if not os.path.exists(self.guest_abs_encoder_destination):
|
||||
print("Path [%s] not found (guest encoder path), skipping" % self.guest_abs_encoder_destination)
|
||||
return
|
||||
self.addCppModule(self.guest_encoder_tag, basename, extraHeader=extraHeader,
|
||||
extraImpl=extraImpl, customAbsDir=self.guest_abs_encoder_destination,
|
||||
useNamespace=useNamespace, headerOnly=headerOnly,
|
||||
suppressFeatureGuards=suppressFeatureGuards, moduleName=moduleName,
|
||||
suppressVulkanHeaders=suppressVulkanHeaders)
|
||||
|
||||
def addHostModule(
|
||||
self, basename, extraHeader="", extraImpl="", useNamespace=True, implOnly=False,
|
||||
suppress=False, headerOnly=False, suppressFeatureGuards=False, moduleName=None,
|
||||
suppressVulkanHeaders=False):
|
||||
if not os.path.exists(self.host_abs_decoder_destination):
|
||||
print("Path [%s] not found (host encoder path), skipping" %
|
||||
self.host_abs_decoder_destination)
|
||||
return
|
||||
if not suppressVulkanHeaders:
|
||||
extraHeader = self.hostCommonExtraVulkanHeaders + '\n' + extraHeader
|
||||
self.addCppModule(
|
||||
self.host_tag, basename, extraHeader=extraHeader, extraImpl=extraImpl,
|
||||
customAbsDir=self.host_abs_decoder_destination, useNamespace=useNamespace,
|
||||
implOnly=implOnly, suppress=suppress, headerOnly=headerOnly,
|
||||
suppressFeatureGuards=suppressFeatureGuards, moduleName=moduleName,
|
||||
suppressVulkanHeaders=suppressVulkanHeaders)
|
||||
|
||||
def addModule(self, module, moduleName=None):
|
||||
if moduleName is None:
|
||||
moduleName = module.basename
|
||||
self.moduleList.append(moduleName)
|
||||
self.modules[moduleName] = module
|
||||
|
||||
def addCppModule(
|
||||
self, directory, basename, extraHeader="", extraImpl="", customAbsDir=None,
|
||||
useNamespace=True, implOnly=False, suppress=False, headerOnly=False,
|
||||
suppressFeatureGuards=False, moduleName=None, suppressVulkanHeaders=False):
|
||||
module = cereal.Module(
|
||||
directory, basename, customAbsDir=customAbsDir, suppress=suppress, implOnly=implOnly,
|
||||
headerOnly=headerOnly, suppressFeatureGuards=suppressFeatureGuards)
|
||||
self.addModule(module, moduleName=moduleName)
|
||||
module.headerPreamble = copyrightHeader
|
||||
module.headerPreamble += \
|
||||
autogeneratedHeaderTemplate % \
|
||||
(basename, "(header) generated by %s" % banner_command(sys.argv))
|
||||
|
||||
module.headerPreamble += "#pragma once\n"
|
||||
if (not suppressVulkanHeaders):
|
||||
module.headerPreamble += "#include <vulkan/vulkan.h>\n"
|
||||
module.headerPreamble += '#include "vulkan_gfxstream.h"\n'
|
||||
module.headerPreamble += extraHeader + '\n'
|
||||
if useNamespace:
|
||||
module.headerPreamble += namespaceBegin
|
||||
|
||||
module.implPreamble = copyrightHeader
|
||||
module.implPreamble += \
|
||||
autogeneratedHeaderTemplate % \
|
||||
(basename, "(impl) generated by %s" % \
|
||||
banner_command(sys.argv))
|
||||
if not implOnly:
|
||||
module.implPreamble += '\n#include "%s.h"' % \
|
||||
(basename)
|
||||
|
||||
module.implPreamble += extraImpl
|
||||
|
||||
if useNamespace:
|
||||
module.implPreamble += namespaceBegin
|
||||
module.implPostamble += namespaceEnd
|
||||
module.headerPostamble += namespaceEnd
|
||||
|
||||
def addWrapper(self, moduleType, moduleName, **kwargs):
|
||||
if moduleName not in self.modules:
|
||||
print(f'Unknown module: {moduleName}. All known modules are: {", ".join(self.modules)}.')
|
||||
return
|
||||
self.wrappers.append(
|
||||
moduleType(
|
||||
self.modules[moduleName],
|
||||
self.typeInfo, **kwargs))
|
||||
|
||||
def forEachModule(self, func):
|
||||
for moduleName in self.moduleList:
|
||||
func(self.modules[moduleName])
|
||||
|
||||
def forEachWrapper(self, func, supportedWrappers):
|
||||
for wrapper in self.wrappers:
|
||||
if supportedWrappers is None:
|
||||
func(wrapper)
|
||||
elif type(wrapper) in supportedWrappers:
|
||||
func(wrapper)
|
||||
|
||||
## Overrides####################################################################
|
||||
|
||||
def beginFile(self, genOpts):
|
||||
OutputGenerator.beginFile(self, genOpts)
|
||||
|
||||
write(self.host_cmake_generator(self.hostCMakeCppFiles),
|
||||
file = self.outFile)
|
||||
|
||||
self.forEachModule(lambda m: m.begin(self.genOpts.directory))
|
||||
self.forEachWrapper(lambda w: w.onBegin(), None)
|
||||
|
||||
def endFile(self):
|
||||
OutputGenerator.endFile(self)
|
||||
|
||||
self.typeInfo.onEnd()
|
||||
|
||||
self.forEachWrapper(lambda w: w.onEnd(), None)
|
||||
self.forEachModule(lambda m: m.end())
|
||||
|
||||
def beginFeature(self, interface, emit):
|
||||
# Start processing in superclass
|
||||
OutputGenerator.beginFeature(self, interface, emit)
|
||||
|
||||
for supportedFeature in SUPPORTED_FEATURES:
|
||||
if self.featureName == supportedFeature:
|
||||
self.featureSupported = True
|
||||
|
||||
if self.featureSupported == False:
|
||||
return
|
||||
|
||||
self.supportedWrappers = SUPPORTED_WRAPPERS.get(self.featureName)
|
||||
self.typeInfo.onBeginFeature(self.featureName, self.featureType)
|
||||
|
||||
self.forEachModule(
|
||||
lambda m: m.appendHeader("#ifdef %s\n" % self.featureName)
|
||||
if isinstance(m, cereal.Module) and not m.suppressFeatureGuards else None)
|
||||
self.forEachModule(
|
||||
lambda m: m.appendImpl("#ifdef %s\n" % self.featureName)
|
||||
if isinstance(m, cereal.Module) and not m.suppressFeatureGuards else None)
|
||||
self.forEachWrapper(lambda w: w.onBeginFeature(self.featureName, self.featureType), self.supportedWrappers)
|
||||
# functable needs to understand the feature type (device vs instance) of each cmd
|
||||
for features in interface.findall('require'):
|
||||
for c in features.findall('command'):
|
||||
self.forEachWrapper(lambda w: w.onFeatureNewCmd(c.get('name')), self.supportedWrappers)
|
||||
|
||||
def endFeature(self):
|
||||
# Finish processing in superclass
|
||||
OutputGenerator.endFeature(self)
|
||||
|
||||
if self.featureSupported == False:
|
||||
return
|
||||
|
||||
self.featureSupported = False
|
||||
|
||||
self.typeInfo.onEndFeature()
|
||||
|
||||
self.forEachModule(lambda m: m.appendHeader("#endif\n") if isinstance(
|
||||
m, cereal.Module) and not m.suppressFeatureGuards else None)
|
||||
self.forEachModule(lambda m: m.appendImpl("#endif\n") if isinstance(
|
||||
m, cereal.Module) and not m.suppressFeatureGuards else None)
|
||||
self.forEachWrapper(lambda w: w.onEndFeature(), self.supportedWrappers)
|
||||
|
||||
def genType(self, typeinfo: TypeInfo, name, alias):
|
||||
OutputGenerator.genType(self, typeinfo, name, alias)
|
||||
|
||||
if self.featureSupported == False and name == "int":
|
||||
self.typeInfo.onGenType(typeinfo, name, alias)
|
||||
return
|
||||
|
||||
if self.featureSupported == False and name == "int64_t":
|
||||
self.typeInfo.onGenType(typeinfo, name, alias)
|
||||
return
|
||||
|
||||
if self.featureSupported == False and name == "double":
|
||||
self.typeInfo.onGenType(typeinfo, name, alias)
|
||||
return
|
||||
|
||||
if self.featureSupported == False and name == "VkPresentScalingFlagsEXT":
|
||||
self.typeInfo.onGenType(typeinfo, name, alias)
|
||||
return
|
||||
|
||||
if self.featureSupported == False and name == "VkPresentGravityFlagsEXT":
|
||||
self.typeInfo.onGenType(typeinfo, name, alias)
|
||||
return
|
||||
|
||||
if self.featureSupported == False:
|
||||
return
|
||||
|
||||
self.typeInfo.onGenType(typeinfo, name, alias)
|
||||
self.forEachWrapper(lambda w: w.onGenType(typeinfo, name, alias), self.supportedWrappers)
|
||||
|
||||
def genStruct(self, typeinfo, typeName, alias):
|
||||
OutputGenerator.genStruct(self, typeinfo, typeName, alias)
|
||||
if self.featureSupported == False:
|
||||
return
|
||||
|
||||
self.typeInfo.onGenStruct(typeinfo, typeName, alias)
|
||||
self.forEachWrapper(lambda w: w.onGenStruct(typeinfo, typeName, alias), self.supportedWrappers)
|
||||
|
||||
def genGroup(self, groupinfo: GroupInfo, groupName, alias = None):
|
||||
OutputGenerator.genGroup(self, groupinfo, groupName, alias)
|
||||
if self.featureSupported == False:
|
||||
return
|
||||
|
||||
self.typeInfo.onGenGroup(groupinfo, groupName, alias)
|
||||
self.forEachWrapper(lambda w: w.onGenGroup(groupinfo, groupName, alias), self.supportedWrappers)
|
||||
|
||||
def genEnum(self, enuminfo: EnumInfo, name, alias):
|
||||
OutputGenerator.genEnum(self, enuminfo, name, alias)
|
||||
if self.featureSupported == False:
|
||||
return
|
||||
self.typeInfo.onGenEnum(enuminfo, name, alias)
|
||||
self.forEachWrapper(lambda w: w.onGenEnum(enuminfo, name, alias), self.supportedWrappers)
|
||||
|
||||
def genCmd(self, cmdinfo, name, alias):
|
||||
OutputGenerator.genCmd(self, cmdinfo, name, alias)
|
||||
if self.featureSupported == False:
|
||||
return
|
||||
|
||||
self.typeInfo.onGenCmd(cmdinfo, name, alias)
|
||||
self.forEachWrapper(lambda w: w.onGenCmd(cmdinfo, name, alias), self.supportedWrappers)
|
||||
Loading…
Add table
Reference in a new issue