Reland "Partial revert of aosp/2858589 to avoid Mesa layer for Android"
This reverts commit 9eef6d0aefcf0aa1c07d42d9b307b1092a6deec9. ... as this does not yet have a way to generically convert Mesa handles into Gfxstream handles in extension structs which causes breakage in dEQP VK for many tests. Moves the mesa based codegen to a separate `mesa_func_table`. Reland fixes the end2end test guest vulkan ICD. cts -m CtsDeqpTestCases --module-arg CtsDeqpTestCases:include-filter:dEQP-VK.* 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:
@@ -4,6 +4,7 @@ from .encoder import *
|
||||
from .extensionstructs import *
|
||||
from .frontend import *
|
||||
from .functable import *
|
||||
from .mesa_functable import *
|
||||
from .marshaling import *
|
||||
from .reservedmarshaling import *
|
||||
from .counting import *
|
||||
|
@@ -2,10 +2,6 @@ from .common.codegen import CodeGen, VulkanWrapperGenerator
|
||||
from .common.vulkantypes import \
|
||||
VulkanAPI, makeVulkanTypeSimple, iterateVulkanType
|
||||
from .common.vulkantypes import EXCLUDED_APIS
|
||||
from .common.vulkantypes import HANDLE_TYPES
|
||||
|
||||
import copy
|
||||
import re
|
||||
|
||||
RESOURCE_TRACKER_ENTRIES = [
|
||||
"vkEnumerateInstanceExtensionProperties",
|
||||
@@ -49,7 +45,6 @@ RESOURCE_TRACKER_ENTRIES = [
|
||||
"vkCreateSamplerYcbcrConversionKHR",
|
||||
"vkDestroySamplerYcbcrConversionKHR",
|
||||
"vkUpdateDescriptorSetWithTemplate",
|
||||
"vkUpdateDescriptorSetWithTemplateKHR",
|
||||
"vkGetPhysicalDeviceImageFormatProperties2",
|
||||
"vkGetPhysicalDeviceImageFormatProperties2KHR",
|
||||
"vkBeginCommandBuffer",
|
||||
@@ -72,6 +67,7 @@ RESOURCE_TRACKER_ENTRIES = [
|
||||
"vkAllocateDescriptorSets",
|
||||
"vkFreeDescriptorSets",
|
||||
"vkCreateDescriptorSetLayout",
|
||||
"vkUpdateDescriptorSets",
|
||||
"vkCmdExecuteCommands",
|
||||
"vkCmdBindDescriptorSets",
|
||||
"vkDestroyDescriptorSetLayout",
|
||||
@@ -95,78 +91,13 @@ SUCCESS_VAL = {
|
||||
"VkResult" : ["VK_SUCCESS"],
|
||||
}
|
||||
|
||||
HANDWRITTEN_ENTRY_POINTS = [
|
||||
# Instance/device/physical-device special-handling, dispatch tables, etc..
|
||||
"vkCreateInstance",
|
||||
"vkDestroyInstance",
|
||||
"vkGetInstanceProcAddr",
|
||||
"vkEnumerateInstanceVersion",
|
||||
"vkEnumerateInstanceLayerProperties",
|
||||
"vkEnumerateInstanceExtensionProperties",
|
||||
"vkEnumerateDeviceExtensionProperties",
|
||||
"vkGetDeviceProcAddr",
|
||||
"vkEnumeratePhysicalDevices",
|
||||
"vkEnumeratePhysicalDeviceGroups",
|
||||
"vkCreateDevice",
|
||||
"vkDestroyDevice",
|
||||
"vkCreateComputePipelines",
|
||||
# Manual alloc/free + vk_*_init/free() call w/ special params
|
||||
"vkGetDeviceQueue",
|
||||
"vkGetDeviceQueue2",
|
||||
# Command pool/buffer handling
|
||||
"vkCreateCommandPool",
|
||||
"vkDestroyCommandPool",
|
||||
"vkAllocateCommandBuffers",
|
||||
"vkResetCommandPool",
|
||||
"vkFreeCommandBuffers",
|
||||
"vkResetCommandPool",
|
||||
# Special cases to handle struct translations in the pNext chain
|
||||
# TODO: Make a codegen module (use deepcopy as reference) to make this more robust
|
||||
"vkCmdBeginRenderPass2KHR",
|
||||
"vkCmdBeginRenderPass",
|
||||
"vkAllocateMemory",
|
||||
"vkUpdateDescriptorSets",
|
||||
"vkQueueCommitDescriptorSetUpdatesGOOGLE",
|
||||
]
|
||||
|
||||
# TODO: handles with no equivalent gfxstream objects (yet).
|
||||
# Might need some special handling.
|
||||
HANDLES_DONT_TRANSLATE = {
|
||||
"VkSurfaceKHR",
|
||||
## The following objects have no need for mesa counterparts
|
||||
# Allows removal of handwritten create/destroy (for array).
|
||||
"VkDescriptorSet",
|
||||
# Bug in translation
|
||||
"VkSampler",
|
||||
"VkSamplerYcbcrConversion",
|
||||
}
|
||||
|
||||
# Handles whose gfxstream object have non-base-object vk_ structs
|
||||
# Optionally includes array of pairs of extraParams: {index, extraParam}
|
||||
# -1 means drop parameter of paramName specified by extraParam
|
||||
HANDLES_MESA_VK = {
|
||||
# Handwritten handlers (added here for completeness)
|
||||
"VkInstance" : None,
|
||||
"VkPhysicalDevice" : None,
|
||||
"VkDevice" : None,
|
||||
"VkQueue" : None,
|
||||
"VkCommandPool" : None,
|
||||
"VkCommandBuffer" : None,
|
||||
# Auto-generated creation/destroy
|
||||
"VkDeviceMemory" : None,
|
||||
"VkQueryPool" : None,
|
||||
"VkBuffer" : [[-1, "pMemoryRequirements"]],
|
||||
"VkBufferView" : None,
|
||||
"VkImage" : [[-1, "pMemoryRequirements"]],
|
||||
"VkImageView": [[1, "false /* driver_internal */"]],
|
||||
"VkSampler" : None,
|
||||
}
|
||||
|
||||
# Types that have a corresponding method for transforming
|
||||
# an input list to its internal counterpart
|
||||
TYPES_TRANSFORM_LIST_METHOD = {
|
||||
"VkSemaphore",
|
||||
"VkSemaphoreSubmitInfo",
|
||||
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):
|
||||
@@ -175,59 +106,6 @@ def is_cmdbuf_dispatch(api):
|
||||
def is_queue_dispatch(api):
|
||||
return "VkQueue" == api.parameters[0].typeName
|
||||
|
||||
def getCreateParam(api):
|
||||
for param in api.parameters:
|
||||
if param.isCreatedBy(api):
|
||||
return param
|
||||
return None
|
||||
|
||||
def getDestroyParam(api):
|
||||
for param in api.parameters:
|
||||
if param.isDestroyedBy(api):
|
||||
return param
|
||||
return None
|
||||
|
||||
# i.e. VkQueryPool --> vk_query_pool
|
||||
def typeNameToMesaType(typeName):
|
||||
vkTypeNameRegex = "(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])"
|
||||
words = re.split(vkTypeNameRegex, typeName)
|
||||
outputType = "vk"
|
||||
for word in words[1:]:
|
||||
outputType += "_"
|
||||
outputType += word.lower()
|
||||
return outputType
|
||||
|
||||
def typeNameToBaseName(typeName):
|
||||
return typeNameToMesaType(typeName)[len("vk_"):]
|
||||
|
||||
def paramNameToObjectName(paramName):
|
||||
return "gfxstream_%s" % paramName
|
||||
|
||||
def typeNameToVkObjectType(typeName):
|
||||
return "VK_OBJECT_TYPE_%s" % typeNameToBaseName(typeName).upper()
|
||||
|
||||
def typeNameToObjectType(typeName):
|
||||
return "gfxstream_vk_%s" % typeNameToBaseName(typeName)
|
||||
|
||||
def transformListFuncName(typeName):
|
||||
return "transform%sList" % (typeName)
|
||||
|
||||
def hasMesaVkObject(typeName):
|
||||
return typeName in HANDLES_MESA_VK
|
||||
|
||||
def isAllocatorParam(param):
|
||||
ALLOCATOR_TYPE_NAME = "VkAllocationCallbacks"
|
||||
return (param.pointerIndirectionLevels == 1
|
||||
and param.isConst
|
||||
and param.typeName == ALLOCATOR_TYPE_NAME)
|
||||
|
||||
def isArrayParam(param):
|
||||
return (1 == param.pointerIndirectionLevels
|
||||
and param.isConst
|
||||
and "len" in param.attribs)
|
||||
|
||||
INTERNAL_OBJECT_NAME = "internal_object"
|
||||
|
||||
class VulkanFuncTable(VulkanWrapperGenerator):
|
||||
def __init__(self, module, typeInfo):
|
||||
VulkanWrapperGenerator.__init__(self, module, typeInfo)
|
||||
@@ -241,6 +119,11 @@ class VulkanFuncTable(VulkanWrapperGenerator):
|
||||
|
||||
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
|
||||
|
||||
@@ -261,365 +144,264 @@ class VulkanFuncTable(VulkanWrapperGenerator):
|
||||
api = typeInfo.apis[name]
|
||||
self.entries.append(api)
|
||||
self.entryFeatures.append(self.feature)
|
||||
self.loopVars = ["i", "j", "k", "l", "m", "n"]
|
||||
self.loopVarIndex = 0
|
||||
|
||||
def getNextLoopVar():
|
||||
if self.loopVarIndex >= len(self.loopVars):
|
||||
raise
|
||||
loopVar = self.loopVars[self.loopVarIndex]
|
||||
self.loopVarIndex += 1
|
||||
return loopVar
|
||||
def genEncoderOrResourceTrackerCall(cgen, api, declareResources=True):
|
||||
cgen.stmt("AEMU_SCOPED_TRACE(\"%s\")" % api.name)
|
||||
|
||||
def isCompoundType(typeName):
|
||||
return typeInfo.isCompoundType(typeName)
|
||||
|
||||
def handleTranslationRequired(typeName):
|
||||
return typeName in HANDLE_TYPES and typeName not in HANDLES_DONT_TRANSLATE
|
||||
|
||||
def translationRequired(typeName):
|
||||
if isCompoundType(typeName):
|
||||
struct = typeInfo.structs[typeName]
|
||||
for member in struct.members:
|
||||
if translationRequired(member.typeName):
|
||||
return True
|
||||
return False
|
||||
else:
|
||||
return handleTranslationRequired(typeName)
|
||||
|
||||
def genDestroyGfxstreamObjects():
|
||||
destroyParam = getDestroyParam(api)
|
||||
if not destroyParam:
|
||||
return
|
||||
if not translationRequired(destroyParam.typeName):
|
||||
return
|
||||
objectName = paramNameToObjectName(destroyParam.paramName)
|
||||
allocatorParam = "NULL"
|
||||
for p in api.parameters:
|
||||
if isAllocatorParam(p):
|
||||
allocatorParam = p.paramName
|
||||
if not hasMesaVkObject(destroyParam.typeName):
|
||||
deviceParam = api.parameters[0]
|
||||
if "VkDevice" != deviceParam.typeName:
|
||||
print("ERROR: Unhandled non-VkDevice parameters[0]: %s (for API: %s)" %(deviceParam.typeName, api.name))
|
||||
raise
|
||||
# call vk_object_free() directly
|
||||
mesaObjectDestroy = "(void *)%s" % objectName
|
||||
cgen.funcCall(
|
||||
None,
|
||||
"vk_object_free",
|
||||
["&%s->vk" % paramNameToObjectName(deviceParam.paramName), allocatorParam, mesaObjectDestroy]
|
||||
)
|
||||
else:
|
||||
baseName = typeNameToBaseName(destroyParam.typeName)
|
||||
# objectName for destroy always at the back
|
||||
mesaObjectPrimary = "&%s->vk" % paramNameToObjectName(api.parameters[0].paramName)
|
||||
mesaObjectDestroy = "&%s->vk" % objectName
|
||||
cgen.funcCall(
|
||||
None,
|
||||
"vk_%s_destroy" % (baseName),
|
||||
[mesaObjectPrimary, allocatorParam, mesaObjectDestroy]
|
||||
)
|
||||
|
||||
def genMesaObjectAlloc(allocCallLhs):
|
||||
deviceParam = api.parameters[0]
|
||||
if "VkDevice" != deviceParam.typeName:
|
||||
print("ERROR: Unhandled non-VkDevice parameters[0]: %s (for API: %s)" %(deviceParam.typeName, api.name))
|
||||
raise
|
||||
allocatorParam = "NULL"
|
||||
for p in api.parameters:
|
||||
if isAllocatorParam(p):
|
||||
allocatorParam = p.paramName
|
||||
createParam = getCreateParam(api)
|
||||
objectType = typeNameToObjectType(createParam.typeName)
|
||||
# Call vk_object_zalloc directly
|
||||
cgen.funcCall(
|
||||
allocCallLhs,
|
||||
"(%s *)vk_object_zalloc" % objectType,
|
||||
["&%s->vk" % paramNameToObjectName(deviceParam.paramName), allocatorParam, ("sizeof(%s)" % objectType), typeNameToVkObjectType(createParam.typeName)]
|
||||
)
|
||||
|
||||
def genMesaObjectCreate(createCallLhs):
|
||||
def dropParam(params, drop):
|
||||
for p in params:
|
||||
if p == drop:
|
||||
params.remove(p)
|
||||
return params
|
||||
createParam = getCreateParam(api)
|
||||
objectType = "struct %s" % typeNameToObjectType(createParam.typeName)
|
||||
modParams = copy.deepcopy(api.parameters)
|
||||
# Mod params for the vk_%s_create() call i.e. vk_buffer_create()
|
||||
for p in modParams:
|
||||
if p.paramName == createParam.paramName:
|
||||
modParams.remove(p)
|
||||
elif handleTranslationRequired(p.typeName):
|
||||
# Cast handle to the mesa type
|
||||
p.paramName = ("(%s*)%s" % (typeNameToMesaType(p.typeName), paramNameToObjectName(p.paramName)))
|
||||
mesaCreateParams = [p.paramName for p in modParams] + ["sizeof(%s)" % objectType]
|
||||
# Some special handling
|
||||
extraParams = HANDLES_MESA_VK[createParam.typeName]
|
||||
if extraParams:
|
||||
for pair in extraParams:
|
||||
if -1 == pair[0]:
|
||||
mesaCreateParams = dropParam(mesaCreateParams, pair[1])
|
||||
else:
|
||||
mesaCreateParams.insert(pair[0], pair[1])
|
||||
cgen.funcCall(
|
||||
createCallLhs,
|
||||
"(%s *)vk_%s_create" % (objectType, typeNameToBaseName(createParam.typeName)),
|
||||
mesaCreateParams
|
||||
)
|
||||
|
||||
# Alloc/create gfxstream_vk_* object
|
||||
def genCreateGfxstreamObjects():
|
||||
createParam = getCreateParam(api)
|
||||
if not createParam:
|
||||
return False
|
||||
if not handleTranslationRequired(createParam.typeName):
|
||||
return False
|
||||
objectType = "struct %s" % typeNameToObjectType(createParam.typeName)
|
||||
callLhs = "%s *%s" % (objectType, paramNameToObjectName(createParam.paramName))
|
||||
if hasMesaVkObject(createParam.typeName):
|
||||
genMesaObjectCreate(callLhs)
|
||||
else:
|
||||
genMesaObjectAlloc(callLhs)
|
||||
|
||||
retVar = api.getRetVarExpr()
|
||||
if retVar:
|
||||
retTypeName = api.getRetTypeExpr()
|
||||
# ex: vkCreateBuffer_VkResult_return = gfxstream_buffer ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
cgen.stmt("%s = %s ? %s : %s" %
|
||||
(retVar, paramNameToObjectName(createParam.paramName), SUCCESS_VAL[retTypeName][0], "VK_ERROR_OUT_OF_HOST_MEMORY"))
|
||||
return True
|
||||
|
||||
def genVkFromHandle(param, fromName):
|
||||
objectName = paramNameToObjectName(param.paramName)
|
||||
cgen.stmt("VK_FROM_HANDLE(%s, %s, %s)" %
|
||||
(typeNameToObjectType(param.typeName), objectName, fromName))
|
||||
return objectName
|
||||
|
||||
def genGetGfxstreamHandles():
|
||||
createParam = getCreateParam(api)
|
||||
for param in api.parameters:
|
||||
if not handleTranslationRequired(param.typeName):
|
||||
continue
|
||||
elif isArrayParam(param):
|
||||
continue
|
||||
elif param != createParam:
|
||||
if param.pointerIndirectionLevels > 0:
|
||||
print("ERROR: Unhandled pointerIndirectionLevels > 1 for API %s (param %s)" % (api.name, param.paramName))
|
||||
raise
|
||||
genVkFromHandle(param, param.paramName)
|
||||
|
||||
def internalNestedParamName(param):
|
||||
parentName = ""
|
||||
if param.parent:
|
||||
parentName = "_%s" % param.parent.typeName
|
||||
return "internal%s_%s" % (parentName, param.paramName)
|
||||
|
||||
def genInternalArrayDeclarations(param, countParamName, nestLevel=0):
|
||||
internalArray = None
|
||||
if 0 == nestLevel:
|
||||
internalArray = "internal_%s" % param.paramName
|
||||
cgen.stmt("std::vector<%s> %s(%s)" % (param.typeName, internalArray, countParamName))
|
||||
elif 1 == nestLevel or 2 == nestLevel:
|
||||
internalArray = internalNestedParamName(param)
|
||||
if isArrayParam(param):
|
||||
cgen.stmt("std::vector<std::vector<%s>> %s" % (param.typeName, internalArray))
|
||||
else:
|
||||
cgen.stmt("std::vector<%s> %s" % (param.typeName, internalArray))
|
||||
else:
|
||||
print("ERROR: nestLevel > 2 not verified.")
|
||||
raise
|
||||
if isCompoundType(param.typeName):
|
||||
for member in typeInfo.structs[param.typeName].members:
|
||||
if translationRequired(member.typeName):
|
||||
if handleTranslationRequired(member.typeName) and not isArrayParam(member):
|
||||
# No declarations for non-array handleType
|
||||
continue
|
||||
genInternalArrayDeclarations(member, countParamName, nestLevel + 1)
|
||||
return internalArray
|
||||
|
||||
def genInternalCompoundType(param, outName, inName, currLoopVar):
|
||||
nextLoopVar = None
|
||||
cgen.stmt("%s = %s" % (outName, inName))
|
||||
for member in typeInfo.structs[param.typeName].members:
|
||||
if not translationRequired(member.typeName):
|
||||
continue
|
||||
cgen.line("/* %s::%s */" % (param.typeName, member.paramName))
|
||||
nestedOutName = ("%s[%s]" % (internalNestedParamName(member), currLoopVar))
|
||||
if isArrayParam(member):
|
||||
countParamName = "%s.%s" % (outName, member.attribs["len"])
|
||||
inArrayName = "%s.%s" % (outName, member.paramName)
|
||||
cgen.stmt("%s.push_back(std::vector<%s>())" % (internalNestedParamName(member), member.typeName))
|
||||
if member.typeName in TYPES_TRANSFORM_LIST_METHOD:
|
||||
# Use the corresponding transformList call
|
||||
cgen.funcCall(nestedOutName, transformListFuncName(member.typeName), [inArrayName, countParamName])
|
||||
cgen.stmt("%s = %s.data()" % (inArrayName, nestedOutName))
|
||||
cgen.stmt("%s = %s.size()" % (countParamName, nestedOutName))
|
||||
else:
|
||||
# Standard translation
|
||||
cgen.stmt("%s.reserve(%s)" % (nestedOutName, countParamName))
|
||||
cgen.stmt("memset(&%s[0], 0, sizeof(%s) * %s)" % (nestedOutName, member.typeName, countParamName))
|
||||
if not nextLoopVar:
|
||||
nextLoopVar = getNextLoopVar()
|
||||
internalArray = genInternalArray(member, countParamName, nestedOutName, inArrayName, nextLoopVar)
|
||||
cgen.stmt("%s = %s" %(inArrayName, internalArray))
|
||||
elif isCompoundType(member.typeName):
|
||||
memberFullName = "%s.%s" % (outName, member.paramName)
|
||||
if 1 == member.pointerIndirectionLevels:
|
||||
cgen.beginIf(memberFullName)
|
||||
inParamName = "%s[0]" % memberFullName
|
||||
genInternalCompoundType(member, nestedOutName, inParamName, currLoopVar)
|
||||
cgen.stmt("%s.%s = &%s" % (outName, member.paramName, nestedOutName))
|
||||
else:
|
||||
cgen.beginBlock()
|
||||
genInternalCompoundType(member, nestedOutName, memberFullName, currLoopVar)
|
||||
cgen.stmt("%s.%s = %s" % (outName, member.paramName, nestedOutName))
|
||||
cgen.endBlock()
|
||||
else:
|
||||
# Replace member with internal object
|
||||
replaceName = "%s.%s" % (outName, member.paramName)
|
||||
if member.isOptional:
|
||||
cgen.beginIf(replaceName)
|
||||
gfxstreamObject = genVkFromHandle(member, replaceName)
|
||||
cgen.stmt("%s = %s->%s" % (replaceName, gfxstreamObject, INTERNAL_OBJECT_NAME))
|
||||
if member.isOptional:
|
||||
cgen.endIf()
|
||||
|
||||
def genInternalArray(param, countParamName, outArrayName, inArrayName, loopVar):
|
||||
cgen.beginFor("uint32_t %s = 0" % loopVar, "%s < %s" % (loopVar, countParamName), "++%s" % loopVar)
|
||||
if param.isOptional:
|
||||
cgen.beginIf(inArrayName)
|
||||
if isCompoundType(param.typeName):
|
||||
genInternalCompoundType(param, ("%s[%s]" % (outArrayName, loopVar)), "%s[%s]" % (inArrayName, loopVar), loopVar)
|
||||
else:
|
||||
gfxstreamObject = genVkFromHandle(param, "%s[%s]" % (inArrayName, loopVar))
|
||||
cgen.stmt("%s[%s] = %s->%s" % (outArrayName, loopVar, gfxstreamObject, INTERNAL_OBJECT_NAME))
|
||||
if param.isOptional:
|
||||
cgen.endIf()
|
||||
cgen.endFor()
|
||||
return "%s.data()" % outArrayName
|
||||
|
||||
# Translate params into params needed for gfxstream-internal
|
||||
# encoder/resource-tracker calls
|
||||
def getEncoderOrResourceTrackerParams():
|
||||
createParam = getCreateParam(api)
|
||||
outParams = copy.deepcopy(api.parameters)
|
||||
nextLoopVar = getNextLoopVar()
|
||||
for param in outParams:
|
||||
if not translationRequired(param.typeName):
|
||||
continue
|
||||
elif isArrayParam(param) or isCompoundType(param.typeName):
|
||||
if param.possiblyOutput():
|
||||
print("ERROR: Unhandled CompoundType / Array output for API %s (param %s)" % (api.name, param.paramName))
|
||||
raise
|
||||
if 1 != param.pointerIndirectionLevels or not param.isConst:
|
||||
print("ERROR: Compound type / array input is not 'const <type>*' (API: %s, paramName: %s)" % (api.name, param.paramName))
|
||||
raise
|
||||
countParamName = "1"
|
||||
if "len" in param.attribs:
|
||||
countParamName = param.attribs["len"]
|
||||
internalArrayName = genInternalArrayDeclarations(param, countParamName)
|
||||
param.paramName = genInternalArray(param, countParamName, internalArrayName, param.paramName, nextLoopVar)
|
||||
elif 0 == param.pointerIndirectionLevels:
|
||||
if param.isOptional:
|
||||
param.paramName = ("%s ? %s->%s : VK_NULL_HANDLE" % (paramNameToObjectName(param.paramName), paramNameToObjectName(param.paramName), INTERNAL_OBJECT_NAME))
|
||||
else:
|
||||
param.paramName = ("%s->%s" % (paramNameToObjectName(param.paramName), INTERNAL_OBJECT_NAME))
|
||||
elif createParam and param.paramName == createParam.paramName:
|
||||
param.paramName = ("&%s->%s" % (paramNameToObjectName(param.paramName), INTERNAL_OBJECT_NAME))
|
||||
else:
|
||||
print("ERROR: Unknown handling for param: %s (API: %s)" % (param, api.name))
|
||||
raise
|
||||
return outParams
|
||||
|
||||
def genEncoderOrResourceTrackerCall(declareResources=True):
|
||||
if is_cmdbuf_dispatch(api):
|
||||
cgen.stmt("auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(%s->%s)" % (paramNameToObjectName(api.parameters[0].paramName), INTERNAL_OBJECT_NAME))
|
||||
cgen.stmt("auto vkEnc = ResourceTracker::getCommandBufferEncoder(commandBuffer)")
|
||||
elif is_queue_dispatch(api):
|
||||
cgen.stmt("auto vkEnc = gfxstream::vk::ResourceTracker::getQueueEncoder(%s->%s)" % (paramNameToObjectName(api.parameters[0].paramName), INTERNAL_OBJECT_NAME))
|
||||
cgen.stmt("auto vkEnc = ResourceTracker::getQueueEncoder(queue)")
|
||||
else:
|
||||
cgen.stmt("auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder()")
|
||||
cgen.stmt("auto vkEnc = ResourceTracker::getThreadLocalEncoder()")
|
||||
callLhs = None
|
||||
retTypeName = api.getRetTypeExpr()
|
||||
if retTypeName != "void":
|
||||
callLhs = api.getRetVarExpr()
|
||||
retVar = api.getRetVarExpr()
|
||||
cgen.stmt("%s %s = (%s)0" % (retTypeName, retVar, retTypeName))
|
||||
callLhs = retVar
|
||||
|
||||
# Get parameter list modded for gfxstream-internal call
|
||||
parameters = getEncoderOrResourceTrackerParams()
|
||||
if name in RESOURCE_TRACKER_ENTRIES:
|
||||
if declareResources:
|
||||
cgen.stmt("auto resources = gfxstream::vk::ResourceTracker::get()")
|
||||
cgen.stmt("auto resources = ResourceTracker::get()")
|
||||
cgen.funcCall(
|
||||
callLhs, "resources->" + "on_" + api.name,
|
||||
["vkEnc"] + SUCCESS_VAL.get(retTypeName, []) + \
|
||||
[p.paramName for p in parameters])
|
||||
[p.paramName for p in api.parameters])
|
||||
else:
|
||||
cgen.funcCall(
|
||||
callLhs, "vkEnc->" + api.name, [p.paramName for p in parameters] + ["true /* do lock */"])
|
||||
callLhs, "vkEnc->" + api.name, [p.paramName for p in api.parameters] + ["true /* do lock */"])
|
||||
|
||||
def genReturnExpression():
|
||||
retTypeName = api.getRetTypeExpr()
|
||||
# Set the createParam output, if applicable
|
||||
createParam = getCreateParam(api)
|
||||
if createParam and handleTranslationRequired(createParam.typeName):
|
||||
if 1 != createParam.pointerIndirectionLevels:
|
||||
print("ERROR: Unhandled pointerIndirectionLevels != 1 in return for API %s (createParam %s)" % api.name, createParam.paramName)
|
||||
raise
|
||||
# ex: *pBuffer = gfxstream_vk_buffer_to_handle(gfxstream_buffer)
|
||||
cgen.funcCall(
|
||||
"*%s" % createParam.paramName,
|
||||
"%s_to_handle" % typeNameToObjectType(createParam.typeName),
|
||||
[paramNameToObjectName(createParam.paramName)]
|
||||
)
|
||||
if name in POSTPROCESSES:
|
||||
cgen.line(POSTPROCESSES[name])
|
||||
|
||||
if retTypeName != "void":
|
||||
cgen.stmt("return %s" % api.getRetVarExpr())
|
||||
cgen.stmt("return %s" % retVar)
|
||||
|
||||
def genGfxstreamEntry(declareResources=True):
|
||||
cgen.stmt("AEMU_SCOPED_TRACE(\"%s\")" % api.name)
|
||||
# declare returnVar
|
||||
retTypeName = api.getRetTypeExpr()
|
||||
retVar = api.getRetVarExpr()
|
||||
if retVar:
|
||||
cgen.stmt("%s %s = (%s)0" % (retTypeName, retVar, retTypeName))
|
||||
# Check non-null destroy param for free/destroy calls
|
||||
destroyParam = getDestroyParam(api)
|
||||
if destroyParam:
|
||||
cgen.beginIf("VK_NULL_HANDLE == %s" % destroyParam.paramName)
|
||||
if api.getRetTypeExpr() != "void":
|
||||
cgen.stmt("return %s" % api.getRetVarExpr())
|
||||
else:
|
||||
cgen.stmt("return")
|
||||
|
||||
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()
|
||||
# Translate handles
|
||||
genGetGfxstreamHandles()
|
||||
# Translation/creation of objects
|
||||
createdObject = genCreateGfxstreamObjects()
|
||||
# Make encoder/resource-tracker call
|
||||
if retVar and createdObject:
|
||||
cgen.beginIf("%s == %s" % (SUCCESS_VAL[retTypeName][0], retVar))
|
||||
else:
|
||||
cgen.beginBlock()
|
||||
genEncoderOrResourceTrackerCall()
|
||||
print("About to generate a frivolous api!: dynCheck entry: %s" % api.name)
|
||||
raise
|
||||
genEncoderOrResourceTrackerCall(cgen, api, declareResources = False)
|
||||
cgen.endBlock()
|
||||
# Destroy gfxstream objects
|
||||
genDestroyGfxstreamObjects()
|
||||
# Set output / return variables
|
||||
genReturnExpression()
|
||||
|
||||
api_entry = api.withModifiedName("gfxstream_vk_" + api.name[2:])
|
||||
if api.name not in HANDWRITTEN_ENTRY_POINTS:
|
||||
cgen.line(self.cgen.makeFuncProto(api_entry))
|
||||
cgen.beginBlock()
|
||||
genGfxstreamEntry()
|
||||
cgen.endBlock()
|
||||
self.module.appendImpl(cgen.swapCode())
|
||||
|
||||
|
||||
def onEnd(self,):
|
||||
pass
|
||||
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"
|
||||
|
@@ -334,6 +334,26 @@ class IOStream;
|
||||
#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) || defined(__Fuchsia__)
|
||||
#undef VK_ANDROID_native_buffer
|
||||
#endif
|
||||
"""
|
||||
|
||||
mesaFunctableImplInclude = """
|
||||
#include "VkEncoder.h"
|
||||
#include "../OpenglSystemCommon/HostConnection.h"
|
||||
#include "ResourceTracker.h"
|
||||
#include "gfxstream_vk_entrypoints.h"
|
||||
#include "gfxstream_vk_private.h"
|
||||
|
||||
@@ -351,6 +371,7 @@ class IOStream;
|
||||
#undef VK_ANDROID_native_buffer
|
||||
#endif
|
||||
"""
|
||||
|
||||
marshalIncludeGuest = """
|
||||
#include "goldfish_vk_marshaling_guest.h"
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
@@ -593,7 +614,8 @@ class BumpPool;
|
||||
suppressVulkanHeaders=True,
|
||||
extraHeader=createVkExtensionStructureTypePreamble('VK_GOOGLE_GFXSTREAM'))
|
||||
|
||||
self.addGuestEncoderModule("func_table", extraImpl=functableImplInclude, implOnly = True,
|
||||
self.addGuestEncoderModule("func_table", extraImpl=functableImplInclude)
|
||||
self.addGuestEncoderModule("mesa_func_table", extraImpl=mesaFunctableImplInclude, implOnly = True,
|
||||
useNamespace = False)
|
||||
|
||||
self.addWrapper(cereal.VulkanEncoder, "VkEncoder")
|
||||
@@ -604,6 +626,7 @@ class BumpPool;
|
||||
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.VulkanMesaFuncTable, "mesa_func_table")
|
||||
self.addWrapper(cereal.VulkanGfxstreamStructureType,
|
||||
"vulkan_gfxstream_structure_type_guest")
|
||||
|
||||
|
@@ -4,65 +4,175 @@
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/hwvulkan.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vulkan/vk_icd.h>
|
||||
|
||||
#include "gfxstream_vk_entrypoints.h"
|
||||
#include "util/macros.h"
|
||||
#include "HostConnection.h"
|
||||
#include "ProcessPipe.h"
|
||||
#include "ResourceTracker.h"
|
||||
#include "VkEncoder.h"
|
||||
#include "func_table.h"
|
||||
|
||||
static int gfxstream_vk_hal_open(const struct hw_module_t* mod, const char* id,
|
||||
struct hw_device_t** dev);
|
||||
static int gfxstream_vk_hal_close(struct hw_device_t* dev);
|
||||
namespace {
|
||||
|
||||
static_assert(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC, "");
|
||||
#define VK_HOST_CONNECTION(ret) \
|
||||
HostConnection* hostCon = HostConnection::getOrCreate(kCapsetGfxStreamVulkan); \
|
||||
gfxstream::vk::VkEncoder* vkEnc = hostCon->vkEncoder(); \
|
||||
if (!vkEnc) { \
|
||||
ALOGE("vulkan: Failed to get Vulkan encoder\n"); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
hw_module_methods_t gfxstream_vk_hal_ops = {
|
||||
.open = gfxstream_vk_hal_open,
|
||||
HostConnection* getConnection(void) {
|
||||
auto hostCon = HostConnection::get();
|
||||
return hostCon;
|
||||
}
|
||||
|
||||
gfxstream::vk::VkEncoder* getVkEncoder(HostConnection* con) { return con->vkEncoder(); }
|
||||
|
||||
gfxstream::vk::ResourceTracker::ThreadingCallbacks threadingCallbacks = {
|
||||
.hostConnectionGetFunc = getConnection,
|
||||
.vkEncoderGetFunc = getVkEncoder,
|
||||
};
|
||||
|
||||
PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
|
||||
VkResult SetupInstance(void) {
|
||||
HostConnection* hostCon = HostConnection::getOrCreate(kCapsetGfxStreamVulkan);
|
||||
if (!hostCon) {
|
||||
ALOGE("vulkan: Failed to get host connection\n");
|
||||
return VK_ERROR_DEVICE_LOST;
|
||||
}
|
||||
|
||||
uint32_t noRenderControlEnc = 0;
|
||||
gfxstream::vk::ResourceTracker::get()->setupCaps(noRenderControlEnc);
|
||||
// Legacy goldfish path: could be deleted once goldfish not used guest-side.
|
||||
if (!noRenderControlEnc) {
|
||||
// Implicitly sets up sequence number
|
||||
ExtendedRCEncoderContext* rcEnc = hostCon->rcEncoder();
|
||||
if (!rcEnc) {
|
||||
ALOGE("vulkan: Failed to get renderControl encoder context\n");
|
||||
return VK_ERROR_DEVICE_LOST;
|
||||
}
|
||||
|
||||
gfxstream::vk::ResourceTracker::get()->setupFeatures(rcEnc->featureInfo_const());
|
||||
}
|
||||
|
||||
gfxstream::vk::ResourceTracker::get()->setThreadingCallbacks(threadingCallbacks);
|
||||
gfxstream::vk::ResourceTracker::get()->setSeqnoPtr(getSeqnoPtrForProcess());
|
||||
gfxstream::vk::VkEncoder* vkEnc = hostCon->vkEncoder();
|
||||
if (!vkEnc) {
|
||||
ALOGE("vulkan: Failed to get Vulkan encoder\n");
|
||||
return VK_ERROR_DEVICE_LOST;
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VKAPI_ATTR
|
||||
VkResult EnumerateInstanceExtensionProperties(const char* layer_name, uint32_t* count,
|
||||
VkExtensionProperties* properties) {
|
||||
VkResult res = SetupInstance();
|
||||
if (res != VK_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
|
||||
|
||||
res = gfxstream::vk::ResourceTracker::get()->on_vkEnumerateInstanceExtensionProperties(
|
||||
vkEnc, VK_SUCCESS, layer_name, count, properties);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
VKAPI_ATTR
|
||||
VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
|
||||
const VkAllocationCallbacks* allocator, VkInstance* out_instance) {
|
||||
VkResult res = SetupInstance();
|
||||
if (res != VK_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
|
||||
res = vkEnc->vkCreateInstance(create_info, nullptr, out_instance, true /* do lock */);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
|
||||
VK_HOST_CONNECTION(nullptr)
|
||||
|
||||
if (!strcmp(name, "vkGetDeviceProcAddr")) {
|
||||
return (PFN_vkVoidFunction)(GetDeviceProcAddr);
|
||||
}
|
||||
return (
|
||||
PFN_vkVoidFunction)(gfxstream::vk::goldfish_vulkan_get_device_proc_address(device, name));
|
||||
}
|
||||
|
||||
VKAPI_ATTR
|
||||
PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
|
||||
VkResult res = SetupInstance();
|
||||
if (res != VK_SUCCESS) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VK_HOST_CONNECTION(nullptr)
|
||||
|
||||
if (!strcmp(name, "vkEnumerateInstanceExtensionProperties")) {
|
||||
return (PFN_vkVoidFunction)EnumerateInstanceExtensionProperties;
|
||||
}
|
||||
if (!strcmp(name, "vkCreateInstance")) {
|
||||
return (PFN_vkVoidFunction)CreateInstance;
|
||||
}
|
||||
if (!strcmp(name, "vkGetDeviceProcAddr")) {
|
||||
return (PFN_vkVoidFunction)(GetDeviceProcAddr);
|
||||
}
|
||||
return (PFN_vkVoidFunction)(gfxstream::vk::goldfish_vulkan_get_instance_proc_address(instance,
|
||||
name));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int OpenDevice(const hw_module_t* /*module*/, const char* id, hw_device_t** device);
|
||||
int CloseDevice(struct hw_device_t* /*device*/);
|
||||
|
||||
hw_module_methods_t gfxstream_vulkan_module_methods = {
|
||||
.open = OpenDevice,
|
||||
};
|
||||
|
||||
__attribute__((visibility("default"))) hwvulkan_module_t HAL_MODULE_INFO_SYM = {
|
||||
.common =
|
||||
{
|
||||
.tag = HARDWARE_MODULE_TAG,
|
||||
.module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
|
||||
.hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),
|
||||
.hal_api_version = HARDWARE_HAL_API_VERSION,
|
||||
.id = HWVULKAN_HARDWARE_MODULE_ID,
|
||||
.name = "gfxstream Vulkan HAL",
|
||||
.author = "Android Open Source Project",
|
||||
.methods = &(gfxstream_vk_hal_ops),
|
||||
.name = "Gfxstream Vulkan Driver",
|
||||
.author = "The Android Open Source Project",
|
||||
.methods = &gfxstream_vulkan_module_methods,
|
||||
},
|
||||
};
|
||||
|
||||
static int gfxstream_vk_hal_open(const struct hw_module_t* mod, const char* id,
|
||||
struct hw_device_t** dev) {
|
||||
assert(mod == &HAL_MODULE_INFO_SYM.common);
|
||||
assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
|
||||
|
||||
hwvulkan_device_t* hal_dev = (hwvulkan_device_t*)calloc(1, sizeof(*hal_dev));
|
||||
if (!hal_dev) return -1;
|
||||
|
||||
*hal_dev = (hwvulkan_device_t){
|
||||
hwvulkan_device_t gfxstream_vulkan_device = {
|
||||
.common =
|
||||
{
|
||||
.tag = HARDWARE_DEVICE_TAG,
|
||||
.version = HWVULKAN_DEVICE_API_VERSION_0_1,
|
||||
.module = &HAL_MODULE_INFO_SYM.common,
|
||||
.close = gfxstream_vk_hal_close,
|
||||
.close = CloseDevice,
|
||||
},
|
||||
.EnumerateInstanceExtensionProperties = gfxstream_vk_EnumerateInstanceExtensionProperties,
|
||||
.CreateInstance = gfxstream_vk_CreateInstance,
|
||||
.GetInstanceProcAddr = gfxstream_vk_GetInstanceProcAddr,
|
||||
.EnumerateInstanceExtensionProperties = EnumerateInstanceExtensionProperties,
|
||||
.CreateInstance = CreateInstance,
|
||||
.GetInstanceProcAddr = GetInstanceProcAddr,
|
||||
};
|
||||
|
||||
*dev = &hal_dev->common;
|
||||
int OpenDevice(const hw_module_t* /*module*/, const char* id, hw_device_t** device) {
|
||||
if (strcmp(id, HWVULKAN_DEVICE_0) == 0) {
|
||||
*device = &gfxstream_vulkan_device.common;
|
||||
gfxstream::vk::ResourceTracker::get();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfxstream_vk_hal_close(struct hw_device_t* dev) {
|
||||
/* hwvulkan.h claims that hw_device_t::close() is never called. */
|
||||
return -1;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int CloseDevice(struct hw_device_t* /*device*/) { return 0; }
|
||||
|
Reference in New Issue
Block a user