diff --git a/src/imagination/vulkan/meson.build b/src/imagination/vulkan/meson.build index 245cd94f1a2..0444dfc57a4 100644 --- a/src/imagination/vulkan/meson.build +++ b/src/imagination/vulkan/meson.build @@ -37,12 +37,14 @@ pvr_files = files( 'pvr_formats.c', 'pvr_hw_pass.c', 'pvr_image.c', + 'pvr_instance.c', 'pvr_job_common.c', 'pvr_job_compute.c', 'pvr_job_context.c', 'pvr_job_render.c', 'pvr_job_transfer.c', 'pvr_pass.c', + 'pvr_physical_device.c', 'pvr_pipeline.c', 'pvr_transfer_frag_store.c', 'pvr_query.c', diff --git a/src/imagination/vulkan/pvr_blit.c b/src/imagination/vulkan/pvr_blit.c index f00770061a5..1dbeaca1426 100644 --- a/src/imagination/vulkan/pvr_blit.c +++ b/src/imagination/vulkan/pvr_blit.c @@ -39,6 +39,7 @@ #include "pvr_image.h" #include "pvr_job_transfer.h" #include "pvr_pass.h" +#include "pvr_physical_device.h" #include "pvr_types.h" #include "pvr_usc.h" #include "util/bitscan.h" diff --git a/src/imagination/vulkan/pvr_bo.c b/src/imagination/vulkan/pvr_bo.c index a321f358e61..4985feb2d82 100644 --- a/src/imagination/vulkan/pvr_bo.c +++ b/src/imagination/vulkan/pvr_bo.c @@ -42,6 +42,7 @@ #include "pvr_device.h" #include "pvr_dump.h" #include "pvr_macros.h" +#include "pvr_physical_device.h" #include "pvr_types.h" #include "pvr_util.h" #include "pvr_winsys.h" diff --git a/src/imagination/vulkan/pvr_border.c b/src/imagination/vulkan/pvr_border.c index 753ad1f3610..39d2b5d0ad8 100644 --- a/src/imagination/vulkan/pvr_border.c +++ b/src/imagination/vulkan/pvr_border.c @@ -34,6 +34,7 @@ #include "pvr_device_info.h" #include "pvr_formats.h" #include "pvr_macros.h" +#include "pvr_physical_device.h" #include "util/bitset.h" #include "util/format/u_format.h" #include "util/format/u_formats.h" diff --git a/src/imagination/vulkan/pvr_clear.c b/src/imagination/vulkan/pvr_clear.c index aa2ef6e1757..ce2f5f917fb 100644 --- a/src/imagination/vulkan/pvr_clear.c +++ b/src/imagination/vulkan/pvr_clear.c @@ -31,8 +31,9 @@ #include "pvr_cmd_buffer.h" #include "pvr_device.h" #include "pvr_pds.h" -#include "pvr_usc.h" +#include "pvr_physical_device.h" #include "pvr_types.h" +#include "pvr_usc.h" #include "vk_alloc.h" #include "vk_log.h" diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index fc05f5faadb..c6c1aee2610 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -53,6 +53,7 @@ #include "pvr_macros.h" #include "pvr_pass.h" #include "pvr_pds.h" +#include "pvr_physical_device.h" #include "pvr_pipeline.h" #include "pvr_query.h" #include "pvr_tex_state.h" diff --git a/src/imagination/vulkan/pvr_common.h b/src/imagination/vulkan/pvr_common.h index 1483a53e7df..b400a61c2cc 100644 --- a/src/imagination/vulkan/pvr_common.h +++ b/src/imagination/vulkan/pvr_common.h @@ -51,8 +51,6 @@ #include "vk_sampler.h" #include "vk_sync.h" -#define VK_VENDOR_ID_IMAGINATION 0x1010 - #define PVR_WORKGROUP_DIMENSIONS 3U #define PVR_SAMPLER_DESCRIPTOR_SIZE 4U diff --git a/src/imagination/vulkan/pvr_csb.c b/src/imagination/vulkan/pvr_csb.c index 01c2c556f24..a7e50948793 100644 --- a/src/imagination/vulkan/pvr_csb.c +++ b/src/imagination/vulkan/pvr_csb.c @@ -41,6 +41,7 @@ #include "pvr_device.h" #include "pvr_device_info.h" #include "pvr_macros.h" +#include "pvr_physical_device.h" #include "pvr_types.h" #include "util/list.h" #include "util/u_dynarray.h" diff --git a/src/imagination/vulkan/pvr_descriptor_set.c b/src/imagination/vulkan/pvr_descriptor_set.c index dfc90ed65e3..e00ad873879 100644 --- a/src/imagination/vulkan/pvr_descriptor_set.c +++ b/src/imagination/vulkan/pvr_descriptor_set.c @@ -37,6 +37,7 @@ #include "pvr_device.h" #include "pvr_entrypoints.h" #include "pvr_image.h" +#include "pvr_physical_device.h" #include "pvr_types.h" #include "util/compiler.h" #include "util/list.h" diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index d18a7a53ef7..d5511602fba 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -38,14 +38,9 @@ #include #include #include -#include #include -#include -#include "git_sha1.h" #include "hwdef/rogue_hw_utils.h" -#include "pco/pco.h" -#include "pco/pco_data.h" #include "pco_uscgen_programs.h" #include "pvr_bo.h" #include "pvr_border.h" @@ -55,17 +50,18 @@ #include "pvr_csb.h" #include "pvr_csb_enum_helpers.h" #include "pvr_debug.h" -#include "pvr_device_info.h" #include "pvr_dump_info.h" #include "pvr_entrypoints.h" #include "pvr_framebuffer.h" #include "pvr_hw_pass.h" #include "pvr_image.h" +#include "pvr_instance.h" #include "pvr_job_render.h" #include "pvr_limits.h" #include "pvr_macros.h" #include "pvr_pass.h" #include "pvr_pds.h" +#include "pvr_physical_device.h" #include "pvr_query.h" #include "pvr_queue.h" #include "pvr_robustness.h" @@ -75,14 +71,12 @@ #include "pvr_util.h" #include "pvr_winsys.h" #include "pvr_wsi.h" -#include "util/build_id.h" #include "util/disk_cache.h" #include "util/log.h" #include "util/macros.h" #include "util/mesa-sha1.h" #include "util/os_misc.h" #include "util/u_math.h" -#include "vk_alloc.h" #include "vk_device_memory.h" #include "vk_extensions.h" #include "vk_log.h" @@ -126,1433 +120,6 @@ #define PVR_SUBALLOCATOR_USC_SIZE (128 * 1024) #define PVR_SUBALLOCATOR_VIS_TEST_SIZE (128 * 1024) -/* Minimum required by the Vulkan 1.1 spec (see Table 32. Required Limits) */ -#define PVR_MAX_MEMORY_ALLOCATION_SIZE (1ull << 30) - -struct pvr_drm_device_config { - struct pvr_drm_device_info { - const char *name; - size_t len; - } render, display; -}; - -#define DEF_CONFIG(render_, display_) \ - { \ - .render = { .name = render_, .len = sizeof(render_) - 1 }, \ - .display = { .name = display_, .len = sizeof(display_) - 1 }, \ - } - -/* This is the list of supported DRM render/display driver configs. */ -static const struct pvr_drm_device_config pvr_drm_configs[] = { - DEF_CONFIG("mediatek,mt8173-gpu", "mediatek-drm"), - DEF_CONFIG("ti,am62-gpu", "ti,am625-dss"), - DEF_CONFIG("ti,j721s2-gpu", "ti,j721e-dss"), -}; - -#undef DEF_CONFIG - -static const struct vk_instance_extension_table pvr_instance_extensions = { - .KHR_device_group_creation = true, - .KHR_display = PVR_USE_WSI_PLATFORM_DISPLAY, - .KHR_external_fence_capabilities = true, - .KHR_external_memory_capabilities = true, - .KHR_external_semaphore_capabilities = true, - .KHR_get_display_properties2 = PVR_USE_WSI_PLATFORM_DISPLAY, - .KHR_get_physical_device_properties2 = true, - .KHR_get_surface_capabilities2 = PVR_USE_WSI_PLATFORM, - .KHR_surface = PVR_USE_WSI_PLATFORM, -#ifdef VK_USE_PLATFORM_WAYLAND_KHR - .KHR_wayland_surface = true, -#endif - .EXT_debug_report = true, - .EXT_debug_utils = true, -#ifndef VK_USE_PLATFORM_WIN32_KHR - .EXT_headless_surface = PVR_USE_WSI_PLATFORM && false, -#endif -}; - -static void pvr_physical_device_get_supported_extensions( - struct vk_device_extension_table *extensions) -{ - *extensions = (struct vk_device_extension_table){ - .KHR_bind_memory2 = true, - .KHR_buffer_device_address = true, - .KHR_copy_commands2 = true, - .KHR_create_renderpass2 = true, - .KHR_dedicated_allocation = true, - .KHR_depth_stencil_resolve = true, - .KHR_descriptor_update_template = true, - .KHR_device_group = true, - .KHR_driver_properties = true, - .KHR_external_fence = true, - .KHR_external_fence_fd = true, - .KHR_external_memory = true, - .KHR_external_memory_fd = true, - .KHR_external_semaphore = PVR_USE_WSI_PLATFORM, - .KHR_external_semaphore_fd = PVR_USE_WSI_PLATFORM, - .KHR_format_feature_flags2 = false, - .KHR_get_memory_requirements2 = true, - .KHR_image_format_list = true, - .KHR_imageless_framebuffer = true, - .KHR_index_type_uint8 = false, - .KHR_line_rasterization = true, - .KHR_maintenance1 = true, - .KHR_maintenance2 = true, - .KHR_maintenance3 = true, - .KHR_map_memory2 = true, - .KHR_multiview = true, - .KHR_present_id2 = PVR_USE_WSI_PLATFORM, - .KHR_present_wait2 = PVR_USE_WSI_PLATFORM, - .KHR_relaxed_block_layout = true, - .KHR_robustness2 = true, - .KHR_sampler_mirror_clamp_to_edge = true, - .KHR_separate_depth_stencil_layouts = true, - .KHR_shader_draw_parameters = true, - .KHR_shader_expect_assume = false, - .KHR_shader_float_controls = true, - .KHR_shader_non_semantic_info = true, - .KHR_shader_relaxed_extended_instruction = true, - .KHR_shader_subgroup_extended_types = true, - .KHR_shader_terminate_invocation = true, - .KHR_spirv_1_4 = true, - .KHR_storage_buffer_storage_class = true, - .KHR_swapchain = PVR_USE_WSI_PLATFORM, - .KHR_swapchain_mutable_format = PVR_USE_WSI_PLATFORM, - .KHR_timeline_semaphore = true, - .KHR_uniform_buffer_standard_layout = true, - .KHR_vertex_attribute_divisor = true, - .KHR_zero_initialize_workgroup_memory = false, - .EXT_border_color_swizzle = true, - .EXT_color_write_enable = true, - .EXT_custom_border_color = true, - .EXT_depth_clamp_zero_one = true, - .EXT_depth_clip_enable = true, - .EXT_extended_dynamic_state = true, - .EXT_extended_dynamic_state2 = true, - .EXT_extended_dynamic_state3 = true, - .EXT_external_memory_dma_buf = true, - .EXT_host_query_reset = true, - .EXT_image_2d_view_of_3d = true, - .EXT_index_type_uint8 = false, - .EXT_line_rasterization = true, - .EXT_map_memory_placed = true, - .EXT_physical_device_drm = true, - .EXT_private_data = true, - .EXT_provoking_vertex = true, - .EXT_queue_family_foreign = true, - .EXT_robustness2 = true, - .EXT_scalar_block_layout = true, - .EXT_separate_stencil_usage = true, - .EXT_shader_demote_to_helper_invocation = true, - .EXT_shader_replicated_composites = true, - .EXT_texel_buffer_alignment = false, - .EXT_tooling_info = true, - .EXT_vertex_attribute_divisor = true, - .EXT_zero_initialize_device_memory = true, - }; -} - -static void pvr_physical_device_get_supported_features( - const struct pvr_device_info *const dev_info, - struct vk_features *const features) -{ - *features = (struct vk_features){ - /* Vulkan 1.0 */ - .robustBufferAccess = true, - .fullDrawIndexUint32 = false, - .imageCubeArray = true, - .independentBlend = true, - .geometryShader = false, - .tessellationShader = false, - .sampleRateShading = true, - .dualSrcBlend = false, - .logicOp = true, - .multiDrawIndirect = false, - .drawIndirectFirstInstance = true, - .depthClamp = false, - .depthBiasClamp = false, - .fillModeNonSolid = false, - .depthBounds = false, - .wideLines = false, - .largePoints = true, - .alphaToOne = true, - .multiViewport = false, - .samplerAnisotropy = true, - .textureCompressionETC2 = true, - .textureCompressionASTC_LDR = false, - .textureCompressionBC = false, - .occlusionQueryPrecise = false, - .pipelineStatisticsQuery = false, - .vertexPipelineStoresAndAtomics = false, - .fragmentStoresAndAtomics = false, - .shaderTessellationAndGeometryPointSize = false, - .shaderImageGatherExtended = false, - .shaderStorageImageExtendedFormats = true, - .shaderStorageImageMultisample = false, - .shaderStorageImageReadWithoutFormat = true, - .shaderStorageImageWriteWithoutFormat = true, - .shaderUniformBufferArrayDynamicIndexing = false, - .shaderSampledImageArrayDynamicIndexing = false, - .shaderStorageBufferArrayDynamicIndexing = false, - .shaderStorageImageArrayDynamicIndexing = false, - .shaderClipDistance = true, - .shaderCullDistance = true, - .shaderFloat64 = false, - .shaderInt64 = false, - .shaderInt16 = false, - .shaderResourceResidency = false, - .shaderResourceMinLod = false, - .sparseBinding = false, - .sparseResidencyBuffer = false, - .sparseResidencyImage2D = false, - .sparseResidencyImage3D = false, - .sparseResidency2Samples = false, - .sparseResidency4Samples = false, - .sparseResidency8Samples = false, - .sparseResidency16Samples = false, - .sparseResidencyAliased = false, - .variableMultisampleRate = false, - .inheritedQueries = false, - - /* Vulkan 1.1 */ - .storageBuffer16BitAccess = false, - .uniformAndStorageBuffer16BitAccess = false, - .storagePushConstant16 = false, - .storageInputOutput16 = false, - .variablePointers = false, - .protectedMemory = false, - .samplerYcbcrConversion = false, - - /* Vulkan 1.2 */ - .samplerMirrorClampToEdge = false, - .drawIndirectCount = false, - .storageBuffer8BitAccess = false, - .uniformAndStorageBuffer8BitAccess = false, - .storagePushConstant8 = false, - .shaderBufferInt64Atomics = false, - .shaderSharedInt64Atomics = false, - .shaderFloat16 = false, - .shaderInt8 = false, - .descriptorIndexing = false, - .shaderInputAttachmentArrayDynamicIndexing = false, - .shaderUniformTexelBufferArrayDynamicIndexing = false, - .shaderStorageTexelBufferArrayDynamicIndexing = false, - .shaderUniformBufferArrayNonUniformIndexing = false, - .shaderSampledImageArrayNonUniformIndexing = false, - .shaderStorageBufferArrayNonUniformIndexing = false, - .shaderStorageImageArrayNonUniformIndexing = false, - .shaderInputAttachmentArrayNonUniformIndexing = false, - .shaderUniformTexelBufferArrayNonUniformIndexing = false, - .shaderStorageTexelBufferArrayNonUniformIndexing = false, - .descriptorBindingUniformBufferUpdateAfterBind = false, - .descriptorBindingSampledImageUpdateAfterBind = false, - .descriptorBindingStorageImageUpdateAfterBind = false, - .descriptorBindingStorageBufferUpdateAfterBind = false, - .descriptorBindingUniformTexelBufferUpdateAfterBind = false, - .descriptorBindingStorageTexelBufferUpdateAfterBind = false, - .descriptorBindingUpdateUnusedWhilePending = false, - .descriptorBindingPartiallyBound = false, - .descriptorBindingVariableDescriptorCount = false, - .runtimeDescriptorArray = false, - .samplerFilterMinmax = false, - .vulkanMemoryModel = false, - .vulkanMemoryModelDeviceScope = false, - .vulkanMemoryModelAvailabilityVisibilityChains = false, - .shaderOutputViewportIndex = false, - .shaderOutputLayer = false, - .subgroupBroadcastDynamicId = true, - - /* VK_EXT_depth_clamp_zero_one */ - .depthClampZeroOne = true, - - /* VK_KHR_index_type_uint8 */ - .indexTypeUint8 = true, - - /* Vulkan 1.2 / VK_KHR_imageless_framebuffer */ - .imagelessFramebuffer = true, - - /* Vulkan 1.1 / VK_KHR_multiview */ - .multiview = true, - .multiviewGeometryShader = false, - .multiviewTessellationShader = false, - - /* Vulkan 1.1 / VK_KHR_shader_draw_parameters */ - .shaderDrawParameters = true, - - /* Vulkan 1.2 / VK_KHR_timeline_semaphore */ - .timelineSemaphore = true, - - /* Vulkan 1.2 / VK_KHR_separate_depth_stencil_layouts */ - .separateDepthStencilLayouts = true, - - /* VK_KHR_shader_relaxed_extended_instruction */ - .shaderRelaxedExtendedInstruction = true, - - /* Vulkan 1.2 / VK_KHR_shader_subgroup_extended_types */ - .shaderSubgroupExtendedTypes = true, - - /* Vulkan 1.1 / VK_KHR_robustness2 */ - .robustBufferAccess2 = false, - .robustImageAccess2 = false, - .nullDescriptor = true, - - /* Vulkan 1.2 / VK_KHR_uniform_buffer_standard_layout */ - .uniformBufferStandardLayout = true, - - /* VK_EXT_color_write_enable */ - .colorWriteEnable = true, - - /* Vulkan 1.3 / VK_EXT_extended_dynamic_state */ - .extendedDynamicState = true, - - /* Vulkan 1.3 / VK_EXT_extended_dynamic_state2 */ - .extendedDynamicState2 = true, - .extendedDynamicState2LogicOp = false, - .extendedDynamicState2PatchControlPoints = false, - - /* VK_EXT_extended_dynamic_state3 */ - .extendedDynamicState3TessellationDomainOrigin = false, - .extendedDynamicState3DepthClampEnable = false, - .extendedDynamicState3PolygonMode = false, - .extendedDynamicState3RasterizationSamples = true, - .extendedDynamicState3SampleMask = true, - .extendedDynamicState3AlphaToCoverageEnable = true, - .extendedDynamicState3AlphaToOneEnable = true, - .extendedDynamicState3LogicOpEnable = false, - .extendedDynamicState3ColorBlendEnable = false, - .extendedDynamicState3ColorBlendEquation = false, - .extendedDynamicState3ColorWriteMask = false, - .extendedDynamicState3RasterizationStream = false, - .extendedDynamicState3ConservativeRasterizationMode = false, - .extendedDynamicState3ExtraPrimitiveOverestimationSize = false, - .extendedDynamicState3DepthClipEnable = false, - .extendedDynamicState3SampleLocationsEnable = false, - .extendedDynamicState3ColorBlendAdvanced = false, - .extendedDynamicState3ProvokingVertexMode = false, - .extendedDynamicState3LineRasterizationMode = false, - .extendedDynamicState3LineStippleEnable = false, - .extendedDynamicState3DepthClipNegativeOneToOne = false, - .extendedDynamicState3ViewportWScalingEnable = false, - .extendedDynamicState3ViewportSwizzle = false, - .extendedDynamicState3CoverageToColorEnable = false, - .extendedDynamicState3CoverageToColorLocation = false, - .extendedDynamicState3CoverageModulationMode = false, - .extendedDynamicState3CoverageModulationTableEnable = false, - .extendedDynamicState3CoverageModulationTable = false, - .extendedDynamicState3CoverageReductionMode = false, - .extendedDynamicState3RepresentativeFragmentTestEnable = false, - .extendedDynamicState3ShadingRateImageEnable = false, - - /* Vulkan 1.2 / VK_EXT_host_query_reset */ - .hostQueryReset = true, - - /* VK_EXT_image_2d_view_of_3d */ - .image2DViewOf3D = true, - .sampler2DViewOf3D = true, - - /* VK_EXT_map_memory_placed */ - .memoryMapPlaced = true, - .memoryMapRangePlaced = false, - .memoryUnmapReserve = true, - - /* Vulkan 1.3 / VK_EXT_private_data */ - .privateData = true, - - /* VK_EXT_provoking_vertex */ - .provokingVertexLast = true, - .transformFeedbackPreservesProvokingVertex = false, - - /* Vulkan 1.2 / VK_EXT_scalar_block_layout */ - .scalarBlockLayout = true, - - /* Vulkan 1.3 / VK_EXT_texel_buffer_alignment */ - .texelBufferAlignment = true, - - /* Vulkan 1.2 / VK_KHR_buffer_device_address */ - .bufferDeviceAddress = true, - .bufferDeviceAddressCaptureReplay = false, - .bufferDeviceAddressMultiDevice = false, - - /* VK_KHR_shader_expect_assume */ - .shaderExpectAssume = false, - - /* VK_EXT_shader_demote_to_helper_invocation */ - .shaderDemoteToHelperInvocation = true, - - /* VK_EXT_shader_replicated_composites */ - .shaderReplicatedComposites = true, - - /* VK_KHR_shader_terminate_invocation */ - .shaderTerminateInvocation = true, - - /* VK_KHR_present_id2 */ - .presentId2 = PVR_USE_WSI_PLATFORM, - - /* VK_KHR_present_wait2 */ - .presentWait2 = PVR_USE_WSI_PLATFORM, - - /* Vulkan 1.4 / VK_EXT_vertex_attribute_divisor / - VK_KHR_vertex_attribute_divisor */ - .vertexAttributeInstanceRateDivisor = true, - .vertexAttributeInstanceRateZeroDivisor = true, - - /* Vulkan 1.3 / VK_KHR_zero_initialize_workgroup_memory */ - .shaderZeroInitializeWorkgroupMemory = false, - - /* VK_EXT_border_color_swizzle */ - .borderColorSwizzle = true, - .borderColorSwizzleFromImage = true, - - /* VK_EXT_custom_border_color */ - .customBorderColors = true, - - /* VK_EXT_depth_clip_enable */ - .depthClipEnable = true, - - /* VK_KHR_line_rasterization */ - .bresenhamLines = true, - - /* VK_EXT_zero_initialize_device_memory */ - .zeroInitializeDeviceMemory = true, - }; -} - -static uint32_t get_api_version(void) -{ - const uint32_t version_override = vk_get_version_override(); - if (version_override) - return version_override; - - return VK_MAKE_API_VERSION(0, 1, 2, VK_HEADER_VERSION); -} - -static bool pvr_physical_device_get_properties( - const struct pvr_physical_device *const pdevice, - struct vk_properties *const properties) -{ - const struct pvr_device_info *const dev_info = &pdevice->dev_info; - const struct pvr_device_runtime_info *dev_runtime_info = - &pdevice->dev_runtime_info; - - /* Default value based on the minimum value found in all existing cores. */ - const uint32_t max_multisample = - PVR_GET_FEATURE_VALUE(dev_info, max_multisample, 4); - - UNUSED const uint32_t sub_pixel_precision = - PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format) ? 4U : 8U; - - UNUSED const uint32_t max_render_size = rogue_get_render_size_max(dev_info); - - UNUSED const uint32_t max_sample_bits = ((max_multisample << 1) - 1); - - UNUSED const uint32_t max_user_vertex_components = - pvr_get_max_user_vertex_output_components(dev_info); - - const bool usc_alu_roundingmode_rne = - PVR_HAS_FEATURE(dev_info, usc_alu_roundingmode_rne); - - /* The workgroup invocations are limited by the case where we have a compute - * barrier - each slot has a fixed number of invocations, the whole workgroup - * may need to span multiple slots. As each slot will WAIT at the barrier - * until the last invocation completes, all have to be schedulable at the - * same time. - * - * Typically all Rogue cores have 16 slots. Some of the smallest cores are - * reduced to 14. - * - * The compute barrier slot exhaustion scenario can be tested with: - * dEQP-VK.memory_model.message_passing*u32.coherent.fence_fence - * .atomicwrite*guard*comp - */ - - /* Default value based on the minimum value found in all existing cores. */ - const uint32_t usc_slots = PVR_GET_FEATURE_VALUE(dev_info, usc_slots, 14); - - /* Default value based on the minimum value found in all existing cores. */ - const uint32_t max_instances_per_pds_task = - PVR_GET_FEATURE_VALUE(dev_info, max_instances_per_pds_task, 32U); - - UNUSED const uint32_t max_compute_work_group_invocations = - (usc_slots * max_instances_per_pds_task >= 512U) ? 512U : 384U; - - assert(pdevice->memory.memoryHeapCount == 1); - const VkDeviceSize max_memory_alloc_size = - pdevice->memory.memoryHeaps[0].size; - - const uint32_t line_sub_pixel_precision_bits = - PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format) ? 4U : 8U; - - *properties = (struct vk_properties){ - /* Vulkan 1.0 */ - .apiVersion = get_api_version(), - .driverVersion = vk_get_driver_version(), - .vendorID = VK_VENDOR_ID_IMAGINATION, - .deviceID = dev_info->ident.device_id, - .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, - /* deviceName and pipelineCacheUUID are filled below .*/ - - .maxImageDimension1D = 4096U, - .maxImageDimension2D = 4096U, - .maxImageDimension3D = 256U, - .maxImageDimensionCube = 4096U, - .maxImageArrayLayers = 256U, - .maxTexelBufferElements = 64U * 1024U, - .maxUniformBufferRange = 16U * 1024U, - .maxStorageBufferRange = 128U * 1024U * 1024U, - .maxPushConstantsSize = 128U, - .maxMemoryAllocationCount = 4096U, - .maxSamplerAllocationCount = 4000U, - .bufferImageGranularity = 1U, - .sparseAddressSpaceSize = 0U, /* Requires sparseBinding */ - .maxBoundDescriptorSets = 4U, - .maxPerStageDescriptorSamplers = 16, - .maxPerStageDescriptorUniformBuffers = 12, - .maxPerStageDescriptorStorageBuffers = 4, - .maxPerStageDescriptorSampledImages = 16, - .maxPerStageDescriptorStorageImages = 4, - .maxPerStageDescriptorInputAttachments = 4, - .maxPerStageResources = 44, - .maxDescriptorSetSamplers = 3U * 16U, - .maxDescriptorSetUniformBuffers = 3U * 12U, - .maxDescriptorSetUniformBuffersDynamic = 8U, - .maxDescriptorSetStorageBuffers = 3U * 4U, - .maxDescriptorSetStorageBuffersDynamic = 4U, - .maxDescriptorSetSampledImages = 3U * 16U, - .maxDescriptorSetStorageImages = 3U * 4U, - .maxDescriptorSetInputAttachments = 4U, - - /* Vertex Shader Limits */ - .maxVertexInputAttributes = 16U, - .maxVertexInputBindings = 16U, - .maxVertexInputAttributeOffset = 2048U - 1U, - .maxVertexInputBindingStride = 2048U, - .maxVertexOutputComponents = 64U, - - /* Tessellation Limits */ - /* Requires tessellationShader */ - .maxTessellationGenerationLevel = 0U, - .maxTessellationPatchSize = 0U, - .maxTessellationControlPerVertexInputComponents = 0U, - .maxTessellationControlPerVertexOutputComponents = 0U, - .maxTessellationControlPerPatchOutputComponents = 0U, - .maxTessellationControlTotalOutputComponents = 0U, - .maxTessellationEvaluationInputComponents = 0U, - .maxTessellationEvaluationOutputComponents = 0U, - - /* Geometry Shader Limits */ - /* Requires geometryShader */ - .maxGeometryShaderInvocations = 0U, - .maxGeometryInputComponents = 0U, - .maxGeometryOutputComponents = 0U, - .maxGeometryOutputVertices = 0U, - .maxGeometryTotalOutputComponents = 0U, - - /* Fragment Shader Limits */ - .maxFragmentInputComponents = 64U, - .maxFragmentOutputAttachments = 4U, - .maxFragmentDualSrcAttachments = 0U, /* Requires dualSrcBlend */ - .maxFragmentCombinedOutputResources = 4U, - - /* Compute Shader Limits */ - .maxComputeSharedMemorySize = 16U * 1024U, - .maxComputeWorkGroupCount = { - [0] = (64U * 1024U) - 1, - [1] = (64U * 1024U) - 1, - [2] = (64U * 1024U) - 1, - }, - .maxComputeWorkGroupInvocations = 128U, - .maxComputeWorkGroupSize = { - [0] = 128U, - [1] = 128U, - [2] = 64U, - }, - - /* Rasterization Limits */ - .subPixelPrecisionBits = 4U, - .subTexelPrecisionBits = 8U, - .mipmapPrecisionBits = 8U, - - .maxDrawIndexedIndexValue = (1U << 24) - 1U, /* Requires fullDrawIndexUint32 */ - .maxDrawIndirectCount = 1U, /* Requires multiDrawIndirect */ - .maxSamplerLodBias = 16.0f, - .maxSamplerAnisotropy = 16.0f, /* Requires samplerAnisotropy */ - .maxViewports = 1U, /* Requires multiViewport */ - - .maxViewportDimensions[0] = 4096U, - .maxViewportDimensions[1] = 4096U, - .viewportBoundsRange[0] = -8192.0f, - .viewportBoundsRange[1] = 8191.0f, - - .viewportSubPixelBits = 0U, - .minMemoryMapAlignment = pdevice->ws->page_size, - .minTexelBufferOffsetAlignment = PVR_TEXEL_BUFFER_OFFSET_ALIGNMENT, - .minUniformBufferOffsetAlignment = PVR_UNIFORM_BUFFER_OFFSET_ALIGNMENT, - .minStorageBufferOffsetAlignment = PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT, - - .minTexelOffset = -8, - .maxTexelOffset = 7U, - - /* Requires shaderImageGatherExtended */ - .minTexelGatherOffset = 0, - .maxTexelGatherOffset = 0U, - - /* Requires sampleRateShading */ - .minInterpolationOffset = -0.5f, - .maxInterpolationOffset = 0.5f, - .subPixelInterpolationOffsetBits = 4U, - - .maxFramebufferWidth = 4096U, - .maxFramebufferHeight = 4096U, - .maxFramebufferLayers = 256U, - - .framebufferColorSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, - .framebufferDepthSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, - .framebufferStencilSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, - .framebufferNoAttachmentsSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, - .maxColorAttachments = 4U, - .sampledImageColorSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, - .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, - .sampledImageDepthSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, - .sampledImageStencilSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, - .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT, /* Requires shaderStorageImageMultisample */ - .maxSampleMaskWords = 1U, - .timestampComputeAndGraphics = false, - .timestampPeriod = 0.0f, - - .maxClipDistances = PVR_MAX_USER_PLANES, - .maxCullDistances = PVR_MAX_USER_PLANES, - .maxCombinedClipAndCullDistances = PVR_MAX_USER_PLANES, - - .discreteQueuePriorities = 2U, - - .pointSizeRange[0] = PVR_POINT_SIZE_RANGE_MIN, - .pointSizeRange[1] = PVR_POINT_SIZE_RANGE_MAX, - .pointSizeGranularity = PVR_POINT_SIZE_GRANULARITY, - - /* Requires wideLines */ - .lineWidthRange[0] = 1.0f, - .lineWidthRange[1] = 1.0f, - .lineWidthGranularity = 0.0f, - - .strictLines = false, - .standardSampleLocations = true, - .optimalBufferCopyOffsetAlignment = PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT, - .optimalBufferCopyRowPitchAlignment = PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT, - .nonCoherentAtomSize = 1U, - - /* Vulkan 1.1 */ - .subgroupSize = 1, - .subgroupSupportedStages = VK_SHADER_STAGE_COMPUTE_BIT, - .subgroupSupportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT, - .subgroupQuadOperationsInAllStages = false, - .protectedNoFault = false, - - /* Vulkan 1.2 */ - .maxUpdateAfterBindDescriptorsInAllPools = 0, - .shaderUniformBufferArrayNonUniformIndexingNative = false, - .shaderSampledImageArrayNonUniformIndexingNative = false, - .shaderStorageBufferArrayNonUniformIndexingNative = false, - .shaderStorageImageArrayNonUniformIndexingNative = false, - .shaderInputAttachmentArrayNonUniformIndexingNative = false, - .robustBufferAccessUpdateAfterBind = false, - .quadDivergentImplicitLod = false, - .maxPerStageDescriptorUpdateAfterBindSamplers = 0, - .maxPerStageDescriptorUpdateAfterBindUniformBuffers = 0, - .maxPerStageDescriptorUpdateAfterBindStorageBuffers = 0, - .maxPerStageDescriptorUpdateAfterBindSampledImages = 0, - .maxPerStageDescriptorUpdateAfterBindStorageImages = 0, - .maxPerStageDescriptorUpdateAfterBindInputAttachments = 0, - .maxPerStageUpdateAfterBindResources = 0, - .maxDescriptorSetUpdateAfterBindSamplers = 0, - .maxDescriptorSetUpdateAfterBindUniformBuffers = 0, - .maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = 0, - .maxDescriptorSetUpdateAfterBindStorageBuffers = 0, - .maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = 0, - .maxDescriptorSetUpdateAfterBindSampledImages = 0, - .maxDescriptorSetUpdateAfterBindStorageImages = 0, - .maxDescriptorSetUpdateAfterBindInputAttachments = 0, - .filterMinmaxSingleComponentFormats = false, - .filterMinmaxImageComponentMapping = false, - .framebufferIntegerColorSampleCounts = - VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, - - /* Vulkan 1.0 / VK_KHR_maintenance2 */ - .pointClippingBehavior = - VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY, - - /* Vulkan 1.1 / VK_KHR_maintenance3 */ - .maxPerSetDescriptors = PVR_MAX_DESCRIPTORS_PER_SET, - .maxMemoryAllocationSize = max_memory_alloc_size, - - /* Vulkan 1.1 / VK_KHR_multiview */ - .maxMultiviewViewCount = PVR_MAX_MULTIVIEW, - .maxMultiviewInstanceIndex = (1 << 27) - 1, - - /* Vulkan 1.2 / VK_KHR_driver_properties */ - .driverID = VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA, - .driverName = "Imagination open-source Mesa driver", - .driverInfo = "Mesa " PACKAGE_VERSION MESA_GIT_SHA1, - .conformanceVersion = { - .major = 1, - .minor = 3, - .subminor = 8, - .patch = 4, - }, - - /* VK_EXT_extended_dynamic_state3 */ - .dynamicPrimitiveTopologyUnrestricted = false, - - /* VK_EXT_map_memory_placed */ - .minPlacedMemoryMapAlignment = pdevice->ws->page_size, - - /* VK_EXT_provoking_vertex */ - .provokingVertexModePerPipeline = true, - .transformFeedbackPreservesTriangleFanProvokingVertex = false, - - /* Vulkan 1.1 / VK_KHR_robustness2 */ - .robustStorageBufferAccessSizeAlignment = PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT, - .robustUniformBufferAccessSizeAlignment = PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT, - - /* Vulkan 1.2 / VK_KHR_shader_float_controls */ - .denormBehaviorIndependence = - VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY, - .roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE, - .shaderSignedZeroInfNanPreserveFloat16 = true, - .shaderSignedZeroInfNanPreserveFloat32 = true, - .shaderSignedZeroInfNanPreserveFloat64 = true, - .shaderDenormPreserveFloat16 = true, - .shaderDenormPreserveFloat32 = false, - .shaderDenormPreserveFloat64 = true, - .shaderDenormFlushToZeroFloat16 = false, - .shaderDenormFlushToZeroFloat32 = false, - .shaderDenormFlushToZeroFloat64 = false, - .shaderRoundingModeRTEFloat16 = usc_alu_roundingmode_rne, - .shaderRoundingModeRTEFloat32 = usc_alu_roundingmode_rne, - .shaderRoundingModeRTEFloat64 = usc_alu_roundingmode_rne, - .shaderRoundingModeRTZFloat16 = !usc_alu_roundingmode_rne, - .shaderRoundingModeRTZFloat32 = !usc_alu_roundingmode_rne, - .shaderRoundingModeRTZFloat64 = !usc_alu_roundingmode_rne, - - /* Vulkan 1.2 / VK_KHR_timeline_semaphore */ - .maxTimelineSemaphoreValueDifference = UINT64_MAX, - - /* Vulkan 1.3 / VK_EXT_texel_buffer_alignment */ - .storageTexelBufferOffsetAlignmentBytes = PVR_TEXEL_BUFFER_OFFSET_ALIGNMENT, - .storageTexelBufferOffsetSingleTexelAlignment = true, - .uniformTexelBufferOffsetAlignmentBytes = PVR_TEXEL_BUFFER_OFFSET_ALIGNMENT, - .uniformTexelBufferOffsetSingleTexelAlignment = false, - - /* Vulkan 1.4 / VK_EXT_vertex_attribute_divisor / VK_KHR_vertex_attribute_divisor */ - .maxVertexAttribDivisor = UINT32_MAX, - .supportsNonZeroFirstInstance = true, - - /* VK_EXT_custom_border_color */ - .maxCustomBorderColorSamplers = PVR_BORDER_COLOR_TABLE_NR_CUSTOM_ENTRIES, - - /* VkPhysicalDeviceDrmPropertiesEXT */ - .drmHasPrimary = true, - .drmPrimaryMajor = (int64_t) major(pdevice->primary_devid), - .drmPrimaryMinor = (int64_t) minor(pdevice->primary_devid), - .drmHasRender = true, - .drmRenderMajor = (int64_t) major(pdevice->render_devid), - .drmRenderMinor = (int64_t) minor(pdevice->render_devid), - - /* Vulkan 1.2 / VK_KHR_depth_stencil_resolve */ - .supportedDepthResolveModes = - VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, - .supportedStencilResolveModes = - VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, - .independentResolveNone = true, - .independentResolve = true, - - /* VK_KHR_line_rasterization */ - .lineSubPixelPrecisionBits = line_sub_pixel_precision_bits, - }; - - if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) { - snprintf(properties->deviceName, - sizeof(properties->deviceName), - "PowerVR %s %s MC%u", - dev_info->ident.series_name, - dev_info->ident.public_name, - dev_runtime_info->core_count); - } else { - snprintf(properties->deviceName, - sizeof(properties->deviceName), - "PowerVR %s %s", - dev_info->ident.series_name, - dev_info->ident.public_name); - } - - return true; -} - -VkResult pvr_EnumerateInstanceVersion(uint32_t *pApiVersion) -{ - *pApiVersion = VK_MAKE_API_VERSION(0, 1, 4, VK_HEADER_VERSION); - return VK_SUCCESS; -} - -VkResult -pvr_EnumerateInstanceExtensionProperties(const char *pLayerName, - uint32_t *pPropertyCount, - VkExtensionProperties *pProperties) -{ - if (pLayerName) - return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); - - return vk_enumerate_instance_extension_properties(&pvr_instance_extensions, - pPropertyCount, - pProperties); -} - -static bool pvr_physical_device_setup_pipeline_cache( - struct pvr_physical_device *const pdevice) -{ -#ifdef ENABLE_SHADER_CACHE - const struct pvr_instance *instance = pdevice->instance; - char device_id[SHA1_DIGEST_LENGTH * 2 + 1]; - char driver_id[SHA1_DIGEST_LENGTH * 2 + 1]; - - _mesa_sha1_format(device_id, pdevice->device_uuid); - _mesa_sha1_format(driver_id, instance->driver_build_sha); - - pdevice->vk.disk_cache = disk_cache_create(device_id, driver_id, 0U); - return !!pdevice->vk.disk_cache; -#else - return true; -#endif /* ENABLE_SHADER_CACHE */ -} - -static void pvr_physical_device_free_pipeline_cache( - struct pvr_physical_device *const pdevice) -{ -#ifdef ENABLE_SHADER_CACHE - if (!pdevice->vk.disk_cache) - return; - - disk_cache_destroy(pdevice->vk.disk_cache); - pdevice->vk.disk_cache = NULL; -#else - assert(pdevice->vk.disk_cache); -#endif /* ENABLE_SHADER_CACHE */ -} - -static void pvr_physical_device_destroy(struct vk_physical_device *vk_pdevice) -{ - struct pvr_physical_device *pdevice = - container_of(vk_pdevice, struct pvr_physical_device, vk); - - /* Be careful here. The device might not have been initialized. This can - * happen since initialization is done in vkEnumeratePhysicalDevices() but - * finish is done in vkDestroyInstance(). Make sure that you check for NULL - * before freeing or that the freeing functions accept NULL pointers. - */ - - ralloc_free(pdevice->pco_ctx); - - pvr_wsi_finish(pdevice); - - pvr_physical_device_free_pipeline_cache(pdevice); - - if (pdevice->ws) - pvr_winsys_destroy(pdevice->ws); - - vk_free(&pdevice->vk.instance->alloc, pdevice->render_path); - vk_free(&pdevice->vk.instance->alloc, pdevice->display_path); - - vk_physical_device_finish(&pdevice->vk); - - vk_free(&pdevice->vk.instance->alloc, pdevice); -} - -void pvr_DestroyInstance(VkInstance _instance, - const VkAllocationCallbacks *pAllocator) -{ - VK_FROM_HANDLE(pvr_instance, instance, _instance); - - if (!instance) - return; - - VG(VALGRIND_DESTROY_MEMPOOL(instance)); - - vk_instance_finish(&instance->vk); - vk_free(&instance->vk.alloc, instance); -} - -static uint64_t pvr_compute_heap_size(void) -{ - /* Query the total ram from the system */ - uint64_t total_ram; - if (!os_get_total_physical_memory(&total_ram)) - return 0; - - if (total_ram < PVR_MAX_MEMORY_ALLOCATION_SIZE) { - mesa_logw( - "Warning: The available RAM is below the minimum required by the Vulkan specification!"); - } - - /* We don't want to burn too much ram with the GPU. If the user has 4GiB - * or less, we use at most half. If they have more than 4GiB, we use 3/4. - */ - uint64_t available_ram; - if (total_ram <= 4ULL * 1024ULL * 1024ULL * 1024ULL) - available_ram = total_ram / 2U; - else - available_ram = total_ram * 3U / 4U; - - return MAX2(available_ram, PVR_MAX_MEMORY_ALLOCATION_SIZE); -} - -static void -pvr_get_device_uuid(const struct pvr_device_info *dev_info, - uint8_t uuid_out[const static SHA1_DIGEST_LENGTH]) -{ - uint64_t bvnc = pvr_get_packed_bvnc(dev_info); - static const char *device_str = "pvr"; - struct mesa_sha1 sha1_ctx; - - _mesa_sha1_init(&sha1_ctx); - _mesa_sha1_update(&sha1_ctx, device_str, strlen(device_str)); - _mesa_sha1_update(&sha1_ctx, &bvnc, sizeof(bvnc)); - _mesa_sha1_final(&sha1_ctx, uuid_out); -} - -static void -pvr_get_cache_uuid(const struct pvr_physical_device *const pdevice, - uint8_t uuid_out[const static SHA1_DIGEST_LENGTH]) -{ - const struct pvr_instance *instance = pdevice->instance; - static const char *cache_str = "cache"; - struct mesa_sha1 sha1_ctx; - - _mesa_sha1_init(&sha1_ctx); - _mesa_sha1_update(&sha1_ctx, cache_str, strlen(cache_str)); - _mesa_sha1_update(&sha1_ctx, - pdevice->device_uuid, - sizeof(pdevice->device_uuid)); - _mesa_sha1_update(&sha1_ctx, - instance->driver_build_sha, - sizeof(instance->driver_build_sha)); - _mesa_sha1_final(&sha1_ctx, uuid_out); -} - -static void -pvr_physical_device_setup_uuids(struct pvr_physical_device *const pdevice) -{ - const struct pvr_instance *instance = pdevice->instance; - - pvr_get_device_uuid(&pdevice->dev_info, pdevice->device_uuid); - pvr_get_cache_uuid(pdevice, pdevice->cache_uuid); - - memcpy(pdevice->vk.properties.driverUUID, - instance->driver_build_sha, - sizeof(pdevice->vk.properties.driverUUID)); - - memcpy(pdevice->vk.properties.deviceUUID, - pdevice->device_uuid, - sizeof(pdevice->vk.properties.deviceUUID)); - - memcpy(pdevice->vk.properties.pipelineCacheUUID, - pdevice->cache_uuid, - sizeof(pdevice->vk.properties.pipelineCacheUUID)); - - memcpy(pdevice->vk.properties.shaderBinaryUUID, - pdevice->cache_uuid, - sizeof(pdevice->vk.properties.shaderBinaryUUID)); -} - -static bool pvr_device_is_conformant(const struct pvr_device_info *info) -{ - const uint64_t bvnc = pvr_get_packed_bvnc(info); - switch (bvnc) { - case PVR_BVNC_PACK(36, 53, 104, 796): - return true; - - default: - break; - } - - return false; -} - -static VkResult pvr_physical_device_init(struct pvr_physical_device *pdevice, - struct pvr_instance *instance, - drmDevicePtr drm_render_device, - drmDevicePtr drm_display_device) -{ - struct vk_physical_device_dispatch_table dispatch_table; - struct vk_device_extension_table supported_extensions; - struct vk_properties supported_properties; - struct vk_features supported_features; - struct pvr_winsys *ws; - struct stat primary_stat = { 0 }, render_stat = { 0 }; - char *primary_path; - char *display_path; - char *render_path; - VkResult result; - - render_path = vk_strdup(&instance->vk.alloc, - drm_render_device->nodes[DRM_NODE_RENDER], - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (!render_path) { - result = VK_ERROR_OUT_OF_HOST_MEMORY; - goto err_out; - } - - if (instance->vk.enabled_extensions.KHR_display) { - display_path = vk_strdup(&instance->vk.alloc, - drm_display_device->nodes[DRM_NODE_PRIMARY], - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (!display_path) { - result = VK_ERROR_OUT_OF_HOST_MEMORY; - goto err_vk_free_render_path; - } - } else { - display_path = NULL; - } - - primary_path = drm_render_device->nodes[DRM_NODE_PRIMARY]; - if (stat(primary_path, &primary_stat) != 0) { - result = vk_errorf(instance, - VK_ERROR_INITIALIZATION_FAILED, - "failed to stat DRM primary node %s", - primary_path); - goto err_vk_free_display_path; - } - pdevice->primary_devid = primary_stat.st_rdev; - - if (stat(render_path, &render_stat) != 0) { - result = vk_errorf(instance, - VK_ERROR_INITIALIZATION_FAILED, - "failed to stat DRM render node %s", - render_path); - goto err_vk_free_display_path; - } - pdevice->render_devid = render_stat.st_rdev; - - result = - pvr_winsys_create(render_path, display_path, &instance->vk.alloc, &ws); - if (result != VK_SUCCESS) - goto err_vk_free_display_path; - - pdevice->instance = instance; - pdevice->render_path = render_path; - pdevice->display_path = display_path; - pdevice->ws = ws; - - result = ws->ops->device_info_init(ws, - &pdevice->dev_info, - &pdevice->dev_runtime_info); - if (result != VK_SUCCESS) - goto err_pvr_winsys_destroy; - - if (!pvr_device_is_conformant(&pdevice->dev_info)) { - if (!os_get_option("PVR_I_WANT_A_BROKEN_VULKAN_DRIVER")) { - result = vk_errorf(instance, - VK_ERROR_INCOMPATIBLE_DRIVER, - "WARNING: powervr is not a conformant Vulkan " - "implementation for %s. Pass " - "PVR_I_WANT_A_BROKEN_VULKAN_DRIVER=1 if you know " - "what you're doing.", - pdevice->dev_info.ident.public_name); - goto err_pvr_winsys_destroy; - } - - vk_warn_non_conformant_implementation("powervr"); - } - - /* Setup available memory heaps and types */ - pdevice->memory.memoryHeapCount = 1; - pdevice->memory.memoryHeaps[0].size = pvr_compute_heap_size(); - pdevice->memory.memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; - - pdevice->memory.memoryTypeCount = 1; - pdevice->memory.memoryTypes[0].propertyFlags = - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - pdevice->memory.memoryTypes[0].heapIndex = 0; - - pvr_physical_device_get_supported_extensions(&supported_extensions); - pvr_physical_device_get_supported_features(&pdevice->dev_info, - &supported_features); - if (!pvr_physical_device_get_properties(pdevice, &supported_properties)) { - result = vk_errorf(instance, - VK_ERROR_INITIALIZATION_FAILED, - "Failed to collect physical device properties"); - goto err_pvr_winsys_destroy; - } - - vk_physical_device_dispatch_table_from_entrypoints( - &dispatch_table, - &pvr_physical_device_entrypoints, - true); - - vk_physical_device_dispatch_table_from_entrypoints( - &dispatch_table, - &wsi_physical_device_entrypoints, - false); - - result = vk_physical_device_init(&pdevice->vk, - &instance->vk, - &supported_extensions, - &supported_features, - &supported_properties, - &dispatch_table); - if (result != VK_SUCCESS) - goto err_pvr_winsys_destroy; - - pvr_physical_device_setup_uuids(pdevice); - - if (!pvr_physical_device_setup_pipeline_cache(pdevice)) { - result = vk_errorf(NULL, - VK_ERROR_INITIALIZATION_FAILED, - "Failed to get driver build sha."); - goto err_vk_physical_device_finish; - } - - pdevice->vk.supported_sync_types = ws->sync_types; - - pdevice->pco_ctx = pco_ctx_create(&pdevice->dev_info, NULL); - if (!pdevice->pco_ctx) { - result = vk_errorf(instance, - VK_ERROR_INITIALIZATION_FAILED, - "Failed to initialize PCO compiler context"); - goto err_free_pipeline_cache; - } - pco_ctx_setup_usclib(pdevice->pco_ctx, - pco_usclib_0_nir, - sizeof(pco_usclib_0_nir)); - - result = pvr_wsi_init(pdevice); - if (result != VK_SUCCESS) { - vk_error(instance, result); - goto err_free_pco_ctx; - } - - return VK_SUCCESS; - -err_free_pco_ctx: - ralloc_free(pdevice->pco_ctx); - -err_free_pipeline_cache: - pvr_physical_device_free_pipeline_cache(pdevice); - -err_vk_physical_device_finish: - vk_physical_device_finish(&pdevice->vk); - -err_pvr_winsys_destroy: - pvr_winsys_destroy(ws); - -err_vk_free_display_path: - vk_free(&instance->vk.alloc, display_path); - -err_vk_free_render_path: - vk_free(&instance->vk.alloc, render_path); - -err_out: - return result; -} - -static VkResult pvr_get_drm_devices(void *const obj, - drmDevicePtr *const devices, - const int max_devices, - int *const num_devices_out) -{ - int ret = drmGetDevices2(0, devices, max_devices); - if (ret < 0) { - return vk_errorf(obj, - VK_ERROR_INITIALIZATION_FAILED, - "Failed to enumerate drm devices (errno %d: %s)", - -ret, - strerror(-ret)); - } - - if (num_devices_out) - *num_devices_out = ret; - - return VK_SUCCESS; -} - -static bool -pvr_drm_device_compatible(const struct pvr_drm_device_info *const info, - drmDevice *const drm_dev) -{ - char **const compatible = drm_dev->deviceinfo.platform->compatible; - - for (char **compat = compatible; *compat; compat++) { - if (strncmp(*compat, info->name, info->len) == 0) - return true; - } - - return false; -} - -static const struct pvr_drm_device_config * -pvr_drm_device_get_config(drmDevice *const drm_dev) -{ - for (size_t i = 0U; i < ARRAY_SIZE(pvr_drm_configs); i++) { - if (pvr_drm_device_compatible(&pvr_drm_configs[i].render, drm_dev)) - return &pvr_drm_configs[i]; - } - - return NULL; -} - -static void -pvr_physical_device_dump_info(const struct pvr_physical_device *pdevice, - char *const *comp_display, - char *const *comp_render) -{ - drmVersionPtr version_display, version_render; - struct pvr_device_dump_info info; - - version_display = drmGetVersion(pdevice->ws->display_fd); - if (!version_display) - return; - - version_render = drmGetVersion(pdevice->ws->render_fd); - if (!version_render) { - drmFreeVersion(version_display); - return; - } - - info.device_info = &pdevice->dev_info; - info.device_runtime_info = &pdevice->dev_runtime_info; - info.drm_display.patchlevel = version_display->version_patchlevel; - info.drm_display.major = version_display->version_major; - info.drm_display.minor = version_display->version_minor; - info.drm_display.name = version_display->name; - info.drm_display.date = version_display->date; - info.drm_display.comp = comp_display; - info.drm_render.patchlevel = version_render->version_patchlevel; - info.drm_render.major = version_render->version_major; - info.drm_render.minor = version_render->version_minor; - info.drm_render.name = version_render->name; - info.drm_render.date = version_render->date; - info.drm_render.comp = comp_render; - - pvr_dump_physical_device_info(&info); - - drmFreeVersion(version_display); - drmFreeVersion(version_render); -} - -static VkResult -pvr_physical_device_enumerate(struct vk_instance *const vk_instance) -{ - struct pvr_instance *const instance = - container_of(vk_instance, struct pvr_instance, vk); - - const struct pvr_drm_device_config *config = NULL; - - drmDevicePtr drm_display_device = NULL; - drmDevicePtr drm_render_device = NULL; - struct pvr_physical_device *pdevice; - drmDevicePtr *drm_devices; - int num_drm_devices = 0; - VkResult result; - - result = pvr_get_drm_devices(instance, NULL, 0, &num_drm_devices); - if (result != VK_SUCCESS) - goto out; - - if (num_drm_devices == 0) { - result = VK_SUCCESS; - goto out; - } - - drm_devices = vk_alloc(&vk_instance->alloc, - sizeof(*drm_devices) * num_drm_devices, - 8, - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (!drm_devices) { - result = vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); - goto out; - } - - result = pvr_get_drm_devices(instance, drm_devices, num_drm_devices, NULL); - if (result != VK_SUCCESS) - goto out_free_drm_device_ptrs; - - /* First search for our render node... */ - for (int i = 0; i < num_drm_devices; i++) { - drmDevice *const drm_dev = drm_devices[i]; - - if (drm_dev->bustype != DRM_BUS_PLATFORM) - continue; - - if (!(drm_dev->available_nodes & BITFIELD_BIT(DRM_NODE_RENDER))) - continue; - - config = pvr_drm_device_get_config(drm_dev); - if (config) { - drm_render_device = drm_dev; - break; - } - } - - if (!config) { - result = VK_SUCCESS; - goto out_free_drm_devices; - } - - mesa_logd("Found compatible render device '%s'.", - drm_render_device->nodes[DRM_NODE_RENDER]); - - /* ...then find the compatible display node. */ - for (int i = 0; i < num_drm_devices; i++) { - drmDevice *const drm_dev = drm_devices[i]; - - if (!(drm_dev->available_nodes & BITFIELD_BIT(DRM_NODE_PRIMARY))) - continue; - - if (pvr_drm_device_compatible(&config->display, drm_dev)) { - drm_display_device = drm_dev; - break; - } - } - - if (!drm_display_device) { - mesa_loge("Render device '%s' has no compatible display device.", - drm_render_device->nodes[DRM_NODE_RENDER]); - result = VK_SUCCESS; - goto out_free_drm_devices; - } - - mesa_logd("Found compatible display device '%s'.", - drm_display_device->nodes[DRM_NODE_PRIMARY]); - - pdevice = vk_alloc(&vk_instance->alloc, - sizeof(*pdevice), - 8, - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (!pdevice) { - result = vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); - goto out_free_drm_devices; - } - - result = pvr_physical_device_init(pdevice, - instance, - drm_render_device, - drm_display_device); - if (result != VK_SUCCESS) { - if (result == VK_ERROR_INCOMPATIBLE_DRIVER) - result = VK_SUCCESS; - - goto err_free_pdevice; - } - - if (PVR_IS_DEBUG_SET(INFO)) { - pvr_physical_device_dump_info( - pdevice, - drm_display_device->deviceinfo.platform->compatible, - drm_render_device->deviceinfo.platform->compatible); - } - - list_add(&pdevice->vk.link, &vk_instance->physical_devices.list); - - result = VK_SUCCESS; - goto out_free_drm_devices; - -err_free_pdevice: - vk_free(&vk_instance->alloc, pdevice); - -out_free_drm_devices: - drmFreeDevices(drm_devices, num_drm_devices); - -out_free_drm_device_ptrs: - vk_free(&vk_instance->alloc, drm_devices); - -out: - return result; -} - -static bool -pvr_get_driver_build_sha(uint8_t sha_out[const static SHA1_DIGEST_LENGTH]) -{ - const struct build_id_note *note; - unsigned build_id_len; - - note = build_id_find_nhdr_for_addr(pvr_get_driver_build_sha); - if (!note) { - mesa_loge("Failed to find build-id."); - return false; - } - - build_id_len = build_id_length(note); - if (build_id_len < SHA1_DIGEST_LENGTH) { - mesa_loge("Build-id too short. It needs to be a SHA."); - return false; - } - - memcpy(sha_out, build_id_data(note), SHA1_DIGEST_LENGTH); - - return true; -} - -VkResult pvr_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkInstance *pInstance) -{ - struct vk_instance_dispatch_table dispatch_table; - struct pvr_instance *instance; - VkResult result; - - assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO); - - if (!pAllocator) - pAllocator = vk_default_allocator(); - - instance = vk_alloc(pAllocator, - sizeof(*instance), - 8, - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (!instance) - return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); - - vk_instance_dispatch_table_from_entrypoints(&dispatch_table, - &pvr_instance_entrypoints, - true); - - vk_instance_dispatch_table_from_entrypoints(&dispatch_table, - &wsi_instance_entrypoints, - false); - - result = vk_instance_init(&instance->vk, - &pvr_instance_extensions, - &dispatch_table, - pCreateInfo, - pAllocator); - if (result != VK_SUCCESS) - goto err_free_instance; - - pvr_process_debug_variable(); - - instance->active_device_count = 0; - - instance->vk.physical_devices.enumerate = pvr_physical_device_enumerate; - instance->vk.physical_devices.destroy = pvr_physical_device_destroy; - - VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false)); - - if (!pvr_get_driver_build_sha(instance->driver_build_sha)) { - result = vk_errorf(NULL, - VK_ERROR_INITIALIZATION_FAILED, - "Failed to get driver build sha."); - goto err_free_instance; - } - - *pInstance = pvr_instance_to_handle(instance); - - return VK_SUCCESS; - -err_free_instance: - vk_free(pAllocator, instance); - return result; -} - static uint32_t pvr_get_simultaneous_num_allocs( const struct pvr_device_info *dev_info, ASSERTED const struct pvr_device_runtime_info *dev_runtime_info) @@ -1635,72 +202,6 @@ uint32_t pvr_calc_fscommon_size_and_tiles_in_flight( return MIN2(num_tile_in_flight, max_tiles_in_flight); } -const static VkQueueFamilyProperties pvr_queue_family_properties = { - .queueFlags = VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | - VK_QUEUE_TRANSFER_BIT, - .queueCount = PVR_MAX_QUEUES, - .timestampValidBits = 0, - .minImageTransferGranularity = { 1, 1, 1 }, -}; - -void pvr_GetPhysicalDeviceQueueFamilyProperties2( - VkPhysicalDevice physicalDevice, - uint32_t *pQueueFamilyPropertyCount, - VkQueueFamilyProperties2 *pQueueFamilyProperties) -{ - VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties2, - out, - pQueueFamilyProperties, - pQueueFamilyPropertyCount); - - vk_outarray_append_typed (VkQueueFamilyProperties2, &out, p) { - p->queueFamilyProperties = pvr_queue_family_properties; - - vk_foreach_struct (ext, p->pNext) { - vk_debug_ignored_stype(ext->sType); - } - } -} - -void pvr_GetPhysicalDeviceMemoryProperties2( - VkPhysicalDevice physicalDevice, - VkPhysicalDeviceMemoryProperties2 *pMemoryProperties) -{ - VK_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice); - - pMemoryProperties->memoryProperties = pdevice->memory; - - vk_foreach_struct (ext, pMemoryProperties->pNext) { - vk_debug_ignored_stype(ext->sType); - } -} - -PFN_vkVoidFunction pvr_GetInstanceProcAddr(VkInstance _instance, - const char *pName) -{ - const struct vk_instance *vk_instance = NULL; - - if (_instance != NULL) { - VK_FROM_HANDLE(pvr_instance, instance, _instance); - vk_instance = &instance->vk; - } - - return vk_instance_get_proc_addr(vk_instance, - &pvr_instance_entrypoints, - pName); -} - -/* With version 1+ of the loader interface the ICD should expose - * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in - * apps. - */ -PUBLIC -VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL -vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName) -{ - return pvr_GetInstanceProcAddr(instance, pName); -} - VkResult pvr_pds_compute_shader_create_and_upload( struct pvr_device *device, struct pvr_pds_compute_shader_program *program, @@ -2294,12 +795,12 @@ static void pvr_device_init_default_sampler_state(struct pvr_device *device) } } -VkResult pvr_CreateDevice(VkPhysicalDevice physicalDevice, - const VkDeviceCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkDevice *pDevice) +VkResult +pvr_create_device(struct pvr_physical_device *pdevice, + const VkDeviceCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDevice *pDevice) { - VK_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice); uint32_t initial_free_list_size = PVR_GLOBAL_FREE_LIST_INITIAL_SIZE; struct pvr_instance *instance = pdevice->instance; struct vk_device_dispatch_table dispatch_table; @@ -2524,11 +1025,10 @@ err_out: return result; } -void pvr_DestroyDevice(VkDevice _device, - const VkAllocationCallbacks *pAllocator) +void +pvr_destroy_device(struct pvr_device *device, + const VkAllocationCallbacks *pAllocator) { - VK_FROM_HANDLE(pvr_device, device, _device); - if (!device) return; @@ -2562,17 +1062,6 @@ void pvr_DestroyDevice(VkDevice _device, vk_free(&device->vk.alloc, device); } -VkResult pvr_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount, - VkLayerProperties *pProperties) -{ - if (!pProperties) { - *pPropertyCount = 0; - return VK_SUCCESS; - } - - return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); -} - VkResult pvr_AllocateMemory(VkDevice _device, const VkMemoryAllocateInfo *pAllocateInfo, const VkAllocationCallbacks *pAllocator, diff --git a/src/imagination/vulkan/pvr_device.h b/src/imagination/vulkan/pvr_device.h index 258a2c7b528..03cd853b189 100644 --- a/src/imagination/vulkan/pvr_device.h +++ b/src/imagination/vulkan/pvr_device.h @@ -14,9 +14,10 @@ #ifndef PVR_DEVICE_H #define PVR_DEVICE_H +#include + #include "vk_device.h" #include "vk_device_memory.h" -#include "vk_instance.h" #include "vk_physical_device.h" #include "wsi_common.h" @@ -30,60 +31,11 @@ #include "pvr_spm.h" #include "pvr_usc.h" -#if defined(VK_USE_PLATFORM_DISPLAY_KHR) -# define PVR_USE_WSI_PLATFORM_DISPLAY true -#else -# define PVR_USE_WSI_PLATFORM_DISPLAY false -#endif - -#if defined(VK_USE_PLATFORM_DISPLAY_KHR) || \ - defined(VK_USE_PLATFORM_WAYLAND_KHR) -# define PVR_USE_WSI_PLATFORM true -#else -# define PVR_USE_WSI_PLATFORM false -#endif - typedef struct _pco_ctx pco_ctx; struct pvr_instance; struct pvr_queue; -struct pvr_physical_device { - struct vk_physical_device vk; - - /* Back-pointer to instance */ - struct pvr_instance *instance; - - char *render_path; - char *display_path; - - /* primary node (cardN) of the render device */ - dev_t primary_devid; - /* render node (renderN) of the render device */ - dev_t render_devid; - - struct pvr_winsys *ws; - struct pvr_device_info dev_info; - struct pvr_device_runtime_info dev_runtime_info; - - VkPhysicalDeviceMemoryProperties memory; - - struct wsi_device wsi_device; - - pco_ctx *pco_ctx; - - uint8_t device_uuid[SHA1_DIGEST_LENGTH]; - uint8_t cache_uuid[SHA1_DIGEST_LENGTH]; -}; - -struct pvr_instance { - struct vk_instance vk; - - uint32_t active_device_count; - - uint8_t driver_build_sha[SHA1_DIGEST_LENGTH]; -}; - struct pvr_compute_query_shader { struct pvr_suballoc_bo *usc_bo; @@ -223,16 +175,6 @@ struct pvr_device_memory { struct pvr_winsys_bo *bo; }; -VK_DEFINE_HANDLE_CASTS(pvr_instance, - vk.base, - VkInstance, - VK_OBJECT_TYPE_INSTANCE) - -VK_DEFINE_HANDLE_CASTS(pvr_physical_device, - vk.base, - VkPhysicalDevice, - VK_OBJECT_TYPE_PHYSICAL_DEVICE) - VK_DEFINE_NONDISP_HANDLE_CASTS(pvr_device_memory, vk.base, VkDeviceMemory, @@ -245,6 +187,16 @@ static inline struct pvr_device *vk_to_pvr_device(struct vk_device *device) return container_of(device, struct pvr_device, vk); } +VkResult +pvr_create_device(struct pvr_physical_device *pdevice, + const VkDeviceCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDevice *pDevice); + +void +pvr_destroy_device(struct pvr_device *device, + const VkAllocationCallbacks *pAllocator); + uint32_t pvr_calc_fscommon_size_and_tiles_in_flight( const struct pvr_device_info *dev_info, const struct pvr_device_runtime_info *dev_runtime_info, diff --git a/src/imagination/vulkan/pvr_dump_csb.c b/src/imagination/vulkan/pvr_dump_csb.c index bc5ce756474..17a374edeba 100644 --- a/src/imagination/vulkan/pvr_dump_csb.c +++ b/src/imagination/vulkan/pvr_dump_csb.c @@ -34,6 +34,7 @@ #include "pvr_device_info.h" #include "pvr_dump.h" #include "pvr_dump_bo.h" +#include "pvr_physical_device.h" #include "pvr_util.h" #include "util/list.h" #include "util/macros.h" diff --git a/src/imagination/vulkan/pvr_formats.c b/src/imagination/vulkan/pvr_formats.c index 28f18350de4..68ffa240562 100644 --- a/src/imagination/vulkan/pvr_formats.c +++ b/src/imagination/vulkan/pvr_formats.c @@ -32,6 +32,7 @@ #include "pvr_device.h" #include "pvr_entrypoints.h" #include "pvr_formats.h" +#include "pvr_physical_device.h" #include "util/bitpack_helpers.h" #include "util/compiler.h" #include "util/format/format_utils.h" diff --git a/src/imagination/vulkan/pvr_hw_pass.c b/src/imagination/vulkan/pvr_hw_pass.c index 2205dc0c46a..a269eaac8c9 100644 --- a/src/imagination/vulkan/pvr_hw_pass.c +++ b/src/imagination/vulkan/pvr_hw_pass.c @@ -34,6 +34,7 @@ #include "pvr_hw_pass.h" #include "pvr_formats.h" #include "pvr_pass.h" +#include "pvr_physical_device.h" #include "util/bitset.h" #include "util/list.h" #include "util/macros.h" diff --git a/src/imagination/vulkan/pvr_image.c b/src/imagination/vulkan/pvr_image.c index 89dac61e4dd..4065d97e018 100644 --- a/src/imagination/vulkan/pvr_image.c +++ b/src/imagination/vulkan/pvr_image.c @@ -34,6 +34,7 @@ #include "pvr_entrypoints.h" #include "pvr_formats.h" #include "pvr_macros.h" +#include "pvr_physical_device.h" #include "pvr_tex_state.h" #include "util/macros.h" #include "util/u_math.h" diff --git a/src/imagination/vulkan/pvr_instance.c b/src/imagination/vulkan/pvr_instance.c new file mode 100644 index 00000000000..0f3cd1e465b --- /dev/null +++ b/src/imagination/vulkan/pvr_instance.c @@ -0,0 +1,406 @@ +/* + * Copyright © 2022 Imagination Technologies Ltd. + * + * based in part on anv driver which is: + * Copyright © 2015 Intel Corporation + * + * based in part on v3dv driver which is: + * Copyright © 2019 Raspberry Pi + * + * SPDX-License-Identifier: MIT + */ + +#include "pvr_instance.h" + +#include + +#include "vk_alloc.h" +#include "vk_log.h" + +#include "wsi_common.h" + +#include "util/build_id.h" + +#include "pvr_debug.h" +#include "pvr_device.h" +#include "pvr_entrypoints.h" +#include "pvr_macros.h" +#include "pvr_physical_device.h" +#include "pvr_wsi.h" + +#if defined(VK_USE_PLATFORM_DISPLAY_KHR) +# define PVR_USE_WSI_PLATFORM_DISPLAY true +#else +# define PVR_USE_WSI_PLATFORM_DISPLAY false +#endif + +struct pvr_drm_device_config { + struct pvr_drm_device_info { + const char *name; + size_t len; + } render, display; +}; + +#define DEF_CONFIG(render_, display_) \ + { \ + .render = { .name = render_, .len = sizeof(render_) - 1 }, \ + .display = { .name = display_, .len = sizeof(display_) - 1 }, \ + } + +/* This is the list of supported DRM render/display driver configs. */ +static const struct pvr_drm_device_config pvr_drm_configs[] = { + DEF_CONFIG("mediatek,mt8173-gpu", "mediatek-drm"), + DEF_CONFIG("ti,am62-gpu", "ti,am625-dss"), + DEF_CONFIG("ti,j721s2-gpu", "ti,j721e-dss"), +}; + +#undef DEF_CONFIG + +static const struct vk_instance_extension_table pvr_instance_extensions = { + .KHR_device_group_creation = true, + .KHR_display = PVR_USE_WSI_PLATFORM_DISPLAY, + .KHR_external_fence_capabilities = true, + .KHR_external_memory_capabilities = true, + .KHR_external_semaphore_capabilities = true, + .KHR_get_display_properties2 = PVR_USE_WSI_PLATFORM_DISPLAY, + .KHR_get_physical_device_properties2 = true, + .KHR_get_surface_capabilities2 = PVR_USE_WSI_PLATFORM, + .KHR_surface = PVR_USE_WSI_PLATFORM, +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + .KHR_wayland_surface = true, +#endif + .EXT_debug_report = true, + .EXT_debug_utils = true, +#ifndef VK_USE_PLATFORM_WIN32_KHR + .EXT_headless_surface = PVR_USE_WSI_PLATFORM && false, +#endif +}; + +static VkResult pvr_get_drm_devices(void *const obj, + drmDevicePtr *const devices, + const int max_devices, + int *const num_devices_out) +{ + int ret = drmGetDevices2(0, devices, max_devices); + if (ret < 0) { + return vk_errorf(obj, + VK_ERROR_INITIALIZATION_FAILED, + "Failed to enumerate drm devices (errno %d: %s)", + -ret, + strerror(-ret)); + } + + if (num_devices_out) + *num_devices_out = ret; + + return VK_SUCCESS; +} + +static bool +pvr_drm_device_compatible(const struct pvr_drm_device_info *const info, + drmDevice *const drm_dev) +{ + char **const compatible = drm_dev->deviceinfo.platform->compatible; + + for (char **compat = compatible; *compat; compat++) { + if (strncmp(*compat, info->name, info->len) == 0) + return true; + } + + return false; +} + +static const struct pvr_drm_device_config * +pvr_drm_device_get_config(drmDevice *const drm_dev) +{ + for (size_t i = 0U; i < ARRAY_SIZE(pvr_drm_configs); i++) { + if (pvr_drm_device_compatible(&pvr_drm_configs[i].render, drm_dev)) + return &pvr_drm_configs[i]; + } + + return NULL; +} + +static VkResult +pvr_physical_device_enumerate(struct vk_instance *const vk_instance) +{ + struct pvr_instance *const instance = + container_of(vk_instance, struct pvr_instance, vk); + + const struct pvr_drm_device_config *config = NULL; + + drmDevicePtr drm_display_device = NULL; + drmDevicePtr drm_render_device = NULL; + struct pvr_physical_device *pdevice; + drmDevicePtr *drm_devices; + int num_drm_devices = 0; + VkResult result; + + result = pvr_get_drm_devices(instance, NULL, 0, &num_drm_devices); + if (result != VK_SUCCESS) + goto out; + + if (num_drm_devices == 0) { + result = VK_SUCCESS; + goto out; + } + + drm_devices = vk_alloc(&vk_instance->alloc, + sizeof(*drm_devices) * num_drm_devices, + 8, + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (!drm_devices) { + result = vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); + goto out; + } + + result = pvr_get_drm_devices(instance, drm_devices, num_drm_devices, NULL); + if (result != VK_SUCCESS) + goto out_free_drm_device_ptrs; + + /* First search for our render node... */ + for (int i = 0; i < num_drm_devices; i++) { + drmDevice *const drm_dev = drm_devices[i]; + + if (drm_dev->bustype != DRM_BUS_PLATFORM) + continue; + + if (!(drm_dev->available_nodes & BITFIELD_BIT(DRM_NODE_RENDER))) + continue; + + config = pvr_drm_device_get_config(drm_dev); + if (config) { + drm_render_device = drm_dev; + break; + } + } + + if (!config) { + result = VK_SUCCESS; + goto out_free_drm_devices; + } + + mesa_logd("Found compatible render device '%s'.", + drm_render_device->nodes[DRM_NODE_RENDER]); + + /* ...then find the compatible display node. */ + for (int i = 0; i < num_drm_devices; i++) { + drmDevice *const drm_dev = drm_devices[i]; + + if (!(drm_dev->available_nodes & BITFIELD_BIT(DRM_NODE_PRIMARY))) + continue; + + if (pvr_drm_device_compatible(&config->display, drm_dev)) { + drm_display_device = drm_dev; + break; + } + } + + if (!drm_display_device) { + mesa_loge("Render device '%s' has no compatible display device.", + drm_render_device->nodes[DRM_NODE_RENDER]); + result = VK_SUCCESS; + goto out_free_drm_devices; + } + + mesa_logd("Found compatible display device '%s'.", + drm_display_device->nodes[DRM_NODE_PRIMARY]); + + pdevice = vk_alloc(&vk_instance->alloc, + sizeof(*pdevice), + 8, + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (!pdevice) { + result = vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); + goto out_free_drm_devices; + } + + result = pvr_physical_device_init(pdevice, + instance, + drm_render_device, + drm_display_device); + if (result != VK_SUCCESS) { + if (result == VK_ERROR_INCOMPATIBLE_DRIVER) + result = VK_SUCCESS; + + goto err_free_pdevice; + } + + if (PVR_IS_DEBUG_SET(INFO)) { + pvr_physical_device_dump_info( + pdevice, + drm_display_device->deviceinfo.platform->compatible, + drm_render_device->deviceinfo.platform->compatible); + } + + list_add(&pdevice->vk.link, &vk_instance->physical_devices.list); + + result = VK_SUCCESS; + goto out_free_drm_devices; + +err_free_pdevice: + vk_free(&vk_instance->alloc, pdevice); + +out_free_drm_devices: + drmFreeDevices(drm_devices, num_drm_devices); + +out_free_drm_device_ptrs: + vk_free(&vk_instance->alloc, drm_devices); + +out: + return result; +} + +static bool +pvr_get_driver_build_sha(uint8_t sha_out[const static SHA1_DIGEST_LENGTH]) +{ + const struct build_id_note *note; + unsigned build_id_len; + + note = build_id_find_nhdr_for_addr(pvr_get_driver_build_sha); + if (!note) { + mesa_loge("Failed to find build-id."); + return false; + } + + build_id_len = build_id_length(note); + if (build_id_len < SHA1_DIGEST_LENGTH) { + mesa_loge("Build-id too short. It needs to be a SHA."); + return false; + } + + memcpy(sha_out, build_id_data(note), SHA1_DIGEST_LENGTH); + + return true; +} + +VkResult pvr_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkInstance *pInstance) +{ + struct vk_instance_dispatch_table dispatch_table; + struct pvr_instance *instance; + VkResult result; + + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO); + + if (!pAllocator) + pAllocator = vk_default_allocator(); + + instance = vk_alloc(pAllocator, + sizeof(*instance), + 8, + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (!instance) + return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); + + vk_instance_dispatch_table_from_entrypoints(&dispatch_table, + &pvr_instance_entrypoints, + true); + + vk_instance_dispatch_table_from_entrypoints(&dispatch_table, + &wsi_instance_entrypoints, + false); + + result = vk_instance_init(&instance->vk, + &pvr_instance_extensions, + &dispatch_table, + pCreateInfo, + pAllocator); + if (result != VK_SUCCESS) + goto err_free_instance; + + pvr_process_debug_variable(); + + instance->active_device_count = 0; + + instance->vk.physical_devices.enumerate = pvr_physical_device_enumerate; + instance->vk.physical_devices.destroy = pvr_physical_device_destroy; + + VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false)); + + if (!pvr_get_driver_build_sha(instance->driver_build_sha)) { + result = vk_errorf(NULL, + VK_ERROR_INITIALIZATION_FAILED, + "Failed to get driver build sha."); + goto err_free_instance; + } + + *pInstance = pvr_instance_to_handle(instance); + + return VK_SUCCESS; + +err_free_instance: + vk_free(pAllocator, instance); + return result; +} + +void pvr_DestroyInstance(VkInstance _instance, + const VkAllocationCallbacks *pAllocator) +{ + VK_FROM_HANDLE(pvr_instance, instance, _instance); + + if (!instance) + return; + + VG(VALGRIND_DESTROY_MEMPOOL(instance)); + + vk_instance_finish(&instance->vk); + vk_free(&instance->vk.alloc, instance); +} + +VkResult pvr_EnumerateInstanceVersion(uint32_t *pApiVersion) +{ + *pApiVersion = VK_MAKE_API_VERSION(0, 1, 4, VK_HEADER_VERSION); + return VK_SUCCESS; +} + +VkResult +pvr_EnumerateInstanceExtensionProperties(const char *pLayerName, + uint32_t *pPropertyCount, + VkExtensionProperties *pProperties) +{ + if (pLayerName) + return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); + + return vk_enumerate_instance_extension_properties(&pvr_instance_extensions, + pPropertyCount, + pProperties); +} + +PFN_vkVoidFunction pvr_GetInstanceProcAddr(VkInstance _instance, + const char *pName) +{ + const struct vk_instance *vk_instance = NULL; + + if (_instance != NULL) { + VK_FROM_HANDLE(pvr_instance, instance, _instance); + vk_instance = &instance->vk; + } + + return vk_instance_get_proc_addr(vk_instance, + &pvr_instance_entrypoints, + pName); +} + +/* With version 1+ of the loader interface the ICD should expose + * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in + * apps. + */ +PUBLIC +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL +vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName) +{ + return pvr_GetInstanceProcAddr(instance, pName); +} + +VkResult pvr_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount, + VkLayerProperties *pProperties) +{ + if (!pProperties) { + *pPropertyCount = 0; + return VK_SUCCESS; + } + + return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); +} diff --git a/src/imagination/vulkan/pvr_instance.h b/src/imagination/vulkan/pvr_instance.h new file mode 100644 index 00000000000..06d985d41d1 --- /dev/null +++ b/src/imagination/vulkan/pvr_instance.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2022 Imagination Technologies Ltd. + * + * based in part on anv driver which is: + * Copyright © 2015 Intel Corporation + * + * based in part on radv driver which is: + * Copyright © 2016 Red Hat. + * Copyright © 2016 Bas Nieuwenhuizen + * + * SPDX-License-Identifier: MIT + */ + +#ifndef PVR_INSTANCE_H +#define PVR_INSTANCE_H + +#include "vk_instance.h" + +#include + +#include "util/mesa-sha1.h" + +struct pvr_instance { + struct vk_instance vk; + + uint32_t active_device_count; + + uint8_t driver_build_sha[SHA1_DIGEST_LENGTH]; +}; + +VK_DEFINE_HANDLE_CASTS(pvr_instance, + vk.base, + VkInstance, + VK_OBJECT_TYPE_INSTANCE) + +#endif /* PVR_INSTANCE_H */ diff --git a/src/imagination/vulkan/pvr_job_compute.c b/src/imagination/vulkan/pvr_job_compute.c index e4d0a89928e..aa3bef98b46 100644 --- a/src/imagination/vulkan/pvr_job_compute.c +++ b/src/imagination/vulkan/pvr_job_compute.c @@ -34,6 +34,7 @@ #include "pvr_job_context.h" #include "pvr_job_compute.h" #include "pvr_macros.h" +#include "pvr_physical_device.h" #include "pvr_types.h" #include "pvr_winsys.h" #include "util/macros.h" diff --git a/src/imagination/vulkan/pvr_job_context.c b/src/imagination/vulkan/pvr_job_context.c index f853f7db573..d328ff13ea6 100644 --- a/src/imagination/vulkan/pvr_job_context.c +++ b/src/imagination/vulkan/pvr_job_context.c @@ -38,6 +38,7 @@ #include "pvr_macros.h" #include "pvr_pass.h" #include "pvr_pds.h" +#include "pvr_physical_device.h" #include "pvr_transfer_frag_store.h" #include "pvr_types.h" #include "pvr_usc.h" diff --git a/src/imagination/vulkan/pvr_job_render.c b/src/imagination/vulkan/pvr_job_render.c index 316b10aaf50..ce0b8709992 100644 --- a/src/imagination/vulkan/pvr_job_render.c +++ b/src/imagination/vulkan/pvr_job_render.c @@ -40,6 +40,7 @@ #include "pvr_job_render.h" #include "pvr_macros.h" #include "pvr_pds.h" +#include "pvr_physical_device.h" #include "pvr_query.h" #include "pvr_rogue_fw.h" #include "pvr_types.h" diff --git a/src/imagination/vulkan/pvr_job_transfer.c b/src/imagination/vulkan/pvr_job_transfer.c index a872eedbfee..fa23c731e02 100644 --- a/src/imagination/vulkan/pvr_job_transfer.c +++ b/src/imagination/vulkan/pvr_job_transfer.c @@ -36,6 +36,7 @@ #include "pvr_job_common.h" #include "pvr_job_context.h" #include "pvr_job_transfer.h" +#include "pvr_physical_device.h" #include "pvr_tex_state.h" #include "pvr_transfer_frag_store.h" #include "pvr_types.h" diff --git a/src/imagination/vulkan/pvr_pass.c b/src/imagination/vulkan/pvr_pass.c index 2c4fbee9e6e..73d1eeb1fcb 100644 --- a/src/imagination/vulkan/pvr_pass.c +++ b/src/imagination/vulkan/pvr_pass.c @@ -35,6 +35,7 @@ #include "pvr_hw_pass.h" #include "pvr_macros.h" #include "pvr_pds.h" +#include "pvr_physical_device.h" #include "pvr_pipeline.h" #include "pvr_types.h" #include "pvr_usc.h" diff --git a/src/imagination/vulkan/pvr_physical_device.c b/src/imagination/vulkan/pvr_physical_device.c new file mode 100644 index 00000000000..26db3a18426 --- /dev/null +++ b/src/imagination/vulkan/pvr_physical_device.c @@ -0,0 +1,1188 @@ +/* + * Copyright © 2022 Imagination Technologies Ltd. + * + * based in part on anv driver which is: + * Copyright © 2015 Intel Corporation + * + * based in part on v3dv driver which is: + * Copyright © 2019 Raspberry Pi + * + * SPDX-License-Identifier: MIT + */ + +#include "pvr_physical_device.h" + +#include + +#include "git_sha1.h" + +#include "util/disk_cache.h" +#include "util/ralloc.h" + +#include "vk_util.h" +#include "vk_log.h" + +#include "hwdef/rogue_hw_utils.h" + +#include "pco/pco.h" +#include "pco_uscgen_programs.h" + +#include "pvr_border.h" +#include "pvr_device.h" +#include "pvr_dump_info.h" +#include "pvr_entrypoints.h" +#include "pvr_winsys.h" +#include "pvr_wsi.h" + +#define VK_VENDOR_ID_IMAGINATION 0x1010 + +void +pvr_physical_device_dump_info(const struct pvr_physical_device *pdevice, + char *const *comp_display, + char *const *comp_render) +{ + drmVersionPtr version_display, version_render; + struct pvr_device_dump_info info; + + version_display = drmGetVersion(pdevice->ws->display_fd); + if (!version_display) + return; + + version_render = drmGetVersion(pdevice->ws->render_fd); + if (!version_render) { + drmFreeVersion(version_display); + return; + } + + info.device_info = &pdevice->dev_info; + info.device_runtime_info = &pdevice->dev_runtime_info; + info.drm_display.patchlevel = version_display->version_patchlevel; + info.drm_display.major = version_display->version_major; + info.drm_display.minor = version_display->version_minor; + info.drm_display.name = version_display->name; + info.drm_display.date = version_display->date; + info.drm_display.comp = comp_display; + info.drm_render.patchlevel = version_render->version_patchlevel; + info.drm_render.major = version_render->version_major; + info.drm_render.minor = version_render->version_minor; + info.drm_render.name = version_render->name; + info.drm_render.date = version_render->date; + info.drm_render.comp = comp_render; + + pvr_dump_physical_device_info(&info); + + drmFreeVersion(version_display); + drmFreeVersion(version_render); +} + +void +pvr_physical_device_destroy(struct vk_physical_device *vk_pdevice) +{ + struct pvr_physical_device *pdevice = + container_of(vk_pdevice, struct pvr_physical_device, vk); + + /* Be careful here. The device might not have been initialized. This can + * happen since initialization is done in vkEnumeratePhysicalDevices() but + * finish is done in vkDestroyInstance(). Make sure that you check for NULL + * before freeing or that the freeing functions accept NULL pointers. + */ + + ralloc_free(pdevice->pco_ctx); + + pvr_wsi_finish(pdevice); + + pvr_physical_device_free_pipeline_cache(pdevice); + + if (pdevice->ws) + pvr_winsys_destroy(pdevice->ws); + + vk_free(&pdevice->vk.instance->alloc, pdevice->render_path); + vk_free(&pdevice->vk.instance->alloc, pdevice->display_path); + + vk_physical_device_finish(&pdevice->vk); + + vk_free(&pdevice->vk.instance->alloc, pdevice); +} + +void +pvr_physical_device_free_pipeline_cache(struct pvr_physical_device *const pdevice) +{ +#ifdef ENABLE_SHADER_CACHE + if (!pdevice->vk.disk_cache) + return; + + disk_cache_destroy(pdevice->vk.disk_cache); + pdevice->vk.disk_cache = NULL; +#else + assert(pdevice->vk.disk_cache); +#endif /* ENABLE_SHADER_CACHE */ +} + +static void pvr_physical_device_get_supported_extensions( + struct vk_device_extension_table *extensions) +{ + *extensions = (struct vk_device_extension_table){ + .KHR_bind_memory2 = true, + .KHR_buffer_device_address = true, + .KHR_copy_commands2 = true, + .KHR_create_renderpass2 = true, + .KHR_dedicated_allocation = true, + .KHR_depth_stencil_resolve = true, + .KHR_descriptor_update_template = true, + .KHR_device_group = true, + .KHR_driver_properties = true, + .KHR_external_fence = true, + .KHR_external_fence_fd = true, + .KHR_external_memory = true, + .KHR_external_memory_fd = true, + .KHR_external_semaphore = PVR_USE_WSI_PLATFORM, + .KHR_external_semaphore_fd = PVR_USE_WSI_PLATFORM, + .KHR_format_feature_flags2 = false, + .KHR_get_memory_requirements2 = true, + .KHR_image_format_list = true, + .KHR_imageless_framebuffer = true, + .KHR_index_type_uint8 = false, + .KHR_line_rasterization = true, + .KHR_maintenance1 = true, + .KHR_maintenance2 = true, + .KHR_maintenance3 = true, + .KHR_map_memory2 = true, + .KHR_multiview = true, + .KHR_present_id2 = PVR_USE_WSI_PLATFORM, + .KHR_present_wait2 = PVR_USE_WSI_PLATFORM, + .KHR_relaxed_block_layout = true, + .KHR_robustness2 = true, + .KHR_sampler_mirror_clamp_to_edge = true, + .KHR_separate_depth_stencil_layouts = true, + .KHR_shader_draw_parameters = true, + .KHR_shader_expect_assume = false, + .KHR_shader_float_controls = true, + .KHR_shader_non_semantic_info = true, + .KHR_shader_relaxed_extended_instruction = true, + .KHR_shader_subgroup_extended_types = true, + .KHR_shader_terminate_invocation = true, + .KHR_spirv_1_4 = true, + .KHR_storage_buffer_storage_class = true, + .KHR_swapchain = PVR_USE_WSI_PLATFORM, + .KHR_swapchain_mutable_format = PVR_USE_WSI_PLATFORM, + .KHR_timeline_semaphore = true, + .KHR_uniform_buffer_standard_layout = true, + .KHR_vertex_attribute_divisor = true, + .KHR_zero_initialize_workgroup_memory = false, + .EXT_border_color_swizzle = true, + .EXT_color_write_enable = true, + .EXT_custom_border_color = true, + .EXT_depth_clamp_zero_one = true, + .EXT_depth_clip_enable = true, + .EXT_extended_dynamic_state = true, + .EXT_extended_dynamic_state2 = true, + .EXT_extended_dynamic_state3 = true, + .EXT_external_memory_dma_buf = true, + .EXT_host_query_reset = true, + .EXT_image_2d_view_of_3d = true, + .EXT_index_type_uint8 = false, + .EXT_line_rasterization = true, + .EXT_map_memory_placed = true, + .EXT_physical_device_drm = true, + .EXT_private_data = true, + .EXT_provoking_vertex = true, + .EXT_queue_family_foreign = true, + .EXT_robustness2 = true, + .EXT_scalar_block_layout = true, + .EXT_separate_stencil_usage = true, + .EXT_shader_demote_to_helper_invocation = true, + .EXT_shader_replicated_composites = true, + .EXT_texel_buffer_alignment = false, + .EXT_tooling_info = true, + .EXT_vertex_attribute_divisor = true, + .EXT_zero_initialize_device_memory = true, + }; +} + +static void pvr_physical_device_get_supported_features( + const struct pvr_device_info *const dev_info, + struct vk_features *const features) +{ + *features = (struct vk_features){ + /* Vulkan 1.0 */ + .robustBufferAccess = true, + .fullDrawIndexUint32 = false, + .imageCubeArray = true, + .independentBlend = true, + .geometryShader = false, + .tessellationShader = false, + .sampleRateShading = true, + .dualSrcBlend = false, + .logicOp = true, + .multiDrawIndirect = false, + .drawIndirectFirstInstance = true, + .depthClamp = false, + .depthBiasClamp = false, + .fillModeNonSolid = false, + .depthBounds = false, + .wideLines = false, + .largePoints = true, + .alphaToOne = true, + .multiViewport = false, + .samplerAnisotropy = true, + .textureCompressionETC2 = true, + .textureCompressionASTC_LDR = false, + .textureCompressionBC = false, + .occlusionQueryPrecise = false, + .pipelineStatisticsQuery = false, + .vertexPipelineStoresAndAtomics = false, + .fragmentStoresAndAtomics = false, + .shaderTessellationAndGeometryPointSize = false, + .shaderImageGatherExtended = false, + .shaderStorageImageExtendedFormats = true, + .shaderStorageImageMultisample = false, + .shaderStorageImageReadWithoutFormat = true, + .shaderStorageImageWriteWithoutFormat = true, + .shaderUniformBufferArrayDynamicIndexing = false, + .shaderSampledImageArrayDynamicIndexing = false, + .shaderStorageBufferArrayDynamicIndexing = false, + .shaderStorageImageArrayDynamicIndexing = false, + .shaderClipDistance = true, + .shaderCullDistance = true, + .shaderFloat64 = false, + .shaderInt64 = false, + .shaderInt16 = false, + .shaderResourceResidency = false, + .shaderResourceMinLod = false, + .sparseBinding = false, + .sparseResidencyBuffer = false, + .sparseResidencyImage2D = false, + .sparseResidencyImage3D = false, + .sparseResidency2Samples = false, + .sparseResidency4Samples = false, + .sparseResidency8Samples = false, + .sparseResidency16Samples = false, + .sparseResidencyAliased = false, + .variableMultisampleRate = false, + .inheritedQueries = false, + + /* Vulkan 1.1 */ + .storageBuffer16BitAccess = false, + .uniformAndStorageBuffer16BitAccess = false, + .storagePushConstant16 = false, + .storageInputOutput16 = false, + .variablePointers = false, + .protectedMemory = false, + .samplerYcbcrConversion = false, + + /* Vulkan 1.2 */ + .samplerMirrorClampToEdge = false, + .drawIndirectCount = false, + .storageBuffer8BitAccess = false, + .uniformAndStorageBuffer8BitAccess = false, + .storagePushConstant8 = false, + .shaderBufferInt64Atomics = false, + .shaderSharedInt64Atomics = false, + .shaderFloat16 = false, + .shaderInt8 = false, + .descriptorIndexing = false, + .shaderInputAttachmentArrayDynamicIndexing = false, + .shaderUniformTexelBufferArrayDynamicIndexing = false, + .shaderStorageTexelBufferArrayDynamicIndexing = false, + .shaderUniformBufferArrayNonUniformIndexing = false, + .shaderSampledImageArrayNonUniformIndexing = false, + .shaderStorageBufferArrayNonUniformIndexing = false, + .shaderStorageImageArrayNonUniformIndexing = false, + .shaderInputAttachmentArrayNonUniformIndexing = false, + .shaderUniformTexelBufferArrayNonUniformIndexing = false, + .shaderStorageTexelBufferArrayNonUniformIndexing = false, + .descriptorBindingUniformBufferUpdateAfterBind = false, + .descriptorBindingSampledImageUpdateAfterBind = false, + .descriptorBindingStorageImageUpdateAfterBind = false, + .descriptorBindingStorageBufferUpdateAfterBind = false, + .descriptorBindingUniformTexelBufferUpdateAfterBind = false, + .descriptorBindingStorageTexelBufferUpdateAfterBind = false, + .descriptorBindingUpdateUnusedWhilePending = false, + .descriptorBindingPartiallyBound = false, + .descriptorBindingVariableDescriptorCount = false, + .runtimeDescriptorArray = false, + .samplerFilterMinmax = false, + .vulkanMemoryModel = false, + .vulkanMemoryModelDeviceScope = false, + .vulkanMemoryModelAvailabilityVisibilityChains = false, + .shaderOutputViewportIndex = false, + .shaderOutputLayer = false, + .subgroupBroadcastDynamicId = true, + + /* VK_EXT_depth_clamp_zero_one */ + .depthClampZeroOne = true, + + /* VK_KHR_index_type_uint8 */ + .indexTypeUint8 = true, + + /* Vulkan 1.2 / VK_KHR_imageless_framebuffer */ + .imagelessFramebuffer = true, + + /* Vulkan 1.1 / VK_KHR_multiview */ + .multiview = true, + .multiviewGeometryShader = false, + .multiviewTessellationShader = false, + + /* Vulkan 1.1 / VK_KHR_shader_draw_parameters */ + .shaderDrawParameters = true, + + /* Vulkan 1.2 / VK_KHR_timeline_semaphore */ + .timelineSemaphore = true, + + /* Vulkan 1.2 / VK_KHR_separate_depth_stencil_layouts */ + .separateDepthStencilLayouts = true, + + /* VK_KHR_shader_relaxed_extended_instruction */ + .shaderRelaxedExtendedInstruction = true, + + /* Vulkan 1.2 / VK_KHR_shader_subgroup_extended_types */ + .shaderSubgroupExtendedTypes = true, + + /* Vulkan 1.1 / VK_KHR_robustness2 */ + .robustBufferAccess2 = false, + .robustImageAccess2 = false, + .nullDescriptor = true, + + /* Vulkan 1.2 / VK_KHR_uniform_buffer_standard_layout */ + .uniformBufferStandardLayout = true, + + /* VK_EXT_color_write_enable */ + .colorWriteEnable = true, + + /* Vulkan 1.3 / VK_EXT_extended_dynamic_state */ + .extendedDynamicState = true, + + /* Vulkan 1.3 / VK_EXT_extended_dynamic_state2 */ + .extendedDynamicState2 = true, + .extendedDynamicState2LogicOp = false, + .extendedDynamicState2PatchControlPoints = false, + + /* VK_EXT_extended_dynamic_state3 */ + .extendedDynamicState3TessellationDomainOrigin = false, + .extendedDynamicState3DepthClampEnable = false, + .extendedDynamicState3PolygonMode = false, + .extendedDynamicState3RasterizationSamples = true, + .extendedDynamicState3SampleMask = true, + .extendedDynamicState3AlphaToCoverageEnable = true, + .extendedDynamicState3AlphaToOneEnable = true, + .extendedDynamicState3LogicOpEnable = false, + .extendedDynamicState3ColorBlendEnable = false, + .extendedDynamicState3ColorBlendEquation = false, + .extendedDynamicState3ColorWriteMask = false, + .extendedDynamicState3RasterizationStream = false, + .extendedDynamicState3ConservativeRasterizationMode = false, + .extendedDynamicState3ExtraPrimitiveOverestimationSize = false, + .extendedDynamicState3DepthClipEnable = false, + .extendedDynamicState3SampleLocationsEnable = false, + .extendedDynamicState3ColorBlendAdvanced = false, + .extendedDynamicState3ProvokingVertexMode = false, + .extendedDynamicState3LineRasterizationMode = false, + .extendedDynamicState3LineStippleEnable = false, + .extendedDynamicState3DepthClipNegativeOneToOne = false, + .extendedDynamicState3ViewportWScalingEnable = false, + .extendedDynamicState3ViewportSwizzle = false, + .extendedDynamicState3CoverageToColorEnable = false, + .extendedDynamicState3CoverageToColorLocation = false, + .extendedDynamicState3CoverageModulationMode = false, + .extendedDynamicState3CoverageModulationTableEnable = false, + .extendedDynamicState3CoverageModulationTable = false, + .extendedDynamicState3CoverageReductionMode = false, + .extendedDynamicState3RepresentativeFragmentTestEnable = false, + .extendedDynamicState3ShadingRateImageEnable = false, + + /* Vulkan 1.2 / VK_EXT_host_query_reset */ + .hostQueryReset = true, + + /* VK_EXT_image_2d_view_of_3d */ + .image2DViewOf3D = true, + .sampler2DViewOf3D = true, + + /* VK_EXT_map_memory_placed */ + .memoryMapPlaced = true, + .memoryMapRangePlaced = false, + .memoryUnmapReserve = true, + + /* Vulkan 1.3 / VK_EXT_private_data */ + .privateData = true, + + /* VK_EXT_provoking_vertex */ + .provokingVertexLast = true, + .transformFeedbackPreservesProvokingVertex = false, + + /* Vulkan 1.2 / VK_EXT_scalar_block_layout */ + .scalarBlockLayout = true, + + /* Vulkan 1.3 / VK_EXT_texel_buffer_alignment */ + .texelBufferAlignment = true, + + /* Vulkan 1.2 / VK_KHR_buffer_device_address */ + .bufferDeviceAddress = true, + .bufferDeviceAddressCaptureReplay = false, + .bufferDeviceAddressMultiDevice = false, + + /* VK_KHR_shader_expect_assume */ + .shaderExpectAssume = false, + + /* VK_EXT_shader_demote_to_helper_invocation */ + .shaderDemoteToHelperInvocation = true, + + /* VK_EXT_shader_replicated_composites */ + .shaderReplicatedComposites = true, + + /* VK_KHR_shader_terminate_invocation */ + .shaderTerminateInvocation = true, + + /* VK_KHR_present_id2 */ + .presentId2 = PVR_USE_WSI_PLATFORM, + + /* VK_KHR_present_wait2 */ + .presentWait2 = PVR_USE_WSI_PLATFORM, + + /* Vulkan 1.4 / VK_EXT_vertex_attribute_divisor / + VK_KHR_vertex_attribute_divisor */ + .vertexAttributeInstanceRateDivisor = true, + .vertexAttributeInstanceRateZeroDivisor = true, + + /* Vulkan 1.3 / VK_KHR_zero_initialize_workgroup_memory */ + .shaderZeroInitializeWorkgroupMemory = false, + + /* VK_EXT_border_color_swizzle */ + .borderColorSwizzle = true, + .borderColorSwizzleFromImage = true, + + /* VK_EXT_custom_border_color */ + .customBorderColors = true, + + /* VK_EXT_depth_clip_enable */ + .depthClipEnable = true, + + /* VK_KHR_line_rasterization */ + .bresenhamLines = true, + + /* VK_EXT_zero_initialize_device_memory */ + .zeroInitializeDeviceMemory = true, + }; +} + +static uint32_t get_api_version(void) +{ + const uint32_t version_override = vk_get_version_override(); + if (version_override) + return version_override; + + return VK_MAKE_API_VERSION(0, 1, 2, VK_HEADER_VERSION); +} + +static bool pvr_physical_device_get_properties( + const struct pvr_physical_device *const pdevice, + struct vk_properties *const properties) +{ + const struct pvr_device_info *const dev_info = &pdevice->dev_info; + const struct pvr_device_runtime_info *dev_runtime_info = + &pdevice->dev_runtime_info; + + /* Default value based on the minimum value found in all existing cores. */ + const uint32_t max_multisample = + PVR_GET_FEATURE_VALUE(dev_info, max_multisample, 4); + + UNUSED const uint32_t sub_pixel_precision = + PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format) ? 4U : 8U; + + UNUSED const uint32_t max_render_size = rogue_get_render_size_max(dev_info); + + UNUSED const uint32_t max_sample_bits = ((max_multisample << 1) - 1); + + UNUSED const uint32_t max_user_vertex_components = + pvr_get_max_user_vertex_output_components(dev_info); + + const bool usc_alu_roundingmode_rne = + PVR_HAS_FEATURE(dev_info, usc_alu_roundingmode_rne); + + /* The workgroup invocations are limited by the case where we have a compute + * barrier - each slot has a fixed number of invocations, the whole workgroup + * may need to span multiple slots. As each slot will WAIT at the barrier + * until the last invocation completes, all have to be schedulable at the + * same time. + * + * Typically all Rogue cores have 16 slots. Some of the smallest cores are + * reduced to 14. + * + * The compute barrier slot exhaustion scenario can be tested with: + * dEQP-VK.memory_model.message_passing*u32.coherent.fence_fence + * .atomicwrite*guard*comp + */ + + /* Default value based on the minimum value found in all existing cores. */ + const uint32_t usc_slots = PVR_GET_FEATURE_VALUE(dev_info, usc_slots, 14); + + /* Default value based on the minimum value found in all existing cores. */ + const uint32_t max_instances_per_pds_task = + PVR_GET_FEATURE_VALUE(dev_info, max_instances_per_pds_task, 32U); + + UNUSED const uint32_t max_compute_work_group_invocations = + (usc_slots * max_instances_per_pds_task >= 512U) ? 512U : 384U; + + assert(pdevice->memory.memoryHeapCount == 1); + const VkDeviceSize max_memory_alloc_size = + pdevice->memory.memoryHeaps[0].size; + + const uint32_t line_sub_pixel_precision_bits = + PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format) ? 4U : 8U; + + *properties = (struct vk_properties){ + /* Vulkan 1.0 */ + .apiVersion = get_api_version(), + .driverVersion = vk_get_driver_version(), + .vendorID = VK_VENDOR_ID_IMAGINATION, + .deviceID = dev_info->ident.device_id, + .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, + /* deviceName and pipelineCacheUUID are filled below .*/ + + .maxImageDimension1D = 4096U, + .maxImageDimension2D = 4096U, + .maxImageDimension3D = 256U, + .maxImageDimensionCube = 4096U, + .maxImageArrayLayers = 256U, + .maxTexelBufferElements = 64U * 1024U, + .maxUniformBufferRange = 16U * 1024U, + .maxStorageBufferRange = 128U * 1024U * 1024U, + .maxPushConstantsSize = 128U, + .maxMemoryAllocationCount = 4096U, + .maxSamplerAllocationCount = 4000U, + .bufferImageGranularity = 1U, + .sparseAddressSpaceSize = 0U, /* Requires sparseBinding */ + .maxBoundDescriptorSets = 4U, + .maxPerStageDescriptorSamplers = 16, + .maxPerStageDescriptorUniformBuffers = 12, + .maxPerStageDescriptorStorageBuffers = 4, + .maxPerStageDescriptorSampledImages = 16, + .maxPerStageDescriptorStorageImages = 4, + .maxPerStageDescriptorInputAttachments = 4, + .maxPerStageResources = 44, + .maxDescriptorSetSamplers = 3U * 16U, + .maxDescriptorSetUniformBuffers = 3U * 12U, + .maxDescriptorSetUniformBuffersDynamic = 8U, + .maxDescriptorSetStorageBuffers = 3U * 4U, + .maxDescriptorSetStorageBuffersDynamic = 4U, + .maxDescriptorSetSampledImages = 3U * 16U, + .maxDescriptorSetStorageImages = 3U * 4U, + .maxDescriptorSetInputAttachments = 4U, + + /* Vertex Shader Limits */ + .maxVertexInputAttributes = 16U, + .maxVertexInputBindings = 16U, + .maxVertexInputAttributeOffset = 2048U - 1U, + .maxVertexInputBindingStride = 2048U, + .maxVertexOutputComponents = 64U, + + /* Tessellation Limits */ + /* Requires tessellationShader */ + .maxTessellationGenerationLevel = 0U, + .maxTessellationPatchSize = 0U, + .maxTessellationControlPerVertexInputComponents = 0U, + .maxTessellationControlPerVertexOutputComponents = 0U, + .maxTessellationControlPerPatchOutputComponents = 0U, + .maxTessellationControlTotalOutputComponents = 0U, + .maxTessellationEvaluationInputComponents = 0U, + .maxTessellationEvaluationOutputComponents = 0U, + + /* Geometry Shader Limits */ + /* Requires geometryShader */ + .maxGeometryShaderInvocations = 0U, + .maxGeometryInputComponents = 0U, + .maxGeometryOutputComponents = 0U, + .maxGeometryOutputVertices = 0U, + .maxGeometryTotalOutputComponents = 0U, + + /* Fragment Shader Limits */ + .maxFragmentInputComponents = 64U, + .maxFragmentOutputAttachments = 4U, + .maxFragmentDualSrcAttachments = 0U, /* Requires dualSrcBlend */ + .maxFragmentCombinedOutputResources = 4U, + + /* Compute Shader Limits */ + .maxComputeSharedMemorySize = 16U * 1024U, + .maxComputeWorkGroupCount = { + [0] = (64U * 1024U) - 1, + [1] = (64U * 1024U) - 1, + [2] = (64U * 1024U) - 1, + }, + .maxComputeWorkGroupInvocations = 128U, + .maxComputeWorkGroupSize = { + [0] = 128U, + [1] = 128U, + [2] = 64U, + }, + + /* Rasterization Limits */ + .subPixelPrecisionBits = 4U, + .subTexelPrecisionBits = 8U, + .mipmapPrecisionBits = 8U, + + .maxDrawIndexedIndexValue = (1U << 24) - 1U, /* Requires fullDrawIndexUint32 */ + .maxDrawIndirectCount = 1U, /* Requires multiDrawIndirect */ + .maxSamplerLodBias = 16.0f, + .maxSamplerAnisotropy = 16.0f, /* Requires samplerAnisotropy */ + .maxViewports = 1U, /* Requires multiViewport */ + + .maxViewportDimensions[0] = 4096U, + .maxViewportDimensions[1] = 4096U, + .viewportBoundsRange[0] = -8192.0f, + .viewportBoundsRange[1] = 8191.0f, + + .viewportSubPixelBits = 0U, + .minMemoryMapAlignment = pdevice->ws->page_size, + .minTexelBufferOffsetAlignment = PVR_TEXEL_BUFFER_OFFSET_ALIGNMENT, + .minUniformBufferOffsetAlignment = PVR_UNIFORM_BUFFER_OFFSET_ALIGNMENT, + .minStorageBufferOffsetAlignment = PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT, + + .minTexelOffset = -8, + .maxTexelOffset = 7U, + + /* Requires shaderImageGatherExtended */ + .minTexelGatherOffset = 0, + .maxTexelGatherOffset = 0U, + + /* Requires sampleRateShading */ + .minInterpolationOffset = -0.5f, + .maxInterpolationOffset = 0.5f, + .subPixelInterpolationOffsetBits = 4U, + + .maxFramebufferWidth = 4096U, + .maxFramebufferHeight = 4096U, + .maxFramebufferLayers = 256U, + + .framebufferColorSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, + .framebufferDepthSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, + .framebufferStencilSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, + .framebufferNoAttachmentsSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, + .maxColorAttachments = 4U, + .sampledImageColorSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, + .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, + .sampledImageDepthSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, + .sampledImageStencilSampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, + .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT, /* Requires shaderStorageImageMultisample */ + .maxSampleMaskWords = 1U, + .timestampComputeAndGraphics = false, + .timestampPeriod = 0.0f, + + .maxClipDistances = PVR_MAX_USER_PLANES, + .maxCullDistances = PVR_MAX_USER_PLANES, + .maxCombinedClipAndCullDistances = PVR_MAX_USER_PLANES, + + .discreteQueuePriorities = 2U, + + .pointSizeRange[0] = PVR_POINT_SIZE_RANGE_MIN, + .pointSizeRange[1] = PVR_POINT_SIZE_RANGE_MAX, + .pointSizeGranularity = PVR_POINT_SIZE_GRANULARITY, + + /* Requires wideLines */ + .lineWidthRange[0] = 1.0f, + .lineWidthRange[1] = 1.0f, + .lineWidthGranularity = 0.0f, + + .strictLines = false, + .standardSampleLocations = true, + .optimalBufferCopyOffsetAlignment = PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT, + .optimalBufferCopyRowPitchAlignment = PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT, + .nonCoherentAtomSize = 1U, + + /* Vulkan 1.1 */ + .subgroupSize = 1, + .subgroupSupportedStages = VK_SHADER_STAGE_COMPUTE_BIT, + .subgroupSupportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT, + .subgroupQuadOperationsInAllStages = false, + .protectedNoFault = false, + + /* Vulkan 1.2 */ + .maxUpdateAfterBindDescriptorsInAllPools = 0, + .shaderUniformBufferArrayNonUniformIndexingNative = false, + .shaderSampledImageArrayNonUniformIndexingNative = false, + .shaderStorageBufferArrayNonUniformIndexingNative = false, + .shaderStorageImageArrayNonUniformIndexingNative = false, + .shaderInputAttachmentArrayNonUniformIndexingNative = false, + .robustBufferAccessUpdateAfterBind = false, + .quadDivergentImplicitLod = false, + .maxPerStageDescriptorUpdateAfterBindSamplers = 0, + .maxPerStageDescriptorUpdateAfterBindUniformBuffers = 0, + .maxPerStageDescriptorUpdateAfterBindStorageBuffers = 0, + .maxPerStageDescriptorUpdateAfterBindSampledImages = 0, + .maxPerStageDescriptorUpdateAfterBindStorageImages = 0, + .maxPerStageDescriptorUpdateAfterBindInputAttachments = 0, + .maxPerStageUpdateAfterBindResources = 0, + .maxDescriptorSetUpdateAfterBindSamplers = 0, + .maxDescriptorSetUpdateAfterBindUniformBuffers = 0, + .maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = 0, + .maxDescriptorSetUpdateAfterBindStorageBuffers = 0, + .maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = 0, + .maxDescriptorSetUpdateAfterBindSampledImages = 0, + .maxDescriptorSetUpdateAfterBindStorageImages = 0, + .maxDescriptorSetUpdateAfterBindInputAttachments = 0, + .filterMinmaxSingleComponentFormats = false, + .filterMinmaxImageComponentMapping = false, + .framebufferIntegerColorSampleCounts = + VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, + + /* Vulkan 1.0 / VK_KHR_maintenance2 */ + .pointClippingBehavior = + VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY, + + /* Vulkan 1.1 / VK_KHR_maintenance3 */ + .maxPerSetDescriptors = PVR_MAX_DESCRIPTORS_PER_SET, + .maxMemoryAllocationSize = max_memory_alloc_size, + + /* Vulkan 1.1 / VK_KHR_multiview */ + .maxMultiviewViewCount = PVR_MAX_MULTIVIEW, + .maxMultiviewInstanceIndex = (1 << 27) - 1, + + /* Vulkan 1.2 / VK_KHR_driver_properties */ + .driverID = VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA, + .driverName = "Imagination open-source Mesa driver", + .driverInfo = "Mesa " PACKAGE_VERSION MESA_GIT_SHA1, + .conformanceVersion = { + .major = 1, + .minor = 3, + .subminor = 8, + .patch = 4, + }, + + /* VK_EXT_extended_dynamic_state3 */ + .dynamicPrimitiveTopologyUnrestricted = false, + + /* VK_EXT_map_memory_placed */ + .minPlacedMemoryMapAlignment = pdevice->ws->page_size, + + /* VK_EXT_provoking_vertex */ + .provokingVertexModePerPipeline = true, + .transformFeedbackPreservesTriangleFanProvokingVertex = false, + + /* Vulkan 1.1 / VK_KHR_robustness2 */ + .robustStorageBufferAccessSizeAlignment = PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT, + .robustUniformBufferAccessSizeAlignment = PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT, + + /* Vulkan 1.2 / VK_KHR_shader_float_controls */ + .denormBehaviorIndependence = + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY, + .roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE, + .shaderSignedZeroInfNanPreserveFloat16 = true, + .shaderSignedZeroInfNanPreserveFloat32 = true, + .shaderSignedZeroInfNanPreserveFloat64 = true, + .shaderDenormPreserveFloat16 = true, + .shaderDenormPreserveFloat32 = false, + .shaderDenormPreserveFloat64 = true, + .shaderDenormFlushToZeroFloat16 = false, + .shaderDenormFlushToZeroFloat32 = false, + .shaderDenormFlushToZeroFloat64 = false, + .shaderRoundingModeRTEFloat16 = usc_alu_roundingmode_rne, + .shaderRoundingModeRTEFloat32 = usc_alu_roundingmode_rne, + .shaderRoundingModeRTEFloat64 = usc_alu_roundingmode_rne, + .shaderRoundingModeRTZFloat16 = !usc_alu_roundingmode_rne, + .shaderRoundingModeRTZFloat32 = !usc_alu_roundingmode_rne, + .shaderRoundingModeRTZFloat64 = !usc_alu_roundingmode_rne, + + /* Vulkan 1.2 / VK_KHR_timeline_semaphore */ + .maxTimelineSemaphoreValueDifference = UINT64_MAX, + + /* Vulkan 1.3 / VK_EXT_texel_buffer_alignment */ + .storageTexelBufferOffsetAlignmentBytes = PVR_TEXEL_BUFFER_OFFSET_ALIGNMENT, + .storageTexelBufferOffsetSingleTexelAlignment = true, + .uniformTexelBufferOffsetAlignmentBytes = PVR_TEXEL_BUFFER_OFFSET_ALIGNMENT, + .uniformTexelBufferOffsetSingleTexelAlignment = false, + + /* Vulkan 1.4 / VK_EXT_vertex_attribute_divisor / VK_KHR_vertex_attribute_divisor */ + .maxVertexAttribDivisor = UINT32_MAX, + .supportsNonZeroFirstInstance = true, + + /* VK_EXT_custom_border_color */ + .maxCustomBorderColorSamplers = PVR_BORDER_COLOR_TABLE_NR_CUSTOM_ENTRIES, + + /* VkPhysicalDeviceDrmPropertiesEXT */ + .drmHasPrimary = true, + .drmPrimaryMajor = (int64_t) major(pdevice->primary_devid), + .drmPrimaryMinor = (int64_t) minor(pdevice->primary_devid), + .drmHasRender = true, + .drmRenderMajor = (int64_t) major(pdevice->render_devid), + .drmRenderMinor = (int64_t) minor(pdevice->render_devid), + + /* Vulkan 1.2 / VK_KHR_depth_stencil_resolve */ + .supportedDepthResolveModes = + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, + .supportedStencilResolveModes = + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, + .independentResolveNone = true, + .independentResolve = true, + + /* VK_KHR_line_rasterization */ + .lineSubPixelPrecisionBits = line_sub_pixel_precision_bits, + }; + + if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) { + snprintf(properties->deviceName, + sizeof(properties->deviceName), + "PowerVR %s %s MC%u", + dev_info->ident.series_name, + dev_info->ident.public_name, + dev_runtime_info->core_count); + } else { + snprintf(properties->deviceName, + sizeof(properties->deviceName), + "PowerVR %s %s", + dev_info->ident.series_name, + dev_info->ident.public_name); + } + + return true; +} + +static bool pvr_physical_device_setup_pipeline_cache( + struct pvr_physical_device *const pdevice) +{ +#ifdef ENABLE_SHADER_CACHE + const struct pvr_instance *instance = pdevice->instance; + char device_id[SHA1_DIGEST_LENGTH * 2 + 1]; + char driver_id[SHA1_DIGEST_LENGTH * 2 + 1]; + + _mesa_sha1_format(device_id, pdevice->device_uuid); + _mesa_sha1_format(driver_id, instance->driver_build_sha); + + pdevice->vk.disk_cache = disk_cache_create(device_id, driver_id, 0U); + return !!pdevice->vk.disk_cache; +#else + return true; +#endif /* ENABLE_SHADER_CACHE */ +} + +static void +pvr_get_device_uuid(const struct pvr_device_info *dev_info, + uint8_t uuid_out[const static SHA1_DIGEST_LENGTH]) +{ + uint64_t bvnc = pvr_get_packed_bvnc(dev_info); + static const char *device_str = "pvr"; + struct mesa_sha1 sha1_ctx; + + _mesa_sha1_init(&sha1_ctx); + _mesa_sha1_update(&sha1_ctx, device_str, strlen(device_str)); + _mesa_sha1_update(&sha1_ctx, &bvnc, sizeof(bvnc)); + _mesa_sha1_final(&sha1_ctx, uuid_out); +} + +static void +pvr_get_cache_uuid(const struct pvr_physical_device *const pdevice, + uint8_t uuid_out[const static SHA1_DIGEST_LENGTH]) +{ + const struct pvr_instance *instance = pdevice->instance; + static const char *cache_str = "cache"; + struct mesa_sha1 sha1_ctx; + + _mesa_sha1_init(&sha1_ctx); + _mesa_sha1_update(&sha1_ctx, cache_str, strlen(cache_str)); + _mesa_sha1_update(&sha1_ctx, + pdevice->device_uuid, + sizeof(pdevice->device_uuid)); + _mesa_sha1_update(&sha1_ctx, + instance->driver_build_sha, + sizeof(instance->driver_build_sha)); + _mesa_sha1_final(&sha1_ctx, uuid_out); +} + +static void +pvr_physical_device_setup_uuids(struct pvr_physical_device *const pdevice) +{ + const struct pvr_instance *instance = pdevice->instance; + + pvr_get_device_uuid(&pdevice->dev_info, pdevice->device_uuid); + pvr_get_cache_uuid(pdevice, pdevice->cache_uuid); + + memcpy(pdevice->vk.properties.driverUUID, + instance->driver_build_sha, + sizeof(pdevice->vk.properties.driverUUID)); + + memcpy(pdevice->vk.properties.deviceUUID, + pdevice->device_uuid, + sizeof(pdevice->vk.properties.deviceUUID)); + + memcpy(pdevice->vk.properties.pipelineCacheUUID, + pdevice->cache_uuid, + sizeof(pdevice->vk.properties.pipelineCacheUUID)); + + memcpy(pdevice->vk.properties.shaderBinaryUUID, + pdevice->cache_uuid, + sizeof(pdevice->vk.properties.shaderBinaryUUID)); +} + +static bool pvr_device_is_conformant(const struct pvr_device_info *info) +{ + const uint64_t bvnc = pvr_get_packed_bvnc(info); + switch (bvnc) { + case PVR_BVNC_PACK(36, 53, 104, 796): + return true; + + default: + break; + } + + return false; +} + +/* Minimum required by the Vulkan 1.1 spec (see Table 32. Required Limits) */ +#define PVR_MAX_MEMORY_ALLOCATION_SIZE (1ull << 30) + +static uint64_t pvr_compute_heap_size(void) +{ + /* Query the total ram from the system */ + uint64_t total_ram; + if (!os_get_total_physical_memory(&total_ram)) + return 0; + + if (total_ram < PVR_MAX_MEMORY_ALLOCATION_SIZE) { + mesa_logw( + "Warning: The available RAM is below the minimum required by the Vulkan specification!"); + } + + /* We don't want to burn too much ram with the GPU. If the user has 4GiB + * or less, we use at most half. If they have more than 4GiB, we use 3/4. + */ + uint64_t available_ram; + if (total_ram <= 4ULL * 1024ULL * 1024ULL * 1024ULL) + available_ram = total_ram / 2U; + else + available_ram = total_ram * 3U / 4U; + + return MAX2(available_ram, PVR_MAX_MEMORY_ALLOCATION_SIZE); +} + +VkResult pvr_physical_device_init(struct pvr_physical_device *pdevice, + struct pvr_instance *instance, + drmDevicePtr drm_render_device, + drmDevicePtr drm_display_device) +{ + struct vk_physical_device_dispatch_table dispatch_table; + struct vk_device_extension_table supported_extensions; + struct vk_properties supported_properties; + struct vk_features supported_features; + struct pvr_winsys *ws; + struct stat primary_stat = { 0 }, render_stat = { 0 }; + char *primary_path; + char *display_path; + char *render_path; + VkResult result; + + render_path = vk_strdup(&instance->vk.alloc, + drm_render_device->nodes[DRM_NODE_RENDER], + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (!render_path) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto err_out; + } + + if (instance->vk.enabled_extensions.KHR_display) { + display_path = vk_strdup(&instance->vk.alloc, + drm_display_device->nodes[DRM_NODE_PRIMARY], + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (!display_path) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto err_vk_free_render_path; + } + } else { + display_path = NULL; + } + + primary_path = drm_render_device->nodes[DRM_NODE_PRIMARY]; + if (stat(primary_path, &primary_stat) != 0) { + result = vk_errorf(instance, + VK_ERROR_INITIALIZATION_FAILED, + "failed to stat DRM primary node %s", + primary_path); + goto err_vk_free_display_path; + } + pdevice->primary_devid = primary_stat.st_rdev; + + if (stat(render_path, &render_stat) != 0) { + result = vk_errorf(instance, + VK_ERROR_INITIALIZATION_FAILED, + "failed to stat DRM render node %s", + render_path); + goto err_vk_free_display_path; + } + pdevice->render_devid = render_stat.st_rdev; + + result = + pvr_winsys_create(render_path, display_path, &instance->vk.alloc, &ws); + if (result != VK_SUCCESS) + goto err_vk_free_display_path; + + pdevice->instance = instance; + pdevice->render_path = render_path; + pdevice->display_path = display_path; + pdevice->ws = ws; + + result = ws->ops->device_info_init(ws, + &pdevice->dev_info, + &pdevice->dev_runtime_info); + if (result != VK_SUCCESS) + goto err_pvr_winsys_destroy; + + if (!pvr_device_is_conformant(&pdevice->dev_info)) { + if (!os_get_option("PVR_I_WANT_A_BROKEN_VULKAN_DRIVER")) { + result = vk_errorf(instance, + VK_ERROR_INCOMPATIBLE_DRIVER, + "WARNING: powervr is not a conformant Vulkan " + "implementation for %s. Pass " + "PVR_I_WANT_A_BROKEN_VULKAN_DRIVER=1 if you know " + "what you're doing.", + pdevice->dev_info.ident.public_name); + goto err_pvr_winsys_destroy; + } + + vk_warn_non_conformant_implementation("powervr"); + } + + /* Setup available memory heaps and types */ + pdevice->memory.memoryHeapCount = 1; + pdevice->memory.memoryHeaps[0].size = pvr_compute_heap_size(); + pdevice->memory.memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; + + pdevice->memory.memoryTypeCount = 1; + pdevice->memory.memoryTypes[0].propertyFlags = + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + pdevice->memory.memoryTypes[0].heapIndex = 0; + + pvr_physical_device_get_supported_extensions(&supported_extensions); + pvr_physical_device_get_supported_features(&pdevice->dev_info, + &supported_features); + if (!pvr_physical_device_get_properties(pdevice, &supported_properties)) { + result = vk_errorf(instance, + VK_ERROR_INITIALIZATION_FAILED, + "Failed to collect physical device properties"); + goto err_pvr_winsys_destroy; + } + + vk_physical_device_dispatch_table_from_entrypoints( + &dispatch_table, + &pvr_physical_device_entrypoints, + true); + + vk_physical_device_dispatch_table_from_entrypoints( + &dispatch_table, + &wsi_physical_device_entrypoints, + false); + + result = vk_physical_device_init(&pdevice->vk, + &instance->vk, + &supported_extensions, + &supported_features, + &supported_properties, + &dispatch_table); + if (result != VK_SUCCESS) + goto err_pvr_winsys_destroy; + + pvr_physical_device_setup_uuids(pdevice); + + if (!pvr_physical_device_setup_pipeline_cache(pdevice)) { + result = vk_errorf(NULL, + VK_ERROR_INITIALIZATION_FAILED, + "Failed to get driver build sha."); + goto err_vk_physical_device_finish; + } + + pdevice->vk.supported_sync_types = ws->sync_types; + + pdevice->pco_ctx = pco_ctx_create(&pdevice->dev_info, NULL); + if (!pdevice->pco_ctx) { + result = vk_errorf(instance, + VK_ERROR_INITIALIZATION_FAILED, + "Failed to initialize PCO compiler context"); + goto err_free_pipeline_cache; + } + pco_ctx_setup_usclib(pdevice->pco_ctx, + pco_usclib_0_nir, + sizeof(pco_usclib_0_nir)); + + result = pvr_wsi_init(pdevice); + if (result != VK_SUCCESS) { + vk_error(instance, result); + goto err_free_pco_ctx; + } + + return VK_SUCCESS; + +err_free_pco_ctx: + ralloc_free(pdevice->pco_ctx); + +err_free_pipeline_cache: + pvr_physical_device_free_pipeline_cache(pdevice); + +err_vk_physical_device_finish: + vk_physical_device_finish(&pdevice->vk); + +err_pvr_winsys_destroy: + pvr_winsys_destroy(ws); + +err_vk_free_display_path: + vk_free(&instance->vk.alloc, display_path); + +err_vk_free_render_path: + vk_free(&instance->vk.alloc, render_path); + +err_out: + return result; +} + +const static VkQueueFamilyProperties pvr_queue_family_properties = { + .queueFlags = VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | + VK_QUEUE_TRANSFER_BIT, + .queueCount = PVR_MAX_QUEUES, + .timestampValidBits = 0, + .minImageTransferGranularity = { 1, 1, 1 }, +}; + +void pvr_GetPhysicalDeviceQueueFamilyProperties2( + VkPhysicalDevice physicalDevice, + uint32_t *pQueueFamilyPropertyCount, + VkQueueFamilyProperties2 *pQueueFamilyProperties) +{ + VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties2, + out, + pQueueFamilyProperties, + pQueueFamilyPropertyCount); + + vk_outarray_append_typed (VkQueueFamilyProperties2, &out, p) { + p->queueFamilyProperties = pvr_queue_family_properties; + + vk_foreach_struct (ext, p->pNext) { + vk_debug_ignored_stype(ext->sType); + } + } +} + +void pvr_GetPhysicalDeviceMemoryProperties2( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties2 *pMemoryProperties) +{ + VK_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice); + + pMemoryProperties->memoryProperties = pdevice->memory; + + vk_foreach_struct (ext, pMemoryProperties->pNext) { + vk_debug_ignored_stype(ext->sType); + } +} + +VkResult pvr_CreateDevice(VkPhysicalDevice physicalDevice, + const VkDeviceCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDevice *pDevice) +{ + VK_FROM_HANDLE(pvr_physical_device, pdevice, physicalDevice); + return pvr_create_device(pdevice, pCreateInfo, pAllocator, pDevice); +} + +void pvr_DestroyDevice(VkDevice _device, + const VkAllocationCallbacks *pAllocator) +{ + VK_FROM_HANDLE(pvr_device, device, _device); + + pvr_destroy_device(device, pAllocator); +} diff --git a/src/imagination/vulkan/pvr_physical_device.h b/src/imagination/vulkan/pvr_physical_device.h new file mode 100644 index 00000000000..5f0a54a5b2e --- /dev/null +++ b/src/imagination/vulkan/pvr_physical_device.h @@ -0,0 +1,90 @@ +/* + * Copyright © 2022 Imagination Technologies Ltd. + * + * based in part on anv driver which is: + * Copyright © 2015 Intel Corporation + * + * based in part on radv driver which is: + * Copyright © 2016 Red Hat. + * Copyright © 2016 Bas Nieuwenhuizen + * + * SPDX-License-Identifier: MIT + */ + +#ifndef PVR_PHYSICAL_DEVICE_H +#define PVR_PHYSICAL_DEVICE_H + +#include "vk_physical_device.h" + +#include +#include +#include + +#include "util/mesa-sha1.h" + +#include "wsi_common.h" + +#include "pvr_device_info.h" +#include "pvr_instance.h" + +#if defined(VK_USE_PLATFORM_DISPLAY_KHR) || \ + defined(VK_USE_PLATFORM_WAYLAND_KHR) +# define PVR_USE_WSI_PLATFORM true +#else +# define PVR_USE_WSI_PLATFORM false +#endif + +struct pvr_instance; +typedef struct _pco_ctx pco_ctx; + +struct pvr_physical_device { + struct vk_physical_device vk; + + /* Back-pointer to instance */ + struct pvr_instance *instance; + + char *render_path; + char *display_path; + + /* primary node (cardN) of the render device */ + dev_t primary_devid; + /* render node (renderN) of the render device */ + dev_t render_devid; + + struct pvr_winsys *ws; + struct pvr_device_info dev_info; + struct pvr_device_runtime_info dev_runtime_info; + + VkPhysicalDeviceMemoryProperties memory; + + struct wsi_device wsi_device; + + pco_ctx *pco_ctx; + + uint8_t device_uuid[SHA1_DIGEST_LENGTH]; + uint8_t cache_uuid[SHA1_DIGEST_LENGTH]; +}; + +VK_DEFINE_HANDLE_CASTS(pvr_physical_device, + vk.base, + VkPhysicalDevice, + VK_OBJECT_TYPE_PHYSICAL_DEVICE) + +VkResult +pvr_physical_device_init(struct pvr_physical_device *pdevice, + struct pvr_instance *instance, + drmDevicePtr drm_render_device, + drmDevicePtr drm_display_device); + +void +pvr_physical_device_dump_info(const struct pvr_physical_device *pdevice, + char *const *comp_display, + char *const *comp_render); + +void +pvr_physical_device_destroy(struct vk_physical_device *vk_pdevice); + +void +pvr_physical_device_free_pipeline_cache(struct pvr_physical_device *const pdevice); + +#endif /* PVR_PHYSICAL_DEVICE_H */ diff --git a/src/imagination/vulkan/pvr_pipeline.c b/src/imagination/vulkan/pvr_pipeline.c index 7bd98284380..ad574112f8e 100644 --- a/src/imagination/vulkan/pvr_pipeline.c +++ b/src/imagination/vulkan/pvr_pipeline.c @@ -47,6 +47,7 @@ #include "pvr_hw_pass.h" #include "pvr_pass.h" #include "pvr_pds.h" +#include "pvr_physical_device.h" #include "pvr_robustness.h" #include "pvr_types.h" #include "pvr_usc.h" diff --git a/src/imagination/vulkan/pvr_query.c b/src/imagination/vulkan/pvr_query.c index 1e1a306c912..a87f163bd8f 100644 --- a/src/imagination/vulkan/pvr_query.c +++ b/src/imagination/vulkan/pvr_query.c @@ -41,6 +41,7 @@ #include "pvr_hw_pass.h" #include "pvr_macros.h" #include "pvr_pass.h" +#include "pvr_physical_device.h" #include "util/macros.h" #include "util/os_time.h" #include "vk_log.h" diff --git a/src/imagination/vulkan/pvr_query_compute.c b/src/imagination/vulkan/pvr_query_compute.c index b610ab8fa79..8c17e6c5194 100644 --- a/src/imagination/vulkan/pvr_query_compute.c +++ b/src/imagination/vulkan/pvr_query_compute.c @@ -38,6 +38,7 @@ #include "pvr_formats.h" #include "pvr_macros.h" #include "pvr_pds.h" +#include "pvr_physical_device.h" #include "pvr_pipeline.h" #include "pvr_query.h" #include "pvr_tex_state.h" diff --git a/src/imagination/vulkan/pvr_queue.c b/src/imagination/vulkan/pvr_queue.c index 36f9339926e..87cd1b1a228 100644 --- a/src/imagination/vulkan/pvr_queue.c +++ b/src/imagination/vulkan/pvr_queue.c @@ -46,6 +46,7 @@ #include "pvr_job_render.h" #include "pvr_job_transfer.h" #include "pvr_limits.h" +#include "pvr_physical_device.h" #include "pvr_pipeline.h" #include "util/macros.h" diff --git a/src/imagination/vulkan/pvr_spm.c b/src/imagination/vulkan/pvr_spm.c index 3dfb2f435cb..11e12fb50c3 100644 --- a/src/imagination/vulkan/pvr_spm.c +++ b/src/imagination/vulkan/pvr_spm.c @@ -40,6 +40,7 @@ #include "pvr_macros.h" #include "pvr_pass.h" #include "pvr_pds.h" +#include "pvr_physical_device.h" #include "pvr_spm.h" #include "pvr_tex_state.h" #include "pvr_types.h" diff --git a/src/imagination/vulkan/pvr_tex_state.c b/src/imagination/vulkan/pvr_tex_state.c index d2cc080a54d..25dcb59dab5 100644 --- a/src/imagination/vulkan/pvr_tex_state.c +++ b/src/imagination/vulkan/pvr_tex_state.c @@ -30,6 +30,7 @@ #include "pvr_device.h" #include "pvr_device_info.h" #include "pvr_formats.h" +#include "pvr_physical_device.h" #include "pvr_tex_state.h" #include "util/macros.h" #include "util/u_math.h" diff --git a/src/imagination/vulkan/pvr_transfer_frag_store.c b/src/imagination/vulkan/pvr_transfer_frag_store.c index 3908d6f6978..b328274918d 100644 --- a/src/imagination/vulkan/pvr_transfer_frag_store.c +++ b/src/imagination/vulkan/pvr_transfer_frag_store.c @@ -33,6 +33,7 @@ #include "pvr_device_info.h" #include "pvr_job_transfer.h" #include "pvr_pds.h" +#include "pvr_physical_device.h" #include "pvr_transfer_frag_store.h" #include "pvr_types.h" #include "pvr_usc.h" diff --git a/src/imagination/vulkan/pvr_wsi.c b/src/imagination/vulkan/pvr_wsi.c index 3cd836413e2..8134a9c7030 100644 --- a/src/imagination/vulkan/pvr_wsi.c +++ b/src/imagination/vulkan/pvr_wsi.c @@ -33,10 +33,13 @@ #include "pvr_device.h" #include "pvr_entrypoints.h" +#include "pvr_instance.h" +#include "pvr_physical_device.h" #include "pvr_queue.h" #include "util/u_atomic.h" #include "vk_object.h" +#include "vk_instance.h" #include "wsi_common.h" static PFN_vkVoidFunction pvr_wsi_proc_addr(VkPhysicalDevice physicalDevice, diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv.c index 1c17e4bcfd5..8c0c79fd546 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv.c +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv.c @@ -30,6 +30,7 @@ #include "pvr_csb.h" #include "pvr_device.h" #include "pvr_device_info.h" +#include "pvr_physical_device.h" #include "pvr_srv.h" #include "pvr_srv_bo.h" #include "pvr_srv_bridge.h"