This commit is contained in:
elwrcl committed 2026-06-06 13:25:15 +03:00
1 parent 04d4dc8b09
commit 818cab85dc
12511 files changed
+6156641

No files matched your search

+380
View File
@@ -0,0 +1,380 @@
# Copyright © 2022 Imagination Technologies Ltd.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
Language: Cpp
Standard: c++11
UseCRLF: false
ColumnLimit: 80
DeriveLineEnding: false
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
DisableFormat: false
########
# Tabs #
########
UseTab: Never
TabWidth: 3
ConstructorInitializerIndentWidth: 6
ContinuationIndentWidth: 3
IndentWidth: 3
#IndentCaseBlocks: true # Requires clang-11
IndentCaseLabels: false
#IndentExternBlock: NoIndent # Requires clang-11
IndentGotoLabels: false
IndentPPDirectives: AfterHash
IndentWrappedFunctionNames: false
AccessModifierOffset: -4 # -IndentWidth
NamespaceIndentation: None
##########
# Braces #
##########
AlignAfterOpenBracket: Align
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
BinPackArguments: false
BinPackParameters: false
Cpp11BracedListStyle: false
########################
# Whitespace Alignment #
########################
AlignConsecutiveAssignments: None
#AlignConsecutiveBitFields: false # Requires clang-11
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: None
AlignTrailingComments: false
AlignEscapedNewlines: Left
#AlignOperands: Align # Requires clang-11
#BitFieldColonSpacing: Both # Requires clang-12
PointerAlignment: Right
#SpaceAroundPointerQualifiers: Both # Requires clang-12
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
#SpaceBeforeParens: ControlStatementsExceptForEachMacros # Requires clang-11
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesInAngles: Never
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpacesBeforeTrailingComments: 2
############################
# Multi-line constructions #
############################
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
#AllowShortEnumsOnASingleLine: false # Requires clang-11
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
# BeforeLambdaBody: false # Requires clang-11
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyNamespace: true
SplitEmptyRecord: true
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
BreakStringLiterals: false
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
#InsertTrailingCommas: Wrapped # Requires clang-11
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
SortUsingDeclarations: true
############
# Includes #
############
# TODO: Temporary config
IncludeBlocks: Preserve
SortIncludes: Never
# TODO: This requires additional work to clean up headers & includes first
#IncludeBlocks: Regroup
#SortIncludes: true
#IncludeIsMainRegex: '(_test)?$'
##IncludeIsMainSourceRegex: <default>
#IncludeCategories:
# - Regex: '^"'
# Priority: 1
############
# Comments #
############
FixNamespaceComments: false
#############
# Penalties #
#############
# Taken from torvalds/kernel:.clang-format
PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60
#######################
# User-defined macros #
#######################
CommentPragmas: '^ IWYU pragma:'
MacroBlockBegin: ''
MacroBlockEnd: ''
#AttributeMacros: [] # Requires clang-12
ForEachMacros: [
'BITSET_FOREACH_SET',
'foreach_instr',
'foreach_instr_safe',
'foreach_list_typed',
'foreach_list_typed_from',
'foreach_list_typed_from_reverse',
'foreach_list_typed_reverse',
'foreach_list_typed_reverse_safe',
'foreach_list_typed_safe',
'foreach_target',
'hash_table_foreach',
'hash_table_u64_foreach',
'LIST_FOR_EACH_ENTRY',
'LIST_FOR_EACH_ENTRY_FROM',
'LIST_FOR_EACH_ENTRY_FROM_REV',
'LIST_FOR_EACH_ENTRY_SAFE',
'LIST_FOR_EACH_ENTRY_SAFE_REV',
'list_for_each_entry',
'list_for_each_entry_from',
'list_for_each_entry_from_rev',
'list_for_each_entry_from_safe',
'list_for_each_entry_rev',
'list_for_each_entry_safe',
'list_for_each_entry_safe_rev',
'list_pair_for_each_entry',
'pvr_csb_emit',
'pvr_csb_pack',
'nir_foreach_block',
'nir_foreach_block_safe',
'nir_foreach_block_unstructured',
'nir_foreach_reg_decl',
'nir_foreach_entrypoint',
'nir_foreach_entrypoint_safe',
'nir_foreach_function',
'nir_foreach_function_with_impl',
'nir_foreach_instr',
'nir_foreach_instr_safe',
'nir_foreach_phi_src',
'nir_foreach_shader_in_variable',
'nir_foreach_shader_out_variable',
'nir_foreach_use',
'nir_foreach_use_safe',
'nir_foreach_variable_with_modes',
'nir_foreach_variable_with_modes_safe',
'pco_foreach_block_in_func',
'pco_foreach_block_in_func_from',
'pco_foreach_block_in_func_from_rev',
'pco_foreach_block_in_func_rev',
'pco_foreach_cf_node_in_func',
'pco_foreach_cf_node_in_func_structured',
'pco_foreach_cf_node_in_if_else',
'pco_foreach_cf_node_in_if_epilogue',
'pco_foreach_cf_node_in_if_interlogue',
'pco_foreach_cf_node_in_if_prologue',
'pco_foreach_cf_node_in_if_then',
'pco_foreach_cf_node_in_loop',
'pco_foreach_cf_node_in_loop_epilogue',
'pco_foreach_cf_node_in_loop_interlogue',
'pco_foreach_cf_node_in_loop_prologue',
'pco_foreach_func_in_shader',
'pco_foreach_func_in_shader_rev',
'pco_foreach_if_in_func',
'pco_foreach_if_in_func_from',
'pco_foreach_if_in_func_from_rev',
'pco_foreach_if_in_func_rev',
'pco_foreach_ssa_bool_if_in_func',
'pco_foreach_ssa_if_in_func',
'pco_foreach_igrp_in_block',
'pco_foreach_igrp_in_func',
'pco_foreach_instr_dest',
'pco_foreach_instr_dest_from',
'pco_foreach_instr_dest_hwreg',
'pco_foreach_instr_dest_ssa',
'pco_foreach_instr_dest_ssa_from',
'pco_foreach_instr_dest_vreg',
'pco_foreach_instr_dest_vreg_ssa',
'pco_foreach_instr_in_block',
'pco_foreach_instr_in_block_from',
'pco_foreach_instr_in_block_from_rev',
'pco_foreach_instr_in_block_rev',
'pco_foreach_instr_in_block_safe',
'pco_foreach_instr_in_block_safe_rev',
'pco_foreach_instr_in_func',
'pco_foreach_instr_in_func_from',
'pco_foreach_instr_in_func_from_rev',
'pco_foreach_instr_in_func_rev',
'pco_foreach_instr_in_func_safe',
'pco_foreach_instr_in_func_safe_rev',
'pco_foreach_instr_in_igrp',
'pco_foreach_instr_in_igrp_rev',
'pco_foreach_instr_src',
'pco_foreach_instr_src_from',
'pco_foreach_instr_src_hwreg',
'pco_foreach_instr_src_ssa',
'pco_foreach_instr_src_ssa_from',
'pco_foreach_instr_src_vreg',
'pco_foreach_instr_src_vreg_ssa',
'pco_foreach_instr_src_vtxin_reg',
'pco_foreach_loop_in_func',
'pco_foreach_loop_in_func_from',
'pco_foreach_loop_in_func_from_rev',
'pco_foreach_loop_in_func_rev',
'pco_foreach_phase',
'pco_foreach_phase_from',
'pco_foreach_phase_from_rev',
'pco_foreach_phase_in_igrp',
'pco_foreach_phase_in_igrp_from',
'pco_foreach_phase_in_igrp_from_rev',
'pco_foreach_phase_in_igrp_rev',
'pco_foreach_phase_rev',
'pco_foreach_phi_src_in_instr',
'pco_foreach_vreg_if_in_func',
'pco_foreach_vreg_ssa_if_in_func',
'pvr_foreach_supported_tex_format',
'pvr_foreach_supported_tex_format_',
'pvr_foreach_supported_tex_format_compressed',
'pvr_foreach_supported_tex_format_compressed_',
'rogue_foreach_block',
'rogue_foreach_block_safe',
'rogue_foreach_block_rev',
'rogue_foreach_block_safe_rev',
'rogue_foreach_block_use',
'rogue_foreach_block_use_safe',
'rogue_foreach_drc_trxn',
'rogue_foreach_drc_trxn_safe',
'rogue_foreach_phase_in_set',
'rogue_foreach_phase_in_set_rev',
'rogue_foreach_imm_use',
'rogue_foreach_imm_use_safe',
'rogue_foreach_instr_group_in_block',
'rogue_foreach_instr_group_in_block_safe',
'rogue_foreach_instr_group_in_shader',
'rogue_foreach_instr_group_in_shader_safe',
'rogue_foreach_instr_in_block',
'rogue_foreach_instr_in_block_safe',
'rogue_foreach_instr_in_block_rev',
'rogue_foreach_instr_in_block_safe_rev',
'rogue_foreach_instr_in_shader',
'rogue_foreach_instr_in_shader_safe',
'rogue_foreach_instr_in_shader_rev',
'rogue_foreach_instr_in_shader_safe_rev',
'rogue_foreach_mod_in_set',
'rogue_foreach_reg',
'rogue_foreach_reg_safe',
'rogue_foreach_reg_use',
'rogue_foreach_reg_use_safe',
'rogue_foreach_reg_write',
'rogue_foreach_reg_write_safe',
'rogue_foreach_regarray',
'rogue_foreach_regarray_safe',
'rogue_foreach_regarray_use',
'rogue_foreach_regarray_use_safe',
'rogue_foreach_regarray_write',
'rogue_foreach_regarray_write_safe',
'rogue_foreach_subarray',
'rogue_foreach_subarray_safe',
'rb_tree_foreach',
'rb_tree_foreach_safe',
'u_foreach_bit',
'u_foreach_bit64',
'u_vector_foreach',
'util_dynarray_foreach',
'util_dynarray_foreach_reverse',
'vk_foreach_struct',
'vk_foreach_struct_const',
# FIXME: vk_outarray_append doesn't fit here, remove
# it when a better solution exists for it.
'vk_outarray_append',
'vk_outarray_append_typed'
]
NamespaceMacros: [
]
StatementMacros: [
]
TypenameMacros: [
]
#WhitespaceSensitiveMacros: [] # Requires clang-11
+9
View File
@@ -0,0 +1,9 @@
((nil . ((show-trailing-whitespace . t)))
(prog-mode
(indent-tabs-mode . nil)
(tab-width . 3)
(c-basic-offset . 3)
(c-file-style . "linux")
(fill-column . 80)
)
)
+6
View File
@@ -0,0 +1,6 @@
[*.{c,h,cpp,hpp,cc,hh}]
max_line_length = 80
[*.xml]
indent_style = space
indent_size = 2
+1
View File
@@ -0,0 +1 @@
+88
View File
@@ -0,0 +1,88 @@
dEQP-VK.api.buffer_view.access.suballocation.buffer_view_memory_test_complete_compute
dEQP-VK.api.copy_and_blit.copy_commands2.blit_image.all_formats.color.1d.r32g32_uint.r32g32_uint.optimal_optimal_nearest
dEQP-VK.api.copy_and_blit.copy_commands2.blit_image.all_formats.color.2d.etc2_r8g8b8a1_srgb_block.a8b8g8r8_srgb_pack32.optimal_general_nearest
dEQP-VK.api.copy_and_blit.core.blit_image.all_formats.color.2d.a1r5g5b5_unorm_pack16.b10g11r11_ufloat_pack32.general_general_nearest
dEQP-VK.api.copy_and_blit.core.blit_image.all_formats.color.2d.b4g4r4a4_unorm_pack16.b10g11r11_ufloat_pack32.optimal_optimal_nearest
dEQP-VK.api.copy_and_blit.core.blit_image.all_formats.color.2d.eac_r11g11_unorm_block.r8g8_snorm.general_general_linear
dEQP-VK.api.copy_and_blit.core.blit_image.all_formats.color.2d.etc2_r8g8b8_srgb_block.r8g8b8a8_srgb.optimal_general_nearest
dEQP-VK.api.copy_and_blit.core.blit_image.all_formats.color.2d.etc2_r8g8b8a1_unorm_block.b4g4r4a4_unorm_pack16.general_optimal_nearest
dEQP-VK.api.copy_and_blit.core.blit_image.all_formats.color.2d.r16g16_sfloat.r16g16_unorm.optimal_general_nearest
dEQP-VK.api.copy_and_blit.core.blit_image.all_formats.color.2d.r8_unorm.r8g8_unorm.optimal_optimal_nearest
dEQP-VK.api.copy_and_blit.core.image_to_image.all_formats.color.2d_to_2d.r16_unorm.r16_unorm.general_optimal
dEQP-VK.api.copy_and_blit.core.image_to_image.cube.cube_to_array_whole
dEQP-VK.api.copy_and_blit.dedicated_allocation.blit_image.simple_tests.mirror_subregions_3d.r32_sfloat_linear
dEQP-VK.api.image_clearing.core.clear_color_image.2d.linear.single_layer.a2b10g10r10_unorm_pack32_64x11
dEQP-VK.api.image_clearing.core.clear_color_image.2d.optimal.single_layer.a8b8g8r8_sint_pack32_1x33_multiple_subresourcerange
dEQP-VK.api.image_clearing.dedicated_allocation.clear_color_image.1d.linear.single_layer.r8g8b8a8_uint_71x1
dEQP-VK.binding_model.shader_access.primary_cmd_buf.bind.combined_image_sampler_immutable.no_access.multiple_descriptor_sets.multiple_contiguous_descriptors.cube_array
dEQP-VK.binding_model.shader_access.primary_cmd_buf.bind.storage_buffer_dynamic.no_access.multiple_descriptor_sets.descriptor_array.offset_view_zero_dynamic_nonzero
dEQP-VK.binding_model.shader_access.primary_cmd_buf.bind.with_template.uniform_buffer_dynamic.vertex_fragment.multiple_arbitrary_descriptors.offset_view_nonzero_dynamic_zero
dEQP-VK.draw.dynamic_rendering.primary_cmd_buff.instanced.draw_indexed_indirect_vk_primitive_topology_line_list_attrib_divisor_0_multiview
dEQP-VK.draw.dynamic_rendering.primary_cmd_buff.instanced.draw_indirect_vk_primitive_topology_triangle_list_attrib_divisor_20_multiview
dEQP-VK.draw.renderpass.instanced.draw_indexed_indirect_vk_primitive_topology_point_list_attrib_divisor_20_multiview
dEQP-VK.draw.renderpass.instanced.draw_indexed_indirect_vk_primitive_topology_triangle_fan_attrib_divisor_2_multiview
dEQP-VK.draw.renderpass.instanced.draw_indirect_vk_primitive_topology_triangle_fan_khr_attrib_divisor_2_multiview
dEQP-VK.draw.renderpass.vertex_attribute_divisor.khr.static_pipeline.draw_indexed.non_zero.0
dEQP-VK.glsl.conversions.vector_to_vector.ivec3_to_bvec3_fragment
dEQP-VK.glsl.matrix.mul.const.highp_mat3x2_vec3_fragment
dEQP-VK.glsl.switch.switch_in_switch_uniform_vertex
dEQP-VK.glsl.texture_functions.query.texturequerylevels.usampler2d_fragment
dEQP-VK.glsl.texture_functions.query.texturesize.usampler2d_vertex
dEQP-VK.glsl.texture_functions.texture.sampler2darrayshadow_fragment
dEQP-VK.graphicsfuzz.cov-nested-loop-not-greater-than-increment-array-element
dEQP-VK.graphicsfuzz.find-msb-from-lsb
dEQP-VK.graphicsfuzz.function-with-float-comparison
dEQP-VK.graphicsfuzz.increment-value-in-nested-for-loop
dEQP-VK.graphicsfuzz.stable-mergesort-clamped-conditional-bit-shift
dEQP-VK.image.atomic_operations.dec.3d.notransfer.normal_read.normal_img.r32i_intermediate_values
dEQP-VK.image.atomic_operations.exchange.3d.transfer.normal_read.normal_img.r32ui_intermediate_values
dEQP-VK.image.atomic_operations.xor.2d_array.notransfer.normal_read.normal_img.r32i_intermediate_values
dEQP-VK.image.format_reinterpret.2d_array.r16_snorm_r8g8_unorm
dEQP-VK.image.format_reinterpret.cube.r16g16b16a16_sint_r16g16b16a16_unorm
dEQP-VK.image.format_reinterpret.cube_array.r32_sint_r32_uint
dEQP-VK.image.mutable.2d_array.r8g8b8a8_snorm_r8g8b8a8_sint_copy_texture_format_list
dEQP-VK.memory.pipeline_barrier.host_write_index_buffer.1048576
dEQP-VK.memory.zero_initialize_device_memory.image_transition.r8g8_unorm_sampled_shader_frag_512x512_first_mip
dEQP-VK.pipeline.monolithic.blend.format.r16g16b16_snorm.states.color_z_1mdc_rsub_alpha_1msa_cc_sub-color_da_1msc_min_alpha_1msc_sc_add-color_sa_sas_add_alpha_z_o_sub-color_dc_1msc_max_alpha_sa_da_sub
dEQP-VK.pipeline.monolithic.depth.format.d32_sfloat_s8_uint_separate_layouts.compare_ops.triangle_list_equal_greater_greater_or_equal_not_equal
dEQP-VK.pipeline.monolithic.multisample.std_sample_locations.draw.depth.samples_1.separate_renderpass_clear_attachments_same_pattern_secondary_cmd_buf
dEQP-VK.pipeline.monolithic.render_to_image.core.1d_array.mipmap.r32g32b32a32_sfloat_d32_sfloat_s8_uint
dEQP-VK.pipeline.monolithic.render_to_image.dedicated_allocation.1d.mipmap.r32_uint
dEQP-VK.pipeline.monolithic.sampler.border_swizzle.r16g16b16_snorm.1gba.transparent_black.gather_3.no_swizzle_hint
dEQP-VK.pipeline.monolithic.sampler.border_swizzle.r32g32b32_uint.rgb1.opaque_white.gather_3.with_swizzle_hint
dEQP-VK.pipeline.monolithic.sampler.border_swizzle.r8g8_uint.r1ba.transparent_black.no_gather.no_swizzle_hint
dEQP-VK.pipeline.monolithic.sampler.border_swizzle.r8g8b8_uint.r1ba.transparent_black.gather_3.no_swizzle_hint
dEQP-VK.pipeline.monolithic.sampler.view_type.2d_array.format.d32_sfloat.address_modes.uvw_mode_mirrored_repeat_mode_repeat_mode_clamp_to_border
dEQP-VK.pipeline.monolithic.stencil.format.d24_unorm_s8_uint.states.fail_decc.pass_decc.dfail_zero.comp_always.any
dEQP-VK.pipeline.monolithic.stencil.format.d24_unorm_s8_uint.states.fail_zero.pass_keep.dfail_repl.comp_never.any
dEQP-VK.pipeline.monolithic.stencil.format.d24_unorm_s8_uint_separate_layouts.states.fail_repl.pass_decw.dfail_zero.comp_greater.any
dEQP-VK.pipeline.monolithic.stencil.format.d24_unorm_s8_uint_separate_layouts.states.fail_wrap.pass_incc.dfail_decc.comp_always.any
dEQP-VK.pipeline.monolithic.stencil.format.d32_sfloat_s8_uint_separate_layouts.states.fail_decc.pass_keep.dfail_zero.comp_equal.any
dEQP-VK.pipeline.monolithic.stencil.format.d32_sfloat_s8_uint_separate_layouts.states.fail_keep.pass_inv.dfail_decc.comp_greater.any
dEQP-VK.pipeline.monolithic.stencil.nocolor.format.d24_unorm_s8_uint_separate_layouts.states.fail_incc.pass_wrap.dfail_keep.comp_always.any
dEQP-VK.pipeline.monolithic.stencil.nocolor.format.d32_sfloat_s8_uint.states.fail_zero.pass_keep.dfail_inv.comp_less.any
dEQP-VK.pipeline.monolithic.vertex_input.multiple_attributes.layout_skip.binding_one_to_one.attributes.uvec2.uvec3.mat2
dEQP-VK.renderpasses.dynamic_rendering.primary_cmd_buff.suballocation.unused_clear_attachments.colorunused_colorused_colorunused_colorunused_stencilonly_d32s8_unused
dEQP-VK.renderpasses.renderpass2.dedicated_allocation.formats.a2b10g10r10_uint_pack32.input.load.dont_care.clear_draw
dEQP-VK.renderpasses.renderpass2.suballocation.attachment_allocation.roll.87
dEQP-VK.renderpasses.renderpass2.suballocation.formats.r16_unorm.input.clear.store.self_dep_clear
dEQP-VK.synchronization.cross_instance.dedicated.write_clear_attachments_read_copy_image.image_128x128_d32_sfloat_binary_semaphore_dma_buf
dEQP-VK.synchronization.cross_instance.suballocated.write_ssbo_compute_read_ssbo_compute.buffer_262144_timeline_semaphore_dma_buf
dEQP-VK.synchronization.op.multi_queue.timeline_semaphore.write_image_compute_read_copy_image_to_buffer.image_64x64x8_r32_sfloat_exclusive
dEQP-VK.synchronization.op.single_queue.binary_semaphore.write_blit_image_read_image_compute_indirect.image_64x64x8_r32_sfloat
dEQP-VK.synchronization.op.single_queue.binary_semaphore.write_image_compute_read_image_compute_indirect.image_128x128_r16g16b16a16_uint
dEQP-VK.synchronization.op.single_queue.fence.write_image_compute_read_image_compute_indirect.image_128x128_r32g32b32a32_sfloat
dEQP-VK.synchronization.signal_order.binary_semaphore.write_blit_image_read_image_compute_indirect.image_128x128_r8g8b8a8_unorm
dEQP-VK.synchronization.signal_order.binary_semaphore.write_image_compute_indirect_read_image_compute.image_64x64x8_r32_sfloat
dEQP-VK.synchronization.signal_order.shared_binary_semaphore.write_image_compute_indirect_read_blit_image.image_64x64x8_r32_sfloat_opaque_fd
dEQP-VK.synchronization.signal_order.shared_binary_semaphore.write_ssbo_compute_read_ssbo_compute.buffer_262144_opaque_fd
dEQP-VK.synchronization.signal_order.shared_timeline_semaphore.write_copy_image_read_image_compute_indirect.image_128x128_r8g8b8a8_unorm_opaque_fd
dEQP-VK.synchronization.signal_order.shared_timeline_semaphore.write_image_compute_read_image_compute.image_128x128_r8_unorm_opaque_fd
dEQP-VK.synchronization.signal_order.timeline_semaphore.write_image_compute_indirect_read_image_compute_indirect.image_64x64x8_r32_sfloat
dEQP-VK.synchronization.timeline_semaphore.device_host.write_copy_image_to_buffer_read_ssbo_compute.buffer_262144
dEQP-VK.synchronization.timeline_semaphore.one_to_n.write_image_compute_indirect_read_copy_image_to_buffer.image_64x64x8_r32_sfloat
dEQP-VK.texture.filtering.3d.combinations.linear.nearest.clamp_to_edge.clamp_to_border.clamp_to_edge
dEQP-VK.texture.filtering.3d.combinations.linear_mipmap_nearest.linear.mirror_clamp_to_edge.mirrored_repeat.clamp_to_edge
dEQP-VK.ubo.instance_array_basic_type.std140.column_major_mat4x3.both
dEQP-VK.ubo.single_basic_type.std430.mediump.mat3.vertex
dEQP-VK.ycbcr.conversion.g8_b8_r8_3plane_420_unorm.color_conversion.ycbcr_2020_itu_full_tiling_optimal_cosited
+7
View File
@@ -0,0 +1,7 @@
# Timeout
dEQP-VK.api.object_management.max_concurrent.compute_pipeline
dEQP-VK.api.object_management.max_concurrent.graphics_pipeline
dEQP-VK.memory.mapping.dedicated_alloc.buffer.full.variable.implicit_unmap
dEQP-VK.memory.mapping.dedicated_alloc.buffer.full.variable.implicit_unmap_map2
dEQP-VK.memory.mapping.dedicated_alloc.image.full.variable.implicit_unmap
dEQP-VK.memory.mapping.dedicated_alloc.image.full.variable.implicit_unmap_map2
+6
View File
@@ -0,0 +1,6 @@
# Basic test set
[[deqp]]
deqp = "/deqp-vk/external/vulkancts/modules/vulkan/deqp-vk"
caselists = ["/deqp-vk/mustpass/vk-main.txt"]
renderer_check = "PowerVR"
tests_per_group = 10000
+59
View File
@@ -0,0 +1,59 @@
.imagination-rules:
stage: imagination
rules:
- !reference [.test, rules]
- !reference [.imagination-farm-rules, rules]
- !reference [.vulkan-rules, rules]
- changes: &imagination_file_list
- src/imagination/*
- src/imagination/ci/gitlab-ci.yml
- src/imagination/ci/gitlab-ci-inc.yml
- src/imagination/ci/deqp-$DEQP_SUITE.toml
- src/imagination/ci/$GPU_VERSION-fails.txt
- src/imagination/ci/$GPU_VERSION-flakes.txt
- src/imagination/ci/$GPU_VERSION-skips.txt
- src/imagination/common/**/*
- src/imagination/csbgen/**/*
- src/imagination/include/**/*
- src/imagination/pco/**/*
- src/imagination/vulkan/**/*
when: on_success
.imagination-manual-rules:
stage: imagination-nightly
extends: .no-auto-retry
rules:
- !reference [.test, rules]
- !reference [.imagination-farm-manual-rules, rules]
- !reference [.vulkan-manual-rules, rules]
- changes:
*imagination_file_list
when: manual
.imagination-ci-tron:
extends:
- .ci-tron-b2c-diskless-v1
variables:
RUNNER_FARM_LOCATION: imagination
CI_TRON_TIMEOUT__FIRST_CONSOLE_ACTIVITY__MINUTES: 0.5
CI_TRON_TIMEOUT__FIRST_CONSOLE_ACTIVITY__RETRIES: 3
CI_TRON_DUT_SETUP_TAGS: $GPU_VENDOR_TAG,$GPU_MODEL_TAG
tags:
- ci-tron:priority:$CI_TRON_JOB_PRIORITY
- $GPU_VENDOR_TAG
- $GPU_MODEL_TAG
# 12 devices
.imagination-ti-am68-sk:arm64:
extends:
- .imagination-ci-tron
parallel: 12
variables:
B2C_VERSION: v0.9.18
CI_TRON_DTB__0__URL: 'https://gitlab.freedesktop.org/gfx-ci/boot2container/-/releases/$B2C_VERSION/downloads/linux-arm64.dtbs.cpio.xz'
CI_TRON_DTB__0__FORMAT__0__ARCHIVE__MATCH: boot/dtbs/ti/k3-am68-sk-base-board.dtb
CI_TRON__B2C_DISKLESS_IMAGESTORE_PLATFORM: linux/arm64/v8
GPU_VENDOR_TAG: dt_gpu:vendor:ti
GPU_MODEL_TAG: dt_gpu:model:j721s2-gpu
GPU_VERSION: bxs-4-64
FDO_CI_CONCURRENT: 3
+15
View File
@@ -0,0 +1,15 @@
include:
- local: 'src/imagination/ci/gitlab-ci-inc.yml'
bxs-4-64-vk:
extends:
- .ci-tron-arm64-test-vk
- .imagination-ti-am68-sk:arm64
- .imagination-manual-rules
timeout: 50m
variables:
CI_TRON_TIMEOUT__OVERALL__MINUTES: 45
DEQP_SUITE: pvr-vk
VK_DRIVER: powervr_mesa
MESA_VK_IGNORE_CONFORMANCE_WARNING: 1
PVR_I_WANT_A_BROKEN_VULKAN_DRIVER: 1
@@ -0,0 +1,127 @@
/*
* Copyright © 2023 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef AXE_1_16M_H
#define AXE_1_16M_H
#include <stdbool.h>
#include "pvr_device_info.h"
#define PVR_DEVICE_IDENT_33_V_11_3 \
.device_id = 0x33011003, .series_name = "A-Series", \
.public_name = "AXE-1-16M", .arch = PVR_DEVICE_ARCH_ROGUE
static const struct pvr_device_features pvr_device_features_33_V_11_3 = {
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_ipf_creq_pf = true,
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_pbe2_in_xe = true,
.has_pbe_filterable_f16 = true,
.has_pbe_yuv = true,
.has_roguexe = true,
.has_screen_size8K = true,
.has_simple_internal_parameter_format = true,
.has_simple_internal_parameter_format_v2 = true,
.has_simple_parameter_format_version = true,
.has_slc_cache_line_size_bits = true,
.has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_border_colour_enhanced = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_f16sop_u8 = true,
.has_usc_itr_parallel_instances = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_pixel_partition_mask = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.has_vdm_degenerate_culling = true,
.common_store_size_in_dwords = 512U * 4U * 4U,
.isp_max_tiles_in_flight = 1U,
.isp_samples_per_pixel = 1U,
.max_instances_per_pds_task = 32U,
.max_multisample = 4U,
.max_partitions = 4U,
.max_usc_tasks = 24U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.simple_parameter_format_version = 2U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 16U,
.tile_size_y = 16U,
.tpu_parallel_instances = 1U,
.unified_store_depth = 64U,
.usc_itr_parallel_instances = 4U,
.usc_min_output_registers_per_pix = 1U,
.usc_slots = 14U,
.uvs_banks = 2U,
.uvs_pba_entries = 320U,
.uvs_vtx_entries = 288U,
.vdm_cam_size = 32U,
.has_s8xe = true,
};
static const struct pvr_device_enhancements pvr_device_enhancements_33_15_11_3 = {
.has_ern35421 = true,
.has_ern38748 = true,
.has_ern42307 = true,
.has_ern45493 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_33_15_11_3 = {
.has_brn70165 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_33_15_11_3 = {
.ident = {
PVR_DEVICE_IDENT_33_V_11_3,
.b = 33,
.v = 15,
.n = 11,
.c = 3,
},
.features = pvr_device_features_33_V_11_3,
.enhancements = pvr_device_enhancements_33_15_11_3,
.quirks = pvr_device_quirks_33_15_11_3,
};
#endif /* AXE_1_16M_H */
@@ -0,0 +1,125 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef BXE_2_32_H
#define BXE_2_32_H
#include <stdbool.h>
#include "pvr_device_info.h"
#define PVR_DEVICE_IDENT_36_V_52_182 \
.device_id = 0x36052182, .series_name = "B-Series", \
.public_name = "BXE-2-32", .arch = PVR_DEVICE_ARCH_ROGUE
static const struct pvr_device_features pvr_device_features_36_V_52_182 = {
.has_astc = true,
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_compute_overlap = true,
.has_fbcdc_algorithm = true,
.has_gpu_multicore_support = true,
/* .has_gs_rta_support = true, */
.has_ipf_creq_pf = true,
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_paired_tiles = true,
.has_pbe2_in_xe = true,
.has_pbe_filterable_f16 = true,
.has_pbe_yuv = true,
.has_pds_ddmadt = true,
.has_roguexe = true,
.has_screen_size8K = true,
.has_simple_internal_parameter_format = true,
.has_simple_internal_parameter_format_v2 = true,
.has_simple_parameter_format_version = true,
.has_slc_cache_line_size_bits = true,
.has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_border_colour_enhanced = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_alu_roundingmode_rne = true,
.has_usc_f16sop_u8 = true,
.has_usc_itrsmp = true,
.has_usc_itrsmp_enhanced = true,
.has_usc_itr_parallel_instances = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_pixel_partition_mask = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.has_xpu_max_slaves = true,
.common_store_size_in_dwords = 832U * 4U * 4U,
.fbcdc_algorithm = 50U,
.isp_max_tiles_in_flight = 2U,
.isp_samples_per_pixel = 1U,
.max_instances_per_pds_task = 32U,
.max_multisample = 4U,
.max_partitions = 8U,
.max_usc_tasks = 72U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.simple_parameter_format_version = 2U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 16U,
.tile_size_y = 16U,
.tpu_parallel_instances = 2U,
.unified_store_depth = 128U,
.usc_itr_parallel_instances = 8U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 32U,
.uvs_banks = 4U,
.uvs_pba_entries = 320U,
.uvs_vtx_entries = 288U,
.vdm_cam_size = 64U,
.xpu_max_slaves = 3U,
.has_s8xe = true,
};
static const struct pvr_device_enhancements
pvr_device_enhancements_36_29_52_182 = {
.has_ern35421 = true,
.has_ern38748 = true,
.has_ern42307 = true,
.has_ern45493 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_36_29_52_182 = {
.has_brn70165 = true,
.has_brn72168 = true,
.has_brn72463 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_36_29_52_182 = {
.ident = {
PVR_DEVICE_IDENT_36_V_52_182,
.b = 36,
.v = 29,
.n = 52,
.c = 182,
},
.features = pvr_device_features_36_V_52_182,
.enhancements = pvr_device_enhancements_36_29_52_182,
.quirks = pvr_device_quirks_36_29_52_182,
};
#endif /* BXE_2_32_H */
@@ -0,0 +1,125 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef BXE_4_32_H
#define BXE_4_32_H
#include <stdbool.h>
#include "pvr_device_info.h"
#define PVR_DEVICE_IDENT_36_V_54_182 \
.device_id = 0x36054182, .series_name = "B-Series", \
.public_name = "BXE-4-32", .arch = PVR_DEVICE_ARCH_ROGUE
static const struct pvr_device_features pvr_device_features_36_V_54_182 = {
.has_astc = true,
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_compute_overlap = true,
.has_fbcdc_algorithm = true,
.has_gpu_multicore_support = true,
/* .has_gs_rta_support = true, */
.has_ipf_creq_pf = true,
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_paired_tiles = true,
.has_pbe2_in_xe = true,
.has_pbe_filterable_f16 = true,
.has_pbe_yuv = true,
.has_pds_ddmadt = true,
.has_roguexe = true,
.has_screen_size8K = true,
.has_simple_internal_parameter_format = true,
.has_simple_internal_parameter_format_v2 = true,
.has_simple_parameter_format_version = true,
.has_slc_cache_line_size_bits = true,
.has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_border_colour_enhanced = true,
.has_tpu_dm_global_registers = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_alu_roundingmode_rne = true,
.has_usc_itrsmp = true,
.has_usc_itrsmp_enhanced = true,
.has_usc_f16sop_u8 = true,
.has_usc_itr_parallel_instances = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_pixel_partition_mask = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.has_xpu_max_slaves = true,
.common_store_size_in_dwords = 1024U * 4U * 4U,
.fbcdc_algorithm = 50U,
.isp_max_tiles_in_flight = 4U,
.isp_samples_per_pixel = 1U,
.max_instances_per_pds_task = 32U,
.max_multisample = 4U,
.max_partitions = 10U,
.max_usc_tasks = 104U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.simple_parameter_format_version = 2U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 16U,
.tile_size_y = 16U,
.tpu_parallel_instances = 4U,
.unified_store_depth = 208U,
.usc_itr_parallel_instances = 16U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 64U,
.uvs_banks = 8U,
.uvs_pba_entries = 160U,
.uvs_vtx_entries = 144U,
.vdm_cam_size = 64U,
.xpu_max_slaves = 3U,
.has_s8xe = true,
};
static const struct pvr_device_enhancements
pvr_device_enhancements_36_50_54_182 = {
.has_ern35421 = true,
.has_ern38748 = true,
.has_ern42307 = true,
.has_ern45493 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_36_50_54_182 = {
.has_brn70165 = true,
.has_brn72168 = true,
.has_brn72463 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_36_50_54_182 = {
.ident = {
PVR_DEVICE_IDENT_36_V_54_182,
.b = 36,
.v = 50,
.n = 54,
.c = 182,
},
.features = pvr_device_features_36_V_54_182,
.enhancements = pvr_device_enhancements_36_50_54_182,
.quirks = pvr_device_quirks_36_50_54_182,
};
#endif /* BXE_4_32_H */
@@ -0,0 +1,240 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef BXM_4_64_H
#define BXM_4_64_H
#include <stdbool.h>
#include "pvr_device_info.h"
#define PVR_DEVICE_IDENT_36_V_104_182 \
.device_id = 0x36104182, .series_name = "B-Series", \
.public_name = "BXM-4-64", .arch = PVR_DEVICE_ARCH_ROGUE
static const struct pvr_device_features pvr_device_features_36_V_104_182 = {
.has_astc = true,
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_compute_overlap = true,
.has_fbcdc_algorithm = true,
.has_gpu_multicore_support = true,
/* .has_gs_rta_support = true, */
.has_ipf_creq_pf = true,
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_paired_tiles = true,
.has_pbe2_in_xe = true,
.has_pbe_filterable_f16 = true,
.has_pbe_yuv = true,
.has_pds_ddmadt = true,
.has_roguexe = true,
.has_screen_size8K = true,
.has_simple_internal_parameter_format = true,
.has_simple_internal_parameter_format_v2 = true,
.has_simple_parameter_format_version = true,
.has_slc_cache_line_size_bits = true,
.has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_border_colour_enhanced = true,
.has_tpu_dm_global_registers = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_alu_roundingmode_rne = true,
.has_usc_f16sop_u8 = true,
.has_usc_itrsmp = true,
.has_usc_itrsmp_enhanced = true,
.has_usc_itr_parallel_instances = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_pixel_partition_mask = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.has_xpu_max_slaves = true,
.common_store_size_in_dwords = 1216U * 4U * 4U,
.fbcdc_algorithm = 50U,
.isp_max_tiles_in_flight = 6U,
.isp_samples_per_pixel = 1U,
.max_instances_per_pds_task = 32U,
.max_multisample = 4U,
.max_partitions = 12U,
.max_usc_tasks = 156U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.simple_parameter_format_version = 2U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 16U,
.tile_size_y = 16U,
.tpu_parallel_instances = 4U,
.unified_store_depth = 256U,
.usc_itr_parallel_instances = 16U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 64U,
.uvs_banks = 8U,
.uvs_pba_entries = 160U,
.uvs_vtx_entries = 144U,
.vdm_cam_size = 64U,
.xpu_max_slaves = 3U,
/* Derived features. */
.has_s8xe = true,
};
static const struct pvr_device_enhancements
pvr_device_enhancements_36_52_104_182 = {
.has_ern35421 = true,
.has_ern38748 = true,
.has_ern42307 = true,
.has_ern45493 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_36_52_104_182 = {
.has_brn44079 = true,
.has_brn70165 = true,
.has_brn72168 = true,
.has_brn72463 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_36_52_104_182 = {
.ident = {
PVR_DEVICE_IDENT_36_V_104_182,
.b = 36,
.v = 52,
.n = 104,
.c = 182,
},
.features = pvr_device_features_36_V_104_182,
.enhancements = pvr_device_enhancements_36_52_104_182,
.quirks = pvr_device_quirks_36_52_104_182,
};
#define PVR_DEVICE_IDENT_36_V_104_183 \
.device_id = 0x36104183, .series_name = "B-Series", .public_name = "BXM-4-64"
static const struct pvr_device_features pvr_device_features_36_V_104_183 = {
.has_astc = true,
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_compute_overlap = true,
.has_fbcdc_algorithm = true,
.has_gpu_multicore_support = true,
/* .has_gs_rta_support = true, */
.has_ipf_creq_pf = true,
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_paired_tiles = true,
.has_pbe2_in_xe = true,
.has_pbe_filterable_f16 = true,
.has_pbe_yuv = true,
.has_pds_ddmadt = true,
.has_roguexe = true,
.has_screen_size8K = true,
.has_simple_internal_parameter_format = true,
.has_simple_internal_parameter_format_v2 = true,
.has_simple_parameter_format_version = true,
.has_slc_cache_line_size_bits = true,
.has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_border_colour_enhanced = true,
.has_tpu_dm_global_registers = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_alu_roundingmode_rne = true,
.has_usc_f16sop_u8 = true,
.has_usc_itrsmp = true,
.has_usc_itrsmp_enhanced = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_pixel_partition_mask = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.has_xpu_max_slaves = true,
.common_store_size_in_dwords = 1216U * 4U * 4U,
.fbcdc_algorithm = 50U,
.isp_max_tiles_in_flight = 6U,
.isp_samples_per_pixel = 1U,
.max_instances_per_pds_task = 32U,
.max_multisample = 4U,
.max_partitions = 12U,
.max_usc_tasks = 156U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.simple_parameter_format_version = 2U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 16U,
.tile_size_y = 16U,
.tpu_parallel_instances = 4U,
.unified_store_depth = 256U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 64U,
.uvs_banks = 8U,
.uvs_pba_entries = 160U,
.uvs_vtx_entries = 144U,
.vdm_cam_size = 64U,
.xpu_max_slaves = 3U,
/* Derived features. */
.has_s8xe = true,
.has_usc_itr_parallel_instances = true,
.usc_itr_parallel_instances = 16U,
};
static const struct pvr_device_enhancements
pvr_device_enhancements_36_56_104_183 = {
.has_ern35421 = true,
.has_ern38748 = true,
.has_ern42307 = true,
.has_ern45493 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_36_56_104_183 = {
.has_brn44079 = true,
.has_brn70165 = true,
.has_brn72168 = true,
.has_brn72463 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_36_56_104_183 = {
.ident = {
PVR_DEVICE_IDENT_36_V_104_183,
.b = 36,
.v = 56,
.n = 104,
.c = 183,
},
.features = pvr_device_features_36_V_104_183,
.enhancements = pvr_device_enhancements_36_56_104_183,
.quirks = pvr_device_quirks_36_56_104_183,
};
#endif /* BXM_4_64_H */
@@ -0,0 +1,144 @@
/*
* Copyright © 2023 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BXS_4_64_H
#define BXS_4_64_H
#include <stdbool.h>
#include "pvr_device_info.h"
#define PVR_DEVICE_IDENT_36_V_104_796 \
.device_id = 0x36104796, .series_name = "B-Series", \
.public_name = "BXS-4-64", .arch = PVR_DEVICE_ARCH_ROGUE
static const struct pvr_device_features pvr_device_features_36_V_104_796 = {
.has_astc = true,
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_compute_overlap = true,
.has_fbcdc_algorithm = true,
.has_gpu_multicore_support = true,
/* .has_gs_rta_support = true, */
.has_ipf_creq_pf = true,
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_paired_tiles = true,
.has_pbe2_in_xe = true,
.has_pbe_filterable_f16 = true,
.has_pbe_yuv = true,
.has_pds_ddmadt = true,
.has_roguexe = true,
.has_screen_size8K = true,
.has_simple_internal_parameter_format = true,
.has_simple_internal_parameter_format_v2 = true,
.has_simple_parameter_format_version = true,
.has_slc_cache_line_size_bits = true,
.has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_border_colour_enhanced = true,
.has_tpu_dm_global_registers = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_alu_roundingmode_rne = true,
.has_usc_f16sop_u8 = true,
.has_usc_itrsmp = true,
.has_usc_itrsmp_enhanced = true,
.has_usc_itr_parallel_instances = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_pixel_partition_mask = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.has_vdm_degenerate_culling = true,
.has_xpu_max_slaves = true,
.common_store_size_in_dwords = 1344U * 4U * 4U,
.fbcdc_algorithm = 50U,
.isp_max_tiles_in_flight = 6U,
.isp_samples_per_pixel = 4U,
.max_instances_per_pds_task = 32U,
.max_multisample = 4U,
.max_partitions = 16U,
.max_usc_tasks = 156U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.simple_parameter_format_version = 2U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 16U,
.tile_size_y = 16U,
.tpu_parallel_instances = 4U,
.unified_store_depth = 256U,
.usc_itr_parallel_instances = 16U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 64U,
.uvs_banks = 8U,
.uvs_pba_entries = 160U,
.uvs_vtx_entries = 144U,
.vdm_cam_size = 64U,
.xpu_max_slaves = 3U,
.has_s8xe = true,
};
static const struct pvr_device_enhancements
pvr_device_enhancements_36_53_104_796 = {
.has_ern35421 = true,
.has_ern38748 = true,
.has_ern42307 = true,
.has_ern45493 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_36_53_104_796 = {
.has_brn44079 = true,
.has_brn70165 = true,
.has_brn72168 = true,
.has_brn72463 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_36_53_104_796 = {
.ident = {
PVR_DEVICE_IDENT_36_V_104_796,
.b = 36,
.v = 53,
.n = 104,
.c = 796,
},
.features = pvr_device_features_36_V_104_796,
.enhancements = pvr_device_enhancements_36_53_104_796,
.quirks = pvr_device_quirks_36_53_104_796,
};
#endif /* BXS_4_64_H */
+106
View File
@@ -0,0 +1,106 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef G6110_H
#define G6110_H
#include <stdbool.h>
#include "pvr_device_info.h"
#define PVR_DEVICE_IDENT_5_V_1_46 \
.device_id = 0x6110, .series_name = "Rogue", \
.public_name = "GX6110", .arch = PVR_DEVICE_ARCH_ROGUE
static const struct pvr_device_features pvr_device_features_5_V_1_46 = {
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_fbcdc_algorithm = true,
/* .has_gs_rta_support = true, */
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_pbe_filterable_f16 = true,
.has_roguexe = true,
.has_slc_cache_line_size_bits = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_itr_parallel_instances = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.common_store_size_in_dwords = 1344U * 4U * 4U,
.fbcdc_algorithm = 2U,
.isp_max_tiles_in_flight = 1U,
.isp_samples_per_pixel = 2U,
.max_instances_per_pds_task = 32U,
.max_multisample = 4U,
.max_partitions = 12U,
.max_usc_tasks = 96U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 32U,
.tile_size_y = 32U,
.tpu_parallel_instances = 4U,
.unified_store_depth = 208U,
.usc_itr_parallel_instances = 16U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 56U,
.uvs_banks = 8U,
.uvs_pba_entries = 160U,
.uvs_vtx_entries = 144U,
.vdm_cam_size = 64U,
.has_requires_fb_cdc_zls_setup = true,
};
static const struct pvr_device_enhancements pvr_device_enhancements_5_9_1_46 = {
.has_ern35421 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_5_9_1_46 = {
.has_brn44079 = true,
.has_brn47727 = true,
.has_brn48492 = true,
.has_brn48545 = true,
.has_brn49032 = true,
.has_brn49927 = true,
.has_brn51025 = true,
.has_brn51210 = true,
.has_brn52942 = true,
.has_brn58839 = true,
.has_brn62269 = true,
.has_brn66011 = true,
.has_brn70165 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_5_9_1_46 = {
.ident = {
PVR_DEVICE_IDENT_5_V_1_46,
.b = 5,
.v = 9,
.n = 1,
.c = 46,
},
.features = pvr_device_features_5_V_1_46,
.enhancements = pvr_device_enhancements_5_9_1_46,
.quirks = pvr_device_quirks_5_9_1_46,
};
#endif /* G6110_H */
+105
View File
@@ -0,0 +1,105 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef GE7800_H
#define GE7800_H
#include <stdbool.h>
#include "pvr_device_info.h"
#define PVR_DEVICE_IDENT_15_V_1_64 \
.device_id = 0x15001064, .series_name = "Rogue", \
.public_name = "GE7800", .arch = PVR_DEVICE_ARCH_ROGUE
static const struct pvr_device_features pvr_device_features_15_V_1_64 = {
.has_astc = true,
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_fbcdc_algorithm = true,
/* .has_gs_rta_support = true, */
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_pbe_filterable_f16 = true,
.has_roguexe = true,
.has_slc_cache_line_size_bits = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_f16sop_u8 = true,
.has_usc_itr_parallel_instances = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.common_store_size_in_dwords = 1344U * 4U * 4U,
.fbcdc_algorithm = 2U,
.isp_max_tiles_in_flight = 2U,
.isp_samples_per_pixel = 2U,
.max_instances_per_pds_task = 32U,
.max_multisample = 4U,
.max_partitions = 12U,
.max_usc_tasks = 96U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 32U,
.tile_size_y = 32U,
.tpu_parallel_instances = 4U,
.unified_store_depth = 208U,
.usc_itr_parallel_instances = 16U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 56U,
.uvs_banks = 8U,
.uvs_pba_entries = 320U,
.uvs_vtx_entries = 288U,
.vdm_cam_size = 128U,
.has_requires_fb_cdc_zls_setup = true,
};
static const struct pvr_device_enhancements
pvr_device_enhancements_15_5_1_64 = {
.has_ern35421 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_15_5_1_64 = {
.has_brn44079 = true,
.has_brn48492 = true,
.has_brn49032 = true,
.has_brn49927 = true,
.has_brn52942 = true,
.has_brn58839 = true,
.has_brn62269 = true,
.has_brn66011 = true,
.has_brn70165 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_15_5_1_64 = {
.ident = {
PVR_DEVICE_IDENT_15_V_1_64,
.b = 15,
.v = 5,
.n = 1,
.c = 64,
},
.features = pvr_device_features_15_V_1_64,
.enhancements = pvr_device_enhancements_15_5_1_64,
.quirks = pvr_device_quirks_15_5_1_64,
};
#endif /* GE7800_H */
+233
View File
@@ -0,0 +1,233 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef GE8300_H
#define GE8300_H
#include <stdbool.h>
#include "pvr_device_info.h"
#define PVR_DEVICE_IDENT_22_V_54_30 \
.device_id = 0x22054030, .series_name = "Rogue", \
.public_name = "GE8300", .arch = PVR_DEVICE_ARCH_ROGUE
static const struct pvr_device_features pvr_device_features_22_V_54_30 = {
.has_astc = true,
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_compute_overlap = true,
/* .has_gs_rta_support = true, */
.has_ipf_creq_pf = true,
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_pbe2_in_xe = true,
.has_pbe_filterable_f16 = true,
.has_pbe_yuv = true,
.has_roguexe = true,
.has_simple_internal_parameter_format = true,
.has_simple_internal_parameter_format_v1 = true,
.has_simple_parameter_format_version = true,
.has_slc_cache_line_size_bits = true,
.has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_f16sop_u8 = true,
.has_usc_itrsmp = true,
.has_usc_itrsmp_enhanced = true,
.has_usc_itr_parallel_instances = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.common_store_size_in_dwords = 1024U * 4U * 4U,
.isp_max_tiles_in_flight = 4U,
.isp_samples_per_pixel = 1U,
.max_instances_per_pds_task = 32U,
.max_multisample = 4U,
.max_partitions = 10U,
.max_usc_tasks = 104U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.simple_parameter_format_version = 1U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 16U,
.tile_size_y = 16U,
.tpu_parallel_instances = 4U,
.unified_store_depth = 208U,
.usc_itr_parallel_instances = 16U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 64U,
.uvs_banks = 4U,
.uvs_pba_entries = 320U,
.uvs_vtx_entries = 288U,
.vdm_cam_size = 64U,
.has_s8xe = true,
};
static const struct pvr_device_enhancements
pvr_device_enhancements_22_67_54_30 = {
.has_ern35421 = true,
.has_ern38748 = true,
.has_ern42307 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_22_67_54_30 = {
.has_brn49927 = true,
.has_brn66011 = true,
.has_brn70165 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_22_67_54_30 = {
.ident = {
PVR_DEVICE_IDENT_22_V_54_30,
.b = 22,
.v = 67,
.n = 54,
.c = 30,
},
.features = pvr_device_features_22_V_54_30,
.enhancements = pvr_device_enhancements_22_67_54_30,
.quirks = pvr_device_quirks_22_67_54_30,
};
static const struct pvr_device_enhancements
pvr_device_enhancements_22_68_54_30 = {
.has_ern35421 = true,
.has_ern38748 = true,
.has_ern42307 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_22_68_54_30 = {
.has_brn49927 = true,
.has_brn66011 = true,
.has_brn70165 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_22_68_54_30 = {
.ident = {
PVR_DEVICE_IDENT_22_V_54_30,
.b = 22,
.v = 68,
.n = 54,
.c = 30,
},
.features = pvr_device_features_22_V_54_30,
.enhancements = pvr_device_enhancements_22_68_54_30,
.quirks = pvr_device_quirks_22_68_54_30,
};
#define PVR_DEVICE_IDENT_22_V_54_38 \
.device_id = 0x22054038, .series_name = "Rogue", .public_name = "GE8300"
static const struct pvr_device_features pvr_device_features_22_V_54_38 = {
.has_astc = true,
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_compute_overlap = true,
/* .has_gs_rta_support = true, */
.has_ipf_creq_pf = true,
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_pbe2_in_xe = true,
.has_pbe_filterable_f16 = true,
.has_pbe_yuv = true,
.has_roguexe = true,
.has_simple_internal_parameter_format = true,
.has_simple_internal_parameter_format_v1 = true,
.has_simple_parameter_format_version = true,
.has_slc_cache_line_size_bits = true,
.has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_f16sop_u8 = true,
.has_usc_itrsmp = true,
.has_usc_itrsmp_enhanced = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.common_store_size_in_dwords = 1024U * 4U * 4U,
.isp_max_tiles_in_flight = 4U,
.isp_samples_per_pixel = 1U,
.max_instances_per_pds_task = 32U,
.max_multisample = 4U,
.max_partitions = 10U,
.max_usc_tasks = 104U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.simple_parameter_format_version = 1U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 16U,
.tile_size_y = 16U,
.tpu_parallel_instances = 4U,
.unified_store_depth = 208U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 64U,
.uvs_banks = 4U,
.uvs_pba_entries = 320U,
.uvs_vtx_entries = 288U,
.vdm_cam_size = 64U,
.has_s8xe = true,
.has_usc_itr_parallel_instances = true,
.usc_itr_parallel_instances = 16U,
};
static const struct pvr_device_enhancements
pvr_device_enhancements_22_102_54_38 = {
.has_ern35421 = true,
.has_ern38748 = true,
.has_ern42307 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_22_102_54_38 = {
.has_brn49927 = true,
.has_brn66011 = true,
.has_brn70165 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_22_102_54_38 = {
.ident = {
PVR_DEVICE_IDENT_22_V_54_38,
.b = 22,
.v = 102,
.n = 54,
.c = 38,
},
.features = pvr_device_features_22_V_54_38,
.enhancements = pvr_device_enhancements_22_102_54_38,
.quirks = pvr_device_quirks_22_102_54_38,
};
#endif /* GE8300_H */
+251
View File
@@ -0,0 +1,251 @@
/*
* Copyright © 2023 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef GX6250_H
#define GX6250_H
#include <stdbool.h>
#include "pvr_device_info.h"
#define PVR_DEVICE_IDENT_4_V_2_51 \
.device_id = 0x6250, .series_name = "Rogue", \
.public_name = "GX6250", .arch = PVR_DEVICE_ARCH_ROGUE
static const struct pvr_device_features pvr_device_features_4_V_2_51 = {
.has_astc = true,
.has_cluster_grouping = true,
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_compute_morton_capable = true,
.has_compute_overlap = true,
.has_eight_output_registers = true,
.has_fbcdc_algorithm = true,
/* .has_gs_rta_support = true, */
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_pbe_filterable_f16 = true,
.has_pbe_yuv = true,
.has_slc_cache_line_size_bits = true,
.has_slc_mcu_cache_controls = true,
.has_tf_bicubic_filter = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_array_textures = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_f16sop_u8 = true,
.has_usc_itrsmp = true,
.has_usc_itr_parallel_instances = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.has_xt_top_infrastructure = true,
.has_zls_subtile = true,
.common_store_size_in_dwords = 1280U * 4U * 4U,
.fbcdc_algorithm = 2,
.isp_max_tiles_in_flight = 4U,
.isp_samples_per_pixel = 2U,
.max_instances_per_pds_task = 32U,
.max_multisample = 8U,
.max_partitions = 8U,
.max_usc_tasks = 56U,
.num_clusters = 2U,
.num_raster_pipes = 1U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 32U,
.tile_size_y = 32U,
.tpu_parallel_instances = 4U,
.unified_store_depth = 256U,
.usc_itr_parallel_instances = 8U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 32U,
.uvs_banks = 8U,
.uvs_pba_entries = 320U,
.uvs_vtx_entries = 288U,
.vdm_cam_size = 256U,
.has_requires_fb_cdc_zls_setup = true,
};
static const struct pvr_device_enhancements pvr_device_enhancements_4_40_2_51 = {
.has_ern35421 = true,
.has_ern38020 = true,
.has_ern38748 = true,
.has_ern42064 = true,
.has_ern42307 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_4_40_2_51 = {
.has_brn44079 = true,
.has_brn47727 = true,
.has_brn48492 = true,
.has_brn48545 = true,
.has_brn49032 = true,
.has_brn49927 = true,
.has_brn51025 = true,
.has_brn51210 = true,
.has_brn51764 = true,
.has_brn52354 = true,
.has_brn52942 = true,
.has_brn58839 = true,
.has_brn62269 = true,
.has_brn66011 = true,
.has_brn70165 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_4_40_2_51 = {
.ident = {
PVR_DEVICE_IDENT_4_V_2_51,
.b = 4,
.v = 40,
.n = 2,
.c = 51,
},
.features = pvr_device_features_4_V_2_51,
.enhancements = pvr_device_enhancements_4_40_2_51,
.quirks = pvr_device_quirks_4_40_2_51,
};
#define PVR_DEVICE_IDENT_4_V_2_58 \
.device_id = 0x6250, .series_name = "Rogue", .public_name = "GX6250"
static const struct pvr_device_features pvr_device_features_4_V_2_58 = {
.has_astc = true,
.has_cluster_grouping = true,
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_compute_morton_capable = true,
.has_compute_overlap = true,
.has_eight_output_registers = true,
.has_fbcdc_algorithm = true,
/* .has_gs_rta_support = true, */
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_pbe_filterable_f16 = true,
.has_pbe_yuv = true,
.has_slc_cache_line_size_bits = true,
.has_slc_mcu_cache_controls = true,
.has_tf_bicubic_filter = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_array_textures = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_f16sop_u8 = true,
.has_usc_itrsmp = true,
.has_usc_itr_parallel_instances = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.has_xt_top_infrastructure = true,
.has_zls_subtile = true,
.common_store_size_in_dwords = 1536U * 4U * 4U,
.fbcdc_algorithm = 2,
.isp_max_tiles_in_flight = 4U,
.isp_samples_per_pixel = 2U,
.max_instances_per_pds_task = 32U,
.max_multisample = 8U,
.max_partitions = 8U,
.max_usc_tasks = 56U,
.num_clusters = 2U,
.num_raster_pipes = 1U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 32U,
.tile_size_y = 32U,
.tpu_parallel_instances = 4U,
.unified_store_depth = 256U,
.usc_itr_parallel_instances = 8U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 32U,
.uvs_banks = 8U,
.uvs_pba_entries = 320U,
.uvs_vtx_entries = 288U,
.vdm_cam_size = 256U,
.has_requires_fb_cdc_zls_setup = true,
};
static const struct pvr_device_enhancements pvr_device_enhancements_4_45_2_58 = {
.has_ern35421 = true,
.has_ern38020 = true,
.has_ern38748 = true,
.has_ern42064 = true,
.has_ern42307 = true,
.has_ern45493 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_4_45_2_58 = {
.has_brn44079 = true,
.has_brn49927 = true,
.has_brn51025 = true,
.has_brn51210 = true,
.has_brn51764 = true,
.has_brn52354 = true,
.has_brn52942 = true,
.has_brn58839 = true,
.has_brn62269 = true,
.has_brn66011 = true,
.has_brn70165 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_4_45_2_58 = {
.ident = {
PVR_DEVICE_IDENT_4_V_2_58,
.b = 4,
.v = 45,
.n = 2,
.c = 58,
},
.features = pvr_device_features_4_V_2_58,
.enhancements = pvr_device_enhancements_4_45_2_58,
.quirks = pvr_device_quirks_4_45_2_58,
};
#endif /* GX6250_H */
+123
View File
@@ -0,0 +1,123 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef GX6650_H
#define GX6650_H
#include <stdbool.h>
#include "pvr_device_info.h"
#define PVR_DEVICE_IDENT_4_V_6_62 \
.device_id = 0x6650, .series_name = "Rogue", \
.public_name = "GX6650", .arch = PVR_DEVICE_ARCH_ROGUE
static const struct pvr_device_features pvr_device_features_4_V_6_62 = {
.has_astc = true,
.has_cluster_grouping = true,
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_compute_morton_capable = true,
.has_compute_overlap = true,
.has_eight_output_registers = true,
.has_fbcdc_algorithm = true,
/* .has_gs_rta_support = true, */
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_instances_per_pds_task = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_pbe_filterable_f16 = true,
.has_pbe_yuv = true,
.has_slc_cache_line_size_bits = true,
.has_slc_mcu_cache_controls = true,
.has_tf_bicubic_filter = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
.has_tpu_array_textures = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_tpu_parallel_instances = true,
.has_unified_store_depth = true,
.has_usc_f16sop_u8 = true,
.has_usc_itrsmp = true,
.has_usc_itr_parallel_instances = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_slots = true,
.has_uvs_banks = true,
.has_uvs_pba_entries = true,
.has_uvs_vtx_entries = true,
.has_vdm_cam_size = true,
.has_xt_top_infrastructure = true,
.has_zls_subtile = true,
.common_store_size_in_dwords = 1280U * 4U * 4U,
.fbcdc_algorithm = 2U,
.isp_max_tiles_in_flight = 8U,
.isp_samples_per_pixel = 2U,
.max_instances_per_pds_task = 32U,
.max_multisample = 8U,
.max_partitions = 8U,
.max_usc_tasks = 56U,
.num_clusters = 6U,
.num_raster_pipes = 2U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 32U,
.tile_size_y = 32U,
.tpu_parallel_instances = 4U,
.unified_store_depth = 256U,
.usc_itr_parallel_instances = 8U,
.usc_min_output_registers_per_pix = 2U,
.usc_slots = 32U,
.uvs_banks = 8U,
.uvs_pba_entries = 320U,
.uvs_vtx_entries = 288U,
.vdm_cam_size = 256U,
.has_requires_fb_cdc_zls_setup = true,
};
static const struct pvr_device_enhancements pvr_device_enhancements_4_46_6_62 = {
.has_ern35421 = true,
.has_ern38020 = true,
.has_ern38748 = true,
.has_ern42064 = true,
.has_ern42307 = true,
.has_ern45493 = true,
};
static const struct pvr_device_quirks pvr_device_quirks_4_46_6_62 = {
.has_brn44079 = true,
.has_brn49927 = true,
.has_brn51025 = true,
.has_brn51210 = true,
.has_brn51764 = true,
.has_brn52354 = true,
.has_brn52942 = true,
.has_brn58839 = true,
.has_brn62269 = true,
.has_brn66011 = true,
.has_brn70165 = true,
.has_brn74056 = true,
};
static const struct pvr_device_info pvr_device_info_4_46_6_62 = {
.ident = {
PVR_DEVICE_IDENT_4_V_6_62,
.b = 4,
.v = 46,
.n = 6,
.c = 62,
},
.features = pvr_device_features_4_V_6_62,
.enhancements = pvr_device_enhancements_4_46_6_62,
.quirks = pvr_device_quirks_4_46_6_62,
};
#endif /* GX6650_H */
+24
View File
@@ -0,0 +1,24 @@
# Copyright © 2022 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
pvr_device_info_dir = join_paths(meson.current_source_dir(), 'device_info')
libpowervr_common = static_library(
'powervr_common',
[
'pvr_debug.c',
'pvr_device_info.c',
'pvr_dump.c',
'pvr_dump_info.c',
'pvr_util.c',
'pvr_ycbcr.c',
sha1_h,
],
include_directories : [
inc_include,
inc_src,
inc_imagination,
],
c_args : [imagination_c_args, no_override_init_args],
gnu_symbol_visibility : 'hidden',
)
+59
View File
@@ -0,0 +1,59 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdint.h>
#include "util/u_debug.h"
#include "pvr_debug.h"
uint32_t PVR_DEBUG = 0;
/* clang-format off */
static const struct debug_named_value debug_control[] = {
{ "cs", PVR_DEBUG_DUMP_CONTROL_STREAM,
"Dump the contents of the control stream buffer on every job submit." },
{ "bo_track", PVR_DEBUG_TRACK_BOS,
"Track all buffer objects with at least one reference." },
{ "vk_desc", PVR_DEBUG_VK_DUMP_DESCRIPTOR_SET_LAYOUT,
"Dump descriptor set and pipeline layouts." },
{ "info", PVR_DEBUG_INFO,
"Display information about the driver and device." },
DEBUG_NAMED_VALUE_END
};
/* clang-format on */
DEBUG_GET_ONCE_FLAGS_OPTION(pvr_debug, "PVR_DEBUG", debug_control, 0)
#define PVR_DEBUG_SET(x) PVR_DEBUG |= (PVR_DEBUG_##x)
void pvr_process_debug_variable(void)
{
PVR_DEBUG = debug_get_option_pvr_debug();
/* Perform any automatic selections. For example, if one debug option
* implies another it should be set here.
*/
if (PVR_IS_DEBUG_SET(DUMP_CONTROL_STREAM))
PVR_DEBUG_SET(TRACK_BOS);
}
+44
View File
@@ -0,0 +1,44 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef PVR_DEBUG_H
#define PVR_DEBUG_H
#include <stdint.h>
#include "util/macros.h"
extern uint32_t PVR_DEBUG;
/* clang-format off */
#define PVR_IS_DEBUG_SET(x) unlikely(PVR_DEBUG & PVR_DEBUG_##x)
/* clang-format on */
#define PVR_DEBUG_DUMP_CONTROL_STREAM BITFIELD_BIT(0)
#define PVR_DEBUG_TRACK_BOS BITFIELD_BIT(1)
#define PVR_DEBUG_VK_DUMP_DESCRIPTOR_SET_LAYOUT BITFIELD_BIT(2)
#define PVR_DEBUG_INFO BITFIELD_BIT(3)
void pvr_process_debug_variable(void);
#endif /* PVR_DEBUG_H */
+125
View File
@@ -0,0 +1,125 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* TODO: This file is currently hand-maintained. However, the intention is to
* auto-generate it in the future based on the hwdefs.
*/
#include <assert.h>
#include <errno.h>
#include <string.h>
#include "pvr_device_info.h"
#include "device_info/g6110.h"
#include "device_info/gx6250.h"
#include "device_info/gx6650.h"
#include "device_info/ge7800.h"
#include "device_info/ge8300.h"
#include "device_info/axe-1-16m.h"
#include "device_info/bxe-2-32.h"
#include "device_info/bxe-4-32.h"
#include "device_info/bxm-4-64.h"
#include "device_info/bxs-4-64.h"
#include "util/u_string.h"
static const struct pvr_device_info *device_infos[] = {
/* clang-format off */
&pvr_device_info_4_40_2_51,
&pvr_device_info_4_45_2_58,
&pvr_device_info_4_46_6_62,
&pvr_device_info_5_9_1_46,
&pvr_device_info_15_5_1_64,
&pvr_device_info_22_67_54_30,
&pvr_device_info_22_68_54_30,
&pvr_device_info_22_102_54_38,
&pvr_device_info_33_15_11_3,
&pvr_device_info_36_29_52_182,
&pvr_device_info_36_50_54_182,
&pvr_device_info_36_52_104_182,
&pvr_device_info_36_53_104_796,
&pvr_device_info_36_56_104_183,
/* clang-format on */
};
/**
* Initialize PowerVR device information.
*
* \param info Device info structure to initialize.
* \param bvnc Packed BVNC.
* \return
* * 0 on success, or
* * -%ENODEV if the device is not supported.
*/
int pvr_device_info_init(struct pvr_device_info *info, uint64_t bvnc)
{
#define CASE_PACKED_BVNC_DEVICE_INFO(_b, _v, _n, _c) \
case PVR_BVNC_PACK(_b, _v, _n, _c): \
*info = pvr_device_info_##_b##_##_v##_##_n##_##_c; \
return 0
switch (bvnc) {
CASE_PACKED_BVNC_DEVICE_INFO(4, 40, 2, 51);
CASE_PACKED_BVNC_DEVICE_INFO(4, 45, 2, 58);
CASE_PACKED_BVNC_DEVICE_INFO(4, 46, 6, 62);
CASE_PACKED_BVNC_DEVICE_INFO(5, 9, 1, 46);
CASE_PACKED_BVNC_DEVICE_INFO(15, 5, 1, 64);
CASE_PACKED_BVNC_DEVICE_INFO(22, 67, 54, 30);
CASE_PACKED_BVNC_DEVICE_INFO(22, 68, 54, 30);
CASE_PACKED_BVNC_DEVICE_INFO(22, 102, 54, 38);
CASE_PACKED_BVNC_DEVICE_INFO(33, 15, 11, 3);
CASE_PACKED_BVNC_DEVICE_INFO(36, 29, 52, 182);
CASE_PACKED_BVNC_DEVICE_INFO(36, 50, 54, 182);
CASE_PACKED_BVNC_DEVICE_INFO(36, 52, 104, 182);
CASE_PACKED_BVNC_DEVICE_INFO(36, 53, 104, 796);
CASE_PACKED_BVNC_DEVICE_INFO(36, 56, 104, 183);
}
#undef CASE_PACKED_BVNC_DEVICE_INFO
assert(!"Unsupported Device");
return -ENODEV;
}
/**
* Initialize PowerVR device information from a public name.
*
* \param info Device info structure to initialize.
* \param public_name Device public name.
* \return True if successful.
*/
bool pvr_device_info_init_public_name(struct pvr_device_info *info,
const char *public_name)
{
for (unsigned d = 0; d < ARRAY_SIZE(device_infos); ++d) {
if (strcasecmp(public_name, device_infos[d]->ident.public_name))
continue;
memcpy(info, device_infos[d], sizeof(*info));
return true;
}
return false;
}
+431
View File
@@ -0,0 +1,431 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef PVR_DEVICE_INFO_H
#define PVR_DEVICE_INFO_H
/* TODO: This file is currently hand-maintained. However, the intention is to
* auto-generate it in the future based on the hwdefs.
*/
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include "util/log.h"
#include "util/macros.h"
#define PVR_BVNC_PACK_SHIFT_B 48
#define PVR_BVNC_PACK_SHIFT_V 32
#define PVR_BVNC_PACK_SHIFT_N 16
#define PVR_BVNC_PACK_SHIFT_C 0
#define PVR_BVNC_PACK_MASK_B UINT64_C(0xFFFF000000000000)
#define PVR_BVNC_PACK_MASK_V UINT64_C(0x0000FFFF00000000)
#define PVR_BVNC_PACK_MASK_N UINT64_C(0x00000000FFFF0000)
#define PVR_BVNC_PACK_MASK_C UINT64_C(0x000000000000FFFF)
enum pvr_device_arch {
PVR_DEVICE_ARCH_ROGUE,
};
/**
* Packs B, V, N and C values into a 64-bit unsigned integer.
*
* The packed layout is as follows:
*
* \verbatim
* +--------+--------+--------+-------+
* | 63..48 | 47..32 | 31..16 | 15..0 |
* +========+========+========+=======+
* | B | V | N | C |
* +--------+--------+--------+-------+
* \endverbatim
*
* #pvr_get_packed_bvnc() should be used instead of this macro when a
* #pvr_device_information is available in order to ensure proper type checking.
*
* \param b Branch ID.
* \param v Version ID.
* \param n Number of scalable units.
* \param c Config ID.
* \return Packed BVNC.
*
* \sa #pvr_get_packed_bvnc(), #PVR_BVNC_UNPACK_B(), #PVR_BVNC_UNPACK_V(),
* #PVR_BVNC_UNPACK_N() and #PVR_BVNC_UNPACK_C()
*/
#define PVR_BVNC_PACK(b, v, n, c) \
((((uint64_t)(b) << PVR_BVNC_PACK_SHIFT_B) & PVR_BVNC_PACK_MASK_B) | \
(((uint64_t)(v) << PVR_BVNC_PACK_SHIFT_V) & PVR_BVNC_PACK_MASK_V) | \
(((uint64_t)(n) << PVR_BVNC_PACK_SHIFT_N) & PVR_BVNC_PACK_MASK_N) | \
(((uint64_t)(c) << PVR_BVNC_PACK_SHIFT_C) & PVR_BVNC_PACK_MASK_C))
/**
* Unpacks B value (branch ID) from packed BVNC.
*
* \param bvnc Packed BVNC.
* \return Branch ID.
*
* \sa #PVR_BVNC_UNPACK_V(), #PVR_BVNC_UNPACK_N(), #PVR_BVNC_UNPACK_C(),
* #pvr_get_packed_bvnc() and #PVR_BVNC_PACK()
*/
#define PVR_BVNC_UNPACK_B(bvnc) \
((uint16_t)(((bvnc) & PVR_BVNC_PACK_MASK_B) >> PVR_BVNC_PACK_SHIFT_B))
/**
* Unpacks V value (version ID) from packed BVNC.
*
* \param bvnc Packed BVNC.
* \return Version ID.
*
* \sa #PVR_BVNC_UNPACK_B(), #PVR_BVNC_UNPACK_N(), #PVR_BVNC_UNPACK_C(),
* #pvr_get_packed_bvnc() and #PVR_BVNC_PACK()
*/
#define PVR_BVNC_UNPACK_V(bvnc) \
((uint16_t)(((bvnc) & PVR_BVNC_PACK_MASK_V) >> PVR_BVNC_PACK_SHIFT_V))
/**
* Unpacks N value (number of scalable units) from packed BVNC.
*
* \param bvnc Packed BVNC.
* \return Number of scalable units.
*
* \sa #PVR_BVNC_UNPACK_B(), #PVR_BVNC_UNPACK_V(), #PVR_BVNC_UNPACK_C(),
* #pvr_get_packed_bvnc() and #PVR_BVNC_PACK()
*/
#define PVR_BVNC_UNPACK_N(bvnc) \
((uint16_t)(((bvnc) & PVR_BVNC_PACK_MASK_N) >> PVR_BVNC_PACK_SHIFT_N))
/**
* Unpacks C value (config ID) from packed BVNC.
*
* \param bvnc Packed BVNC.
* \return Config ID.
*
* \sa #PVR_BVNC_UNPACK_B(), #PVR_BVNC_UNPACK_V(), #PVR_BVNC_UNPACK_N(),
* #pvr_get_packed_bvnc() and #PVR_BVNC_PACK()
*/
#define PVR_BVNC_UNPACK_C(bvnc) \
((uint16_t)(((bvnc) & PVR_BVNC_PACK_MASK_C) >> PVR_BVNC_PACK_SHIFT_C))
/**
* Tests whether a physical device has a given feature.
*
* Feature names are derived from those found in #pvr_device_features by
* dropping the 'has_' prefix, which is applied by this macro.
*
* \param dev_info #pvr_device_info object associated with the target physical
* device.
* \param feature Device feature name.
*
* \return
* * true if the named feature is present in the hardware.
* * false if the named feature is not present in the hardware.
*
* \sa #PVR_FEATURE_VALUE() and #PVR_GET_FEATURE_VALUE()
*/
#define PVR_HAS_FEATURE(dev_info, feature) ((dev_info)->features.has_##feature)
/**
* Gets a physical device feature value if feature is supported.
*
* Feature names are derived from those found in #pvr_device_features by
* dropping the 'has_' prefix.
*
* This macro should be used in preference to #PVR_GET_FEATURE_VALUE() as it has
* proper error handling.
*
* \param dev_info #pvr_device_info object associated with the target physical
* device.
* \param feature Feature name.
* \param value_out Feature value.
*
* \return
* * 0 on success, or
* * -%EINVAL if the named feature is not present in the hardware.
*
* \sa #PVR_HAS_FEATURE() and #PVR_GET_FEATURE_VALUE()
*/
#define PVR_FEATURE_VALUE(dev_info, feature, value_out) \
({ \
const struct pvr_device_info *__dev_info = dev_info; \
int __ret = -EINVAL; \
if (__dev_info->features.has_##feature) { \
*(value_out) = __dev_info->features.feature; \
__ret = 0; \
} \
__ret; \
})
/**
* Gets a physical device feature value if supported, but otherwise returns a
* default value.
*
* Feature names are derived from those found in #pvr_device_features by
* dropping the 'has_' prefix.
*
* #PVR_FEATURE_VALUE() should be used in preference to this macro when errors
* can be returned by the caller. This macro is intended for cases where errors
* can't be returned.
*
* \param dev_info #pvr_device_info object associated with the target
* physical device.
* \param feature Feature name.
* \param default_value Default feature value.
*
* \return Feature value.
*
* \sa #PVR_HAS_FEATURE() and #PVR_FEATURE_VALUE()
*/
#define PVR_GET_FEATURE_VALUE(dev_info, feature, default_value) \
({ \
const struct pvr_device_info *__dev_info = dev_info; \
__typeof__(default_value) __ret = default_value; \
if (__dev_info->features.has_##feature) { \
__ret = __dev_info->features.feature; \
} else { \
mesa_logw("Missing " #feature \
" feature (defaulting to: " #default_value ")"); \
assert(0); \
} \
__ret; \
})
/**
* Tests whether a physical device has a given enhancement.
*
* Enhancement numbers are derived from those found in #pvr_device_enhancements
* by dropping the 'has_ern' prefix, which is applied by this macro.
*
* \param dev_info #pvr_device_info object associated with the target physical
* device.
* \param number Enhancement number.
*
* \return
* * true if the enhancement is present in the hardware.
* * false if the enhancement is not present in the hardware.
*/
#define PVR_HAS_ENHANCEMENT(dev_info, number) \
((dev_info)->enhancements.has_ern##number)
/**
* Tests whether a physical device has a given quirk.
*
* Quirk numbers are derived from those found in #pvr_device_quirks by
* dropping the 'has_brn' prefix, which is applied by this macro.
*
* \param dev_info #pvr_device_info object associated with the target physical
* device.
* \param number Quirk number.
*
* \return
* * true if the quirk is present in the hardware.
* * false if the quirk is not present in the hardware.
*/
#define PVR_HAS_QUIRK(dev_info, number) ((dev_info)->quirks.has_brn##number)
struct pvr_device_ident {
enum pvr_device_arch arch;
uint16_t b, v, n, c;
uint32_t device_id;
const char *series_name;
const char *public_name;
};
struct pvr_device_features {
bool has_astc : 1;
bool has_cluster_grouping : 1;
bool has_common_store_size_in_dwords : 1;
bool has_compute : 1;
bool has_compute_morton_capable : 1;
bool has_compute_overlap : 1;
bool has_eight_output_registers : 1;
bool has_fb_cdc_v4 : 1;
bool has_fbcdc_algorithm : 1;
bool has_gpu_multicore_support : 1;
bool has_gs_rta_support : 1;
bool has_ipf_creq_pf : 1;
bool has_isp_max_tiles_in_flight : 1;
bool has_isp_samples_per_pixel : 1;
bool has_max_instances_per_pds_task : 1;
bool has_max_multisample : 1;
bool has_max_partitions : 1;
bool has_max_usc_tasks : 1;
bool has_num_clusters : 1;
bool has_num_raster_pipes : 1;
bool has_paired_tiles : 1;
bool has_pbe2_in_xe : 1;
bool has_pbe_filterable_f16 : 1;
bool has_pbe_stride_align_1pixel : 1;
bool has_pbe_yuv : 1;
bool has_pds_ddmadt : 1;
bool has_roguexe : 1;
bool has_screen_size8K : 1;
bool has_simple_internal_parameter_format : 1;
bool has_simple_internal_parameter_format_v1 : 1;
bool has_simple_internal_parameter_format_v2 : 1;
bool has_simple_parameter_format_version : 1;
bool has_slc_cache_line_size_bits : 1;
bool has_slc_mcu_cache_controls : 1;
bool has_tf_bicubic_filter : 1;
bool has_tile_per_usc : 1;
bool has_tile_size_16x16 : 1;
bool has_tile_size_x : 1;
bool has_tile_size_y : 1;
bool has_tpu_array_textures : 1;
bool has_tpu_border_colour_enhanced : 1;
bool has_tpu_dm_global_registers : 1;
bool has_tpu_extended_integer_lookup : 1;
bool has_tpu_image_state_v2 : 1;
bool has_tpu_parallel_instances : 1;
bool has_unified_store_depth : 1;
bool has_usc_alu_roundingmode_rne : 1;
bool has_usc_f16sop_u8 : 1;
bool has_usc_itrsmp : 1;
bool has_usc_itrsmp_enhanced : 1;
bool has_usc_itr_parallel_instances : 1;
bool has_usc_min_output_registers_per_pix : 1;
bool has_usc_pixel_partition_mask : 1;
bool has_usc_slots : 1;
bool has_uvs_banks : 1;
bool has_uvs_pba_entries : 1;
bool has_uvs_vtx_entries : 1;
bool has_vdm_cam_size : 1;
bool has_vdm_degenerate_culling : 1;
bool has_xpu_max_slaves : 1;
bool has_xt_top_infrastructure : 1;
bool has_zls_subtile : 1;
uint32_t common_store_size_in_dwords;
uint32_t fbcdc_algorithm;
uint32_t isp_max_tiles_in_flight;
uint32_t isp_samples_per_pixel;
uint32_t max_instances_per_pds_task;
uint32_t max_multisample;
uint32_t max_partitions;
uint32_t max_usc_tasks;
uint32_t num_clusters;
uint32_t num_raster_pipes;
uint32_t simple_parameter_format_version;
uint32_t slc_cache_line_size_bits;
uint32_t tile_size_x;
uint32_t tile_size_y;
uint32_t tpu_parallel_instances;
uint32_t unified_store_depth;
uint32_t usc_itr_parallel_instances;
uint32_t usc_min_output_registers_per_pix;
uint32_t usc_slots;
uint32_t uvs_banks;
uint32_t uvs_pba_entries;
uint32_t uvs_vtx_entries;
uint32_t vdm_cam_size;
uint32_t xpu_max_slaves;
/* Derived features. */
bool has_requires_fb_cdc_zls_setup : 1;
bool has_s8xe : 1;
};
struct pvr_device_enhancements {
bool has_ern35421 : 1;
bool has_ern38020 : 1;
bool has_ern38748 : 1;
bool has_ern42064 : 1;
bool has_ern42307 : 1;
bool has_ern45493 : 1;
};
struct pvr_device_quirks {
bool has_brn44079 : 1;
bool has_brn47727 : 1;
bool has_brn48492 : 1;
bool has_brn48545 : 1;
bool has_brn49032 : 1;
bool has_brn49927 : 1;
bool has_brn51025 : 1;
bool has_brn51210 : 1;
bool has_brn51764 : 1;
bool has_brn52354 : 1;
bool has_brn52942 : 1;
bool has_brn58839 : 1;
bool has_brn62269 : 1;
bool has_brn66011 : 1;
bool has_brn70165 : 1;
bool has_brn72168 : 1;
bool has_brn72463 : 1;
bool has_brn74056 : 1;
};
struct pvr_device_info {
struct pvr_device_ident ident;
struct pvr_device_features features;
struct pvr_device_enhancements enhancements;
struct pvr_device_quirks quirks;
};
struct pvr_device_runtime_info {
uint64_t min_free_list_size;
uint64_t max_free_list_size;
uint64_t reserved_shared_size;
uint64_t total_reserved_partition_size;
uint64_t num_phantoms;
uint64_t max_coeffs;
uint64_t cdm_max_local_mem_size_regs;
uint32_t core_count;
};
/**
* Packs B, V, N and C values into a 64-bit unsigned integer.
*
* The packed layout is as follows:
*
* \verbatim
* +--------+--------+--------+-------+
* | 63..48 | 47..32 | 31..16 | 15..0 |
* +========+========+========+=======+
* | B | V | N | C |
* +--------+--------+--------+-------+
* \endverbatim
*
* This should be used in preference to #PVR_BVNC_PACK() when a
* #pvr_device_info is available in order to ensure proper type checking.
*
* \param dev_info Device information.
* \return Packed BVNC.
*/
static ALWAYS_INLINE uint64_t
pvr_get_packed_bvnc(const struct pvr_device_info *dev_info)
{
return PVR_BVNC_PACK(dev_info->ident.b,
dev_info->ident.v,
dev_info->ident.n,
dev_info->ident.c);
}
int pvr_device_info_init(struct pvr_device_info *info, uint64_t bvnc);
bool pvr_device_info_init_public_name(struct pvr_device_info *info,
const char *public_name);
#endif /* PVR_DEVICE_INFO_H */
+299
View File
@@ -0,0 +1,299 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "pvr_dump.h"
#include "pvr_util.h"
#include "util/u_math.h"
const struct pvr_dump_ctx __pvr_dump_ctx_invalid = {
.active_child = &__pvr_dump_ctx_invalid,
};
/*****************************************************************************
Hex dumps
*****************************************************************************/
#define HEX_WORD_SIZE ((unsigned)sizeof(uint32_t))
#define HEX_BYTE_FMT "%02" PRIx8
/* This must be even, and should probably always be a power of 2. */
#define HEX_LINE_SIZE (HEX_WORD_SIZE * 8)
struct pvr_dump_hex_ctx {
struct pvr_dump_ctx base;
const uint8_t *start_ptr;
const uint8_t *end_ptr;
uint64_t nr_bytes;
uint32_t offset_digits;
/* User-modifiable values */
const uint8_t *line_ptr;
uint32_t prev_non_zero_trailing_zero_bytes;
uint64_t prev_non_zero_leading_zero_lines;
const uint8_t *prev_non_zero_line;
uint64_t zero_lines;
};
static bool pvr_dump_hex_ctx_push(struct pvr_dump_hex_ctx *const ctx,
struct pvr_dump_buffer_ctx *const parent_ctx,
const uint64_t nr_bytes)
{
const uint64_t real_nr_bytes = nr_bytes ? nr_bytes
: parent_ctx->remaining_size;
bool ret;
if (parent_ctx->remaining_size < nr_bytes)
return false;
ret = pvr_dump_ctx_push(&ctx->base, &parent_ctx->base);
if (!ret)
return false;
ctx->start_ptr = parent_ctx->ptr;
ctx->end_ptr = ctx->start_ptr + real_nr_bytes;
ctx->nr_bytes = real_nr_bytes;
ctx->offset_digits = u64_hex_digits(real_nr_bytes);
ctx->line_ptr = ctx->start_ptr;
ctx->prev_non_zero_trailing_zero_bytes = 0;
ctx->prev_non_zero_leading_zero_lines = 0;
ctx->prev_non_zero_line = NULL;
ctx->zero_lines = 0;
return true;
}
static struct pvr_dump_buffer_ctx *
pvr_dump_hex_ctx_pop(struct pvr_dump_hex_ctx *const ctx)
{
struct pvr_dump_buffer_ctx *parent;
struct pvr_dump_ctx *parent_base;
if (ctx->line_ptr != ctx->end_ptr) {
ctx->base.ok = false;
return NULL;
}
parent_base = pvr_dump_ctx_pop(&ctx->base);
if (!parent_base)
return NULL;
parent = container_of(parent_base, struct pvr_dump_buffer_ctx, base);
pvr_dump_buffer_advance(parent, ctx->nr_bytes);
return parent;
}
static inline void pvr_dump_hex_print_prefix(const struct pvr_dump_hex_ctx *ctx,
const uint64_t offset)
{
pvr_dump_printf(&ctx->base,
PVR_DUMP_OFFSET_PREFIX,
ctx->offset_digits,
offset);
}
#define pvr_dump_hex_println(ctx, offset, format, args...) \
pvr_dump_println(&(ctx)->base, \
PVR_DUMP_OFFSET_PREFIX format, \
(ctx)->offset_digits, \
offset, \
##args)
#define pvr_dump_hex_println_no_prefix(ctx, format, args...) \
pvr_dump_println(&(ctx)->base, \
"%*c" format, \
(ctx)->offset_digits + 3, \
' ', \
##args)
static void pvr_dump_hex_print_line(const struct pvr_dump_hex_ctx *ctx,
const uint8_t *const line_ptr,
const uint32_t truncate)
{
const uint32_t nr_bytes =
MIN2(HEX_LINE_SIZE - truncate, ctx->end_ptr - line_ptr);
pvr_dump_hex_print_prefix(ctx, line_ptr - ctx->start_ptr);
for (uint32_t i = 0; i < nr_bytes; i++) {
if (i == HEX_LINE_SIZE / 2)
pvr_dump_printf_cont(&ctx->base, " ");
if (i % HEX_WORD_SIZE == 0)
pvr_dump_printf_cont(&ctx->base, " ");
if (line_ptr[i])
pvr_dump_printf_cont(&ctx->base, HEX_BYTE_FMT, line_ptr[i]);
else
pvr_dump_printf_cont(&ctx->base, "..");
}
pvr_dump_print_eol(&ctx->base);
}
static void
pvr_dump_hex_print_zero_lines(const struct pvr_dump_hex_ctx *const ctx,
const uint64_t zero_lines)
{
const uint64_t zero_bytes = zero_lines * HEX_LINE_SIZE;
if (!zero_lines)
return;
/* If we've only buffered a single zero line, print it normally. We don't
* save any space by folding it, and it's more readable this way.
*/
if (zero_lines == 1) {
pvr_dump_hex_print_line(ctx, ctx->prev_non_zero_line + HEX_LINE_SIZE, 0);
return;
}
pvr_dump_hex_println_no_prefix(ctx,
" + %" PRIu64 " zero line%s (%" PRIu64
"/0x%" PRIx64 " bytes)",
zero_lines,
zero_lines == 1 ? "" : "s",
zero_bytes,
zero_bytes);
}
static void
pvr_dump_hex_print_trailing_zeroes(const struct pvr_dump_hex_ctx *const ctx)
{
const uint64_t zero_bytes =
ctx->zero_lines * HEX_LINE_SIZE + ctx->prev_non_zero_trailing_zero_bytes;
if (!ctx->prev_non_zero_trailing_zero_bytes)
return pvr_dump_hex_print_zero_lines(ctx, ctx->zero_lines);
if (!ctx->zero_lines)
return;
pvr_dump_hex_println_no_prefix(ctx,
" + %" PRIu64 "+%" PRIu32
" zero lines (%" PRIu64 "/0x%" PRIx64
" bytes)",
ctx->zero_lines,
ctx->prev_non_zero_trailing_zero_bytes,
zero_bytes,
zero_bytes);
}
static void pvr_dump_hex_process_line(struct pvr_dump_hex_ctx *const ctx,
uint32_t truncate)
{
const uint32_t max_bytes = HEX_LINE_SIZE - truncate;
uint32_t trailing_zero_bytes = max_bytes;
for (uint32_t i = max_bytes; i > 0; i--) {
if (ctx->line_ptr[i - 1]) {
trailing_zero_bytes = HEX_LINE_SIZE - i;
break;
}
}
if (trailing_zero_bytes == max_bytes) {
/* No non-zero words were found in this line; mark it and move on. */
ctx->zero_lines++;
return;
}
/* We have at least one non-zero word in this line. If we have a previous
* non-zero line stored, collapse and print any leading zero-only lines
* before it then print the stored line.
*/
if (ctx->prev_non_zero_line) {
pvr_dump_hex_print_zero_lines(ctx, ctx->prev_non_zero_leading_zero_lines);
pvr_dump_hex_print_line(ctx, ctx->prev_non_zero_line, truncate);
}
/* Now we store the current non-zero line for printing later. This way we
* can treat the last non-zero line specially.
*/
ctx->prev_non_zero_line = ctx->line_ptr;
ctx->prev_non_zero_leading_zero_lines = ctx->zero_lines;
ctx->prev_non_zero_trailing_zero_bytes = trailing_zero_bytes;
ctx->zero_lines = 0;
}
static void pvr_dump_hex(struct pvr_dump_hex_ctx *const ctx)
{
while (ctx->line_ptr < (ctx->end_ptr - HEX_LINE_SIZE)) {
pvr_dump_hex_process_line(ctx, 0);
ctx->line_ptr += HEX_LINE_SIZE;
}
pvr_dump_hex_process_line(ctx,
HEX_LINE_SIZE - (ctx->end_ptr - ctx->line_ptr));
ctx->line_ptr = ctx->end_ptr;
if (ctx->prev_non_zero_line) {
/* If we don't have any zero lines to collapse, print the trailing zeroes
* on the last line.
*/
if (!ctx->zero_lines) {
pvr_dump_hex_print_line(ctx, ctx->prev_non_zero_line, 0);
} else {
pvr_dump_hex_print_zero_lines(ctx,
ctx->prev_non_zero_leading_zero_lines);
pvr_dump_hex_print_line(ctx,
ctx->prev_non_zero_line,
ctx->prev_non_zero_trailing_zero_bytes);
/* Collapse and print any trailing zeroes. */
pvr_dump_hex_print_trailing_zeroes(ctx);
}
} else {
/* We made it to the end of the buffer without ever encountering a
* non-zero word. Make this known.
*/
pvr_dump_hex_println(ctx, UINT64_C(0), " <empty buffer>");
}
pvr_dump_hex_println(ctx, ctx->nr_bytes, " <end of buffer>");
}
bool pvr_dump_buffer_hex(struct pvr_dump_buffer_ctx *const ctx,
const uint64_t nr_bytes)
{
struct pvr_dump_hex_ctx hex_ctx;
if (!pvr_dump_hex_ctx_push(&hex_ctx, ctx, nr_bytes))
return false;
pvr_dump_hex(&hex_ctx);
return !!pvr_dump_hex_ctx_pop(&hex_ctx);
}
+739
View File
@@ -0,0 +1,739 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef PVR_DUMP_H
#define PVR_DUMP_H
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "pvr_types.h"
#include "pvr_util.h"
#include "util/macros.h"
#include "util/u_math.h"
/** BASIC PRINTING **/
#define PVR_DUMP_OFFSET_PREFIX "[%0*" PRIx64 "] "
/** CONTEXTS **/
#define PVR_DUMP_INDENT_SIZE 2U
#define PVR_DUMP_FIELD_COLUMN_WIDTH 36U
/* This is an invalid context used to permanently mark popped contexts as
* unusable. All operations on a context check that it's the "top" context
* by ensuring it has no active child. The only way to remove the active child
* of a context is by popping the active child directly. Assigning an invalid
* context as the active child of a context therefore makes it impossible to
* use.
*/
extern const struct pvr_dump_ctx __pvr_dump_ctx_invalid;
struct pvr_dump_ctx {
/* This is const because only the "top" context should ever be modified. It's
* fine to extract information from the parent context, but not to modify it.
* There is *one* exception: pvr_dump_ctx_pop() must cast away the const to
* return the parent context as the new "top" context. This is considered
* sound because the parent context was not const when assigned here in
* pvr_dump_ctx_push().
*/
const struct pvr_dump_ctx *parent;
/* This is const because it's not meant to be used for access - it's just a
* way of checking if this context is the "top" context (see the comment on
* __pvr_dump_ctx_invalid for more details). Unlike parent, the const
* qualifier here should never be cast away.
*/
const struct pvr_dump_ctx *active_child;
FILE *file;
const char *name;
uint32_t allowed_child_depth;
uint32_t parent_indent;
/* User-modifiable values */
uint32_t indent;
bool ok;
};
static inline uint32_t
__pvr_dump_ctx_get_indent(const struct pvr_dump_ctx *const ctx)
{
return (ctx->parent_indent + ctx->indent) * PVR_DUMP_INDENT_SIZE;
}
struct pvr_dump_buffer_ctx {
struct pvr_dump_ctx base;
const void *initial_ptr;
uint64_t capacity;
/* User-modifiable values */
const void *ptr;
uint64_t remaining_size;
};
#define pvr_dump_printf(ctx, format, args...) \
pvr_dump_printf_cont(ctx, \
"%*s" format, \
__pvr_dump_ctx_get_indent(ctx), \
"", \
##args)
/* Same as pvr_dump_printf(), but with no indent.
* Intended for continuation lines.
*/
#define pvr_dump_printf_cont(ctx, format, args...) \
fprintf((ctx)->file, format, ##args)
#define pvr_dump_println(ctx, format, args...) \
pvr_dump_printf(ctx, format "\n", ##args)
#define pvr_dump_println_cont(ctx, format, args...) \
pvr_dump_printf_cont(ctx, format "\n", ##args)
#define pvr_dump_print_eol(ctx) fprintf((ctx)->file, "\n")
#define pvr_dump_mark_section(ctx, format, args...) \
do { \
pvr_dump_print_eol(ctx); \
pvr_dump_println(ctx, "------- " format " -------", ##args); \
} while (0)
#define pvr_dump_buffer_print_header_prefix(ctx) \
do { \
struct pvr_dump_buffer_ctx *_prefix_ctx = (ctx); \
pvr_dump_printf(&_prefix_ctx->base, \
PVR_DUMP_OFFSET_PREFIX, \
u64_dec_digits(_prefix_ctx->capacity), \
_prefix_ctx->capacity - _prefix_ctx->remaining_size); \
} while (0)
#define pvr_dump_buffer_print_header_line(ctx, format, args...) \
do { \
struct pvr_dump_buffer_ctx *_ctx = (ctx); \
pvr_dump_buffer_print_header_prefix(_ctx); \
pvr_dump_printf_cont(&_ctx->base, format "\n", ##args); \
} while (0)
#define pvr_dump_msg(ctx, prefix, ret, format, args...) \
({ \
bool _ret = (ret); \
struct pvr_dump_ctx *_ctx = (ctx); \
pvr_dump_println(_ctx, "<!" prefix "! " format ">", ##args); \
if (!_ret) \
_ctx->ok = _ret; \
_ret; \
})
#define pvr_dump_error(ctx, format, args...) \
pvr_dump_msg(ctx, "ERROR", false, format, ##args)
#define pvr_dump_warn(ctx, format, args...) \
pvr_dump_msg(ctx, "WARN", true, format, ##args)
static inline bool pvr_dump_ctx_require_top(struct pvr_dump_ctx *const ctx)
{
if (ctx->active_child != NULL)
return pvr_dump_error(ctx, "use of non-top context");
return true;
}
static inline void pvr_dump_indent(struct pvr_dump_ctx *const ctx)
{
ctx->indent++;
}
static inline void pvr_dump_dedent(struct pvr_dump_ctx *const ctx)
{
if (ctx->indent)
ctx->indent--;
}
static inline void __pvr_dump_ctx_init(struct pvr_dump_ctx *const ctx,
const struct pvr_dump_ctx *const parent,
FILE *const file,
const char *const name,
const uint32_t allowed_child_depth,
const uint32_t parent_indent)
{
ctx->parent = parent;
ctx->active_child = NULL;
ctx->file = file;
ctx->name = name;
ctx->allowed_child_depth = allowed_child_depth;
ctx->parent_indent = parent_indent;
ctx->indent = 0;
ctx->ok = true;
}
static inline void __pvr_dump_ctx_mark_popped(struct pvr_dump_ctx *const ctx)
{
ctx->active_child = &__pvr_dump_ctx_invalid;
}
static inline void pvr_dump_begin(struct pvr_dump_ctx *const root_ctx,
FILE *const file,
const char *const name,
const uint32_t max_depth)
{
__pvr_dump_ctx_init(root_ctx, NULL, file, name, max_depth, 0);
flockfile(file);
pvr_dump_println(root_ctx, "======= BEGIN %s =======", name);
}
static inline bool pvr_dump_end(struct pvr_dump_ctx *const root_ctx)
{
/* In order to end a dump, we must be in a root context (no parent) and have
* no active child context.
*/
if (!pvr_dump_ctx_require_top(root_ctx))
return false;
if (root_ctx->parent)
return pvr_dump_error(root_ctx, "ending non-root context");
pvr_dump_println(root_ctx, "======= END %s =======", root_ctx->name);
funlockfile(root_ctx->file);
__pvr_dump_ctx_mark_popped(root_ctx);
return true;
}
static inline bool pvr_dump_ctx_push(struct pvr_dump_ctx *const ctx,
struct pvr_dump_ctx *const parent_ctx)
{
if (!parent_ctx->ok)
return false;
if (!parent_ctx->allowed_child_depth)
return pvr_dump_error(parent_ctx, "context stack depth limit reached");
__pvr_dump_ctx_init(ctx,
parent_ctx,
parent_ctx->file,
parent_ctx->name,
parent_ctx->allowed_child_depth - 1,
parent_ctx->parent_indent + parent_ctx->indent);
parent_ctx->active_child = ctx;
return true;
}
static inline struct pvr_dump_ctx *
pvr_dump_ctx_pop(struct pvr_dump_ctx *const ctx)
{
struct pvr_dump_ctx *const parent = (struct pvr_dump_ctx *)ctx->parent;
if (!pvr_dump_ctx_require_top(ctx))
return NULL;
if (!parent) {
pvr_dump_error(ctx, "popped root context");
return NULL;
}
parent->active_child = NULL;
__pvr_dump_ctx_mark_popped(ctx);
return parent;
}
static inline bool
pvr_dump_buffer_ctx_push(struct pvr_dump_buffer_ctx *const ctx,
struct pvr_dump_ctx *const parent_ctx,
const void *const initial_ptr,
const uint64_t size)
{
if (!pvr_dump_ctx_push(&ctx->base, parent_ctx))
return false;
ctx->initial_ptr = initial_ptr;
ctx->capacity = size;
ctx->ptr = initial_ptr;
ctx->remaining_size = size;
return true;
}
static inline struct pvr_dump_ctx *
pvr_dump_buffer_ctx_pop(struct pvr_dump_buffer_ctx *const ctx)
{
return pvr_dump_ctx_pop(&ctx->base);
}
bool pvr_dump_buffer_hex(struct pvr_dump_buffer_ctx *ctx, uint64_t nr_bytes);
static inline void __pvr_dump_buffer_advance(struct pvr_dump_buffer_ctx *ctx,
const uint64_t nr_bytes)
{
ctx->ptr = (uint8_t *)ctx->ptr + nr_bytes;
ctx->remaining_size -= nr_bytes;
}
static inline bool pvr_dump_buffer_advance(struct pvr_dump_buffer_ctx *ctx,
const uint64_t nr_bytes)
{
if (!ctx->base.ok || !pvr_dump_ctx_require_top(&ctx->base))
return false;
if (nr_bytes > ctx->remaining_size)
return pvr_dump_error(&ctx->base, "advanced past end of context buffer");
__pvr_dump_buffer_advance(ctx, nr_bytes);
return true;
}
static inline void __pvr_dump_buffer_rewind(struct pvr_dump_buffer_ctx *ctx,
const uint32_t nr_bytes)
{
ctx->ptr = (uint8_t *)ctx->ptr - nr_bytes;
ctx->remaining_size += nr_bytes;
}
static inline bool pvr_dump_buffer_rewind(struct pvr_dump_buffer_ctx *ctx,
const uint32_t nr_bytes)
{
if (!ctx->base.ok || !pvr_dump_ctx_require_top(&ctx->base))
return false;
if (nr_bytes > ctx->capacity - ctx->remaining_size)
return pvr_dump_error(&ctx->base, "rewound past start of context buffer");
__pvr_dump_buffer_rewind(ctx, nr_bytes);
return true;
}
static inline bool pvr_dump_buffer_truncate(struct pvr_dump_buffer_ctx *ctx,
const uint64_t remaining_size)
{
if (!ctx->base.ok || !pvr_dump_ctx_require_top(&ctx->base))
return false;
if (remaining_size > ctx->remaining_size)
return pvr_dump_error(&ctx->base, "truncated to larger size");
ctx->remaining_size = remaining_size;
return true;
}
static inline const void *restrict pvr_dump_buffer_peek(
struct pvr_dump_buffer_ctx *const restrict ctx,
const uint64_t nr_bytes)
{
if (!ctx->base.ok || !pvr_dump_ctx_require_top(&ctx->base))
return NULL;
if (nr_bytes > ctx->remaining_size) {
pvr_dump_error(&ctx->base, "peeked past end of context buffer");
return NULL;
}
return ctx->ptr;
}
static inline const void *restrict pvr_dump_buffer_take(
struct pvr_dump_buffer_ctx *const restrict ctx,
const uint64_t nr_bytes)
{
const void *const ptr = pvr_dump_buffer_peek(ctx, nr_bytes);
if (ptr)
__pvr_dump_buffer_advance(ctx, nr_bytes);
return ptr;
}
static inline void
pvr_dump_buffer_restart(struct pvr_dump_buffer_ctx *const ctx)
{
ctx->ptr = ctx->initial_ptr;
ctx->remaining_size = ctx->capacity;
}
/*****************************************************************************
Field printers
*****************************************************************************/
#define pvr_dump_field(ctx, name, format, args...) \
pvr_dump_println(ctx, \
"%-*s : " format, \
PVR_DUMP_FIELD_COLUMN_WIDTH - \
__pvr_dump_ctx_get_indent(ctx), \
name, \
##args)
#define pvr_dump_field_computed(ctx, name, format, raw_format, args...) \
pvr_dump_field(ctx, name, format " (" raw_format ")", ##args)
#define pvr_dump_field_error(ctx, format, args...) \
({ \
struct pvr_dump_ctx *_ctx = (ctx); \
pvr_dump_field(_ctx, "<!ERROR!>", "<" format ">", ##args); \
_ctx->ok = false; \
false; \
})
/*****************************************************************************
Field printers: integers
*****************************************************************************/
static inline void pvr_dump_field_u32(struct pvr_dump_ctx *const ctx,
const char *const name,
const uint32_t value)
{
pvr_dump_field(ctx, name, "%" PRIu32, value);
}
static inline void pvr_dump_field_u32_units(struct pvr_dump_ctx *const ctx,
const char *const name,
const uint32_t value,
const char *const units)
{
pvr_dump_field(ctx, name, "%" PRIu32 " %s", value, units);
}
static inline void pvr_dump_field_u32_offset(struct pvr_dump_ctx *const ctx,
const char *const name,
const uint32_t value,
const uint32_t offset)
{
pvr_dump_field_computed(ctx,
name,
"%" PRIu32,
"%" PRIu32 " + %" PRIu32,
value + offset,
value,
offset);
}
static inline void pvr_dump_field_u32_scaled(struct pvr_dump_ctx *const ctx,
const char *const name,
const uint32_t value,
const uint32_t scale)
{
pvr_dump_field_computed(ctx,
name,
"%" PRIu32,
"%" PRIu32 " x %" PRIu32,
value * scale,
value,
scale);
}
static inline void
pvr_dump_field_u32_scaled_units(struct pvr_dump_ctx *const ctx,
const char *const name,
const uint32_t value,
const uint32_t scale,
const char *const units)
{
pvr_dump_field_computed(ctx,
name,
"%" PRIu32 " %s",
"%" PRIu32 " x %" PRIu32 " %s",
value * scale,
units,
value,
scale,
units);
}
static inline void pvr_dump_field_u32_zero(struct pvr_dump_ctx *const ctx,
const char *const name,
const uint32_t value,
const uint32_t zero_value)
{
if (value)
pvr_dump_field_u32(ctx, name, value);
else
pvr_dump_field_computed(ctx, name, "%" PRIu32, "0", zero_value);
}
static inline void pvr_dump_field_x32(struct pvr_dump_ctx *const ctx,
const char *const name,
const uint32_t value,
const uint32_t chars)
{
pvr_dump_field(ctx,
name,
"0x%0*" PRIx32,
chars,
value & BITFIELD_MASK(chars * 4));
}
static inline void pvr_dump_field_u64(struct pvr_dump_ctx *const ctx,
const char *const name,
const uint64_t value)
{
pvr_dump_field(ctx, name, "%" PRIu64, value);
}
static inline void pvr_dump_field_u64_units(struct pvr_dump_ctx *const ctx,
const char *const name,
const uint64_t value,
const char *const units)
{
pvr_dump_field(ctx, name, "%" PRIu64 " %s", value, units);
}
/*****************************************************************************
Field printers: floating point
*****************************************************************************/
static inline void pvr_dump_field_f32(struct pvr_dump_ctx *const ctx,
const char *const name,
const float value)
{
pvr_dump_field_computed(ctx, name, "%f", "0x%08" PRIx32, value, fui(value));
}
/*****************************************************************************
Field printers: fixed point
*****************************************************************************/
/* clang-format off */
static const char *const __fixed_frac_str_table_4[1 << 4] = {
"0", "0625", "125", "1875", "25", "3125", "375", "4375",
"5", "5625", "625", "6875", "75", "8125", "875", "9375",
};
/* clang-format on */
static inline void pvr_dump_field_uq4_4(struct pvr_dump_ctx *const ctx,
const char *const name,
const uint32_t raw_value)
{
const uint32_t int_part = (raw_value & BITFIELD_RANGE(4, 4)) >> 4;
const uint32_t frac_part = raw_value & BITFIELD_MASK(4);
pvr_dump_field_computed(ctx,
name,
"%" PRIu32 ".%s",
"0x%02" PRIx32, /* Or %0*x where *=(nr_bits+3)/4 */
int_part,
__fixed_frac_str_table_4[frac_part],
raw_value & BITFIELD_MASK(8));
}
static inline void pvr_dump_field_uq4_4_offset(struct pvr_dump_ctx *const ctx,
const char *const name,
const uint32_t raw_value,
const uint32_t raw_offset)
{
const uint32_t raw_offset_value = raw_value + raw_offset;
const uint32_t int_part = (raw_offset_value & BITFIELD_RANGE(4, 4)) >> 4;
const uint32_t frac_part = raw_offset_value & BITFIELD_MASK(4);
pvr_dump_field_computed(ctx,
name,
"%" PRIu32 ".%s",
"0x%02" PRIx32 " + 0x%02" PRIx32,
int_part,
__fixed_frac_str_table_4[frac_part],
raw_value & BITFIELD_MASK(8),
raw_offset);
}
/*****************************************************************************
Field printers: device address
*****************************************************************************/
static inline void pvr_dump_field_addr_non_null(struct pvr_dump_ctx *const ctx,
const char *const name,
const pvr_dev_addr_t value)
{
pvr_dump_field(ctx, name, PVR_DEV_ADDR_FMT, value.addr);
}
static inline void pvr_dump_field_addr(struct pvr_dump_ctx *const ctx,
const char *const name,
const pvr_dev_addr_t value)
{
if (value.addr)
pvr_dump_field_addr_non_null(ctx, name, value);
else
pvr_dump_field(ctx, name, "<null>");
}
static inline void pvr_dump_field_addr_split(struct pvr_dump_ctx *const ctx,
const char *const name,
const pvr_dev_addr_t msb,
const pvr_dev_addr_t lsb)
{
pvr_dump_field_addr(ctx, name, PVR_DEV_ADDR(msb.addr | lsb.addr));
pvr_dump_indent(ctx);
pvr_dump_field_addr_non_null(ctx, "msb", msb);
pvr_dump_field_addr_non_null(ctx, "lsb", lsb);
pvr_dump_dedent(ctx);
}
static inline void pvr_dump_field_addr_offset(struct pvr_dump_ctx *const ctx,
const char *const name,
const pvr_dev_addr_t value,
const pvr_dev_addr_t base)
{
pvr_dump_field_computed(ctx,
name,
PVR_DEV_ADDR_FMT,
PVR_DEV_ADDR_FMT " + " PVR_DEV_ADDR_FMT,
PVR_DEV_ADDR_OFFSET(base, value.addr).addr,
base.addr,
value.addr);
}
/*****************************************************************************
Field printers: enums
*****************************************************************************/
#define pvr_dump_field_enum(ctx, name, value, to_str) \
do { \
__typeof__(value) _value = (value); \
const char *_str = to_str(_value); \
if (!_str) \
_str = "<unknown>"; \
pvr_dump_field_computed(ctx, name, "%s", "%u", _str, _value); \
} while (0)
static inline const char *__bool_to_str(const bool b)
{
return b ? "yes" : "no";
}
/* A bool is just an enum with two values. */
static inline void pvr_dump_field_bool(struct pvr_dump_ctx *const ctx,
const char *const name,
const bool value)
{
pvr_dump_field_enum(ctx, name, value, __bool_to_str);
}
/*****************************************************************************
Field printers: string
*****************************************************************************/
static inline void pvr_dump_field_string(struct pvr_dump_ctx *const ctx,
const char *const name,
const char *const value)
{
pvr_dump_field(ctx, name, "%s", value);
}
/*****************************************************************************
Field printers: not present
*****************************************************************************/
static inline void pvr_dump_field_no_fields(struct pvr_dump_ctx *const ctx)
{
pvr_dump_println(ctx, "<no fields>");
}
static inline void pvr_dump_field_not_present(struct pvr_dump_ctx *const ctx,
const char *const name)
{
pvr_dump_field(ctx, name, "<not present>");
}
/*****************************************************************************
Field printers: helpers for members
*****************************************************************************/
/* clang-format off */
#define pvr_dump_field_member_u32(ctx, compound, member) \
pvr_dump_field_u32(ctx, #member, (compound)->member)
#define pvr_dump_field_member_u32_units(ctx, compound, member, units) \
pvr_dump_field_u32_units(ctx, #member, (compound)->member, units)
#define pvr_dump_field_member_u32_offset(ctx, compound, member, offset) \
pvr_dump_field_u32_offset(ctx, #member, (compound)->member, offset)
#define pvr_dump_field_member_u32_scaled(ctx, compound, member, scale) \
pvr_dump_field_u32_scaled(ctx, #member, (compound)->member, scale)
#define pvr_dump_field_member_u32_scaled_units(ctx, compound, member, scale, units) \
pvr_dump_field_u32_scaled_units(ctx, #member, (compound)->member, scale, units)
#define pvr_dump_field_member_u32_zero(ctx, compound, member, zero_value) \
pvr_dump_field_u32_zero(ctx, #member, (compound)->member, zero_value)
#define pvr_dump_field_member_x32(ctx, compound, member, chars) \
pvr_dump_field_x32(ctx, #member, (compound)->member, chars)
#define pvr_dump_field_member_u64(ctx, compound, member) \
pvr_dump_field_u64(ctx, #member, (compound)->member)
#define pvr_dump_field_member_u64_units(ctx, compound, member, units) \
pvr_dump_field_u64_units(ctx, #member, (compound)->member, units)
#define pvr_dump_field_member_f32(ctx, compound, member) \
pvr_dump_field_f32(ctx, #member, (compound)->member)
#define pvr_dump_field_member_uq4_4(ctx, compound, member) \
pvr_dump_field_uq4_4(ctx, #member, (compound)->member)
#define pvr_dump_field_member_uq4_4_offset(ctx, compound, member, raw_offset) \
pvr_dump_field_uq4_4_offset(ctx, #member, (compound)->member, raw_offset)
#define pvr_dump_field_member_addr(ctx, compound, member) \
pvr_dump_field_addr(ctx, #member, (compound)->member)
#define pvr_dump_field_member_addr_offset(ctx, compound, member, base) \
pvr_dump_field_addr_offset(ctx, #member, (compound)->member, base)
#define pvr_dump_field_member_enum(ctx, compound, member, to_str) \
pvr_dump_field_enum(ctx, #member, (compound)->member, to_str)
#define pvr_dump_field_member_bool(ctx, compound, member) \
pvr_dump_field_bool(ctx, #member, (compound)->member)
#define pvr_dump_field_member_string(ctx, compound, member) \
pvr_dump_field_string(ctx, #member, (compound)->member)
/* clang-format on */
#define pvr_dump_field_member_not_present(ctx, compound, member) \
do { \
(void)&(compound)->member; \
pvr_dump_field_not_present(ctx, #member); \
} while (0)
#endif /* PVR_DUMP_H */
+147
View File
@@ -0,0 +1,147 @@
/*
* Copyright © 2023 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "git_sha1.h"
#include "pvr_dump_info.h"
#include "pvr_dump.h"
static inline void pvr_dump_field_bvnc(struct pvr_dump_ctx *ctx,
const char *const name,
const struct pvr_device_info *info)
{
pvr_dump_field_computed(ctx,
name,
"%" PRIu16 ".%" PRIu16 ".%" PRIu16 ".%" PRIu16,
"0x%08" PRIx64,
info->ident.b,
info->ident.v,
info->ident.n,
info->ident.c,
pvr_get_packed_bvnc(info));
}
static inline void pvr_dump_field_drm_version(struct pvr_dump_ctx *ctx,
const char *const name,
const char *const drm_name,
int drm_version_major,
int drm_version_minor,
int drm_version_patchlevel,
const char *const drm_date)
{
pvr_dump_field(ctx,
name,
"%s %d.%d.%d (%s)",
drm_name,
drm_version_major,
drm_version_minor,
drm_version_patchlevel,
drm_date);
}
static inline void pvr_dump_field_compatible_strings(struct pvr_dump_ctx *ctx,
char *const *comp)
{
char *const *temp_comp = comp;
uint32_t count_log10;
uint32_t index = 0;
if (!*comp) {
pvr_dump_println(ctx, "<empty>");
return;
}
while (*temp_comp++)
index++;
count_log10 = u32_dec_digits(index);
index = 0;
while (*comp)
pvr_dump_println(ctx, "[%0*" PRIu32 "] %s", count_log10, index++, *comp++);
}
void pvr_dump_physical_device_info(const struct pvr_device_dump_info *dump_info)
{
const struct pvr_device_runtime_info *run_info =
dump_info->device_runtime_info;
const struct pvr_device_info *dev_info = dump_info->device_info;
struct pvr_dump_ctx ctx;
pvr_dump_begin(&ctx, stderr, "DEBUG INFORMATION", 1);
pvr_dump_mark_section(&ctx, "General Info");
pvr_dump_indent(&ctx);
pvr_dump_field_string(&ctx, "Public Name", dev_info->ident.public_name);
pvr_dump_field_string(&ctx, "Series Name", dev_info->ident.series_name);
pvr_dump_field_bvnc(&ctx, "BVNC", dev_info);
pvr_dump_field_drm_version(&ctx,
"DRM Display Driver Version",
dump_info->drm_display.name,
dump_info->drm_display.major,
dump_info->drm_display.minor,
dump_info->drm_display.patchlevel,
dump_info->drm_display.date);
pvr_dump_field_drm_version(&ctx,
"DRM Render Driver Version",
dump_info->drm_render.name,
dump_info->drm_render.major,
dump_info->drm_render.minor,
dump_info->drm_render.patchlevel,
dump_info->drm_render.date);
pvr_dump_field_string(&ctx, "MESA ", PACKAGE_VERSION MESA_GIT_SHA1);
pvr_dump_dedent(&ctx);
if (dump_info->drm_display.comp) {
pvr_dump_mark_section(&ctx, "Display Platform Compatible Strings");
pvr_dump_indent(&ctx);
pvr_dump_field_compatible_strings(&ctx, dump_info->drm_display.comp);
pvr_dump_dedent(&ctx);
}
pvr_dump_mark_section(&ctx, "Render Platform Compatible Strings");
pvr_dump_indent(&ctx);
pvr_dump_field_compatible_strings(&ctx, dump_info->drm_render.comp);
pvr_dump_dedent(&ctx);
pvr_dump_print_eol(&ctx);
pvr_dump_mark_section(&ctx, "Runtime Info");
pvr_dump_indent(&ctx);
pvr_dump_field_member_u64(&ctx, run_info, cdm_max_local_mem_size_regs);
pvr_dump_field_member_u64_units(&ctx, run_info, max_free_list_size, "bytes");
pvr_dump_field_member_u64_units(&ctx, run_info, min_free_list_size, "bytes");
pvr_dump_field_member_u64_units(&ctx,
run_info,
reserved_shared_size,
"bytes");
pvr_dump_field_member_u64_units(&ctx,
run_info,
total_reserved_partition_size,
"bytes");
pvr_dump_field_member_u32(&ctx, run_info, core_count);
pvr_dump_field_member_u64(&ctx, run_info, max_coeffs);
pvr_dump_field_member_u64(&ctx, run_info, num_phantoms);
pvr_dump_dedent(&ctx);
pvr_dump_print_eol(&ctx);
pvr_dump_end(&ctx);
}
+44
View File
@@ -0,0 +1,44 @@
/*
* Copyright © 2023 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef PVR_DUMP_INFO_H
#define PVR_DUMP_INFO_H
#include "pvr_device_info.h"
struct pvr_device_dump_info {
const struct pvr_device_info *device_info;
const struct pvr_device_runtime_info *device_runtime_info;
struct {
int patchlevel;
int major;
int minor;
const char *name;
const char *date;
char *const *comp;
} drm_display, drm_render;
};
void pvr_dump_physical_device_info(const struct pvr_device_dump_info *dump_info);
#endif
+144
View File
@@ -0,0 +1,144 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
* SPDX-License-Identifier: MIT
*/
#ifndef PVR_IFACE_H
#define PVR_IFACE_H
/**
* \file pvr_iface.h
*
* \brief USC program interface.
*/
/** Query availability shader data; shared registers. */
enum pvr_query_availability_data {
PVR_QUERY_AVAILABILITY_DATA_INDEX_COUNT,
PVR_QUERY_AVAILABILITY_DATA_INDEX_BO_LO,
PVR_QUERY_AVAILABILITY_DATA_INDEX_BO_HI,
PVR_QUERY_AVAILABILITY_DATA_BO_LO,
PVR_QUERY_AVAILABILITY_DATA_BO_HI,
_PVR_QUERY_AVAILABILITY_DATA_COUNT,
};
/** Query copy shader data; shared registers. */
enum pvr_query_copy_data {
PVR_QUERY_COPY_DATA_INDEX_COUNT,
PVR_QUERY_COPY_DATA_DEST_BO_LO,
PVR_QUERY_COPY_DATA_DEST_BO_HI,
PVR_QUERY_COPY_DATA_AVAILABILITY_BO_LO,
PVR_QUERY_COPY_DATA_AVAILABILITY_BO_HI,
PVR_QUERY_COPY_DATA_RESULT_BO_LO,
PVR_QUERY_COPY_DATA_RESULT_BO_HI,
PVR_QUERY_COPY_DATA_DEST_STRIDE,
PVR_QUERY_COPY_DATA_FLAGS,
_PVR_QUERY_COPY_DATA_COUNT,
};
/** Query reset shader data; shared registers. */
enum pvr_query_reset_data {
PVR_QUERY_RESET_DATA_INDEX_COUNT,
PVR_QUERY_RESET_DATA_RESULT_BO_LO,
PVR_QUERY_RESET_DATA_RESULT_BO_HI,
PVR_QUERY_RESET_DATA_AVAILABILITY_BO_LO,
PVR_QUERY_RESET_DATA_AVAILABILITY_BO_HI,
_PVR_QUERY_RESET_DATA_COUNT,
};
/** Clear attachment shader data; shared registers. */
enum pvr_clear_attach_data {
PVR_CLEAR_ATTACH_DATA_DWORD0,
PVR_CLEAR_ATTACH_DATA_DWORD1,
PVR_CLEAR_ATTACH_DATA_DWORD2,
PVR_CLEAR_ATTACH_DATA_DWORD3,
PVR_CLEAR_ATTACH_DATA_TILE_ADDR_LO,
PVR_CLEAR_ATTACH_DATA_TILE_ADDR_HI,
_PVR_CLEAR_ATTACH_DATA_COUNT,
};
/** SPM load shader data; shared registers. */
enum pvr_spm_load_data {
PVR_SPM_LOAD_DATA_SMP = 0,
PVR_SPM_LOAD_DATA_REG_TEX = 4,
PVR_SPM_LOAD_DATA_BUF_TEX_0 = 8,
PVR_SPM_LOAD_DATA_BUF_ADDR_0 = 12,
PVR_SPM_LOAD_DATA_BUF_ADDR_1 = 14,
PVR_SPM_LOAD_DATA_BUF_TEX_1 = 16,
PVR_SPM_LOAD_DATA_BUF_TEX_2 = 20,
PVR_SPM_LOAD_DATA_BUF_ADDR_2 = 24,
PVR_SPM_LOAD_DATA_BUF_ADDR_3 = 26,
PVR_SPM_LOAD_DATA_BUF_TEX_3 = 28,
PVR_SPM_LOAD_DATA_BUF_TEX_4 = 32,
PVR_SPM_LOAD_DATA_BUF_ADDR_4 = 36,
PVR_SPM_LOAD_DATA_BUF_ADDR_5 = 38,
PVR_SPM_LOAD_DATA_BUF_TEX_5 = 40,
PVR_SPM_LOAD_DATA_BUF_TEX_6 = 44,
PVR_SPM_LOAD_DATA_BUF_ADDR_6 = 48,
_PVR_SPM_LOAD_DATA_COUNT = 50,
};
/** Load/store sr shader data; vertex input registers. */
enum pvr_load_store_sr_data {
PVR_LOAD_STORE_SR_DATA_SIZE_ADDR_LO,
PVR_LOAD_STORE_SR_DATA_SIZE_ADDR_HI,
PVR_LOAD_STORE_SR_DATA_STORE_ADDR_LO,
PVR_LOAD_STORE_SR_DATA_STORE_ADDR_HI,
_PVR_LOAD_STORE_SR_DATA_COUNT,
};
/** IDFWDF shader data; shared registers. */
enum pvr_idfwdf_sr_data {
PVR_IDFWDF_DATA_TEX = 0,
PVR_IDFWDF_DATA_SMP = 4,
PVR_IDFWDF_DATA_ADDR_LO,
PVR_IDFWDF_DATA_ADDR_HI,
_PVR_IDFWDF_DATA_COUNT,
};
#define PVR_IDFWDF_TEX_FORMAT VK_FORMAT_R32G32B32A32_SFLOAT
#define PVR_IDFWDF_TEX_WIDTH 4U
#define PVR_IDFWDF_TEX_HEIGHT 2U
#define PVR_IDFWDF_TEX_STRIDE 4U
/** pck_info and pck_format bitfield helpers. */
#define PVR_PCK_FORMAT_INVALID 0b11111U
#define PVR_PCK_INFO_FORMAT_LENGTH 5U
#define PVR_PCK_INFO_FORMAT_OFFSET 0U
#define PVR_PCK_INFO_SPLIT_OFFSET 5U
#define PVR_PCK_INFO_SCALE_OFFSET 6U
#define PVR_PCK_INFO_ROUNDZERO_OFFSET 7U
#define PVR_PCK_INFO_UNORM_OFFSET 8U
#define PVR_PCK_INFO_SPLIT_BIT BITFIELD_BIT(PVR_PCK_INFO_SPLIT_OFFSET)
#define PVR_PCK_INFO_SCALE_BIT BITFIELD_BIT(PVR_PCK_INFO_SCALE_OFFSET)
#define PVR_PCK_INFO_ROUNDZERO_BIT BITFIELD_BIT(PVR_PCK_INFO_ROUNDZERO_OFFSET)
#define PVR_PCK_INFO_UNORM_BIT BITFIELD_BIT(PVR_PCK_INFO_UNORM_OFFSET)
#endif /* PVR_IFACE_H */
+89
View File
@@ -0,0 +1,89 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* Constants for VkPhysicalDeviceLimits.
*/
#ifndef PVR_LIMITS_H
#define PVR_LIMITS_H
#include "hwdef/rogue_hw_defs.h"
#include "pvr_device_info.h"
#include "util/u_math.h"
#define PVR_MAX_COLOR_ATTACHMENTS PVR_NUM_PBE_EMIT_REGS
#define PVR_MAX_QUEUES 2U
#define PVR_MAX_VIEWPORTS 1U
#define PVR_MAX_NEG_OFFSCREEN_OFFSET 4096U
#define PVR_MAX_MULTIVIEW 6U
#define PVR_MAX_PUSH_CONSTANTS_SIZE 128U
#define PVR_LINE_WIDTH_MIN (1.0f / 16.0f)
#define PVR_LINE_WIDTH_MAX 16.0f
#define PVR_LINE_WIDTH_GRANULARITY (1.0f / 16.0f)
#define PVR_POINT_SIZE_RANGE_MIN 1.0f
#define PVR_POINT_SIZE_RANGE_MAX 511.0f
#define PVR_POINT_SIZE_GRANULARITY 0.0625f
#define PVR_TEX_FORMAT_COUNT \
(ROGUE_TEXSTATE_IMAGE_WORD0_TEXFORMAT_MAX_SIZE + 1U)
#define PVR_MAX_ARRAY_LAYERS (ROGUE_TEXSTATE_IMAGE_WORD1_DEPTH_MAX_SIZE + 1U)
#define PVR_MAX_DESCRIPTOR_SETS 4U
#define PVR_MAX_DESCRIPTOR_SET_UNIFORM_DYNAMIC_BUFFERS 8U
#define PVR_MAX_DESCRIPTOR_SET_STORAGE_DYNAMIC_BUFFERS 8U
#define PVR_MAX_DESCRIPTORS_PER_SET 1024U
#define PVR_MAX_FRAMEBUFFER_LAYERS PVR_MAX_ARRAY_LAYERS
/* The limit is somewhat arbitrary, it just translates into more pds code
* and larger arrays, 32 appears to be the popular (and highest choice) across
* other implementations.
*/
#define PVR_MAX_VERTEX_INPUT_BINDINGS 16U
#define PVR_TEXEL_BUFFER_OFFSET_ALIGNMENT 16U
#define PVR_UNIFORM_BUFFER_OFFSET_ALIGNMENT 4U
#define PVR_STORAGE_BUFFER_OFFSET_ALIGNMENT 4U
#define PVR_MAX_USER_PLANES 8U
/* We need one RenderTarget per supported MSAA mode as each render target
* contains state that is dependent on the sample count of the render that is
* rendering to it.
*
* As we do not know the sample count until we know the renderpass framebuffer
* combination being used, we create one per supported sample mode.
*/
#define PVR_RENDER_TARGETS_PER_FRAMEBUFFER(dev_info) \
({ \
uint32_t __ret = PVR_GET_FEATURE_VALUE(dev_info, max_multisample, 4U); \
util_logbase2(__ret) + 1; \
})
#endif
+74
View File
@@ -0,0 +1,74 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "pvr_util.h"
/* Generated by floor(n/log2(10)). This is a compact representation of a
* log10(2**n) estimation. Estimations of log2(n) +1/-0 are very fast on modern
* CPUs with clz (or equivalent) instructions, which makes this log2-indexed
* lookup both compact and fast. Assuming an input of log2(x) +1/-0; this lut
* should produce an output of ceil(log10(x)) +0/-1.
*/
const uint8_t est_log10_from_log2[64 + 1] = {
0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9,
10, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15,
15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19,
};
/* Generated by 10**n with one exception: we make the first power of ten 0
* (instead of 1) to ensure a 0-input produces a single digit (instead of no
* digits).
*/
const uint32_t u32_powers_of_ten[10] = {
UINT32_C(0), UINT32_C(10), UINT32_C(100),
UINT32_C(1000), UINT32_C(10000), UINT32_C(100000),
UINT32_C(1000000), UINT32_C(10000000), UINT32_C(100000000),
UINT32_C(1000000000),
};
/* This is an extension of u32_powers_of_ten to include all possible 64-bit
* values.
*/
const uint64_t u64_powers_of_ten[20] = {
UINT64_C(0),
UINT64_C(10),
UINT64_C(100),
UINT64_C(1000),
UINT64_C(10000),
UINT64_C(100000),
UINT64_C(1000000),
UINT64_C(10000000),
UINT64_C(100000000),
UINT64_C(1000000000),
UINT64_C(10000000000),
UINT64_C(100000000000),
UINT64_C(1000000000000),
UINT64_C(10000000000000),
UINT64_C(100000000000000),
UINT64_C(1000000000000000),
UINT64_C(10000000000000000),
UINT64_C(100000000000000000),
UINT64_C(1000000000000000000),
UINT64_C(10000000000000000000),
};
+102
View File
@@ -0,0 +1,102 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef PVR_UTIL_H
#define PVR_UTIL_H
#include <assert.h>
#include <stdint.h>
#include "pvr_types.h"
#include "util/bitscan.h"
#include "util/u_math.h"
static inline bool pvr_dev_addr_is_aligned(pvr_dev_addr_t addr,
const uint32_t alignment)
{
return util_is_aligned(addr.addr, alignment);
}
/*****************************************************************************
Math functions
*****************************************************************************/
static inline uint32_t u32_bin_digits(uint32_t x)
{
return x == 0 ? 1 : util_last_bit(x);
}
static inline uint32_t u64_bin_digits(uint64_t x)
{
return x == 0 ? 1 : util_last_bit64(x);
}
extern const uint8_t est_log10_from_log2[64 + 1];
extern const uint32_t u32_powers_of_ten[10];
extern const uint64_t u64_powers_of_ten[20];
/*
* This function includes parts of a public-domain log10 algorithm from
* "Bit Twiddling Hacks", an aggregate collection which is:
*
* © 1997-2005 Sean Eron Anderson.
*
* https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
*/
static inline uint32_t u32_dec_digits(uint32_t x)
{
/* The value of nr_digits is an estimation of ceil(log10(x)) with variance
* +0/-1 (as per the comment on the estimation lut).
*/
const uint32_t nr_digits = est_log10_from_log2[util_last_bit(x)];
/* We then convert this approximation to a real value by adding 1 iff
* x >= 10**nr_digits using another lut to quickly compute the
* exponentiation. See the comment on u32_powers_of_ten for details of this.
*/
return nr_digits + (x >= u32_powers_of_ten[nr_digits]);
}
/* This function is an extended form of u32_dec_digits(); see the comments on
* that function for details.
*/
static inline uint32_t u64_dec_digits(uint64_t x)
{
const uint32_t nr_digits = est_log10_from_log2[util_last_bit64(x)];
return nr_digits + (x >= u64_powers_of_ten[nr_digits]);
}
static inline uint32_t u32_hex_digits(uint32_t x)
{
const uint32_t binary_digits = u32_bin_digits(x);
return (binary_digits >> 2) + !!(binary_digits & 3);
}
static inline uint32_t u64_hex_digits(uint64_t x)
{
const uint32_t binary_digits = u64_bin_digits(x);
return (binary_digits >> 2) + !!(binary_digits & 3);
}
#endif /* PVR_UTIL_H */
+101
View File
@@ -0,0 +1,101 @@
/*
* Copyright © 2026 Imagination Technologies Ltd.
* SPDX-License-Identifier: MIT
*/
#include "pvr_ycbcr.h"
#include "util/macros.h"
/* number of slots occupied */
#define PVR_YCBCR_SLOTS 9
struct pvr_ycbcr_csc_table_entry {
uint16_t value[32];
} PACKED;
struct pvr_ycbcr_csc_table {
struct pvr_ycbcr_csc_table_entry slots[PVR_YCBCR_SLOTS];
} PACKED;
/* clang-format off */
static const uint16_t RGB_IDENTITY[] = {
0x0000, 0x1ffc, 0x0000,
0x0000, 0x0000, 0x1ffc,
0x1ffc, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000,
};
static const uint16_t YCBCR_IDENTITY_FULL[] = {
0x0000, 0x1ffc, 0x0000,
0x0000, 0x0000, 0x1ffc,
0x1ffc, 0x0000, 0x0000,
0xfff0, 0x0000, 0xfff0,
};
static const uint16_t YCBCR_IDENTITY[] = {
0x0000, 0x253e, 0x0000,
0x0000, 0x0000, 0x2469,
0x2469, 0x0000, 0x0000,
0xfdb9, 0xfdac, 0xfdb9,
};
static const uint16_t YCBCR_709_FULL[] = {
0x1ffc, 0x1ffc, 0x1ffc,
0x0000, 0xfa02, 0x3b5a,
0x325e, 0xf107, 0x0000,
0xe6d1, 0x0a7b, 0xe253,
};
static const uint16_t YCBCR_709[] = {
0x253e, 0x253e, 0x253e,
0x0000, 0xf92e, 0x4390,
0x3957, 0xeef5, 0x0000,
0xe101, 0x099b, 0xdbe4,
};
static const uint16_t YCBCR_601_FULL[] = {
0x1ffc, 0x1ffc, 0x1ffc,
0x0000, 0xf4fe, 0x38ad,
0x2cd8, 0xe929, 0x0000,
0xe994, 0x10ed, 0xe3a9,
};
static const uint16_t YCBCR_601[] = {
0x253e, 0x253e, 0x253e,
0x0000, 0xf378, 0x4085,
0x330c, 0xe5ff, 0x0000,
0xe426, 0x10f0, 0xdd6a,
};
static const uint16_t YCBCR_2020_FULL[] = {
0x1ffc, 0x1ffc, 0x1ffc,
0x0000, 0xfabd, 0x3c2d,
0x2f2a, 0xedba, 0x0000,
0xe86b, 0x0bc5, 0xe1ea,
};
static const uint16_t YCBCR_2020[] = {
0x253e, 0x253e, 0x253e,
0x0000, 0xfa02, 0x4481,
0x35b1, 0xeb32, 0x0000,
0xe2d4, 0x0b12, 0xdb6c,
};
/* clang-format on */
#define fill_slot(table, entry) \
memcpy(&table->slots[PVR_YCBCR_SLOT_##entry].value, entry, sizeof(entry))
void pvr_setup_static_yuv_csc_table(uint8_t *map, uint64_t offset)
{
struct pvr_ycbcr_csc_table *table =
(struct pvr_ycbcr_csc_table *)(&map[offset]);
fill_slot(table, RGB_IDENTITY);
fill_slot(table, YCBCR_IDENTITY_FULL);
fill_slot(table, YCBCR_IDENTITY);
fill_slot(table, YCBCR_709_FULL);
fill_slot(table, YCBCR_709);
fill_slot(table, YCBCR_601_FULL);
fill_slot(table, YCBCR_601);
fill_slot(table, YCBCR_2020_FULL);
fill_slot(table, YCBCR_2020);
}
+23
View File
@@ -0,0 +1,23 @@
/*
* Copyright © 2026 Imagination Technologies Ltd.
* SPDX-License-Identifier: MIT
*/
#ifndef PVR_YCBCR_H
#define PVR_YCBCR_H
#include <stdint.h>
void pvr_setup_static_yuv_csc_table(uint8_t *const heap_ptr,
uint64_t yuv_table_offset_in_bytes);
#define PVR_YCBCR_SLOT_RGB_IDENTITY 0
#define PVR_YCBCR_SLOT_YCBCR_IDENTITY_FULL 1
#define PVR_YCBCR_SLOT_YCBCR_IDENTITY 2
#define PVR_YCBCR_SLOT_YCBCR_709_FULL 3
#define PVR_YCBCR_SLOT_YCBCR_709 4
#define PVR_YCBCR_SLOT_YCBCR_601_FULL 5
#define PVR_YCBCR_SLOT_YCBCR_601 6
#define PVR_YCBCR_SLOT_YCBCR_2020_FULL 7
#define PVR_YCBCR_SLOT_YCBCR_2020 8
#endif /* PVR_YCBCR_H */
File diff suppressed because it is too large. Load diff
+8
View File
@@ -0,0 +1,8 @@
# Copyright © 2022 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
pvr_xml_pack = []
subdir('rogue')
subdir('volcanic')
dep_csbgen = declare_dependency(sources : [pvr_xml_pack])
+231
View File
@@ -0,0 +1,231 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* based in part on anv driver which is:
* Copyright © 2016 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef PVR_PACKET_HELPERS_H
#define PVR_PACKET_HELPERS_H
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#ifndef __pvr_validate_value
# define __pvr_validate_value(x)
#endif
#ifdef NDEBUG
# define NDEBUG_UNUSED __attribute__((unused))
#else
# define NDEBUG_UNUSED
#endif
#ifndef __pvr_address_type
# error #define __pvr_address_type before including this file
#endif
#ifndef __pvr_get_address
# error #define __pvr_get_address before including this file
#endif
#ifndef __pvr_make_address
# error #define __pvr_make_address before including this file
#endif
union __pvr_value {
float f;
uint32_t dw;
};
static inline __attribute__((always_inline)) uint64_t __pvr_mbo(uint32_t start,
uint32_t end)
{
return (~UINT64_C(0) >> (64 - (end - start + 1))) << start;
}
static inline __attribute__((always_inline)) uint64_t
__pvr_uint(uint64_t v, uint32_t start, NDEBUG_UNUSED uint32_t end)
{
__pvr_validate_value(v);
#ifndef NDEBUG
const int width = end - start + 1;
if (width < 64) {
const uint64_t max = (UINT64_C(1) << width) - 1;
assert(v <= max);
}
#endif
return v << start;
}
static inline __attribute__((always_inline)) uint64_t
__pvr_uint_unpack(uint64_t packed, uint32_t start, uint32_t end)
{
const int width = end - start + 1;
const uint64_t mask = ~UINT64_C(0) >> (64 - width);
return (packed >> start) & mask;
}
static inline __attribute__((always_inline)) uint64_t
__pvr_sint(int64_t v, uint32_t start, uint32_t end)
{
const int width = end - start + 1;
__pvr_validate_value(v);
#ifndef NDEBUG
if (width < 64) {
const int64_t max = (1ll << (width - 1)) - 1;
const int64_t min = -(1ll << (width - 1));
assert(min <= v && v <= max);
}
#endif
const uint64_t mask = ~UINT64_C(0) >> (64 - width);
return (v & mask) << start;
}
static inline __attribute__((always_inline)) int64_t
__pvr_sint_unpack(uint64_t packed, uint32_t start, uint32_t end)
{
const int width = end - start + 1;
const uint64_t mask = ~UINT64_C(0) >> (64 - width);
return (int64_t)((packed >> start) & mask);
}
static inline __attribute__((always_inline)) uint64_t
__pvr_offset(uint64_t v,
NDEBUG_UNUSED uint32_t start,
NDEBUG_UNUSED uint32_t end)
{
__pvr_validate_value(v);
#ifndef NDEBUG
uint64_t mask = (~UINT64_C(0) >> (64 - (end - start + 1))) << start;
assert((v & ~mask) == 0);
#endif
return v;
}
static inline __attribute__((always_inline)) uint64_t
__pvr_offset_unpack(uint64_t packed,
NDEBUG_UNUSED uint32_t start,
NDEBUG_UNUSED uint32_t end)
{
#ifndef NDEBUG
uint64_t mask = (~UINT64_C(0) >> (64 - (end - start + 1))) << start;
assert((packed & ~mask) == 0);
#endif
return packed;
}
static inline __attribute__((always_inline)) uint64_t
__pvr_address(__pvr_address_type address,
uint32_t shift,
uint32_t start,
uint32_t end)
{
uint64_t addr_u64 = __pvr_get_address(address);
uint64_t mask = (~UINT64_C(0) >> (64 - (end - start + 1))) << start;
return ((addr_u64 >> shift) << start) & mask;
}
static inline __attribute__((always_inline)) __pvr_address_type
__pvr_address_unpack(uint64_t packed,
uint32_t shift,
uint32_t start,
uint32_t end)
{
uint64_t mask = (~UINT64_C(0) >> (64 - (end - start + 1))) << start;
uint64_t addr_u64 = ((packed & mask) >> start) << shift;
return __pvr_make_address(addr_u64);
}
static inline __attribute__((always_inline)) uint32_t __pvr_float(float v)
{
__pvr_validate_value(v);
return ((union __pvr_value){ .f = (v) }).dw;
}
static inline __attribute__((always_inline)) float
__pvr_float_unpack(uint32_t packed)
{
return ((union __pvr_value){ .dw = (packed) }).f;
}
static inline __attribute__((always_inline)) uint64_t
__pvr_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits)
{
__pvr_validate_value(v);
const float factor = (1 << fract_bits);
#ifndef NDEBUG
const float max = ((1 << (end - start)) - 1) / factor;
const float min = -(1 << (end - start)) / factor;
assert(min <= v && v <= max);
#endif
const int64_t int_val = llroundf(v * factor);
const uint64_t mask = ~UINT64_C(0) >> (64 - (end - start + 1));
return (int_val & mask) << start;
}
static inline __attribute__((always_inline)) uint64_t
__pvr_ufixed(float v,
uint32_t start,
NDEBUG_UNUSED uint32_t end,
uint32_t fract_bits)
{
__pvr_validate_value(v);
const float factor = (1 << fract_bits);
#ifndef NDEBUG
const float max = ((1 << (end - start + 1)) - 1) / factor;
const float min = 0.0f;
assert(min <= v && v <= max);
#endif
const uint64_t uint_val = llroundf(v * factor);
return uint_val << start;
}
#undef NDEBUG_UNUSED
#endif /* PVR_PACKET_HELPERS_H */
+134
View File
@@ -0,0 +1,134 @@
<?xml version="1.0" ?>
<!--
Copyright © 2022 Imagination Technologies Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<csbgen name="ROGUE" prefix="CDMCTRL">
<define name="GUARD_SIZE_DEFAULT" value="64"/>
<enum name="BLOCK_TYPE">
<value name="COMPUTE_KERNEL" value="0"/>
<value name="STREAM_LINK" value="1"/>
<value name="STREAM_TERMINATE" value="2"/>
</enum>
<enum name="USC_TARGET">
<value name="ALL" value="0"/>
<value name="ANY" value="1"/>
</enum>
<enum name="SD_TYPE">
<value name="NONE" value="0"/>
<value name="PDS" value="1"/>
<value name="USC" value="2"/>
</enum>
<struct name="KERNEL0" length="1">
<field name="block_type" start="30" end="31" type="BLOCK_TYPE" default="COMPUTE_KERNEL"/>
<field name="indirect_present" start="29" end="29" type="bool"/>
<field name="global_offsets_present" start="28" end="28" type="bool"/>
<field name="event_object_present" start="27" end="27" type="bool"/>
<field name="usc_common_size" start="18" end="26" type="uint">
<define name="UNIT_SIZE" value="64"/>
<define name="MAX_SIZE" value="256"/>
</field>
<field name="usc_unified_size" start="12" end="17" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="pds_temp_size" start="8" end="11" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="pds_data_size" start="2" end="7" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="usc_target" start="1" end="1" type="USC_TARGET"/>
<field name="fence" start="0" end="0" type="bool"/>
</struct>
<struct name="KERNEL1" length="1">
<field name="data_addr" start="4" end="31" shift="4" type="address"/>
<field name="sd_type" start="2" end="3" type="SD_TYPE"/>
<field name="usc_common_shared" start="1" end="1" type="bool"/>
</struct>
<struct name="KERNEL2" length="1">
<field name="code_addr" start="4" end="31" shift="4" type="address"/>
<field name="one_wg_per_task" start="0" end="0" type="bool"/>
</struct>
<struct name="KERNEL3" length="1">
<field name="workgroup_x" start="0" end="31" type="uint"/>
</struct>
<struct name="KERNEL4" length="1">
<field name="workgroup_y" start="0" end="31" type="uint"/>
</struct>
<struct name="KERNEL5" length="1">
<field name="workgroup_z" start="0" end="31" type="uint"/>
</struct>
<struct name="KERNEL6" length="1">
<field name="indirect_addrmsb" start="0" end="7" shift="32" type="address"/>
</struct>
<struct name="KERNEL7" length="1">
<field name="indirect_addrlsb" start="2" end="31" shift="2" type="address"/>
</struct>
<struct name="KERNEL8" length="1">
<field name="max_instances" start="27" end="31" type="uint">
<define name="MAX_SIZE" value="31"/>
</field>
<field name="workgroup_size_x" start="18" end="26" type="uint"/>
<field name="workgroup_size_y" start="9" end="17" type="uint"/>
<field name="workgroup_size_z" start="0" end="8" type="uint"/>
</struct>
<struct name="KERNEL9" length="1">
<field name="global_offset_x" start="0" end="31" type="uint"/>
</struct>
<struct name="KERNEL10" length="1">
<field name="global_offset_y" start="0" end="31" type="uint"/>
</struct>
<struct name="KERNEL11" length="1">
<field name="global_offset_z" start="0" end="31" type="uint"/>
</struct>
<struct name="STREAM_LINK0" length="1">
<field name="block_type" start="30" end="31" type="BLOCK_TYPE" default="STREAM_LINK"/>
<field name="link_addrmsb" start="0" end="7" shift="32" type="address"/>
</struct>
<struct name="STREAM_LINK1" length="1">
<field name="link_addrlsb" start="2" end="31" shift="2" type="address"/>
</struct>
<struct name="STREAM_TERMINATE" length="1">
<field name="block_type" start="30" end="31" type="BLOCK_TYPE" default="STREAM_TERMINATE"/>
</struct>
</csbgen>
+701
View File
@@ -0,0 +1,701 @@
<?xml version="1.0" ?>
<!--
Copyright © 2022 Imagination Technologies Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<csbgen name="ROGUE" prefix="CR">
<define name="PM_VHEAP_TABLE_SIZE" value="0x180" />
<enum name="COMP_IADDR_TYPE">
<value name="INDIRECT_1TILE" value="0"/>
<value name="INDIRECT_4TILE" value="1"/>
</enum>
<enum name="COMPRESS_SIZE">
<value name="BLOCK_8X8" value="0"/>
<value name="BLOCK_16X4" value="1"/>
</enum>
<enum name="DIR_TYPE">
<value name="TL2BR" value="0"/>
<value name="TR2BL" value="1"/>
<value name="BL2TR" value="2"/>
<value name="BR2TL" value="3"/>
</enum>
<enum name="ISP_AA_MODE_TYPE">
<value name="AA_NONE" value="0"/>
<value name="AA_2X" value="1"/>
<value name="AA_4X" value="2"/>
<value name="AA_8X" value="3"/>
</enum>
<enum name="ISP_RENDER_MODE_TYPE">
<value name="NORM" value="0"/>
<value name="FAST_2D" value="2"/>
<value name="FAST_SCALE" value="3"/>
</enum>
<enum name="MEMLAYOUT">
<value name="LINEAR" value="0"/>
<value name="TWIDDLE_2D" value="1"/>
<value name="TWIDDLE_3D" value="2"/>
<value name="TILED" value="3"/>
</enum>
<enum name="MODE_TYPE">
<value name="DX9" value="0"/>
<value name="DX10" value="1"/>
<value name="OGL" value="2"/>
</enum>
<enum name="PIPE_NUM">
<value name="PIPE_ONE" value="0"/>
<value name="PIPE_TWO" value="1"/>
<value name="PIPE_THREE" value="2"/>
<value name="PIPE_FOUR" value="3"/>
<value name="PIPE_FIVE" value="4"/>
<value name="PIPE_SIX" value="5"/>
<value name="PIPE_SEVEN" value="6"/>
<value name="PIPE_EIGHT" value="7"/>
<value name="PIPE_NINE" value="8"/>
<value name="PIPE_TEN" value="9"/>
<value name="PIPE_ELEVEN" value="10"/>
<value name="PIPE_TWELVE" value="11"/>
<value name="PIPE_THIRTEEN" value="12"/>
<value name="PIPE_FOURTEEN" value="13"/>
<value name="PIPE_FIFTEEN" value="14"/>
<value name="PIPE_SIXTEEN" value="15"/>
</enum>
<enum name="PIXEL_WIDTH">
<value name="2REGISTERS" value="0"/>
<value name="4REGISTERS" value="1"/>
<value name="8REGISTERS" value="2"/>
<value name="1REGISTER" value="3"/>
</enum>
<enum name="ROTATION_TYPE">
<value name="0_DEG" value="0"/>
<value name="90_DEG" value="1"/>
<value name="180_DEG" value="2"/>
<value name="270_DEG" value="3"/>
</enum>
<enum name="SIZE">
<value name="1_PIXEL" value="0"/>
<value name="2_PIXEL" value="1"/>
<value name="4_PIXEL" value="2"/>
<value name="8_PIXEL" value="3"/>
<value name="16_PIXEL" value="4"/>
<value name="32_PIXEL" value="5"/>
<value name="64_PIXEL" value="6"/>
<value name="128_PIXEL" value="7"/>
<value name="256_PIXEL" value="8"/>
<value name="512_PIXEL" value="9"/>
<value name="1K_PIXEL" value="10"/>
<value name="2K_PIXEL" value="11"/>
<value name="4K_PIXEL" value="12"/>
<value name="8K_PIXEL" value="13"/>
<value name="16K_PIXEL" value="14"/>
</enum>
<enum name="SWIZ">
<value name="SOURCE_CHAN0" value="0"/>
<value name="SOURCE_CHAN1" value="1"/>
<value name="SOURCE_CHAN2" value="2"/>
<value name="SOURCE_CHAN3" value="3"/>
<value name="ONE" value="4"/>
<value name="ZERO" value="5"/>
</enum>
<enum name="TFBC_LOSSY">
<value name="LOSSLESS" value="0"/>
<value name="LOSSY_75" value="1"/>
<value name="LOSSY_50" value="2"/>
<value name="LOSSY_25" value="3"/>
</enum>
<enum name="TWOCOMP_GAMMA">
<value name="GAMMA_BOTTOM_CHANNEL" value="0"/>
<value name="GAMMA_BOTH_CHANNELS" value="1"/>
</enum>
<enum name="ZLS_FORMAT_TYPE">
<!-- Separate depth and stencil -->
<value name="F32Z" value="0"/>
<!-- Packed depth and stencil -->
<value name="24BITINT" value="1"/>
<!-- Separate depth and stencil -->
<value name="16BITINT" value="2"/>
<!-- Packed depth and stencil -->
<value name="F64Z" value="3"/>
</enum>
<struct name="PM_MTILE_ARRAY" length="2">
<field name="base_addr" start="4" end="39" shift="4" type="address"/>
</struct>
<struct name="PM_VHEAP_TABLE" length="2">
<field name="base_addr" start="4" end="39" shift="4" type="address"/>
</struct>
<struct name="PM_MLIST0_BASE" length="2">
<field name="addr" start="4" end="39" shift="4" type="address"/>
</struct>
<struct name="VDM_CTRL_STREAM_BASE" length="2">
<field name="addr" start="2" end="39" shift="2" type="address"/>
</struct>
<struct name="VDM_CALL_STACK_POINTER" length="2">
<field name="addr" start="3" end="39" shift="3" type="address"/>
</struct>
<struct name="VDM_CONTEXT_STATE_BASE" length="2">
<field name="addr" start="4" end="39" shift="4" type="address"/>
</struct>
<struct name="VDM_CONTEXT_STORE_TASK0" length="2">
<field name="pds_state1" start="32" end="63" type="uint"/>
<field name="pds_state0" start="0" end="31" type="uint"/>
</struct>
<struct name="VDM_CONTEXT_STORE_TASK1" length="1">
<field name="pds_state2" start="0" end="31" type="uint"/>
</struct>
<struct name="VDM_CONTEXT_STORE_TASK2" length="2">
<field name="stream_out2" start="32" end="63" type="uint"/>
<field name="stream_out1" start="0" end="31" type="uint"/>
</struct>
<struct name="VDM_CONTEXT_RESUME_TASK0" length="2">
<field name="pds_state1" start="32" end="63" type="uint"/>
<field name="pds_state0" start="0" end="31" type="uint"/>
</struct>
<struct name="VDM_CONTEXT_RESUME_TASK1" length="1">
<field name="pds_state2" start="0" end="31" type="uint"/>
</struct>
<struct name="VDM_CONTEXT_RESUME_TASK2" length="2">
<field name="stream_out2" start="32" end="63" type="uint"/>
<field name="stream_out1" start="0" end="31" type="uint"/>
</struct>
<struct name="CDM_CONTEXT_STATE_BASE" length="2">
<field name="addr" start="4" end="39" shift="4" type="address"/>
</struct>
<struct name="CDM_CONTEXT_PDS0" length="2">
<field name="data_addr" start="36" end="63" shift="4" type="address"/>
<field name="code_addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="CDM_CTRL_STREAM_BASE" length="2">
<field name="addr" start="2" end="39" shift="2" type="address"/>
</struct>
<struct name="CDM_CONTEXT_PDS1" length="1">
<field name="pds_seq_dep" start="29" end="29" type="bool"/>
<field name="usc_seq_dep" start="28" end="28" type="bool"/>
<!-- false=All, true=Any -->
<field name="target" start="27" end="27" type="bool"/>
<field name="unified_size" start="21" end="26" type="uint"/>
<field name="common_shared" start="20" end="20" type="bool"/>
<field name="common_size" start="11" end="19" type="uint">
<define name="UNIT_SIZE" value="64"/>
</field>
<field name="temp_size" start="7" end="10" type="uint"/>
<field name="data_size" start="1" end="6" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="fence" start="0" end="0" type="bool"/>
</struct>
<struct name="CDM_TERMINATE_PDS" length="2">
<field name="data_addr" start="36" end="63" shift="4" type="address"/>
<field name="code_addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="CDM_TERMINATE_PDS1" length="1">
<field name="pds_seq_dep" start="29" end="29" type="bool"/>
<field name="usc_seq_dep" start="28" end="28" type="bool"/>
<field name="target" start="27" end="27" type="bool"/>
<field name="unified_size" start="21" end="26" type="uint"/>
<field name="common_shared" start="20" end="20" type="bool"/>
<field name="common_size" start="11" end="19" type="uint"/>
<field name="temp_size" start="7" end="10" type="uint"/>
<field name="data_size" start="1" end="6" type="uint"/>
<field name="fence" start="0" end="0" type="bool"/>
</struct>
<struct name="CDM_CONTEXT_LOAD_PDS0" length="2">
<field name="data_addr" start="36" end="63" shift="4" type="address"/>
<field name="code_addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="COMPUTE_CLUSTER" length="1">
<field name="mask" start="0" end="31" type="uint"/>
</struct>
<struct name="CDM_ITEM" length="1">
<field name="mode" start="0" end="1" type="uint"/>
</struct>
<struct name="PDS_CTRL0" length="1">
<condition type="if" check="ROGUEXE"/>
<condition type="if" check="COMPUTE"/>
<field name="roguexe_max_num_cdm_tasks" start="24" end="31" type="uint"/>
<condition type="endif" check="COMPUTE"/>
<condition type="if" check="NUM_RASTER_PIPES &gt; 0"/>
<field name="roguexe_max_num_pdm_tasks" start="16" end="23" type="uint"/>
<condition type="endif" check="NUM_RASTER_PIPES &gt; 0"/>
<condition type="if" check="NUM_TA &gt; 0"/>
<field name="roguexe_max_num_vdm_tasks" start="8" end="15" type="uint"/>
<condition type="endif" check="NUM_TA &gt; 0"/>
<condition type="else" check="ROGUEXE"/>
<condition type="if" check="COMPUTE"/>
<field name="max_num_cdm_tasks" start="24" end="30" type="uint"/>
<condition type="endif" check="COMPUTE"/>
<field name="max_num_pdm_tasks" start="16" end="22" type="uint"/>
<field name="max_num_vdm_tasks" start="8" end="14" type="uint"/>
<condition type="endif" check="ROGUEXE"/>
</struct>
<struct name="PDS_CTRL1" length="1">
<field name="sm_overlap_enable" start="23" end="23" type="bool"/>
</struct>
<struct name="EVENT_PIXEL_PDS_CODE" length="1">
<field name="addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="EVENT_PIXEL_PDS_DATA" length="1">
<!-- This is an offset actually. Note for when we auto-generate the xmls. -->
<field name="addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="EVENT_PIXEL_PDS_INFO" length="1">
<field name="usc_sr_size" start="9" end="14" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="temp_stride" start="5" end="8" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
<field name="const_size" start="0" end="4" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
</struct>
<struct name="PDS_BGRND0_BASE" length="2">
<!-- This is an offset actually. Note for when we auto-generate the xmls. -->
<field name="texunicode_addr" start="36" end="63" shift="4" type="address"/>
<!-- This is an offset actually. Note for when we auto-generate the xmls. -->
<field name="shader_addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="PDS_BGRND1_BASE" length="2">
<!-- This is an offset actually. Note for when we auto-generate the xmls. -->
<field name="texturedata_addr" start="36" end="63" shift="4" type="address"/>
<!-- Unused in the Vulkan driver. -->
<field name="varying_addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="PDS_BGRND2_BASE" length="2">
<!-- This is an offset actually. Note for when we auto-generate the xmls. -->
<field name="uniformdata_addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="PDS_BGRND3_SIZEINFO" length="2">
<field name="usc_sharedsize" start="55" end="63" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="pds_batchnum" start="32" end="45" type="uint"/>
<field name="pds_uniformsize" start="23" end="31" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
<field name="pds_texturestatesize" start="16" end="22" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
<field name="pds_varyingsize" start="10" end="15" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
<field name="usc_varyingsize" start="4" end="9" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="pds_tempsize" start="0" end="3" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
</struct>
<struct name="TE_AA" length="1">
<condition type="if" check="SIMPLE_INTERNAL_PARAMETER_FORMAT &amp;&amp; ISP_SAMPLES_PER_PIXEL &gt; 2"/>
<field name="y2" start="3" end="3" type="bool"/>
<condition type="endif" check="SIMPLE_INTERNAL_PARAMETER_FORMAT &amp;&amp; ISP_SAMPLES_PER_PIXEL &gt; 2"/>
<field name="y" start="2" end="2" type="bool"/>
<field name="x" start="1" end="1" type="bool"/>
<field name="x2" start="0" end="0" type="bool"/>
</struct>
<struct name="TE_MTILE1" length="1">
<field name="x1" start="18" end="26" type="uint"/>
<field name="x2" start="9" end="17" type="uint"/>
<field name="x3" start="0" end="8" type="uint"/>
</struct>
<struct name="TE_MTILE2" length="1">
<field name="y1" start="18" end="26" type="uint"/>
<field name="y2" start="9" end="17" type="uint"/>
<field name="y3" start="0" end="8" type="uint"/>
</struct>
<struct name="TE_SCREEN" length="1">
<field name="ymax" start="12" end="20" type="uint"/>
<field name="xmax" start="0" end="8" type="uint"/>
</struct>
<struct name="TE_PSG" length="1">
<condition type="if" check="ROGUEXE"/>
<condition type="if" check="TILE_REGION_PROTECTION"/>
<field name="force_protect" start="22" end="22" type="uint"/>
<condition type="endif" check="TILE_REGION_PROTECTION"/>
<field name="cs_size" start="21" end="21" type="uint"/>
<field name="enable_pwr_gate_state" start="20" end="20" type="bool"/>
<condition type="endif" check="ROGUEXE"/>
<field name="enable_context_state_restore" start="19" end="19" type="bool"/>
<field name="zonlyrender" start="18" end="18" type="bool"/>
<field name="completeonterminate" start="17" end="17" type="bool"/>
<field name="cache_bypass" start="14" end="14" type="bool"/>
<field name="forcenewstate" start="13" end="13" type="bool"/>
<field name="region_stride" start="0" end="10" type="uint">
<define name="UNIT_SIZE" value="4096"/>
</field>
</struct>
<!-- FIXME: This is only a partial definition as (at the time of writing)
csbgen doesn't support multiple address fields within structure.
-->
<!-- FIXME: When csbgen supports conditional structs, make this
conditional on NUM_TA > 0.
-->
<struct name="TE_PSGREGION_ADDR" length="2">
<field name="base" start="6" end="33" shift="6" type="address"/>
</struct>
<!-- FIXME: This is only a partial definition as (at the time of writing)
csbgen doesn't support multiple address fields within structure.
-->
<struct name="TE_TPC_ADDR" length="2">
<field name="base" start="6" end="33" shift="6" type="address"/>
</struct>
<struct name="PPP_MULTISAMPLECTL" length="2">
<condition type="if" check="MAX_MULTISAMPLE == 8"/>
<field name="msaa_y7" start="60" end="63" type="uint"/>
<field name="msaa_x7" start="56" end="59" type="uint"/>
<field name="msaa_y6" start="52" end="55" type="uint"/>
<field name="msaa_x6" start="48" end="51" type="uint"/>
<field name="msaa_y5" start="44" end="47" type="uint"/>
<field name="msaa_x5" start="40" end="43" type="uint"/>
<field name="msaa_y4" start="36" end="39" type="uint"/>
<field name="msaa_x4" start="32" end="35" type="uint"/>
<condition type="endif" check="MAX_MULTISAMPLE == 8"/>
<field name="msaa_y3" start="28" end="31" type="uint"/>
<field name="msaa_x3" start="24" end="27" type="uint"/>
<field name="msaa_y2" start="20" end="23" type="uint"/>
<field name="msaa_x2" start="16" end="19" type="uint"/>
<field name="msaa_y1" start="12" end="15" type="uint"/>
<field name="msaa_x1" start="8" end="11" type="uint"/>
<field name="msaa_y0" start="4" end="7" type="uint"/>
<field name="msaa_x0" start="0" end="3" type="uint"/>
</struct>
<struct name="PPP_CTRL" length="1">
<field name="vpt_scissor" start="12" end="12" type="bool"/>
<field name="flush_mode" start="11" end="11" type="uint"/>
<field name="bfcull_restrict_clip" start="10" end="10" type="bool"/>
<field name="fixed_point_format" start="9" end="9" type="uint"/>
<field name="default_point_size" start="8" end="8" type="bool"/>
<field name="bfcull1_disable" start="7" end="7" type="bool"/>
<field name="bfcull2_disable" start="6" end="6" type="bool"/>
<field name="fccull_disable" start="5" end="5" type="bool"/>
<field name="oscull_disable" start="4" end="4" type="bool"/>
<field name="socull_disable" start="2" end="2" type="bool"/>
<field name="wclampen" start="1" end="1" type="bool"/>
<field name="opengl" start="0" end="0" type="bool"/>
</struct>
<struct name="PPP_SCREEN" length="1">
<field name="pixymax" start="16" end="30" type="uint"/>
<field name="pixxmax" start="0" end="14" type="uint"/>
</struct>
<!-- FIXME: This is only a partial definition as (at the time of writing)
csbgen doesn't support multiple address fields within structure.
-->
<struct name="TA_RTC_ADDR" length="2">
<field name="base" start="6" end="33" shift="6" type="address"/>
</struct>
<struct name="TA_CONTEXT_STATE_BASE" length="2">
<field name="addr" start="4" end="39" shift="4" type="address"/>
</struct>
<struct name="ISP_RENDER" length="1">
<field name="disable_eomt" start="5" end="5" type="bool"/>
<field name="resume" start="4" end="4" type="bool"/>
<field name="dir_type" start="2" end="3" type="DIR_TYPE"/>
<field name="mode_type" start="0" end="1" type="ISP_RENDER_MODE_TYPE"/>
</struct>
<struct name="ISP_RENDER_ORIGIN" length="1">
<field name="x" start="16" end="25" type="uint"/>
<field name="y" start="0" end="9" type="uint"/>
</struct>
<struct name="ISP_MTILE_BASE" length="2">
<field name="addr" start="2" end="39" shift="2" type="address"/>
</struct>
<struct name="ISP_MTILE_SIZE" length="1">
<field name="x" start="16" end="25" type="uint"/>
<field name="y" start="0" end="9" type="uint"/>
</struct>
<struct name="ISP_RGN" length="1">
<field name="size" start="0" end="23" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
</struct>
<!-- FIXME: This is the SIMPLE_INTERNAL_PARAMETER_FORMAT variant.
Should we use the "condition" tag for this?
-->
<struct name="ISP_RGN_SIPF" length="1">
<condition type="if" check="IPF_CREQ_PF"/>
<!-- FIXME: This should have a default value of 0x1F not setting it since
csbgen doesn't check if the feature is present or not so this will
be set even when the feature is not present.
-->
<field name="cs_size_ipf_creq_pf" start="24" end="28" type="uint">
<define name="MAX" value="31"/>
</field>
<condition type="endif" check="IPF_CREQ_PF"/>
<field name="size" start="0" end="23" type="uint">
<!-- Note that this differs from ISP_RGN. -->
<define name="UNIT_SIZE" value="1"/>
</field>
</struct>
<struct name="ISP_BGOBJDEPTH" length="1">
<field name="value" start="0" end="31" type="uint"/>
</struct>
<struct name="ISP_BGOBJVALS" length="1">
<field name="enablebgtag" start="9" end="9" type="bool"/>
<field name="mask" start="8" end="8" type="bool"/>
<field name="stencil" start="0" end="7" type="uint"/>
</struct>
<struct name="ISP_AA" length="1">
<field name="mode" start="0" end="1" type="ISP_AA_MODE_TYPE" default="AA_NONE"/>
</struct>
<struct name="ISP_CTL" length="1">
<field name="skip_init_hdrs" start="31" end="31" type="bool"/>
<field name="line_style" start="30" end="30" type="bool"/>
<field name="line_style_pix" start="29" end="29" type="bool"/>
<field name="pair_tiles_vert" start="28" end="28" type="bool"/>
<field name="pair_tiles" start="27" end="27" type="bool"/>
<field name="creq_buf_en" start="26" end="26" type="bool"/>
<field name="tile_age_en" start="25" end="25" type="bool"/>
<field name="isp_sample_pos_mode" start="23" end="24" type="MODE_TYPE"/>
<field name="num_tiles_per_usc" start="21" end="22" type="uint"/>
<field name="dbias_is_int" start="20" end="20" type="bool"/>
<field name="overlap_check_mode" start="19" end="19" type="bool"/>
<field name="pt_upfront_depth_disable" start="18" end="18" type="bool"/>
<field name="process_empty_tiles" start="17" end="17" type="bool"/>
<field name="sample_pos" start="16" end="16" type="bool"/>
<field name="pipe_enable" start="12" end="15" type="PIPE_NUM"/>
<field name="valid_id" start="4" end="9" type="uint"/>
<field name="upass_start" start="0" end="3" type="uint">
<define name="SIZE_MAX" value="15"/>
</field>
</struct>
<struct name="ISP_ZLSCTL" length="2">
<field name="zlsextent_y_s" start="48" end="57" type="uint"/>
<field name="zlsextent_x_s" start="38" end="47" type="uint"/>
<field name="stencil_extent_enable" start="37" end="37" type="bool"/>
<field name="zlsextent_y_z" start="27" end="36" type="uint"/>
<field name="zstoreformat" start="25" end="26" type="ZLS_FORMAT_TYPE"/>
<field name="zloadformat" start="23" end="24" type="ZLS_FORMAT_TYPE"/>
<field name="fb_storeen" start="22" end="22" type="bool"/>
<field name="fb_loaden" start="21" end="21" type="bool"/>
<field name="mstoreen" start="20" end="20" type="bool"/>
<field name="zstoreen" start="19" end="19" type="bool"/>
<field name="sstoreen" start="18" end="18" type="bool"/>
<field name="storetwiddled" start="17" end="17" type="bool"/>
<field name="mloaden" start="16" end="16" type="bool"/>
<field name="zloaden" start="15" end="15" type="bool"/>
<field name="sloaden" start="14" end="14" type="bool"/>
<field name="loadtwiddled" start="13" end="13" type="bool"/>
<field name="zlsextent_x_z" start="3" end="12" type="uint"/>
<field name="forcezstore" start="2" end="2" type="bool"/>
<field name="forcezload" start="1" end="1" type="bool"/>
<field name="zonlyrender" start="0" end="0" type="bool"/>
</struct>
<struct name="ISP_ZLOAD_BASE" length="2">
<field name="addr" start="4" end="39" shift="4" type="address"/>
</struct>
<struct name="ISP_STENCIL_LOAD_BASE" length="2">
<field name="addr" start="4" end="39" shift="4" type="address"/>
<field name="enable" start="0" end="0" type="bool"/>
</struct>
<struct name="ISP_SCISSOR_BASE" length="2">
<field name="addr" start="2" end="39" shift="2" type="address"/>
</struct>
<struct name="ISP_DBIAS_BASE" length="2">
<field name="addr" start="2" end="39" shift="2" type="address"/>
</struct>
<struct name="ISP_OCLQRY_BASE" length="2">
<field name="addr" start="4" end="39" shift="4" type="address"/>
</struct>
<struct name="ISP_ZLS_PIXELS" length="1">
<field name="y" start="15" end="29" type="uint"/>
<field name="x" start="0" end="14" type="uint"/>
</struct>
<struct name="PBE_WORD0_MRT0" length="2">
<condition type="if" check="TFBC"/>
<field name="tfbc_lossy" start="62" end="63" type="TFBC_LOSSY"/>
<condition type="endif" check="TFBC"/>
<field name="x_rsrvd" start="63" end="63" type="bool"/>
<field name="pair_tiles" start="60" end="60" type="uint"/>
<field name="comp_iaddr_mode" start="60" end="60" type="COMP_IADDR_TYPE"/>
<field name="x_rsrvd2" start="59" end="59" type="bool"/>
<field name="comp_cor_enable" start="59" end="59" type="bool"/>
<field name="dither" start="58" end="58" type="bool"/>
<field name="tilerelative" start="57" end="57" type="bool"/>
<field name="downscale" start="56" end="56" type="bool"/>
<field name="size_z" start="52" end="55" type="SIZE"/>
<field name="rotation" start="50" end="51" type="ROTATION_TYPE"/>
<field name="linestride" start="34" end="49" type="uint">
<define name="ALIGNMENT" value="2"/>
</field>
<field name="memlayout" start="32" end="33" type="MEMLAYOUT"/>
<field name="swiz_chan3" start="29" end="31" type="SWIZ"/>
<field name="swiz_chan2" start="26" end="28" type="SWIZ"/>
<field name="swiz_chan1" start="23" end="25" type="SWIZ"/>
<field name="swiz_chan0" start="20" end="22" type="SWIZ"/>
<field name="minclip_x" start="6" end="19" type="uint"/>
<field name="twocomp_gamma" start="5" end="5" type="TWOCOMP_GAMMA"/>
<field name="gamma" start="4" end="4" type="bool"/>
<field name="compression" start="3" end="3" type="bool"/>
<field name="compress_size" start="2" end="2" type="COMPRESS_SIZE"/>
<field name="comp_indirect_table" start="1" end="1" type="bool"/>
<condition type="if" check="PBE_YFLIP"/>
<field name="y_flip" start="0" end="0" type="bool"/>
<condition type="endif" check="PBE_YFLIP"/>
</struct>
<struct name="FRAG_SCREEN" length="1">
<field name="ymax" start="16" end="30" type="uint"/>
<field name="xmax" start="0" end="14" type="uint"/>
</struct>
<struct name="TPU" length="1">
<condition type="if" check="PDSL0SIZE &gt; 0"/>
<field name="mcu_pds_l0_off" start="8" end="8" type="bool"/>
<condition type="endif" check="PDSL0SIZE &gt; 0"/>
<condition type="if" check="TPU_CEM_DATAMASTER_GLOBAL_REGISTERS"/>
<field name="tag_cem_64_face_packing" start="7" end="7" type="bool"/>
<condition type="endif" check="TPU_CEM_DATAMASTER_GLOBAL_REGISTERS"/>
<field name="tag_enable_mmu_prefetch" start="6" end="6" type="bool"/>
<field name="tag_cem_4k_face_packing" start="5" end="5" type="bool"/>
<field name="madd_config_l0off" start="4" end="4" type="bool"/>
<field name="tag_cem_face_packing" start="3" end="3" type="bool"/>
<field name="tag_cemedge_dontfilter" start="2" end="2" type="bool"/>
<condition type="if" check="TPU_CEM_USG_NORMALISATION"/>
<field name="tag_cemgrad_dontnegate" start="1" end="1" type="bool"/>
<condition type="endif" check="TPU_CEM_USG_NORMALISATION"/>
<field name="madd_config_dxt35_transovr" start="0" end="0" type="bool"/>
</struct>
<struct name="TPU_BORDER_COLOUR_TABLE_PDM" length="2">
<field name="border_colour_table_address" start="0" end="37" shift="2" type="address"/>
</struct>
<struct name="TPU_BORDER_COLOUR_TABLE_VDM" length="2">
<field name="border_colour_table_address" start="0" end="37" shift="2" type="address"/>
</struct>
<struct name="TPU_BORDER_COLOUR_TABLE_CDM" length="2">
<field name="border_colour_table_address" start="0" end="37" shift="2" type="address"/>
</struct>
<!-- FIXME: This register depends on TPU_DM_GLOBAL_REGISTERS. -->
<struct name="TPU_TAG_CDM_CTRL" length="1">
<field name="af_ratio_truncate_to_integer" start="3" end="3" type="bool"/>
<field name="af_ratio_truncate_to_half" start="2" end="2" type="bool"/>
<field name="af_filtering_mode" start="1" end="1" type="bool"/>
<field name="yuv_cam_invalidate" start="0" end="0" type="bool"/>
</struct>
<struct name="USC_PIXEL_OUTPUT_CTRL" length="1">
<field name="partition_mask" start="3" end="20" type="uint"/>
<field name="enable_4th_partition" start="2" end="2" type="bool"/>
<field name="width" start="0" end="1" type="PIXEL_WIDTH"/>
</struct>
<struct name="USC_CLEAR_REGISTER" length="1">
<field name="val" start="0" end="31" type="uint"/>
</struct>
<!-- FIXME: When csbgen supports conditional structs, make this conditional
on FB_CDC.
-->
<struct name="FB_CDC_ZLS" length="2">
<condition type="if" check="!ROGUEXE"/>
<field name="fbc_iaddr_mode" start="42" end="42" type="bool"/>
<field name="fbdc_iaddr_mode" start="41" end="41" type="bool"/>
<condition type="endif" check="!ROGUEXE"/>
<!-- FIXME: should be dependent on !ROGUEXE || (ROGUEXE && FB_CDC_V4) -->
<field name="fbdc_stencil_fmt" start="34" end="40" type="uint"/>
<!-- FIXME: should be dependent on !ROGUEXE || (ROGUEXE && FB_CDC_V4) -->
<field name="fbdc_depth_fmt" start="27" end="33" type="uint"/>
<field name="fbc_num_tiles" start="4" end="26" type="uint"/>
<field name="fbc_iaddr" start="1" end="1" type="bool"/>
<field name="fbdc_iaddr" start="0" end="0" type="bool"/>
</struct>
</csbgen>
+510
View File
@@ -0,0 +1,510 @@
<?xml version="1.0" ?>
<!--
Copyright © 2022 Imagination Technologies Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<csbgen name="ROGUE" prefix="IPF">
<define name="TILE_SIZE_PIXELS" value="32"/>
<define name="CONTROL_STREAM_SIZE_DWORDS" value="32"/>
<define name="ISP_VERTEX_XY_BIAS_VALUE" value="4096"/>
<!-- FIXME: This is the SIMPLE_INTERNAL_PARAMETER_FORMAT variant.
Should we use the "condition" tag for this?
-->
<define name="ISP_VERTEX_XY_BIAS_VALUE_SIPF" value="2048"/>
<enum name="COMPRESSION_FORMAT">
<value name="UNIQUE_1" value="0"/>
<value name="ORIGIN_1_DELTA_1" value="1"/>
<value name="ORIGIN_1_DELTA_2" value="2"/>
<value name="ORIGIN_1_DELTA_3" value="3"/>
<value name="ORIGIN_1_DELTA_4" value="4"/>
<value name="ORIGIN_1_DELTA_5" value="5"/>
<value name="ORIGIN_1_DELTA_6" value="6"/>
<value name="ORIGIN_1_DELTA_7" value="7"/>
<value name="RAW_BYTE" value="8"/>
<value name="UNIQUE_2" value="9"/>
<value name="ORIGIN_2_DELTA_1" value="10"/>
<value name="ORIGIN_2_DELTA_2" value="11"/>
<value name="ORIGIN_2_DELTA_3" value="12"/>
<value name="ORIGIN_2_DELTA_4" value="13"/>
<value name="ORIGIN_2_DELTA_5" value="14"/>
<value name="ORIGIN_2_DELTA_6" value="15"/>
</enum>
<enum name="CS_MASK_FMT">
<value name="INDEX" value="0"/>
<value name="BYTE" value="1"/>
<value name="BIT" value="2"/>
<value name="FULL" value="3"/>
</enum>
<enum name="CS_TYPE">
<value name="PRIM" value="0"/>
<value name="LINK" value="2"/>
<value name="TERM" value="3"/>
</enum>
<!-- FIXME: This is only available with SIMPLE_INTERNAL_PARAMETER_FORMAT_V2. -->
<enum name="CS_CTRL_TYPE_SIPF2">
<value name="PRIM" value="0"/>
<value name="LINK" value="1"/>
<value name="TERM" value="3"/>
</enum>
<!-- FIXME: This is only available with SIMPLE_INTERNAL_PARAMETER_FORMAT. -->
<struct name="INDEX_DATA_WORDS_SIPF" length="2">
<field name="ix_triangle3_bf_flag" start="63" end="63" type="bool"/>
<field name="ix_triangle3_edge_flag_ca" start="62" end="62" type="bool"/>
<field name="ix_triangle3_index_2" start="58" end="61" type="uint"/>
<field name="ix_triangle3_edge_flag_bc" start="57" end="57" type="bool"/>
<field name="ix_triangle3_index_1" start="53" end="56" type="uint"/>
<field name="ix_triangle3_edge_flag_ab" start="52" end="52" type="bool"/>
<field name="ix_triangle3_index_0" start="48" end="51" type="uint"/>
<field name="ix_triangle2_bf_flag" start="47" end="47" type="bool"/>
<field name="ix_triangle2_edge_flag_ca" start="46" end="46" type="bool"/>
<field name="ix_triangle2_index_2" start="42" end="45" type="uint"/>
<field name="ix_triangle2_edge_flag_bc" start="41" end="41" type="bool"/>
<field name="ix_triangle2_index_1" start="37" end="40" type="uint"/>
<field name="ix_triangle2_edge_flag_ab" start="36" end="36" type="bool"/>
<field name="ix_triangle2_index_0" start="32" end="35" type="uint"/>
<field name="ix_triangle1_bf_flag" start="31" end="31" type="bool"/>
<field name="ix_triangle1_edge_flag_ca" start="30" end="30" type="bool"/>
<field name="ix_triangle1_index_2" start="26" end="29" type="uint"/>
<field name="ix_triangle1_edge_flag_bc" start="25" end="25" type="bool"/>
<field name="ix_triangle1_index_1" start="21" end="24" type="uint"/>
<field name="ix_triangle1_edge_flag_ab" start="20" end="20" type="bool"/>
<field name="ix_triangle1_index_0" start="16" end="19" type="uint"/>
<field name="ix_triangle0_bf_flag" start="15" end="15" type="bool"/>
<field name="ix_triangle0_edge_flag_ca" start="14" end="14" type="bool"/>
<field name="ix_triangle0_index_2" start="10" end="13" type="uint"/>
<field name="ix_triangle0_edge_flag_bc" start="9" end="9" type="bool"/>
<field name="ix_triangle0_index_1" start="5" end="8" type="uint"/>
<field name="ix_triangle0_edge_flag_ab" start="4" end="4" type="bool"/>
<field name="ix_triangle0_index_0" start="0" end="3" type="uint"/>
</struct>
<!-- FIXME: This is only available with SIMPLE_INTERNAL_PARAMETER_FORMAT_V2. -->
<struct name="VERTEX_FORMAT_WORD_SIPF2" length="2">
<field name="vf_isp_format_word" start="42" end="63" type="uint"/>
<field name="vf_isp_state_size" start="39" end="41" type="uint"/>
<field name="vf_tsp_vtx_raw" start="38" end="38" type="bool"/>
<field name="vf_isp_vtx_raw" start="37" end="37" type="bool"/>
<field name="vf_varying_total_16" start="30" end="36" type="uint"/>
<field name="vf_varying_total_32" start="23" end="29" type="uint"/>
<field name="vf_varying_vertex_bits" start="11" end="22" type="uint"/>
<field name="vf_primitive_total" start="6" end="10" type="uint"/>
<field name="vf_vertex_total" start="2" end="5" type="uint"/>
<field name="vf_prim_msaa_disable" start="1" end="1" type="bool"/>
<field name="vf_vertex_clipped" start="0" end="0" type="bool"/>
</struct>
<struct name="SCISSOR_WORD_0" length="1">
<field name="scw0_xmin" start="16" end="31" type="uint"/>
<field name="scw0_xmax" start="0" end="15" type="uint"/>
</struct>
<struct name="SCISSOR_WORD_1" length="1">
<field name="scw1_ymin" start="16" end="31" type="uint"/>
<field name="scw1_ymax" start="0" end="15" type="uint"/>
</struct>
<struct name="CONTROL_STREAM" length="1">
<field name="cs_type" start="30" end="31" type="CS_TYPE"/>
<field name="cs_link" start="3" end="29" shift="7" type="address">
<define name="UNIT_SIZE" value="128"/>
</field>
</struct>
<!-- FIXME: This is only available with SIMPLE_INTERNAL_PARAMETER_FORMAT_V2. -->
<struct name="CONTROL_STREAM_LINK_SIPF2" length="1">
<field name="cs_link" start="2" end="31" shift="6" type="address">
<define name="UNIT_SIZE" value="64"/>
</field>
<field name="cs_ctrl_type" start="0" end="1" type="CS_CTRL_TYPE_SIPF2" default="LINK"/>
</struct>
<!-- FIXME: This is only available with SIMPLE_INTERNAL_PARAMETER_FORMAT_V2. -->
<struct name="CONTROL_STREAM_TERMINATE_SIPF2" length="1">
<field name="rsvd" start="2" end="7" type="uint"/>
<field name="cs_ctrl_type" start="0" end="1" type="CS_CTRL_TYPE_SIPF2" default="TERM"/>
</struct>
<!-- FIXME: This is only available with SIMPLE_INTERNAL_PARAMETER_FORMAT_V2. -->
<struct name="PRIMITIVE_HEADER_SIPF2" length="1">
<field name="cs_valid_tile3" start="7" end="7" type="bool"/>
<field name="cs_valid_tile2" start="6" end="6" type="bool"/>
<field name="cs_valid_tile1" start="5" end="5" type="bool"/>
<field name="cs_valid_tile0" start="4" end="4" type="bool"/>
<field name="cs_mask_num_bytes" start="2" end="3" type="uint"/>
<field name="cs_prim_base_size" start="1" end="1" type="bool"/>
<field name="cs_ctrl_type" start="0" end="0" type="CS_CTRL_TYPE_SIPF2" default="PRIM"/>
</struct>
<struct name="PRIMITIVE_FORMAT" length="1">
<field name="cs_type" start="30" end="31" type="CS_TYPE"/>
<field name="cs_isp_state_read" start="29" end="29" type="bool"/>
<field name="cs_isp_state_size" start="26" end="28" type="uint"/>
<field name="cs_prim_total" start="19" end="25" type="uint"/>
<field name="cs_mask_fmt" start="17" end="18" type="CS_MASK_FMT"/>
<field name="cs_prim_base_pres" start="16" end="16" type="bool"/>
<field name="cs_prim_base_offset" start="0" end="15" type="uint"/>
</struct>
<struct name="PRIMITIVE_BASE" length="1">
<field name="cs_prim_base" start="0" end="31" shift="2" type="address"/>
</struct>
<!-- FIXME: This is the SIMPLE_INTERNAL_PARAMETER_FORMAT_V2 variant.
Should we use the "condition" tag for this?
-->
<struct name="PRIMITIVE_BASE_SIPF2" length="1">
<field name="cs_prim_base" start="0" end="31" shift="3" type="address"/>
</struct>
<!-- Labeling of fields within Byte Based Mask One-Byte Word 0.
See ROGUE_IPF_PRIMITIVE_HEADER_SIPF2.cs_mask_num_bytes.
-->
<struct name="BYTE_BASED_MASK_ONE_BYTE_WORD_0_SIPF2" length="1">
<field name="cs_mask_one_byte_tile3_7" start="31" end="31" type="bool"/>
<field name="cs_mask_one_byte_tile3_6" start="30" end="30" type="bool"/>
<field name="cs_mask_one_byte_tile3_5" start="29" end="29" type="bool"/>
<field name="cs_mask_one_byte_tile3_4" start="28" end="28" type="bool"/>
<field name="cs_mask_one_byte_tile3_3" start="27" end="27" type="bool"/>
<field name="cs_mask_one_byte_tile3_2" start="26" end="26" type="bool"/>
<field name="cs_mask_one_byte_tile3_1" start="25" end="25" type="bool"/>
<field name="cs_mask_one_byte_tile3_0" start="24" end="24" type="bool"/>
<field name="cs_mask_one_byte_tile2_7" start="23" end="23" type="bool"/>
<field name="cs_mask_one_byte_tile2_6" start="22" end="22" type="bool"/>
<field name="cs_mask_one_byte_tile2_5" start="21" end="21" type="bool"/>
<field name="cs_mask_one_byte_tile2_4" start="20" end="20" type="bool"/>
<field name="cs_mask_one_byte_tile2_3" start="19" end="19" type="bool"/>
<field name="cs_mask_one_byte_tile2_2" start="18" end="18" type="bool"/>
<field name="cs_mask_one_byte_tile2_1" start="17" end="17" type="bool"/>
<field name="cs_mask_one_byte_tile2_0" start="16" end="16" type="bool"/>
<field name="cs_mask_one_byte_tile1_7" start="15" end="15" type="bool"/>
<field name="cs_mask_one_byte_tile1_6" start="14" end="14" type="bool"/>
<field name="cs_mask_one_byte_tile1_5" start="13" end="13" type="bool"/>
<field name="cs_mask_one_byte_tile1_4" start="12" end="12" type="bool"/>
<field name="cs_mask_one_byte_tile1_3" start="11" end="11" type="bool"/>
<field name="cs_mask_one_byte_tile1_2" start="10" end="10" type="bool"/>
<field name="cs_mask_one_byte_tile1_1" start="9" end="9" type="bool"/>
<field name="cs_mask_one_byte_tile1_0" start="8" end="8" type="bool"/>
<field name="cs_mask_one_byte_tile0_7" start="7" end="7" type="bool"/>
<field name="cs_mask_one_byte_tile0_6" start="6" end="6" type="bool"/>
<field name="cs_mask_one_byte_tile0_5" start="5" end="5" type="bool"/>
<field name="cs_mask_one_byte_tile0_4" start="4" end="4" type="bool"/>
<field name="cs_mask_one_byte_tile0_3" start="3" end="3" type="bool"/>
<field name="cs_mask_one_byte_tile0_2" start="2" end="2" type="bool"/>
<field name="cs_mask_one_byte_tile0_1" start="1" end="1" type="bool"/>
<field name="cs_mask_one_byte_tile0_0" start="0" end="0" type="bool"/>
</struct>
<!-- Labeling of fields within Byte Based Mask Two-Byte Word 0.
See ROGUE_IPF_PRIMITIVE_HEADER_SIPF2.cs_mask_num_bytes.
-->
<struct name="BYTE_BASED_MASK_TWO_BYTE_WORD_0_SIPF2" length="1">
<field name="cs_mask_two_byte_tile1_15" start="31" end="31" type="bool"/>
<field name="cs_mask_two_byte_tile1_14" start="30" end="30" type="bool"/>
<field name="cs_mask_two_byte_tile1_13" start="29" end="29" type="bool"/>
<field name="cs_mask_two_byte_tile1_12" start="28" end="28" type="bool"/>
<field name="cs_mask_two_byte_tile1_11" start="27" end="27" type="bool"/>
<field name="cs_mask_two_byte_tile1_10" start="26" end="26" type="bool"/>
<field name="cs_mask_two_byte_tile1_9" start="25" end="25" type="bool"/>
<field name="cs_mask_two_byte_tile1_8" start="24" end="24" type="bool"/>
<field name="cs_mask_two_byte_tile1_7" start="23" end="23" type="bool"/>
<field name="cs_mask_two_byte_tile1_6" start="22" end="22" type="bool"/>
<field name="cs_mask_two_byte_tile1_5" start="21" end="21" type="bool"/>
<field name="cs_mask_two_byte_tile1_4" start="20" end="20" type="bool"/>
<field name="cs_mask_two_byte_tile1_3" start="19" end="19" type="bool"/>
<field name="cs_mask_two_byte_tile1_2" start="18" end="18" type="bool"/>
<field name="cs_mask_two_byte_tile1_1" start="17" end="17" type="bool"/>
<field name="cs_mask_two_byte_tile1_0" start="16" end="16" type="bool"/>
<field name="cs_mask_two_byte_tile0_15" start="15" end="15" type="bool"/>
<field name="cs_mask_two_byte_tile0_14" start="14" end="14" type="bool"/>
<field name="cs_mask_two_byte_tile0_13" start="13" end="13" type="bool"/>
<field name="cs_mask_two_byte_tile0_12" start="12" end="12" type="bool"/>
<field name="cs_mask_two_byte_tile0_11" start="11" end="11" type="bool"/>
<field name="cs_mask_two_byte_tile0_10" start="10" end="10" type="bool"/>
<field name="cs_mask_two_byte_tile0_9" start="9" end="9" type="bool"/>
<field name="cs_mask_two_byte_tile0_8" start="8" end="8" type="bool"/>
<field name="cs_mask_two_byte_tile0_7" start="7" end="7" type="bool"/>
<field name="cs_mask_two_byte_tile0_6" start="6" end="6" type="bool"/>
<field name="cs_mask_two_byte_tile0_5" start="5" end="5" type="bool"/>
<field name="cs_mask_two_byte_tile0_4" start="4" end="4" type="bool"/>
<field name="cs_mask_two_byte_tile0_3" start="3" end="3" type="bool"/>
<field name="cs_mask_two_byte_tile0_2" start="2" end="2" type="bool"/>
<field name="cs_mask_two_byte_tile0_1" start="1" end="1" type="bool"/>
<field name="cs_mask_two_byte_tile0_0" start="0" end="0" type="bool"/>
</struct>
<!-- Labeling of fields within Byte Based Mask Two-Byte Word 1.
See ROGUE_IPF_PRIMITIVE_HEADER_SIPF2.cs_mask_num_bytes.
-->
<struct name="BYTE_BASED_MASK_TWO_BYTE_WORD_1_SIPF2" length="1">
<field name="cs_mask_two_byte_tile3_15" start="31" end="31" type="bool"/>
<field name="cs_mask_two_byte_tile3_14" start="30" end="30" type="bool"/>
<field name="cs_mask_two_byte_tile3_13" start="29" end="29" type="bool"/>
<field name="cs_mask_two_byte_tile3_12" start="28" end="28" type="bool"/>
<field name="cs_mask_two_byte_tile3_11" start="27" end="27" type="bool"/>
<field name="cs_mask_two_byte_tile3_10" start="26" end="26" type="bool"/>
<field name="cs_mask_two_byte_tile3_9" start="25" end="25" type="bool"/>
<field name="cs_mask_two_byte_tile3_8" start="24" end="24" type="bool"/>
<field name="cs_mask_two_byte_tile3_7" start="23" end="23" type="bool"/>
<field name="cs_mask_two_byte_tile3_6" start="22" end="22" type="bool"/>
<field name="cs_mask_two_byte_tile3_5" start="21" end="21" type="bool"/>
<field name="cs_mask_two_byte_tile3_4" start="20" end="20" type="bool"/>
<field name="cs_mask_two_byte_tile3_3" start="19" end="19" type="bool"/>
<field name="cs_mask_two_byte_tile3_2" start="18" end="18" type="bool"/>
<field name="cs_mask_two_byte_tile3_1" start="17" end="17" type="bool"/>
<field name="cs_mask_two_byte_tile3_0" start="16" end="16" type="bool"/>
<field name="cs_mask_two_byte_tile2_15" start="15" end="15" type="bool"/>
<field name="cs_mask_two_byte_tile2_14" start="14" end="14" type="bool"/>
<field name="cs_mask_two_byte_tile2_13" start="13" end="13" type="bool"/>
<field name="cs_mask_two_byte_tile2_12" start="12" end="12" type="bool"/>
<field name="cs_mask_two_byte_tile2_11" start="11" end="11" type="bool"/>
<field name="cs_mask_two_byte_tile2_10" start="10" end="10" type="bool"/>
<field name="cs_mask_two_byte_tile2_9" start="9" end="9" type="bool"/>
<field name="cs_mask_two_byte_tile2_8" start="8" end="8" type="bool"/>
<field name="cs_mask_two_byte_tile2_7" start="7" end="7" type="bool"/>
<field name="cs_mask_two_byte_tile2_6" start="6" end="6" type="bool"/>
<field name="cs_mask_two_byte_tile2_5" start="5" end="5" type="bool"/>
<field name="cs_mask_two_byte_tile2_4" start="4" end="4" type="bool"/>
<field name="cs_mask_two_byte_tile2_3" start="3" end="3" type="bool"/>
<field name="cs_mask_two_byte_tile2_2" start="2" end="2" type="bool"/>
<field name="cs_mask_two_byte_tile2_1" start="1" end="1" type="bool"/>
<field name="cs_mask_two_byte_tile2_0" start="0" end="0" type="bool"/>
</struct>
<!-- Labeling of fields within Byte Based Mask Three-Byte Word 0.
See ROGUE_IPF_PRIMITIVE_HEADER_SIPF2.cs_mask_num_bytes.
-->
<struct name="BYTE_BASED_MASK_THREE_BYTE_WORD_0_SIPF2" length="1">
<field name="cs_mask_three_byte_tile1_7" start="31" end="31" type="bool"/>
<field name="cs_mask_three_byte_tile1_6" start="30" end="30" type="bool"/>
<field name="cs_mask_three_byte_tile1_5" start="29" end="29" type="bool"/>
<field name="cs_mask_three_byte_tile1_4" start="28" end="28" type="bool"/>
<field name="cs_mask_three_byte_tile1_3" start="27" end="27" type="bool"/>
<field name="cs_mask_three_byte_tile1_2" start="26" end="26" type="bool"/>
<field name="cs_mask_three_byte_tile1_1" start="25" end="25" type="bool"/>
<field name="cs_mask_three_byte_tile1_0" start="24" end="24" type="bool"/>
<field name="cs_mask_three_byte_tile0_23" start="23" end="23" type="bool"/>
<field name="cs_mask_three_byte_tile0_22" start="22" end="22" type="bool"/>
<field name="cs_mask_three_byte_tile0_21" start="21" end="21" type="bool"/>
<field name="cs_mask_three_byte_tile0_20" start="20" end="20" type="bool"/>
<field name="cs_mask_three_byte_tile0_19" start="19" end="19" type="bool"/>
<field name="cs_mask_three_byte_tile0_18" start="18" end="18" type="bool"/>
<field name="cs_mask_three_byte_tile0_17" start="17" end="17" type="bool"/>
<field name="cs_mask_three_byte_tile0_16" start="16" end="16" type="bool"/>
<field name="cs_mask_three_byte_tile0_15" start="15" end="15" type="bool"/>
<field name="cs_mask_three_byte_tile0_14" start="14" end="14" type="bool"/>
<field name="cs_mask_three_byte_tile0_13" start="13" end="13" type="bool"/>
<field name="cs_mask_three_byte_tile0_12" start="12" end="12" type="bool"/>
<field name="cs_mask_three_byte_tile0_11" start="11" end="11" type="bool"/>
<field name="cs_mask_three_byte_tile0_10" start="10" end="10" type="bool"/>
<field name="cs_mask_three_byte_tile0_9" start="9" end="9" type="bool"/>
<field name="cs_mask_three_byte_tile0_8" start="8" end="8" type="bool"/>
<field name="cs_mask_three_byte_tile0_7" start="7" end="7" type="bool"/>
<field name="cs_mask_three_byte_tile0_6" start="6" end="6" type="bool"/>
<field name="cs_mask_three_byte_tile0_5" start="5" end="5" type="bool"/>
<field name="cs_mask_three_byte_tile0_4" start="4" end="4" type="bool"/>
<field name="cs_mask_three_byte_tile0_3" start="3" end="3" type="bool"/>
<field name="cs_mask_three_byte_tile0_2" start="2" end="2" type="bool"/>
<field name="cs_mask_three_byte_tile0_1" start="1" end="1" type="bool"/>
<field name="cs_mask_three_byte_tile0_0" start="0" end="0" type="bool"/>
</struct>
<!-- Labeling of fields within Byte Based Mask Three-Byte Word 1.
See ROGUE_IPF_PRIMITIVE_HEADER_SIPF2.cs_mask_num_bytes.
-->
<struct name="BYTE_BASED_MASK_THREE_BYTE_WORD_1_SIPF2" length="1">
<field name="cs_mask_three_byte_tile2_15" start="31" end="31" type="bool"/>
<field name="cs_mask_three_byte_tile2_14" start="30" end="30" type="bool"/>
<field name="cs_mask_three_byte_tile2_13" start="29" end="29" type="bool"/>
<field name="cs_mask_three_byte_tile2_12" start="28" end="28" type="bool"/>
<field name="cs_mask_three_byte_tile2_11" start="27" end="27" type="bool"/>
<field name="cs_mask_three_byte_tile2_10" start="26" end="26" type="bool"/>
<field name="cs_mask_three_byte_tile2_9" start="25" end="25" type="bool"/>
<field name="cs_mask_three_byte_tile2_8" start="24" end="24" type="bool"/>
<field name="cs_mask_three_byte_tile2_7" start="23" end="23" type="bool"/>
<field name="cs_mask_three_byte_tile2_6" start="22" end="22" type="bool"/>
<field name="cs_mask_three_byte_tile2_5" start="21" end="21" type="bool"/>
<field name="cs_mask_three_byte_tile2_4" start="20" end="20" type="bool"/>
<field name="cs_mask_three_byte_tile2_3" start="19" end="19" type="bool"/>
<field name="cs_mask_three_byte_tile2_2" start="18" end="18" type="bool"/>
<field name="cs_mask_three_byte_tile2_1" start="17" end="17" type="bool"/>
<field name="cs_mask_three_byte_tile2_0" start="16" end="16" type="bool"/>
<field name="cs_mask_three_byte_tile1_23" start="15" end="15" type="bool"/>
<field name="cs_mask_three_byte_tile1_22" start="14" end="14" type="bool"/>
<field name="cs_mask_three_byte_tile1_21" start="13" end="13" type="bool"/>
<field name="cs_mask_three_byte_tile1_20" start="12" end="12" type="bool"/>
<field name="cs_mask_three_byte_tile1_19" start="11" end="11" type="bool"/>
<field name="cs_mask_three_byte_tile1_18" start="10" end="10" type="bool"/>
<field name="cs_mask_three_byte_tile1_17" start="9" end="9" type="bool"/>
<field name="cs_mask_three_byte_tile1_16" start="8" end="8" type="bool"/>
<field name="cs_mask_three_byte_tile1_15" start="7" end="7" type="bool"/>
<field name="cs_mask_three_byte_tile1_14" start="6" end="6" type="bool"/>
<field name="cs_mask_three_byte_tile1_13" start="5" end="5" type="bool"/>
<field name="cs_mask_three_byte_tile1_12" start="4" end="4" type="bool"/>
<field name="cs_mask_three_byte_tile1_11" start="3" end="3" type="bool"/>
<field name="cs_mask_three_byte_tile1_10" start="2" end="2" type="bool"/>
<field name="cs_mask_three_byte_tile1_9" start="1" end="1" type="bool"/>
<field name="cs_mask_three_byte_tile1_8" start="0" end="0" type="bool"/>
</struct>
<!-- Labeling of fields within Byte Based Mask Three-Byte Word 2.
See ROGUE_IPF_PRIMITIVE_HEADER_SIPF2.cs_mask_num_bytes.
-->
<struct name="BYTE_BASED_MASK_THREE_BYTE_WORD_2_SIPF2" length="1">
<field name="cs_mask_three_byte_tile3_23" start="31" end="31" type="bool"/>
<field name="cs_mask_three_byte_tile3_22" start="30" end="30" type="bool"/>
<field name="cs_mask_three_byte_tile3_21" start="29" end="29" type="bool"/>
<field name="cs_mask_three_byte_tile3_20" start="28" end="28" type="bool"/>
<field name="cs_mask_three_byte_tile3_19" start="27" end="27" type="bool"/>
<field name="cs_mask_three_byte_tile3_18" start="26" end="26" type="bool"/>
<field name="cs_mask_three_byte_tile3_17" start="25" end="25" type="bool"/>
<field name="cs_mask_three_byte_tile3_16" start="24" end="24" type="bool"/>
<field name="cs_mask_three_byte_tile3_15" start="23" end="23" type="bool"/>
<field name="cs_mask_three_byte_tile3_14" start="22" end="22" type="bool"/>
<field name="cs_mask_three_byte_tile3_13" start="21" end="21" type="bool"/>
<field name="cs_mask_three_byte_tile3_12" start="20" end="20" type="bool"/>
<field name="cs_mask_three_byte_tile3_11" start="19" end="19" type="bool"/>
<field name="cs_mask_three_byte_tile3_10" start="18" end="18" type="bool"/>
<field name="cs_mask_three_byte_tile3_9" start="17" end="17" type="bool"/>
<field name="cs_mask_three_byte_tile3_8" start="16" end="16" type="bool"/>
<field name="cs_mask_three_byte_tile3_7" start="15" end="15" type="bool"/>
<field name="cs_mask_three_byte_tile3_6" start="14" end="14" type="bool"/>
<field name="cs_mask_three_byte_tile3_5" start="13" end="13" type="bool"/>
<field name="cs_mask_three_byte_tile3_4" start="12" end="12" type="bool"/>
<field name="cs_mask_three_byte_tile3_3" start="11" end="11" type="bool"/>
<field name="cs_mask_three_byte_tile3_2" start="10" end="10" type="bool"/>
<field name="cs_mask_three_byte_tile3_1" start="9" end="9" type="bool"/>
<field name="cs_mask_three_byte_tile3_0" start="8" end="8" type="bool"/>
<field name="cs_mask_three_byte_tile2_23" start="7" end="7" type="bool"/>
<field name="cs_mask_three_byte_tile2_22" start="6" end="6" type="bool"/>
<field name="cs_mask_three_byte_tile2_21" start="5" end="5" type="bool"/>
<field name="cs_mask_three_byte_tile2_20" start="4" end="4" type="bool"/>
<field name="cs_mask_three_byte_tile2_19" start="3" end="3" type="bool"/>
<field name="cs_mask_three_byte_tile2_18" start="2" end="2" type="bool"/>
<field name="cs_mask_three_byte_tile2_17" start="1" end="1" type="bool"/>
<field name="cs_mask_three_byte_tile2_16" start="0" end="0" type="bool"/>
</struct>
<struct name="COMPRESSION_SIZE_WORD" length="1">
<field name="cs_isp_comp_table_size" start="27" end="31" type="uint"/>
<field name="cs_tsp_comp_format_size" start="21" end="26" type="uint"/>
<field name="cs_tsp_comp_table_size" start="9" end="18" type="uint"/>
<field name="cs_tsp_comp_vertex_size" start="0" end="8" type="uint"/>
</struct>
<struct name="ISP_COMPRESSION_WORD_0" length="1">
<field name="cf_isp_comp_fmt_z1" start="28" end="31" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_z0" start="24" end="27" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_y2" start="20" end="23" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_y1" start="16" end="19" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_y0" start="12" end="15" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_x2" start="8" end="11" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_x1" start="4" end="7" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_x0" start="0" end="3" type="COMPRESSION_FORMAT"/>
</struct>
<struct name="ISP_COMPRESSION_WORD_1" length="1">
<field name="vf_prim_msaa" start="16" end="16" type="bool"/>
<field name="vf_prim_id_pres" start="15" end="15" type="bool"/>
<field name="vf_vertex_clipped" start="14" end="14" type="bool"/>
<field name="vf_vertex_total" start="8" end="13" type="uint"/>
<field name="cf_isp_comp_fmt_z3" start="4" end="7" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_z2" start="0" end="3" type="COMPRESSION_FORMAT"/>
</struct>
<struct name="INDEX_DATA" length="1">
<field name="ix_edge_flag1_ab" start="30" end="30" type="bool"/>
<field name="ix_index1_0" start="24" end="29" type="uint"/>
<field name="ix_bf_flag0" start="23" end="23" type="bool"/>
<field name="ix_edge_flag0_ca" start="22" end="22" type="bool"/>
<field name="ix_index0_2" start="16" end="21" type="uint"/>
<field name="ix_edge_flag0_bc" start="14" end="14" type="bool"/>
<field name="ix_index0_1" start="8" end="13" type="uint"/>
<field name="ix_edge_flag0_ab" start="6" end="6" type="bool"/>
<field name="ix_index0_0" start="0" end="5" type="uint"/>
</struct>
<!-- FIXME: This should be of 24 bit length. Should we change the length to
be in terms of uint8_t instead of uint32_t.
-->
<struct name="ISP_VERTEX_XY" length="1">
<field name="sign" start="23" end="23" type="bool"/>
<field name="integer" start="8" end="22" type="uint"/>
<field name="frac" start="0" end="7" type="uint"/>
</struct>
<!-- FIXME: This is the SIMPLE_INTERNAL_PARAMETER_FORMAT variant.
Should we use the "condition" tag for this?
-->
<struct name="ISP_VERTEX_XY_SIPF" length="1">
<field name="integer" start="4" end="16" type="uint">
<define name="MAX_VAL" value="0x1FFF"/>
</field>
<field name="frac" start="0" end="3" type="uint">
<define name="MAX_VAL" value="0xF"/>
</field>
</struct>
<!-- FIXME: This is only available with SIMPLE_INTERNAL_PARAMETER_FORMAT. -->
<struct name="ISP_VERTEX_WORD_SIPF" length="2">
<field name="z" start="34" end="63" type="uint"/>
<field name="y" start="17" end="33" type="uint"/>
<field name="x" start="0" end="16" type="uint"/>
</struct>
<struct name="ISP_VERTEX_WORD_0" length="1">
<field name="y0" start="24" end="31" type="uint"/>
<field name="x0" start="0" end="23" type="uint"/>
</struct>
<struct name="ISP_VERTEX_WORD_1" length="1">
<field name="z0" start="16" end="31" type="uint"/>
<field name="y0" start="0" end="15" type="uint">
<define name="SHIFT" value="8"/>
</field>
</struct>
<struct name="ISP_VERTEX_WORD_2" length="1">
<field name="x1" start="16" end="31" type="uint"/>
<field name="z0" start="0" end="15" type="uint">
<define name="SHIFT" value="16"/>
</field>
</struct>
<struct name="ISP_VERTEX_WORD_3" length="1">
<field name="y1" start="8" end="31" type="uint"/>
<field name="x1" start="0" end="7" type="uint">
<define name="SHIFT" value="16"/>
</field>
</struct>
<struct name="ISP_VERTEX_WORD_4" length="1">
<field name="z1" start="0" end="31" type="uint"/>
</struct>
</csbgen>
+286
View File
@@ -0,0 +1,286 @@
<?xml version="1.0" ?>
<!--
Copyright © 2022 Imagination Technologies Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<!--
These definitions are based on the ones for the firmware streams found
in the fwif header (pvr_rogue_fwif_stream.h).
TODO: Once the kernel driver is merged upstream, check to see if this comment
needs updating.
-->
<!--
This file is structured as follows:
- defines
- enums
- structs
- streams
Elements in each section are ordered alphabetically.
-->
<!--
TODO: Currently the sizes for fields are in bits. Those should be changed to
bytes. Might want to do this in conjunction with csbgen being changed from
dword to bytes granular.
-->
<!--
TODO: Allow embedding of struct definitions withing stream elements. And for
structs that might be shared between multiple streams, allow for the field
type to be set to a struct.
-->
<csbgen name="ROGUE" prefix="KMD_STREAM">
<define name="EXTHDR_DATA_MASK" value="0xFFFFFFF"/>
<!--
Note: this does not depend on
\ref pvr_device_features.has_eight_output_registers .
It's always 8 catering for the largest size.
-->
<!--
TODO: Instead of defining this, see if we can use something like anvil's
"group" where a field is repeated n times. That would allow us to get the
total length of the whole group instead of the driver calculating it by
multiplying this with the size of the usc reg.
-->
<!--
TODO: This should only be defined for `CMD_FRAG`. Allow the definition of
`define` elements within structs and streams.
-->
<define name="USC_CLEAR_REGISTER_COUNT" value="8"/>
<enum name="EXTHDR_TYPE_COMPUTE">
<value name="0" value="0"/>
</enum>
<enum name="EXTHDR_TYPE_FRAG">
<value name="0" value="0"/>
</enum>
<enum name="EXTHDR_TYPE_GEOM">
<value name="0" value="0"/>
</enum>
<enum name="PIXEL_PHANTOM_STATE">
<value name="DISABLED" value="0x0"/>
<value name="ENABLED" value="0xF"/>
</enum>
<struct name="EXTHDR_COMPUTE0" length="1">
<field name="type" start="29" end="31" type="EXTHDR_TYPE_COMPUTE" default="0"/>
<field name="continuation" start="28" end="28" type="bool"/>
<field name="has_brn49927" start="0" end="0" type="bool"/>
</struct>
<struct name="EXTHDR_FRAG0" length="1">
<field name="type" start="29" end="31" type="EXTHDR_TYPE_FRAG" default="0"/>
<field name="continuation" start="28" end="28" type="bool"/>
<field name="has_brn49927" start="1" end="1" type="bool"/>
<field name="has_brn47217" start="0" end="0" type="bool"/>
</struct>
<struct name="EXTHDR_GEOM0" length="1">
<field name="type" start="29" end="31" type="EXTHDR_TYPE_GEOM" default="0"/>
<field name="continuation" start="28" end="28" type="bool"/>
<field name="has_brn49927" start="0" end="0" type="bool"/>
</struct>
<struct name="HDR" length="2">
<field name="length" start="0" end="31" type="uint"/>
</struct>
<!--
Note: if there's an attempt to disable all phantoms, they will all be set
to their default states (i.e. all enabled).
-->
<struct name="PIXEL_PHANTOM" length="1">
<field name="phantom_1" start="4" end="7" type="PIXEL_PHANTOM_STATE"/>
<field name="phantom_0" start="0" end="3" type="PIXEL_PHANTOM_STATE"/>
</struct>
<struct name="VIEW_IDX" length="1">
<field name="idx" start="0" end="7" type="uint"/>
</struct>
<stream name="CMD_COMPUTE" length="18">
<field name="tpu_border_colour_table" size="64" type="uint"/>
<!-- Only present if PVR_FEATURE_CDM_USER_MODE_QUEUE supported on the current device -->
<field name="cdm_cb_queue" size="64" type="uint" feature="PVR_FEATURE_CDM_USER_MODE_QUEUE"/>
<!-- Only present if PVR_FEATURE_CDM_USER_MODE_QUEUE supported on the current device -->
<field name="cbm_cb_base" size="64" type="address" shift="0" feature="PVR_FEATURE_CDM_USER_MODE_QUEUE"/>
<!-- Only present if PVR_FEATURE_CDM_USER_MODE_QUEUE supported on the current device -->
<field name="cdm_cb" size="64" type="uint" feature="PVR_FEATURE_CDM_USER_MODE_QUEUE"/>
<!-- Only present if PVR_FEATURE_CDM_USER_MODE_QUEUE supported on the current device -->
<field name="cdm_ctrl_stream_base" size="64" type="address" shift="0" feature="PVR_FEATURE_CDM_USER_MODE_QUEUE"/>
<field name="cdm_context_state_base_addr" size="64" type="address" shift="0"/>
<field name="cdm_resume_pds1" size="32" type="uint"/>
<!-- Only present if PVR_FEATURE_COMPUTE_MORTON_CAPABLE supported on the current device -->
<field name="cdm_item" size="32" type="uint" feature="PVR_FEATURE_COMPUTE_MORTON_CAPABLE"/>
<!-- Only present if PVR_FEATURE_CLUSTER_GROUPING supported on the current device -->
<field name="compute_cluster" size="32" type="uint" feature="PVR_FEATURE_CLUSTER_GROUPING"/>
<!-- Only present if PVR_FEATURE_TPU_DM_GLOBAL_REGISTERS supported on the current device -->
<field name="tpu_tag_cdm_ctrl" size="32" type="uint" feature="PVR_FEATURE_TPU_DM_GLOBAL_REGISTERS"/>
<!-- Only present if PVR_FEATURE_CDM_USER_MODE_QUEUE supported on the current device -->
<field name="stream_start_offset" size="32" type="uint" feature="PVR_FEATURE_CDM_USER_MODE_QUEUE"/>
<!-- Only present if PVR_FEATURE_GPU_MULTICORE_SUPPORT supported on the current device -->
<field name="execute_count" size="32" type="uint" feature="PVR_FEATURE_GPU_MULTICORE_SUPPORT"/>
</stream>
<stream name="CMD_COMPUTE_EXT_BRN49927" length="1">
<field name="tpu" size="32" type="uint"/>
</stream>
<stream name="CMD_FRAG" length="100">
<field name="isp_scissor_base" size="64" type="address" shift="0"/>
<field name="isp_dbias_base" size="64" type="address" shift="0"/>
<field name="isp_oclqry_base" size="64" type="address" shift="0"/>
<field name="isp_zlsctl" size="64" type="address" shift="0"/>
<field name="isp_zload_store_base" size="64" type="address" shift="0"/>
<field name="isp_stencil_load_store_base" size="64" type="address" shift="0"/>
<!-- Only present if PVR_FEATURE_REQUIRES_FB_CDC_ZLS_SETUP supported on the current device -->
<field name="fb_cdc_zls" size="64" type="uint" feature="PVR_FEATURE_REQUIRES_FB_CDC_ZLS_SETUP"/>
<field name="pbe_word" size="1536" type="uint_array"/>
<field name="tpu_border_colour_table" size="64" type="uint"/>
<field name="pds_bgnd" size="192" type="uint_array"/>
<field name="pds_pr_bgnd" size="192" type="uint_array"/>
<field name="usc_clear_register" size="256" type="uint_array"/>
<field name="usc_pixel_output_ctrl" size="32" type="uint"/>
<field name="isp_bgobjdepth" size="32" type="uint"/>
<field name="isp_bgobjvals" size="32" type="uint"/>
<field name="isp_aa" size="32" type="uint"/>
<!-- Only present if PVR_FEATURE_S7_TOP_INFRASTRUCTURE supported on the current device -->
<field name="isp_xtp_pipe_enable" size="32" type="uint" feature="PVR_FEATURE_S7_TOP_INFRASTRUCTURE"/>
<field name="isp_ctl" size="32" type="uint"/>
<field name="event_pixel_pds_info" size="32" type="uint"/>
<!-- Only present if PVR_FEATURE_CLUSTER_GROUPING supported on the current device -->
<field name="pixel_phantom" size="32" type="uint" feature="PVR_FEATURE_CLUSTER_GROUPING"/>
<field name="view_idx" size="32" type="uint"/>
<field name="event_pixel_pds_data" size="32" type="uint"/>
<!-- Only present if PVR_FEATURE_GPU_MULTICORE_SUPPORT supported on the current device -->
<field name="isp_oclqry_stride" size="32" type="uint" feature="PVR_FEATURE_GPU_MULTICORE_SUPPORT"/>
<!-- Only present if PVR_FEATURE_ZLS_SUBTILE supported on the current device -->
<field name="isp_zls_pixels" size="32" type="uint" feature="PVR_FEATURE_ZLS_SUBTILE"/>
<!-- Only present if PVR_FEATURE_ISP_ZLS_D24_S8_PACKING_OGL_MODE supported on the current device -->
<field name="rgx_cr_blackpearl_fix" size="32" type="uint" feature="PVR_FEATURE_ISP_ZLS_D24_S8_PACKING_OGL_MODE"/>
<field name="zls_stride" size="32" type="uint"/>
<field name="sls_stride" size="32" type="uint"/>
<!-- Only present if PVR_FEATURE_GPU_MULTICORE_SUPPORT supported on the current device -->
<field name="execute_count" size="32" type="uint" feature="PVR_FEATURE_GPU_MULTICORE_SUPPORT"/>
</stream>
<stream name="CMD_FRAG_EXT_BRN47217" length="1">
<field name="isp_oclqry_stride" size="32" type="uint"/>
</stream>
<stream name="CMD_FRAG_EXT_BRN49927" length="1">
<field name="tpu" size="32" type="uint"/>
</stream>
<stream name="CMD_GEOM" length="13">
<field name="vdm_ctrl_stream_base" size="64" type="address" shift="0"/>
<field name="tpu_border_colour_table" size="64" type="uint"/>
<!-- Only present if PVR_FEATURE_VDM_DRAWINDIRECT supported on the current device -->
<field name="vdm_draw_indirect0" size="64" type="uint" feature="PVR_FEATURE_VDM_DRAWINDIRECT"/>
<!-- Only present if PVR_FEATURE_VDM_DRAWINDIRECT supported on the current device -->
<field name="vdm_draw_indirect1" size="32" type="uint" feature="PVR_FEATURE_VDM_DRAWINDIRECT"/>
<field name="ppp_ctrl" size="32" type="uint"/>
<field name="te_psg" size="32" type="uint"/>
<field name="vdm_context_resume_task0_size" size="32" type="uint"/>
<!-- Only present if PVR_FEATURE_VDM_OBJECT_LEVEL_LLS supported on the current device -->
<field name="vdm_context_resume_task3_size" size="32" type="uint" feature="PVR_FEATURE_VDM_OBJECT_LEVEL_LLS"/>
<field name="view_idx" size="32" type="uint"/>
<!-- Only present if PVR_FEATURE_TESSELLATION supported on the current device -->
<field name="pds_coeff_free_prog" size="32" type="uint" feature="PVR_FEATURE_TESSELLATION"/>
</stream>
<stream name="CMD_GEOM_EXT_BRN49927" length="1">
<field name="tpu" size="32" type="uint"/>
</stream>
<stream name="CMD_TRANSFER" length="43">
<field name="pds_bgnd0_base" size="64" type="address" shift="0"/>
<field name="pds_bgnd1_base" size="64" type="address" shift="0"/>
<field name="pds_bgnd3_sizeinfo" size="64" type="uint"/>
<field name="isp_mtile_base" size="64" type="address" shift="0"/>
<field name="pbr_wordx_mrty" size="576" type="uint_array"/>
<field name="isp_bgobjvals" size="32" type="uint"/>
<field name="usc_pixel_output_ctrl" size="32" type="uint"/>
<field name="usc_clear_register0" size="32" type="uint"/>
<field name="usc_clear_register1" size="32" type="uint"/>
<field name="usc_clear_register2" size="32" type="uint"/>
<field name="usc_clear_register3" size="32" type="uint"/>
<field name="isp_mtile_size" size="32" type="uint"/>
<field name="isp_render_origin" size="32" type="uint"/>
<field name="isp_ctl" size="32" type="uint"/>
<field name="isp_aa" size="32" type="uint"/>
<field name="event_pixel_pds_info" size="32" type="uint"/>
<field name="event_pixel_pds_code" size="32" type="uint"/>
<field name="event_pixel_pds_data" size="32" type="uint"/>
<field name="isp_render" size="32" type="uint"/>
<field name="isp_rgn" size="32" type="uint"/>
<!-- Only present if PVR_FEATURE_S7_TOP_INFRASTRUCTURE supported on the current device -->
<field name="isp_xtp_pipe_enable" size="32" type="uint" feature="PVR_FEATURE_S7_TOP_INFRASTRUCTURE"/>
<!-- Only present if PVR_FEATURE_GPU_MULTICORE_SUPPORT supported on the current device -->
<field name="frag_screen" size="32" type="uint" feature="PVR_FEATURE_GPU_MULTICORE_SUPPORT"/>
</stream>
<stream name="STATIC_COMPUTE_CONTEXT_STATE" length="14">
<field name="cdm_reg_context_pds0" size="64" type="uint"/>
<field name="cdm_reg_context_pds1" size="64" type="uint"/>
<field name="cdm_reg_terminate_pds0" size="64" type="uint"/>
<field name="cdm_reg_terminate_pds1" size="64" type="uint"/>
<field name="cdm_reg_resume_pds0" size="64" type="uint"/>
<field name="cdm_reg_context_pds0_b" size="64" type="uint"/>
<field name="cdm_reg_resume_pds0_b" size="64" type="uint"/>
</stream>
<stream name="STATIC_RENDER_CONTEXT_STATE" length="46">
<field name="geom_reg_vdm_context_state_base_addr" size="64" type="address" shift="0"/>
<field name="geom_reg_vdm_context_state_resume_addr" size="64" type="address" shift="0"/>
<field name="geom_reg_ta_context_state_base_addr" size="64" type="address" shift="0"/>
<field name="geom_state0_geom_reg_vdm_context_store_task0" size="64" type="uint"/>
<field name="geom_state0_geom_reg_vdm_context_store_task1" size="64" type="uint"/>
<field name="geom_state0_geom_reg_vdm_context_store_task2" size="64" type="uint"/>
<field name="geom_state0_geom_reg_vdm_context_store_task3" size="64" type="uint"/>
<field name="geom_state0_geom_reg_vdm_context_store_task4" size="64" type="uint"/>
<field name="geom_state0_geom_reg_vdm_context_resume_task0" size="64" type="uint"/>
<field name="geom_state0_geom_reg_vdm_context_resume_task1" size="64" type="uint"/>
<field name="geom_state0_geom_reg_vdm_context_resume_task2" size="64" type="uint"/>
<field name="geom_state0_geom_reg_vdm_context_resume_task3" size="64" type="uint"/>
<field name="geom_state0_geom_reg_vdm_context_resume_task4" size="64" type="uint"/>
<field name="geom_state1_geom_reg_vdm_context_store_task0" size="64" type="uint"/>
<field name="geom_state1_geom_reg_vdm_context_store_task1" size="64" type="uint"/>
<field name="geom_state1_geom_reg_vdm_context_store_task2" size="64" type="uint"/>
<field name="geom_state1_geom_reg_vdm_context_store_task3" size="64" type="uint"/>
<field name="geom_state1_geom_reg_vdm_context_store_task4" size="64" type="uint"/>
<field name="geom_state1_geom_reg_vdm_context_resume_task0" size="64" type="uint"/>
<field name="geom_state1_geom_reg_vdm_context_resume_task1" size="64" type="uint"/>
<field name="geom_state1_geom_reg_vdm_context_resume_task2" size="64" type="uint"/>
<field name="geom_state1_geom_reg_vdm_context_resume_task3" size="64" type="uint"/>
<field name="geom_state1_geom_reg_vdm_context_resume_task4" size="64" type="uint"/>
</stream>
</csbgen>
+48
View File
@@ -0,0 +1,48 @@
<?xml version="1.0" ?>
<!--
Copyright © 2022 Imagination Technologies Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<csbgen name="ROGUE" prefix="LLS">
<!-- Size of the CDM's context state buffer in bytes. -->
<define name="CDM_CONTEXT_RESUME_BUFFER_SIZE" value="72"/>
<define name="CDM_CONTEXT_RESUME_BUFFER_ALIGNMENT" value="16"/>
<!-- Size of the PDS's persistent-temporary register context state buffer in bytes. -->
<define name="PDS_PERSISTENT_TEMPS_BUFFER_ALIGNMENT" value="16"/>
<define name="PDS_PERSISTENT_TEMPS_BUFFER_SIZE" value="128"/>
<!-- Size of the TA's context state buffer in bytes. -->
<define name="TA_STATE_BUFFER_ALIGNMENT" value="16"/>
<define name="TA_STATE_BUFFER_SIZE" value="484"/>
<!-- Size of the USC's shared register context state buffer in bytes. -->
<define name="USC_SHARED_REGS_BUFFER_ALIGNMENT" value="16"/>
<define name="USC_SHARED_REGS_BUFFER_SIZE" value="16384"/>
<!-- Size of the VDM's context resume control stream buffer in bytes. -->
<define name="VDM_CONTEXT_RESUME_BUFFER_ALIGNMENT" value="16"/>
<define name="VDM_CONTEXT_RESUME_BUFFER_SIZE" value="92"/>
</csbgen>
+26
View File
@@ -0,0 +1,26 @@
# Copyright © 2022 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
pvr_xml_files = [
'cdm.xml',
'cr.xml',
'ipf.xml',
'kmd_stream.xml',
'lls.xml',
'pbestate.xml',
'pds.xml',
'ppp.xml',
'texstate.xml',
'vdm.xml',
]
foreach f : pvr_xml_files
_name = '@[email protected]'.format(f.split('.')[0])
pvr_xml_pack += custom_target(
_name,
input : ['../gen_pack_header.py', f],
output : _name,
command : [prog_python, '@INPUT@'],
capture : true,
)
endforeach
+293
View File
@@ -0,0 +1,293 @@
<?xml version="1.0" ?>
<!--
Copyright © 2022 Imagination Technologies Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<csbgen name="ROGUE" prefix="PBESTATE">
<enum name="COMP_IADDR_TYPE">
<value name="INDIRECT_1TILE" value="0"/>
<value name="INDIRECT_4TILE" value="1"/>
</enum>
<enum name="COMPRESS_SIZE">
<value name="BLOCK_8X8" value="0"/>
<value name="BLOCK_16X4" value="1"/>
</enum>
<enum name="COMPRESS_SIZE_EXT">
<value name="BLOCK_8X8_16X4" value="0"/>
<value name="BLOCK_32X2_RSRVD" value="1"/>
</enum>
<enum name="COMPRESSION">
<value name="DISABLED" value="0"/>
<value name="ENABLED" value="1"/>
</enum>
<enum name="LOSSY">
<value name="DISABLED" value="0"/>
<value name="ENABLED" value="1"/>
</enum>
<enum name="MEMLAYOUT">
<value name="LINEAR" value="0"/>
<value name="TWIDDLE_2D" value="1"/>
<value name="TWIDDLE_3D" value="2"/>
<value name="TILED" value="3"/>
</enum>
<enum name="PACKMODE">
<value name="U8U8U8U8" value="0x0"/>
<value name="S8S8S8S8" value="0x1"/>
<value name="X8U8S8S8" value="0x2"/>
<value name="X8S8S8U8" value="0x3"/>
<value name="A1R5G5B5" value="0x4"/>
<value name="R5G5B5A1" value="0x5"/>
<value name="A4R4G4B4" value="0x6"/>
<value name="A8R3G3B2" value="0x7"/>
<value name="U16U16U16U16" value="0x8"/>
<value name="S16S16S16S16" value="0x9"/>
<value name="F16F16F16F16" value="0xa"/>
<value name="U32U32U32U32" value="0xb"/>
<value name="S32S32S32S32" value="0xc"/>
<value name="F32F32F32F32" value="0xd"/>
<value name="A2R10B10G10" value="0xe"/>
<value name="R10B10G10A2" value="0xf"/>
<value name="A2F10F10F10" value="0x10"/>
<value name="F10F10F10A2" value="0x11"/>
<value name="U8U8U8" value="0x12"/>
<value name="S8S8S8" value="0x13"/>
<value name="R5G6B5" value="0x14"/>
<value name="R5SG5SB6" value="0x15"/>
<value name="B6G5SR5S" value="0x16"/>
<value name="U16U16U16" value="0x17"/>
<value name="S16S16S16" value="0x18"/>
<value name="F16F16F16" value="0x19"/>
<value name="U32U32U32" value="0x1a"/>
<value name="S32S32S32" value="0x1b"/>
<value name="F11F11F10" value="0x1c"/>
<value name="F10F11F11" value="0x1d"/>
<value name="SE9995" value="0x1e"/>
<value name="F32F32F32" value="0x1f"/>
<value name="X24U8F32" value="0x20"/>
<value name="X24X8F32" value="0x21"/>
<value name="X24G8X32" value="0x22"/>
<value name="U8U8" value="0x23"/>
<value name="S8S8" value="0x24"/>
<value name="U16U16" value="0x25"/>
<value name="S16S16" value="0x26"/>
<value name="F16F16" value="0x27"/>
<value name="U32U32" value="0x28"/>
<value name="S32S32" value="0x29"/>
<value name="F32F32" value="0x2a"/>
<value name="U24ST8" value="0x2b"/>
<value name="ST8U24" value="0x2c"/>
<value name="X8U24" value="0x2d"/>
<value name="U8X24" value="0x2e"/>
<value name="U8" value="0x2f"/>
<value name="S8" value="0x30"/>
<value name="U16" value="0x31"/>
<value name="S16" value="0x32"/>
<value name="F16" value="0x33"/>
<value name="U32" value="0x34"/>
<value name="S32" value="0x35"/>
<value name="F32" value="0x36"/>
<value name="PBYTE" value="0x37"/>
<value name="PWORD" value="0x38"/>
<value name="ARGBV16_XR10" value="0x39"/>
<value name="A2_XRBIAS_U10U10U10" value="0x3a"/>
<value name="YUV" value="0x3b"/>
<value name="U10U10U10_XRBIAS_A2" value="0x3c"/>
<value name="INVALID" value="0xFFFFFFFF"/>
</enum>
<enum name="PAIR_TILES">
<value name="DISABLED" value="0"/>
<value name="ENABLED" value="1"/>
</enum>
<enum name="ROTATION_TYPE">
<value name="0_DEG" value="0"/>
<value name="90_DEG" value="1"/>
<value name="180_DEG" value="2"/>
<value name="270_DEG" value="3"/>
</enum>
<enum name="SIZE">
<value name="1_PIXEL" value="0"/>
<value name="2_PIXEL" value="1"/>
<value name="4_PIXEL" value="2"/>
<value name="8_PIXEL" value="3"/>
<value name="16_PIXEL" value="4"/>
<value name="32_PIXEL" value="5"/>
<value name="64_PIXEL" value="6"/>
<value name="128_PIXEL" value="7"/>
<value name="256_PIXEL" value="8"/>
<value name="512_PIXEL" value="9"/>
<value name="1K_PIXEL" value="10"/>
<value name="2K_PIXEL" value="11"/>
<value name="4K_PIXEL" value="12"/>
<value name="8K_PIXEL" value="13"/>
<value name="16K_PIXEL" value="14"/>
</enum>
<enum name="SOURCE_FORMAT">
<value name="F16_PER_CHANNEL" value="0"/>
<value name="8_PER_CHANNEL" value="1"/>
</enum>
<enum name="SOURCE_POS">
<value name="START_BIT0" value="0"/>
<value name="START_BIT32" value="1"/>
<value name="START_BIT64" value="2"/>
<value name="START_BIT96" value="3"/>
</enum>
<enum name="SWIZ">
<value name="SOURCE_CHAN0" value="0"/>
<value name="SOURCE_CHAN1" value="1"/>
<value name="SOURCE_CHAN2" value="2"/>
<value name="SOURCE_CHAN3" value="3"/>
<value name="ONE" value="4"/>
<value name="ZERO" value="5"/>
</enum>
<enum name="TFBC_LOSSY">
<value name="LOSSLESS" value="0"/>
<value name="LOSSY75" value="1"/>
<value name="LOSSY50" value="2"/>
<value name="LOSSY25" value="3"/>
</enum>
<enum name="TWOCOMP_GAMMA">
<value name="GAMMA_BOTTOM_CHANNEL" value="0"/>
<value name="GAMMA_BOTH_CHANNELS" value="1"/>
</enum>
<enum name="Y_FLIP">
<value name="DISABLED" value="0"/>
<value name="ENABLED" value="1"/>
</enum>
<enum name="YUV_DOWNSCALE">
<value name="NO_DOWNSCALING" value="0"/>
<value name="ONE_SAMPLE_LEFT" value="1"/>
<value name="EMPTY" value="2"/>
<value name="TWO_SAMPLES" value="3"/>
<value name="FOUR_SAMPLES" value="4"/>
<value name="ONE_SAMPLE_RIGHT" value="5"/>
</enum>
<enum name="YUV_PMODE">
<value name="UV8_420_2PLANE" value="0"/>
<value name="U8_420_3PLANE" value="1"/>
<value name="V8_420_3PLANE" value="2"/>
<value name="YUV8_422_1PLANE" value="3"/>
<value name="UV8_422_2PLANE" value="4"/>
<value name="UV8_444_2PLANE" value="5"/>
<value name="Y8_23PLANE" value="6"/>
<value name="U8_444_3PLANE" value="7"/>
<value name="V8_444_3PLANE" value="8"/>
<value name="YUV10_444_1PLANE" value="9"/>
<value name="RESERVED_YUV1" value="10"/>
<value name="RESERVED_YUV2" value="11"/>
<value name="YUV10_422_1PLANE" value="12"/>
<value name="UV10_420_2PLANE" value="13"/>
<value name="Y10_23PLANE" value="14"/>
<value name="UV16_420_2PLANE" value="15"/>
<value name="UV16_422_2PLANE" value="16"/>
<value name="UV16_444_2PLANE" value="17"/>
<value name="Y16_23PLANE" value="18"/>
<value name="U16_444_3PLANE" value="19"/>
<value name="V16_444_3PLANE" value="20"/>
</enum>
<struct name="STATE_WORD0" length="1">
<field name="address_low" start="0" end="31" shift="2" type="address"/>
</struct>
<struct name="STATE_WORD1" length="1">
<condition type="if" check="8_OUTPUT_REGISTERS"/>
<field name="source_pos_offset_128" start="28" end="28" type="bool"/>
<condition type="endif" check="8_OUTPUT_REGISTERS"/>
<field name="yuv_pmode" start="23" end="27" type="YUV_PMODE"/>
<field name="yuv_downscale" start="20" end="22" type="YUV_DOWNSCALE"/>
<field name="source_format" start="19" end="19" type="SOURCE_FORMAT"/>
<field name="mrt_index" start="16" end="18" type="uint"/>
<field name="source_pos" start="14" end="15" type="SOURCE_POS"/>
<field name="norm" start="13" end="13" type="bool"/>
<field name="packmode" start="7" end="12" type="PACKMODE"/>
<field name="emptytile" start="6" end="6" type="bool"/>
<field name="address_high" start="0" end="5" shift="34" type="address"/>
</struct>
<struct name="REG_WORD0" length="2">
<field name="tfbc_lossy" start="62" end="63" type="TFBC_LOSSY">
<define name="LOSSY37_75_TFBC_LOSSY_37_PERCENT_ENABLED" value="1"/>
</field>
<field name="lossy" start="62" end="62" type="LOSSY"/>
<field name="compress_size_ext" start="61" end="61" type="COMPRESS_SIZE_EXT"/>
<field name="comp_iaddr_mode" start="60" end="60" type="COMP_IADDR_TYPE"/>
<field name="comp_cor_enable" start="59" end="59" type="bool"/>
<field name="dither" start="58" end="58" type="bool"/>
<field name="tilerelative" start="57" end="57" type="bool"/>
<field name="downscale" start="56" end="56" type="bool"/>
<field name="size_z" start="52" end="55" type="SIZE"/>
<field name="rotation" start="50" end="51" type="ROTATION_TYPE"/>
<field name="linestride" start="34" end="49" type="uint">
<define name="UNIT_SIZE" value="2"/>
</field>
<field name="memlayout" start="32" end="33" type="MEMLAYOUT"/>
<field name="swiz_chan3" start="29" end="31" type="SWIZ"/>
<field name="swiz_chan2" start="26" end="28" type="SWIZ"/>
<field name="swiz_chan1" start="23" end="25" type="SWIZ"/>
<field name="swiz_chan0" start="20" end="22" type="SWIZ"/>
<field name="minclip_x" start="6" end="19" type="uint"/>
<field name="twocomp_gamma" start="5" end="5" type="TWOCOMP_GAMMA"/>
<field name="gamma" start="4" end="4" type="bool"/>
<field name="compression" start="3" end="3" type="COMPRESSION"/>
<field name="compress_size" start="2" end="2" type="COMPRESS_SIZE"/>
<field name="comp_indirect_table" start="1" end="1" type="bool"/>
<field name="y_flip" start="0" end="0" type="Y_FLIP"/>
</struct>
<struct name="REG_WORD1" length="2">
<field name="size_x" start="60" end="63" type="SIZE"/>
<field name="minclip_y" start="46" end="59" type="uint"/>
<field name="maxclip_x" start="32" end="45" type="uint"/>
<field name="size_y" start="28" end="31" type="SIZE"/>
<field name="zslice" start="14" end="27" type="uint"/>
<field name="maxclip_y" start="0" end="13" type="uint"/>
</struct>
<struct name="REG_WORD2" length="2">
<field name="pair_tiles" start="46" end="46" type="PAIR_TILES">
<!-- TODO: Do we need this? -->
<define name="SHIFT" value="46"/>
</field>
<field name="surface_y_size" start="32" end="45" type="uint"/>
<field name="sw_bytemask" start="0" end="31" type="uint"/>
</struct>
</csbgen>
+135
View File
@@ -0,0 +1,135 @@
<?xml version="1.0" ?>
<!--
Copyright © 2022 Imagination Technologies Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<csbgen name="ROGUE" prefix="PDSINST">
<enum name="CMODE_LD">
<value name="CACHED" value="0"/>
<value name="BYPASS" value="1"/>
<value name="FORCE_LINE_FILL" value="2"/>
</enum>
<enum name="DOUTD_DEST">
<value name="UNIFIED_STORE" value="0"/>
<value name="COMMON_STORE" value="1"/>
</enum>
<enum name="DEST">
<value name="UNIFIED_STORE" value="0"/>
<value name="COMMON_STORE" value="1"/>
</enum>
<enum name="DOUTI_SHADEMODEL">
<value name="FLAT_VERTEX0" value="0"/>
<value name="FLAT_VERTEX1" value="1"/>
<value name="FLAT_VERTEX2" value="2"/>
<value name="GOURUAD" value="3"/>
</enum>
<enum name="DOUTI_SIZE">
<value name="1D" value="0"/>
<value name="2D" value="1"/>
<value name="3D" value="2"/>
<value name="4D" value="3"/>
</enum>
<enum name="DOUTU_SAMPLE_RATE">
<value name="INSTANCE" value="0"/>
<value name="SELECTIVE" value="1"/>
<value name="FULL" value="2"/>
</enum>
<enum name="SLC_MODE_LD">
<value name="BYPASS" value="0"/>
<value name="CACHED" value="1"/>
<value name="CACHED_RD_NA" value="3"/>
</enum>
<enum name="WORDSIZE">
<value name="ONE" value="0"/>
<value name="TWO" value="1"/>
<value name="THREE" value="2"/>
<value name="FOUR" value="3"/>
</enum>
<struct name="DDMAD_FIELDS_SRC3" length="2">
<condition type="if" check="PDS_DDMADT"/>
<field name="msize" start="33" end="63" type="uint"/>
<field name="test" start="32" end="32" type="bool"/>
<condition type="endif" check="PDS_DDMADT"/>
<field name="last" start="31" end="31" type="bool"/>
<field name="wordsize" start="29" end="30" type="WORDSIZE"/>
<field name="dest" start="28" end="28" type="DEST"/>
<field name="cmode" start="26" end="27" type="CMODE_LD"/>
<field name="a0" start="13" end="25" type="uint"/>
<field name="repeat" start="12" end="12" type="bool"/>
<field name="bsize" start="0" end="11" type="uint"/>
</struct>
<struct name="DOUTU_SRC0" length="2">
<field name="dual_phase" start="41" end ="41" type="bool"/>
<field name="temps" start="35" end="40" type="uint">
<define name="UNIT_SIZE" value="2"/>
</field>
<field name="sample_rate" start="33" end="34" type="DOUTU_SAMPLE_RATE"/>
<field name="exe_off" start="2" end="31" shift="2" type="address"/>
</struct>
<struct name="DOUT_FIELDS_DOUTD_SRC0" length="2">
<condition type="if" check="SLC_MCU_CACHE_CONTROLS"/>
<field name="slcmode" start="60" end="61" type="SLC_MODE_LD"/>
<condition type="endif" check="SLC_MCU_CACHE_CONTROLS"/>
<field name="doffset" start="40" end="52" type="uint"/>
<field name="sbase" start="0" end="39" shift="0" type="address"/>
</struct>
<struct name="DOUT_FIELDS_DOUTD_SRC1" length="1">
<field name="last" start="31" end="31" type="bool"/>
<field name="wordsize" start="29" end="30" type="WORDSIZE"/>
<field name="dest" start="28" end="28" type="DOUTD_DEST"/>
<field name="cmode" start="26" end="27" type="CMODE_LD"/>
<field name="a0" start="13" end="25" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
<field name="repeat" start="12" end="12" type="bool"/>
<field name="bsize" start="0" end="11" type="uint"/>
</struct>
<struct name="DOUT_FIELDS_DOUTI_SRC" length="1">
<field name="depthbias" start="27" end="27" type="bool"/>
<field name="primitiveid" start="26" end="26" type="bool"/>
<field name="shademodel" start="24" end="25" type="DOUTI_SHADEMODEL"/>
<field name="pointsprite" start="23" end="23" type="bool"/>
<field name="wraps" start="22" end="22" type="bool"/>
<field name="wrapv" start="21" end="21" type="bool"/>
<field name="wrapu" start="20" end="20" type="bool"/>
<field name="size" start="18" end="19" type="DOUTI_SIZE"/>
<field name="f16" start="17" end="17" type="bool"/>
<field name="perspective" start="16" end="16" type="bool"/>
<field name="f32_offset" start="8" end="15" type="uint"/>
<field name="f16_offset" start="0" end="7" type="uint"/>
</struct>
</csbgen>
+343
View File
@@ -0,0 +1,343 @@
<?xml version="1.0" ?>
<!--
Copyright © 2022 Imagination Technologies Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<csbgen name="ROGUE" prefix="TA">
<enum name="CLIP_MODE">
<value name="NO_FRONT_OR_REAR" value="0"/>
<value name="FRONT_REAR" value="1"/>
<value name="FRONT_REAR_DEPTH" value="2"/>
</enum>
<enum name="CMPMODE">
<value name="NEVER" value="0"/>
<value name="LESS" value="1"/>
<value name="EQUAL" value="2"/>
<value name="LESS_OR_EQUAL" value="3"/>
<value name="GREATER" value="4"/>
<value name="NOT_EQUAL" value="5"/>
<value name="GREATER_OR_EQUAL" value="6"/>
<value name="ALWAYS" value="7"/>
</enum>
<enum name="CULLMODE">
<value name="NO_CULLING" value="0"/>
<value name="CULL_CW" value="1"/>
<value name="CULL_CCW" value="2"/>
</enum>
<enum name="FLATSHADE">
<value name="VTX_VERTEX_0" value="1"/>
<value name="VTX_VERTEX_1" value="2"/>
<value name="VTX_VERTEX_2" value="3"/>
</enum>
<enum name="GS_OUTPUT_TOPOLOGY">
<value name="POINT_LIST" value="0"/>
<value name="LINE_STRIP" value="1"/>
<value name="TRI_STRIP" value="2"/>
</enum>
<enum name="ISPB_STENCILOP">
<value name="KEEP" value="0"/>
<value name="ZERO" value="1"/>
<value name="REPLACE" value="2"/>
<value name="INCREMENT_SATURATE" value="3"/>
<value name="DECREMENT_SATURATE" value="4"/>
<value name="INVERT" value="5"/>
<value name="INCREMENT" value="6"/>
<value name="DECREMENT" value="7"/>
</enum>
<enum name="OBJTYPE">
<value name="TRIANGLE" value="0"/>
<value name="LINE" value="1"/>
<value name="SPRITE_10UV" value="2"/>
<value name="SPRITE_UV" value="3"/>
<value name="SPRITE_01UV" value="4"/>
<value name="LINE_FILLED_TRIANGLE" value="5"/>
<value name="POINT_FILLED_TRIANGLE" value="6"/>
<value name="TESSELLATED_OBJECT_NO_GS" value="7"/>
<value name="TESSELLATED_OBJECT_WITH_GS" value="8"/>
</enum>
<!--
TODO: Add support for "ifs" in csbgen root element.
-->
<enum name="PASSTYPE">
<value name="OPAQUE" value="0"/>
<value name="TRANSLUCENT" value="1"/>
<value name="PUNCH_THROUGH" value="2"/>
<value name="VIEWPORT_OBJECT" value="3"/>
<value name="FAST_PUNCH_THROUGH" value="4"/>
<value name="DEPTH_FEEDBACK" value="5"/>
<value name="ANTI_ALIASED" value="6"/>
</enum>
<enum name="REGION_CLIP_MODE">
<value name="NONE" value="0"/>
<value name="OUTSIDE" value="1"/>
</enum>
<struct name="STATE_HEADER" length="1">
<field name="not_final_term" start="26" end="26" type="bool"/>
<field name="pres_terminate" start="25" end="25" type="bool"/>
<field name="context_switch" start="24" end="24" type="bool"/>
<field name="pres_stream_out_program" start="23" end="23" type="bool"/>
<field name="pres_stream_out_size" start="22" end="22" type="bool"/>
<field name="pres_ppp_ctrl" start="21" end="21" type="bool"/>
<field name="pres_varying_word2" start="20" end="20" type="bool"/>
<field name="pres_varying_word1" start="19" end="19" type="bool"/>
<field name="pres_varying_word0" start="18" end="18" type="bool"/>
<field name="pres_outselects" start="17" end="17" type="bool"/>
<field name="pres_wclamp" start="16" end="16" type="bool"/>
<field name="view_port_count" start="12" end="15" type="uint"/>
<field name="pres_viewport" start="11" end="11" type="bool"/>
<field name="pres_region_clip" start="10" end="10" type="bool"/>
<field name="pres_pds_state_ptr3" start="9" end="9" type="bool"/>
<field name="pres_pds_state_ptr2" start="8" end="8" type="bool"/>
<field name="pres_pds_state_ptr1" start="7" end="7" type="bool"/>
<field name="pres_pds_state_ptr0" start="6" end="6" type="bool"/>
<field name="pres_ispctl_dbsc" start="5" end="5" type="bool"/>
<field name="pres_ispctl_bb" start="4" end="4" type="bool"/>
<field name="pres_ispctl_ba" start="3" end="3" type="bool"/>
<field name="pres_ispctl_fb" start="2" end="2" type="bool"/>
<field name="pres_ispctl_fa" start="1" end="1" type="bool"/>
<field name="pres_ispctl" start="0" end="0" type="bool"/>
</struct>
<struct name="STATE_ISPCTL" length="1">
<field name="validid" start="26" end="31" type="uint"/>
<field name="upass" start="22" end="25" type="uint"/>
<field name="tagwritedisable" start="21" end="21" type="bool"/>
<field name="ovgmtestdisable" start="20" end="20" type="bool"/>
<field name="two_sided" start="19" end="19" type="bool"/>
<field name="bpres" start="18" end="18" type="bool"/>
<field name="dbenable" start="17" end="17" type="bool"/>
<field name="scenable" start="16" end="16" type="bool"/>
<field name="vistest" start="15" end="15" type="bool"/>
<field name="visbool" start="14" end="14" type="bool"/>
<field name="visreg" start="0" end="13" type="uint"/>
</struct>
<struct name="STATE_ISPA" length="1">
<field name="objtype" start="28" end="31" type="OBJTYPE"/>
<field name="passtype" start="24" end="26" type="PASSTYPE"/>
<field name="ovgvispassmaskop" start="23" end="23" type="bool"/>
<field name="maskval" start="22" end="22" type="bool"/>
<field name="dwritedisable" start="21" end="21" type="bool"/>
<field name="dfbztestenable" start="20" end="20" type="bool"/>
<field name="dcmpmode" start="17" end="19" type="CMPMODE"/>
<field name="linefilllastpixel" start="16" end="16" type="bool"/>
<field name="pointlinewidth" start="8" end="15" type="uint">
<define name="SIZE_MAX" value="255"/>
</field>
<field name="sref" start="0" end="7" type="uint">
<define name="SIZE_MAX" value="255"/>
</field>
</struct>
<struct name="STATE_ISPB" length="1">
<field name="scmpmode" start="25" end="27" type="CMPMODE"/>
<field name="sop1" start="22" end="24" type="ISPB_STENCILOP"/>
<field name="sop2" start="19" end="21" type="ISPB_STENCILOP"/>
<field name="sop3" start="16" end="18" type="ISPB_STENCILOP"/>
<field name="scmpmask" start="8" end="15" type="uint"/>
<field name="swmask" start="0" end="7" type="uint"/>
</struct>
<!-- `REGION_CLIP{0,1}` `left`,`right`,`top`,`bottom`, are all 9 bits. -->
<define name="REGION_CLIP_MAX" value="0x1FF"/>
<struct name="REGION_CLIP0" length="1">
<field name="mode" start="31" end="31" type="REGION_CLIP_MODE"/>
<field name="left" start="16" end="24" type="uint"/>
<field name="right" start="0" end="8" type="uint"/>
</struct>
<struct name="REGION_CLIP1" length="1">
<field name="top" start="16" end="24" type="uint"/>
<field name="bottom" start="0" end="8" type="uint"/>
</struct>
<struct name="WCLAMP" length="1">
<field name="val" start="0" end="31" type="uint"/>
</struct>
<struct name="STATE_ISPDBSC" length="1">
<field name="dbindex" start="16" end="31" type="uint"/>
<field name="scindex" start="0" end="15" type="uint"/>
</struct>
<struct name="OUTPUT_SEL" length="1">
<field name="vtxsize" start="24" end="31" type="uint"/>
<field name="tsp_unclamped_z_pres" start="21" end="21" type="bool"/>
<field name="render_tgt_pres" start="20" end="20" type="bool"/>
<field name="vpt_tgt_pres" start="19" end="19" type="bool"/>
<field name="psprite_size_pres" start="18" end="18" type="bool"/>
<field name="isp_position_depth_clamp_z" start="17" end="17" type="bool"/>
<field name="rhw_pres" start="16" end="16" type="bool"/>
<field name="cullplane7" start="15" end="15" type="bool"/>
<field name="cullplane6" start="14" end="14" type="bool"/>
<field name="cullplane5" start="13" end="13" type="bool"/>
<field name="cullplane4" start="12" end="12" type="bool"/>
<field name="cullplane3" start="11" end="11" type="bool"/>
<field name="cullplane2" start="10" end="10" type="bool"/>
<field name="cullplane1" start="9" end="9" type="bool"/>
<field name="cullplane0" start="8" end="8" type="bool"/>
<field name="plane7" start="7" end="7" type="bool"/>
<field name="plane6" start="6" end="6" type="bool"/>
<field name="plane5" start="5" end="5" type="bool"/>
<field name="plane4" start="4" end="4" type="bool"/>
<field name="plane3" start="3" end="3" type="bool"/>
<field name="plane2" start="2" end="2" type="bool"/>
<field name="plane1" start="1" end="1" type="bool"/>
<field name="plane0" start="0" end="0" type="bool"/>
</struct>
<struct name="STATE_VARYING0" length="1">
<field name="f32_npc" start="16" end="23" type="uint"/>
<field name="f32_flat" start="8" end="15" type="uint"/>
<field name="f32_linear" start="0" end="7" type="uint"/>
</struct>
<struct name="STATE_VARYING1" length="1">
<field name="f16_npc" start="24" end="31" type="uint"/>
<field name="f16_flat" start="16" end="23" type="uint"/>
<field name="f16_linear" start="8" end="15" type="uint"/>
</struct>
<struct name="STATE_VARYING2" length="1">
<field name="output_clip_planes" start="16" end="19" type="uint"/>
</struct>
<struct name="STATE_TERMINATE0" length="1">
<field name="clip_right" start="18" end="26" type="uint">
<define name="BLOCK_SIZE_IN_PIXELS" value="32"/>
</field>
<field name="clip_top" start="9" end="17" type="uint">
<define name="BLOCK_SIZE_IN_PIXELS" value="32"/>
</field>
<field name="clip_bottom" start="0" end="8" type="uint">
<define name="BLOCK_SIZE_IN_PIXELS" value="32"/>
</field>
</struct>
<struct name="STATE_TERMINATE1" length="1">
<field name="clip_left" start="23" end="31" type="uint">
<define name="BLOCK_SIZE_IN_PIXELS" value="32"/>
</field>
<field name="render_target" start="0" end="10" type="uint"/>
</struct>
<struct name="STATE_STREAM_OUT0" length="1">
<field name="stream3_size" start="24" end="31" type="uint"/>
<field name="stream2_size" start="16" end="23" type="uint"/>
<field name="stream1_size" start="8" end="15" type="uint"/>
<field name="stream0_mem_output" start="1" end="1" type="bool"/>
<field name="stream0_ta_output" start="0" end="0" type="bool"/>
</struct>
<struct name="STATE_STREAM_OUT1" length="1">
<field name="sync" start="10" end="10" type="bool"/>
<field name="pds_data_size" start="4" end="9" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="pds_temp_size" start="0" end="3" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
</struct>
<struct name="STATE_STREAM_OUT2" length="1">
<!-- This is an offset actually. Note for when we auto-generate the xmls. -->
<field name="pds_data_addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="STATE_PDS_SHADERBASE" length="1">
<!-- This is an offset actually. Note for when we auto-generate the xmls. -->
<field name="addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="STATE_PDS_TEXUNICODEBASE" length="1">
<field name="addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="STATE_PDS_VARYINGBASE" length="1">
<!-- This is an offset actually. Note for when we auto-generate the xmls. -->
<field name="addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="STATE_PDS_TEXTUREDATABASE" length="1">
<field name="addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="STATE_PDS_UNIFORMDATABASE" length="1">
<!-- This is an offset actually. Note for when we auto-generate the xmls. -->
<field name="addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="STATE_PDS_SIZEINFO1" length="1">
<field name="pds_uniformsize" start="23" end="31" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
<field name="pds_texturestatesize" start="16" end="22" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
<field name="pds_varyingsize" start="10" end="15" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
<field name="usc_varyingsize" start="4" end="9" type="uint">
<define name="UNIT_SIZE" value="16"/>
<define name="MAX_SIZE" value="63"/>
</field>
<field name="pds_tempsize" start="0" end="3" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
</struct>
<struct name="STATE_PDS_SIZEINFO2" length="1">
<field name="usc_sharedsize" start="23" end="31" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="pds_tri_merge_disable" start="14" end="14" type="bool"/>
<field name="pds_batchnum" start="0" end="13" type="uint"/>
</struct>
<struct name="STATE_PPP_CTRL" length="1">
<field name="prim_msaa" start="15" end="15" type="bool"/>
<field name="gs_output_topology" start="13" end="14" type="GS_OUTPUT_TOPOLOGY"/>
<field name="pres_prim_id" start="12" end="12" type="bool"/>
<field name="clip_mode" start="10" end="11" type="CLIP_MODE"/>
<field name="drawclippededges" start="9" end="9" type="bool"/>
<field name="flatshade_vtx" start="7" end="8" type="FLATSHADE"/>
<field name="pretransform" start="6" end="6" type="bool"/>
<field name="wclampen" start="5" end="5" type="bool"/>
<field name="wbuffen" start="4" end="4" type="bool"/>
<field name="resetbbox" start="3" end="3" type="bool"/>
<field name="updatebbox" start="2" end="2" type="bool"/>
<field name="cullmode" start="0" end="1" type="CULLMODE"/>
</struct>
</csbgen>
+369
View File
@@ -0,0 +1,369 @@
<?xml version="1.0" ?>
<!--
Copyright © 2022 Imagination Technologies Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<csbgen name="ROGUE" prefix="TEXSTATE">
<enum name="ADDRMODE">
<value name="REPEAT" value="0"/>
<value name="FLIP" value="1"/>
<value name="CLAMP_TO_EDGE" value="2"/>
<value name="FLIP_ONCE_THEN_CLAMP" value="3"/>
<value name="CLAMP_TO_BORDER" value="4"/>
<value name="OGL_CLAMP" value="5"/>
</enum>
<enum name="ANISOCTL">
<value name="DISABLED" value="0"/>
<value name="X2" value="1"/>
<value name="X4" value="2"/>
<value name="X8" value="3"/>
<value name="X16" value="4"/>
</enum>
<enum name="CLAMP">
<value name="MIN" value="0"/>
<value name="MAX" value="959"/>
<value name="INTEGER_BITS" value="4"/>
<value name="FRACTIONAL_BITS" value="6"/>
</enum>
<enum name="CMP_MODE">
<value name="NEVER" value="0"/>
<value name="LESS" value="1"/>
<value name="EQUAL" value="2"/>
<value name="LESSEQUAL" value="3"/>
<value name="GREATER" value="4"/>
<value name="NOTEQUAL" value="5"/>
<value name="GREATEREQUAL" value="6"/>
<value name="ALWAYS" value="7"/>
</enum>
<enum name="COMPRESSION_LEVEL">
<value name="LOSSLESS" value="0"/>
<value name="LOSSY_75" value="1"/>
<value name="LOSSY_50" value="2"/>
<value name="LOSSY_25" value="3"/>
</enum>
<enum name="COMPRESSION_MODE">
<value name="NONE" value="0"/>
<value name="TPU" value="1"/>
<value name="FB_DIRECT_8X8" value="2"/>
<value name="FB_DIRECT_16X4" value="3"/>
<value name="FB_INDIRECT_1TILE_8X8" value="4"/>
<value name="FB_INDIRECT_1TILE_16X4" value="5"/>
<value name="FB_INDIRECT_4TILE_8X8" value="6"/>
<value name="FB_INDIRECT_4TILE_16X4" value="7"/>
</enum>
<enum name="DADJUST">
<value name="MIN_UINT" value="0"/>
<value name="ZERO_UINT" value="4095"/>
<value name="MAX_UINT" value="8191"/>
<value name="INTEGER_BITS" value="5"/>
<value name="FRACTIONAL_BITS" value="8"/>
</enum>
<enum name="FILTER">
<value name="POINT" value="0"/>
<value name="LINEAR" value="1"/>
<value name="BICUBIC" value="2"/>
</enum>
<enum name="FORMAT">
<value name="U8" value="0"/>
<value name="S8" value="1"/>
<value name="A4R4G4B4" value="2"/>
<value name="A8R3G3B2" value="3"/>
<value name="A1R5G5B5" value="4"/>
<value name="R5G6B5" value="5"/>
<value name="R5sG5sB6" value="6"/>
<value name="U8U8" value="7"/>
<value name="S8S8" value="8"/>
<value name="U16" value="9"/>
<value name="S16" value="10"/>
<value name="F16" value="11"/>
<value name="U8U8U8U8" value="12"/>
<value name="S8S8S8S8" value="13"/>
<value name="A2R10B10G10" value="14"/>
<value name="U16U16" value="15"/>
<value name="S16S16" value="16"/>
<value name="F16F16" value="17"/>
<value name="F32" value="18"/>
<value name="F32_SIGNMASK" value="19"/>
<value name="X8U8S8S8" value="20"/>
<value name="X8U24" value="21"/>
<value name="ST8U24" value="22"/>
<value name="U8X24" value="23"/>
<value name="U32" value="24"/>
<value name="S32" value="25"/>
<value name="SE9995" value="26"/>
<value name="F11F11F10" value="27"/>
<value name="F16F16F16F16" value="28"/>
<value name="U16U16U16U16" value="29"/>
<value name="S16S16S16S16" value="30"/>
<value name="F16F16F16" value="31"/>
<value name="U16U16U16" value="32"/>
<value name="S16S16S16" value="33"/>
<value name="F32F32" value="34"/>
<value name="U32U32" value="35"/>
<value name="S32S32" value="36"/>
<value name="X24U8F32" value="37"/>
<value name="X24X8F32" value="38"/>
<value name="X24G8X32" value="39"/>
<value name="YUV420_2PLANE" value="54"/>
<value name="YVU420_2PLANE" value="55"/>
<value name="YUV420_3PLANE" value="56"/>
<value name="YVU420_3PLANE" value="57"/>
<value name="U8U8U8" value="58"/>
<value name="S8S8S8" value="59"/>
<value name="A2F10F10F10" value="60"/>
<value name="F32F32F32F32" value="61"/>
<value name="U32U32U32U32" value="62"/>
<value name="S32S32S32S32" value="63"/>
<value name="F32F32F32" value="64"/>
<value name="U32U32U32" value="65"/>
<value name="S32S32S32" value="66"/>
<value name="A2_XRBIAS_U10U10U10" value="67"/>
<value name="O8" value="81"/>
<value name="O8O8" value="82"/>
<value name="R5G5B5A1" value="83"/>
<value name="B6G5sR5s" value="84"/>
<value name="R10B10G10A2" value="85"/>
<value name="X8S8S8U8" value="86"/>
<value name="U24ST8" value="87"/>
<value name="F10F11F11" value="88"/>
<value name="VYUY" value="89"/>
<value name="UYVY" value="90"/>
<value name="YVYU" value="91"/>
<value name="YUYV" value="92"/>
<value name="F10F10F10A2" value="93"/>
<value name="YUV420_2PLANE_MACRO_BLOCK" value="94"/>
<value name="YVU420_2PLANE_MACRO_BLOCK" value="95"/>
<value name="ARGBV16_XR10" value="96"/>
<value name="YVU8_422_2PLANE_PACK8" value="97"/>
<value name="YVU8_444_2PLANE_PACK8" value="98"/>
<value name="YVU10_444_1PLANE_PACK10" value="99"/>
<value name="YVU10_422_2PLANE_PACK16" value="100"/>
<value name="YVU10_420_2PLANE_PACK16" value="101"/>
<value name="YVU10_444_2PLANE_PACK16" value="102"/>
<value name="YUV8_422_2PLANE_PACK8" value="103"/>
<value name="YUV8_444_3PLANE_PACK8" value="104"/>
<value name="YUV10_444_3PLANE_PACK16" value="105"/>
<value name="YVU10_420_2PLANE_PACK10" value="106"/>
<value name="YUV10_420_2PLANE_PACK10" value="107"/>
<value name="YVU10_422_2PLANE_PACK10" value="108"/>
<value name="YUV10_422_2PLANE_PACK10" value="109"/>
<value name="YUV10_444_3PLANE_PACK10" value="110"/>
<value name="R8G8_B8G8" value="111"/>
<value name="G8R8_G8B8" value="112"/>
<value name="YVYU_IMPLIED_CSC" value="113"/>
<value name="VYUY_IMPLIED_CSC" value="114"/>
<value name="YUV10_420_2PLANE_PACK10_R" value="115"/>
<value name="YVU10_420_2PLANE_PACK10_R" value="116"/>
<value name="YUV10_420_2PLANE_PACK10_T" value="117"/>
<value name="YVU10_420_2PLANE_PACK10_T" value="118"/>
<value name="YUV8_420_2PLANE_PACK8_P" value="119"/>
<value name="YVU8_420_2PLANE_PACK8_P" value="120"/>
<value name="YUV8_420_2PLANE_PACK8_F" value="121"/>
<value name="YVU8_420_2PLANE_PACK8_F" value="122"/>
<value name="INVALID" value="0xFFFFFFFF"/>
</enum>
<enum name="FORMAT_COMPRESSED">
<value name="ASTC_4x4" value="0"/>
<value name="ASTC_5x4" value="1"/>
<value name="ASTC_5x5" value="2"/>
<value name="ASTC_6x5" value="3"/>
<value name="ASTC_6x6" value="4"/>
<value name="ASTC_8x5" value="5"/>
<value name="ASTC_8x6" value="6"/>
<value name="ASTC_8x8" value="7"/>
<value name="ASTC_10x5" value="8"/>
<value name="ASTC_10x6" value="9"/>
<value name="ASTC_10x8" value="10"/>
<value name="ASTC_10x10" value="11"/>
<value name="ASTC_12x10" value="12"/>
<value name="ASTC_12x12" value="13"/>
<value name="PVRT2BPP" value="40"/>
<value name="PVRT4BPP" value="41"/>
<value name="PVRTII2BPP" value="42"/>
<value name="PVRTII4BPP" value="43"/>
<value name="UBC1" value="44"/>
<value name="UBC2" value="45"/>
<value name="UBC3" value="46"/>
<value name="UBC4" value="47"/>
<value name="SBC4" value="48"/>
<value name="UBC5" value="49"/>
<value name="SBC5" value="50"/>
<value name="UBC6" value="51"/>
<value name="SBC6" value="52"/>
<value name="UBC7" value="53"/>
<value name="ETC2_RGB" value="68"/>
<value name="ETC2A_RGBA" value="69"/>
<value name="ETC2_PUNCHTHROUGHA" value="70"/>
<value name="EAC_R11_UNSIGNED" value="71"/>
<value name="EAC_R11_SIGNED" value="72"/>
<value name="EAC_RG11_UNSIGNED" value="73"/>
<value name="EAC_RG11_SIGNED" value="74"/>
<value name="INVALID" value="0xFFFFFFFF"/>
</enum>
<enum name="GAMMA">
<value name="OFF" value="0"/>
<value name="ON" value="1"/>
</enum>
<enum name="SWIZ">
<value name="SRCCHAN_0" value="0"/>
<value name="SRCCHAN_1" value="1"/>
<value name="SRCCHAN_2" value="2"/>
<value name="SRCCHAN_3" value="3"/>
<value name="SRC_ONE" value="4"/>
<value name="SRC_ZERO" value="5"/>
</enum>
<enum name="TEXTYPE">
<value name="1D" value="0"/>
<value name="2D" value="1"/>
<value name="3D" value="2"/>
<value name="CUBE" value="3"/>
<value name="STRIDE" value="4"/>
<value name="PAGETILE" value="5"/>
<value name="BUFFER_LOOKUP" value="6"/>
</enum>
<enum name="TWOCOMP_GAMMA">
<value name="OFF" value="0"/>
<value name="R" value="1"/>
<value name="RG" value="3"/>
</enum>
<!-- FIXME: This is the definition for hardware with TPU_IMAGE_STATE_V2.
Add V1 definition when condition tags can be nested in enum tags.
-->
<enum name="CHROMAINTERP">
<value name="ZERO" value="0"/>
<value name="ENABLED" value="1"/>
</enum>
<struct name="IMAGE_WORD0" length="2">
<field name="smpcnt" start="62" end="63" type="uint"/>
<field name="height" start="48" end="61" type="uint"/>
<field name="width" start="34" end="47" type="uint">
<define name="MAX_SIZE" value="16383"/>
</field>
<field name="texformat" start="27" end="33" type="FORMAT">
<define name="MAX_SIZE" value="127"/>
</field>
<field name="texformat_compressed" start="27" end="33" type="FORMAT_COMPRESSED"/>
<field name="minlod" start="17" end="26" type="uint"/>
<field name="swiz0" start="14" end="16" type="SWIZ"/>
<field name="swiz1" start="11" end="13" type="SWIZ"/>
<field name="swiz2" start="8" end="10" type="SWIZ"/>
<field name="swiz3" start="5" end="7" type="SWIZ"/>
<field name="twocomp_gamma" start="3" end="4" type="TWOCOMP_GAMMA"/>
<field name="gamma" start="3" end="3" type="GAMMA"/>
<field name="textype" start="0" end="2" type="TEXTYPE"/>
</struct>
<struct name="IMAGE_WORD1" length="2">
<field name="baselevel" start="60" end="63" type="uint"/>
<field name="alpha_msb" start="59" end="59" type="bool"/>
<field name="border" start="58" end="58" type="bool"/>
<condition type="if" check="TPU_IMAGE_STATE_V2"/>
<condition type="if" check="TFBC"/>
<field name="lossy_compression_mode" start="56" end="57" type="COMPRESSION_LEVEL"/>
<condition type="endif" check="TFBC"/>
<field name="tpu_image_state_v2_compression_mode" start="54" end="56" type="COMPRESSION_MODE"/>
<condition type="else" check="TPU_IMAGE_STATE_V2"/>
<field name="tile_size" start="57" end="57" type="bool"/>
<field name="index_lookup" start="56" end="56" type="bool"/>
<field name="frame_buffer_compression" start="55" end="55" type="bool"/>
<field name="frame_buffer_compression_addressing_mode" start="54" end="54" type="bool"/>
<condition type="endif" check="TPU_IMAGE_STATE_V2"/>
<field name="texaddr" start="16" end="53" shift="2" type="address"/>
<field name="mipmaps_present" start="15" end="15" type="bool"/>
<field name="depth" start="4" end="14" type="uint">
<define name="MAX_SIZE" value="2047"/>
</field>
<field name="num_mip_levels" start="0" end="3" type="uint"/>
</struct>
<struct name="STRIDE_IMAGE_WORD1" length="2">
<field name="num_mip_levels" start="60" end="63" type="uint"/>
<field name="alpha_msb" start="59" end="59" type="bool"/>
<condition type="if" check="TPU_IMAGE_STATE_V2"/>
<condition type="if" check="TFBC"/>
<field name="lossy_compression_mode" start="56" end="57" type="COMPRESSION_LEVEL"/>
<condition type="endif" check="TFBC"/>
<field name="tpu_image_state_v2_compression_mode" start="54" end="56" type="COMPRESSION_MODE"/>
<condition type="else" check="TPU_IMAGE_STATE_V2"/>
<field name="tile_size" start="57" end="57" type="bool"/>
<field name="index_lookup" start="56" end="56" type="bool"/>
<field name="frame_buffer_compression" start="55" end="55" type="bool"/>
<field name="frame_buffer_compression_addressing_mode" start="54" end="54" type="bool"/>
<condition type="endif" check="TPU_IMAGE_STATE_V2"/>
<field name="texaddr" start="16" end="53" shift="2" type="address"/>
<field name="mipmaps_present" start="15" end="15" type="bool"/>
<field name="stride" start="0" end="14" type="uint"/>
</struct>
<struct name="YUV_IMAGE_WORD1" length="2">
<field name="csc_coeff_index" start="60" end="63" type="uint"/>
<field name="chroma_interpolation_v" start="59" end="59" type="CHROMAINTERP"/>
<field name="chroma_interpolation_u" start="53" end="53" type="CHROMAINTERP"/>
<field name="stride" start="38" end="52" type="uint"/>
<field name="texaddr" start="0" end="37" shift="2" type="address"/>
</struct>
<struct name="SAMPLER_WORD0" length="2">
<field name="texaddr_plane2_lo" start="50" end="63" shift="2" type="address"/>
<field name="cmp_mode" start="59" end="61" type="CMP_MODE"/>
<field name="addrmode_w" start="56" end="58" type="ADDRMODE"/>
<field name="bordercolor_index" start="50" end="55" type="uint">
<define name="MAX_SIZE" value="63"/>
</field>
<field name="non_normalized_coords" start="49" end="49" type="bool"/>
<field name="lumakey_alphamult" start="48" end="48" type="bool"/>
<field name="lumakey" start="47" end="47" type="bool"/>
<field name="addrmode_v" start="44" end="46" type="ADDRMODE"/>
<field name="addrmode_u" start="41" end="43" type="ADDRMODE"/>
<field name="mipfilter" start="40" end="40" type="bool"/>
<field name="minfilter" start="38" end="39" type="FILTER"/>
<field name="magfilter" start="36" end="37" type="FILTER"/>
<field name="anisoctl" start="33" end="35" type="ANISOCTL"/>
<field name="maxlod" start="23" end="32" type="CLAMP"/>
<field name="minlod" start="13" end="22" type="CLAMP"/>
<field name="dadjust" start="0" end="12" type="DADJUST"/>
</struct>
<struct name="SAMPLER_WORD1" length="2">
<field name="cemedge_dontfilter" start="63" end="63" type="bool"/>
<field name="texaddr_plane3" start="24" end="61" shift="2" type="address"/>
<field name="texaddr_plane2_hi" start="0" end="23" shift="16" type="address"/>
</struct>
</csbgen>
+258
View File
@@ -0,0 +1,258 @@
<?xml version="1.0" ?>
<!--
Copyright © 2022 Imagination Technologies Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<csbgen name="ROGUE" prefix="VDMCTRL">
<define name="GUARD_SIZE_DEFAULT" value="64"/>
<enum name="BLOCK_TYPE">
<value name="PPP_STATE_UPDATE" value="0"/>
<value name="PDS_STATE_UPDATE" value="1"/>
<value name="VDM_STATE_UPDATE" value="2"/>
<value name="INDEX_LIST" value="3"/>
<value name="STREAM_LINK" value="4"/>
<value name="STREAM_RETURN" value="5"/>
<value name="STREAM_TERMINATE" value="6"/>
<value name="CONTROL" value="7"/>
</enum>
<enum name="DM_TARGET">
<value name="VDM" value="0"/>
<value name="DDM" value="1"/>
</enum>
<enum name="FLATSHADE_CONTROL">
<value name="VERTEX_0" value="0"/>
<value name="VERTEX_1" value="1"/>
<value name="VERTEX_2" value="2"/>
</enum>
<enum name="INDEX_SIZE">
<value name="B8" value="0"/>
<value name="B16" value="1"/>
<value name="B32" value="2"/>
</enum>
<enum name="PRIMITIVE_TOPOLOGY">
<value name="POINT_LIST" value="0"/>
<value name="LINE_LIST" value="1"/>
<value name="LINE_LIST_ADJ" value="2"/>
<value name="LINE_STRIP" value="3"/>
<value name="LINE_STRIP_ADJ" value="4"/>
<value name="LINE_LOOP" value="5"/>
<value name="TRI_LIST" value="6"/>
<value name="TRI_LIST_ADJ" value="7"/>
<value name="TRI_LIST_EDGE" value="8"/>
<value name="TRI_STRIP" value="9"/>
<value name="TRI_STRIP_ADJ" value="10"/>
<value name="TRI_FAN" value="11"/>
<value name="PATCH_LIST" value="12"/>
</enum>
<enum name="SD_TYPE">
<value name="NONE" value="0"/>
<value name="PDS" value="1"/>
<value name="USC" value="2"/>
</enum>
<enum name="USC_TARGET">
<value name="ALL" value="0"/>
<value name="ANY" value="1"/>
</enum>
<enum name="UVS_SCRATCH_SIZE_SELECT">
<value name="FIVE" value="0"/>
<value name="ONE" value="1"/>
</enum>
<struct name="PPP_STATE0" length="1">
<field name="block_type" start="29" end="31" type="BLOCK_TYPE" default="PPP_STATE_UPDATE"/>
<field name="word_count" start="8" end="15" type="uint"/>
<field name="addrmsb" start="0" end="7" shift="32" type="address"/>
</struct>
<struct name="PPP_STATE1" length="1">
<field name="addrlsb" start="2" end="31" shift="2" type="address"/>
</struct>
<struct name="PDS_STATE0" length="1">
<field name="block_type" start="29" end="31" type="BLOCK_TYPE" default="PDS_STATE_UPDATE"/>
<field name="dm_target" start="28" end="28" type="DM_TARGET"/>
<field name="usc_target" start="25" end="25" type="USC_TARGET"/>
<field name="usc_common_size" start="16" end="24" type="uint">
<define name="UNIT_SIZE" value="64"/>
</field>
<field name="usc_unified_size" start="10" end="15" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="pds_temp_size" start="6" end="9" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="pds_data_size" start="0" end="5" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
</struct>
<struct name="PDS_STATE1" length="1">
<!-- This is an offset actually. Note for when we auto-generate the xmls. -->
<field name="pds_data_addr" start="4" end="31" shift="4" type="address"/>
<field name="sd_type" start="2" end="3" type="SD_TYPE"/>
<field name="sd_next_type" start="0" end="1" type="SD_TYPE"/>
</struct>
<struct name="PDS_STATE2" length="1">
<!-- This is an offset actually. Note for when we auto-generate the xmls. -->
<field name="pds_code_addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="STREAM_LINK0" length="1">
<field name="block_type" start="29" end="31" type="BLOCK_TYPE" default="STREAM_LINK"/>
<field name="with_return" start="28" end="28" type="bool"/>
<field name="compare_present" start="27" end="27" type="bool"/>
<field name="compare_mode" start="24" end="26" type="uint"/>
<field name="compare_data" start="8" end="23" type="uint"/>
<field name="link_addrmsb" start="0" end="7" shift="32" type="address"/>
</struct>
<struct name="STREAM_LINK1" length="1">
<field name="link_addrlsb" start="2" end="31" shift="2" type="address"/>
</struct>
<struct name="STREAM_RETURN" length="1">
<field name="block_type" start="29" end="31" type="BLOCK_TYPE" default="STREAM_RETURN"/>
</struct>
<struct name="STREAM_TERMINATE" length="1">
<field name="block_type" start="29" end="31" type="BLOCK_TYPE" default="STREAM_TERMINATE"/>
<field name="context" start="0" end="0" type="bool"/>
</struct>
<struct name="VDM_STATE0" length="1">
<field name="block_type" start="29" end="31" type="BLOCK_TYPE" default="VDM_STATE_UPDATE"/>
<field name="cut_index_present" start="28" end="28" type="bool"/>
<field name="vs_data_addr_present" start="27" end="27" type="bool"/>
<field name="vs_other_present" start="26" end="26" type="bool"/>
<field name="ds_present" start="24" end="24" type="bool"/>
<field name="gs_present" start="23" end="23" type="bool"/>
<field name="hs_present" start="22" end="22" type="bool"/>
<field name="cam_size" start="7" end="14" type="uint"/>
<field name="uvs_scratch_size_select" start="6" end="6" type="UVS_SCRATCH_SIZE_SELECT"/>
<field name="cut_index_enable" start="5" end="5" type="bool"/>
<field name="tess_enable" start="4" end="4" type="bool"/>
<field name="gs_enable" start="3" end="3" type="bool"/>
<field name="flatshade_control" start="1" end="2" type="FLATSHADE_CONTROL"/>
<field name="generate_primitive_id" start="0" end="0" type="bool"/>
</struct>
<struct name="VDM_STATE1" length="1">
<field name="cut_index" start="0" end="31" type="uint"/>
</struct>
<struct name="VDM_STATE2" length="1">
<field name="vs_pds_data_base_addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="VDM_STATE3" length="1">
<field name="vs_pds_code_base_addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="VDM_STATE4" length="1">
<field name="vs_output_size" start="0" end="7" type="uint">
<define name="UNIT_SIZE" value="4"/>
</field>
</struct>
<struct name="VDM_STATE5" length="1">
<field name="vs_max_instances_ext" start="31" end="31" type="bool"/>
<field name="vs_max_instances" start="25" end="29" type="uint"/>
<field name="vs_usc_common_size" start="16" end="24" type="uint">
<define name="UNIT_SIZE" value="64"/>
</field>
<field name="vs_usc_unified_size" start="10" end="15" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="vs_pds_temp_size" start="6" end="9" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
<field name="vs_pds_data_size" start="0" end="5" type="uint">
<define name="UNIT_SIZE" value="16"/>
</field>
</struct>
<struct name="INDEX_LIST0" length="1">
<field name="block_type" start="29" end="31" type="BLOCK_TYPE" default="INDEX_LIST"/>
<field name="index_addr_present" start="28" end="28" type="bool"/>
<field name="index_count_present" start="27" end="27" type="bool"/>
<field name="index_instance_count_present" start="26" end="26" type="bool"/>
<field name="index_offset_present" start="25" end="25" type="bool"/>
<field name="start_present" start="24" end="24" type="bool"/>
<field name="indirect_addr_present" start="23" end="23" type="bool"/>
<field name="split_count_present" start="22" end="22" type="bool"/>
<condition type="if" check="VDM_DEGENERATE_CULLING"/>
<field name="degen_cull_enable" start="19" end="19" type="bool"/>
<condition type="endif" check="VDM_DEGENERATE_CULLING"/>
<field name="index_size" start="17" end="18" type="INDEX_SIZE"/>
<field name="patch_count" start="12" end="16" type="uint"/>
<field name="primitive_topology" start="8" end="11" type="PRIMITIVE_TOPOLOGY"/>
<field name="index_base_addrmsb" start="0" end="7" shift="32" type="address"/>
</struct>
<struct name="INDEX_LIST1" length="1">
<field name="index_base_addrlsb" start="0" end="31" shift="0" type="address"/>
</struct>
<struct name="INDEX_LIST2" length="1">
<field name="index_count" start="0" end="31" type="uint"/>
</struct>
<struct name="INDEX_LIST3" length="1">
<field name="instance_count" start="0" end="31" type="uint"/>
</struct>
<struct name="INDEX_LIST4" length="1">
<field name="index_offset" start="0" end="31" type="uint"/>
</struct>
<struct name="INDEX_LIST5" length="1">
<field name="start_index" start="0" end="31" type="uint"/>
</struct>
<struct name="INDEX_LIST6" length="1">
<field name="start_instance" start="0" end="31" type="uint"/>
</struct>
<struct name="INDEX_LIST7" length="1">
<field name="indirect_base_addrmsb" start="0" end="7" shift="32" type="address"/>
</struct>
<struct name="INDEX_LIST8" length="1">
<field name="indirect_base_addrlsb" start="2" end="31" shift="2" type="address"/>
</struct>
<struct name="INDEX_LIST9" length="1">
<field name="split_count" start="0" end="15" type="uint"/>
</struct>
</csbgen>
+105
View File
@@ -0,0 +1,105 @@
<?xml version="1.0" ?>
<!--
Copyright © 2025 Imagination Technologies Ltd.
SPDX-License-Identifier: MIT
-->
<csbgen name="VOLCANIC" prefix="CDMCTRL">
<define name="GUARD_SIZE_DEFAULT" value="64"/>
<enum name="BLOCK_TYPE">
<value name="COMPUTE_KERNEL" value="0"/>
<value name="STREAM_LINK" value="1"/>
<value name="STREAM_TERMINATE" value="2"/>
</enum>
<enum name="USC_TARGET">
<value name="ALL" value="0"/>
<value name="ANY" value="1"/>
</enum>
<enum name="SD_TYPE">
<value name="NONE" value="0"/>
<value name="PDS" value="1"/>
<value name="USC" value="2"/>
</enum>
<struct name="KERNEL0" length="1">
<field name="block_type" start="30" end="31" type="BLOCK_TYPE" default="COMPUTE_KERNEL"/>
<field name="indirect_present" start="29" end="29" type="bool"/>
<field name="usc_unified_size" start="12" end="18" type="uint"/>
<field name="pds_temp_size" start="7" end="11" type="uint"/>
<field name="pds_data_size" start="1" end="6" type="uint"/>
<field name="usc_target" start="0" end="0" type="USC_TARGET"/>
</struct>
<struct name="KERNEL1" length="1">
<field name="data_addr" start="4" end="31" shift="4" type="address"/>
<field name="sd_type" start="2" end="3" type="SD_TYPE"/>
</struct>
<struct name="KERNEL2" length="1">
<field name="code_addr" start="4" end="31" shift="4" type="address"/>
</struct>
<struct name="KERNEL3" length="1">
<field name="workgroup_x" start="0" end="31" type="uint"/>
</struct>
<struct name="KERNEL4" length="1">
<field name="workgroup_y" start="0" end="31" type="uint"/>
</struct>
<struct name="KERNEL5" length="1">
<field name="workgroup_z" start="0" end="31" type="uint"/>
</struct>
<struct name="KERNEL6" length="1">
<field name="indirect_addrmsb" start="0" end="15" shift="32" type="address"/>
</struct>
<struct name="KERNEL7" length="1">
<field name="indirect_addrlsb" start="2" end="31" shift="2" type="address"/>
</struct>
<struct name="KERNEL8" length="1">
<field name="max_instances" start="25" end="31" type="uint"/>
</struct>
<struct name="KERNEL9" length="1">
<field name="workgroup_size_x" start="20" end="29" type="uint"/>
<field name="workgroup_size_y" start="10" end="19" type="uint"/>
<field name="workgroup_size_z" start="0" end="9" type="uint"/>
</struct>
<struct name="KERNEL10" length="1">
</struct>
<struct name="KERNEL11" length="1">
</struct>
<struct name="KERNEL12" length="1">
</struct>
<struct name="KERNEL13" length="1">
</struct>
<struct name="STREAM_LINK0" length="1">
<field name="block_type" start="30" end="31" type="BLOCK_TYPE" default="STREAM_LINK"/>
<field name="link_addrmsb" start="0" end="15" shift="32" type="address"/>
</struct>
<struct name="STREAM_LINK1" length="1">
<field name="link_addrlsb" start="2" end="31" shift="2" type="address"/>
</struct>
<struct name="STREAM_TERMINATE" length="1">
<field name="block_type" start="30" end="31" type="BLOCK_TYPE" default="STREAM_TERMINATE"/>
</struct>
</csbgen>
+139
View File
@@ -0,0 +1,139 @@
<?xml version="1.0" ?>
<!--
Copyright © 2025 Imagination Technologies Ltd.
SPDX-License-Identifier: MIT
-->
<csbgen name="VOLCANIC" prefix="IPF">
<define name="TILE_SIZE_PIXELS" value="32"/>
<define name="CONTROL_STREAM_SIZE_DWORDS" value="32"/>
<define name="ISP_VERTEX_XY_BIAS_VALUE" value="4096"/>
<enum name="COMPRESSION_FORMAT">
<value name="UNIQUE_1" value="0"/>
<value name="ORIGIN_1_DELTA_1" value="1"/>
<value name="ORIGIN_1_DELTA_2" value="2"/>
<value name="ORIGIN_1_DELTA_3" value="3"/>
<value name="ORIGIN_1_DELTA_4" value="4"/>
<value name="ORIGIN_1_DELTA_5" value="5"/>
<value name="ORIGIN_1_DELTA_6" value="6"/>
<value name="ORIGIN_1_DELTA_7" value="7"/>
<value name="RAW_BYTE" value="8"/>
<value name="UNIQUE_2" value="9"/>
<value name="ORIGIN_2_DELTA_1" value="10"/>
<value name="ORIGIN_2_DELTA_2" value="11"/>
<value name="ORIGIN_2_DELTA_3" value="12"/>
<value name="ORIGIN_2_DELTA_4" value="13"/>
<value name="ORIGIN_2_DELTA_5" value="14"/>
<value name="ORIGIN_2_DELTA_6" value="15"/>
</enum>
<enum name="CS_MASK_FMT">
<value name="INDEX" value="0"/>
<value name="BYTE" value="1"/>
<value name="BIT" value="2"/>
<value name="FULL" value="3"/>
</enum>
<enum name="CS_TYPE">
<value name="PRIM" value="0"/>
<value name="LINK" value="2"/>
<value name="TERM" value="3"/>
</enum>
<struct name="CONTROL_STREAM" length="1">
<field name="cs_type" start="30" end="31" type="CS_TYPE"/>
<field name="cs_link" start="3" end="29" shift="7" type="address"/>
</struct>
<struct name="PRIMITIVE_FORMAT" length="1">
<field name="cs_type" start="30" end="31" type="CS_TYPE"/>
<field name="cs_isp_state_size" start="26" end="28" type="uint"/>
<field name="cs_prim_total" start="19" end="25" type="uint"/>
<field name="cs_mask_fmt" start="17" end="18" type="CS_MASK_FMT"/>
<field name="cs_prim_base_pres" start="16" end="16" type="bool"/>
<field name="cs_prim_base_offset" start="0" end="15" type="uint"/>
</struct>
<struct name="PRIMITIVE_BASE" length="1">
<field name="cs_prim_base" start="0" end="31" shift="2" type="address"/>
</struct>
<struct name="COMPRESSION_SIZE_WORD" length="1">
<field name="cs_tsp_comp_format_size" start="22" end="27" type="uint"/>
<field name="cs_tsp_comp_table_size" start="12" end="21" type="uint"/>
<field name="cs_tsp_comp_vertex_size" start="0" end="11" type="uint"/>
</struct>
<struct name="ISP_COMPRESSION_WORD_0" length="1">
<field name="cf_isp_comp_fmt_z1" start="28" end="31" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_z0" start="24" end="27" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_y2" start="20" end="23" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_y1" start="16" end="19" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_y0" start="12" end="15" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_x2" start="8" end="11" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_x1" start="4" end="7" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_x0" start="0" end="3" type="COMPRESSION_FORMAT"/>
</struct>
<struct name="ISP_COMPRESSION_WORD_1" length="1">
<field name="vf_prim_msaa" start="16" end="16" type="bool"/>
<field name="vf_prim_id_pres" start="15" end="15" type="bool"/>
<field name="vf_vertex_clipped" start="14" end="14" type="bool"/>
<field name="vf_vertex_total" start="8" end="13" type="uint"/>
<field name="cf_isp_comp_fmt_z3" start="4" end="7" type="COMPRESSION_FORMAT"/>
<field name="cf_isp_comp_fmt_z2" start="0" end="3" type="COMPRESSION_FORMAT"/>
</struct>
<struct name="INDEX_DATA" length="1">
<field name="ix_edge_flag1_ab" start="30" end="30" type="bool"/>
<field name="ix_index1_0" start="24" end="29" type="uint"/>
<field name="ix_bf_flag0" start="23" end="23" type="bool"/>
<field name="ix_edge_flag0_ca" start="22" end="22" type="bool"/>
<field name="ix_index0_2" start="16" end="21" type="uint"/>
<field name="ix_edge_flag0_bc" start="14" end="14" type="bool"/>
<field name="ix_index0_1" start="8" end="13" type="uint"/>
<field name="ix_edge_flag0_ab" start="6" end="6" type="bool"/>
<field name="ix_index0_0" start="0" end="5" type="uint"/>
</struct>
<struct name="ISP_VERTEX_XY" length="1">
<field name="sign" start="23" end="23" type="bool"/>
<field name="integer" start="8" end="22" type="uint"/>
<field name="frac" start="0" end="7" type="uint"/>
</struct>
<struct name="ISP_VERTEX_WORD_0" length="1">
<field name="y0" start="24" end="31" type="uint"/>
<field name="x0" start="0" end="23" type="uint"/>
</struct>
<struct name="ISP_VERTEX_WORD_1" length="1">
<field name="z0" start="16" end="31" type="uint"/>
<field name="y0" start="0" end="15" type="uint">
<define name="SHIFT" value="8"/>
</field>
</struct>
<struct name="ISP_VERTEX_WORD_2" length="1">
<field name="x1" start="16" end="31" type="uint"/>
<field name="z0" start="0" end="15" type="uint">
<define name="SHIFT" value="16"/>
</field>
</struct>
<struct name="ISP_VERTEX_WORD_3" length="1">
<field name="y1" start="8" end="31" type="uint"/>
<field name="x1" start="0" end="7" type="uint">
<define name="SHIFT" value="16"/>
</field>
</struct>
<struct name="ISP_VERTEX_WORD_4" length="1">
<field name="z1" start="0" end="31" type="uint"/>
</struct>
</csbgen>
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" ?>
<!--
Copyright © 2025 Imagination Technologies Ltd.
SPDX-License-Identifier: MIT
-->
<csbgen name="VOLCANIC" prefix="LLS">
<define name="CDM_CONTEXT_RESUME_BUFFER_SIZE" value="72"/>
<define name="CDM_CONTEXT_RESUME_BUFFER_ALIGNMENT" value="32"/>
<define name="TA_STATE_BUFFER_SIZE" value="468"/>
<define name="TA_STATE_BUFFER_ALIGNMENT" value="32"/>
<define name="USC_SHARED_REGS_BUFFER_SIZE" value="16384"/>
<define name="USC_SHARED_REGS_BUFFER_ALIGNMENT" value="32"/>
</csbgen>
@@ -0,0 +1,22 @@
# Copyright © 2025 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
pvr_xml_files = [
'cdm.xml',
'ipf.xml',
'lls.xml',
'pbestate.xml',
'pds.xml',
'texstate.xml',
]
foreach f : pvr_xml_files
_name = '@[email protected]'.format(f.split('.')[0])
pvr_xml_pack += custom_target(
_name,
input : ['../gen_pack_header.py', f],
output : _name,
command : [prog_python, '@INPUT@'],
capture : true,
)
endforeach
@@ -0,0 +1,80 @@
<?xml version="1.0" ?>
<!--
Copyright © 2025 Imagination Technologies Ltd.
SPDX-License-Identifier: MIT
-->
<csbgen name="VOLCANIC" prefix="PBESTATE">
<enum name="PACKMODE">
<value name="U8U8U8U8" value="0x0"/>
<value name="S8S8S8S8" value="0x1"/>
<value name="A1R5G5B5" value="0x2"/>
<value name="R5G5B5A1" value="0x3"/>
<value name="A4R4G4B4" value="0x4"/>
<value name="A8R3G3B2" value="0x5"/>
<value name="U16U16U16U16" value="0x6"/>
<value name="S16S16S16S16" value="0x7"/>
<value name="F16F16F16F16" value="0x8"/>
<value name="U32U32U32U32" value="0x9"/>
<value name="S32S32S32S32" value="0xa"/>
<value name="F32F32F32F32" value="0xb"/>
<value name="A2R10B10G10" value="0xc"/>
<value name="R10B10G10A2" value="0xd"/>
<value name="A2F10F10F10" value="0xe"/>
<value name="F10F10F10A2" value="0xf"/>
<value name="U8U8U8" value="0x10"/>
<value name="S8S8S8" value="0x11"/>
<value name="R5G6B5" value="0x12"/>
<value name="R5SG5SB6" value="0x13"/>
<value name="B6G5SR5S" value="0x14"/>
<value name="U16U16U16" value="0x15"/>
<value name="S16S16S16" value="0x16"/>
<value name="F16F16F16" value="0x17"/>
<value name="U32U32U32" value="0x18"/>
<value name="S32S32S32" value="0x19"/>
<value name="F11F11F10" value="0x1a"/>
<value name="F10F11F11" value="0x1b"/>
<value name="F32F32F32" value="0x1d"/>
<value name="U8U8" value="0x1e"/>
<value name="S8S8" value="0x1f"/>
<value name="U16U16" value="0x20"/>
<value name="S16S16" value="0x21"/>
<value name="F16F16" value="0x22"/>
<value name="U32U32" value="0x23"/>
<value name="S32S32" value="0x24"/>
<value name="F32F32" value="0x25"/>
<value name="U24ST8" value="0x26"/>
<value name="ST8U24" value="0x27"/>
<value name="U8" value="0x28"/>
<value name="S8" value="0x29"/>
<value name="U16" value="0x2a"/>
<value name="S16" value="0x2b"/>
<value name="F16" value="0x2c"/>
<value name="U32" value="0x2d"/>
<value name="S32" value="0x2e"/>
<value name="F32" value="0x2f"/>
<value name="ARGBV16_XR10" value="0x30"/>
<value name="A2_XRBIAS_U10U10U10" value="0x31"/>
<value name="U10U10U10_XRBIAS_A2" value="0x32"/>
</enum>
<enum name="SOURCE_FORMAT">
<value name="F16_PER_CHANNEL" value="0"/>
<value name="8_OR_RAW_PER_CHANNEL" value="1"/>
</enum>
<enum name="SOURCE_POS">
<value name="START_BIT0" value="0"/>
<value name="START_BIT32" value="1"/>
<value name="START_BIT64" value="2"/>
<value name="START_BIT96" value="3"/>
</enum>
<struct name="STATE_WORD0" length="1">
<field name="address_low" start="0" end="31" shift="2" type="address"/>
</struct>
</csbgen>
+57
View File
@@ -0,0 +1,57 @@
<?xml version="1.0" ?>
<!--
Copyright © 2025 Imagination Technologies Ltd.
SPDX-License-Identifier: MIT
-->
<csbgen name="VOLCANIC" prefix="PDSINST">
<enum name="DOUTI_SHADEMODEL">
<value name="FLAT_VERTEX0" value="0"/>
<value name="FLAT_VERTEX1" value="1"/>
<value name="FLAT_VERTEX2" value="2"/>
<value name="GOURUAD" value="3"/>
</enum>
<enum name="DOUTI_SIZE">
<value name="1D" value="0"/>
<value name="2D" value="1"/>
<value name="3D" value="2"/>
<value name="4D" value="3"/>
</enum>
<enum name="DOUTU_SAMPLE_RATE">
<value name="INSTANCE" value="0"/>
<value name="SELECTIVE" value="1"/>
<value name="FULL" value="2"/>
</enum>
<struct name="DOUT_FIELDS_DOUTD_SRC0" length="1">
<field name="doffset" start="48" end="60" type="uint"/>
<field name="sbase" start="0" end="47" shift="0" type="address"/>
</struct>
<struct name="DOUT_FIELDS_DOUTD_SRC1" length="1">
<field name="last" start="31" end="31" type="bool"/>
<field name="dest" start="28" end="30" type="uint"/>
<field name="bsize" start="0" end="11" type="uint"/>
</struct>
<struct name="DOUT_FIELDS_DOUTI_SRC" length="1">
<field name="depthbias" start="27" end="27" type="bool"/>
<field name="primitiveid" start="26" end="26" type="bool"/>
<field name="shademodel" start="24" end="25" type="DOUTI_SHADEMODEL"/>
<field name="pointsprite" start="23" end="23" type="bool"/>
<field name="wraps" start="22" end="22" type="bool"/>
<field name="wrapv" start="21" end="21" type="bool"/>
<field name="wrapu" start="20" end="20" type="bool"/>
<field name="size" start="18" end="19" type="DOUTI_SIZE"/>
<field name="f16" start="17" end="17" type="bool"/>
<field name="perspective" start="16" end="16" type="bool"/>
<field name="f32_offset" start="8" end="15" type="uint"/>
<field name="f16_offset" start="0" end="7" type="uint"/>
</struct>
</csbgen>
@@ -0,0 +1,260 @@
<?xml version="1.0" ?>
<!--
Copyright © 2025 Imagination Technologies Ltd.
SPDX-License-Identifier: MIT
-->
<csbgen name="VOLCANIC" prefix="TEXSTATE">
<enum name="ADDRMODE">
<value name="REPEAT" value="0"/>
<value name="FLIP" value="1"/>
<value name="CLAMP_TO_EDGE" value="2"/>
<value name="FLIP_ONCE_THEN_CLAMP" value="3"/>
<value name="CLAMP_TO_BORDER" value="4"/>
<value name="OGL_CLAMP" value="5"/>
</enum>
<enum name="ANISOCTL">
<value name="DISABLED" value="0"/>
<value name="X2" value="1"/>
<value name="X4" value="2"/>
<value name="X8" value="3"/>
<value name="X16" value="4"/>
</enum>
<enum name="CLAMP">
<value name="INTEGER_BITS" value="4"/>
<value name="FRACTIONAL_BITS" value="8"/>
</enum>
<enum name="CMP_MODE">
<value name="NEVER" value="0"/>
<value name="LESS" value="1"/>
<value name="EQUAL" value="2"/>
<value name="LESSEQUAL" value="3"/>
<value name="GREATER" value="4"/>
<value name="NOTEQUAL" value="5"/>
<value name="GREATEREQUAL" value="6"/>
<value name="ALWAYS" value="7"/>
</enum>
<enum name="DADJUST">
<value name="MIN_UINT" value="0"/>
<value name="ZERO_UINT" value="4095"/>
<value name="MAX_UINT" value="8191"/>
<value name="INTEGER_BITS" value="5"/>
<value name="FRACTIONAL_BITS" value="8"/>
</enum>
<enum name="FILTER">
<value name="POINT" value="0"/>
<value name="LINEAR" value="1"/>
<value name="BICUBIC" value="2"/>
</enum>
<enum name="FORMAT">
<value name="U8" value="0"/>
<value name="S8" value="1"/>
<value name="A4R4G4B4" value="2"/>
<value name="A8R3G3B2" value="3"/>
<value name="A1R5G5B5" value="4"/>
<value name="R5G6B5" value="5"/>
<value name="R5sG5sB6" value="6"/>
<value name="U8U8" value="7"/>
<value name="S8S8" value="8"/>
<value name="U16" value="9"/>
<value name="S16" value="10"/>
<value name="F16" value="11"/>
<value name="U8U8U8U8" value="12"/>
<value name="S8S8S8S8" value="13"/>
<value name="A2R10B10G10" value="14"/>
<value name="U16U16" value="15"/>
<value name="S16S16" value="16"/>
<value name="F16F16" value="17"/>
<value name="F32" value="18"/>
<!-- 19 -->
<value name="X8U8S8S8" value="20"/>
<value name="X8U24" value="21"/>
<value name="ST8U24" value="22"/>
<value name="U8X24" value="23"/>
<value name="U32" value="24"/>
<value name="S32" value="25"/>
<value name="SE9995" value="26"/>
<value name="F11F11F10" value="27"/>
<value name="F16F16F16F16" value="28"/>
<value name="U16U16U16U16" value="29"/>
<value name="S16S16S16S16" value="30"/>
<value name="F16F16F16" value="31"/>
<value name="U16U16U16" value="32"/>
<value name="S16S16S16" value="33"/>
<value name="F32F32" value="34"/>
<value name="U32U32" value="35"/>
<value name="S32S32" value="36"/>
<value name="X24U8F32" value="37"/>
<value name="X24X8F32" value="38"/>
<value name="X24G8X32" value="39"/>
<value name="YUV420_2PLANE" value="40"/>
<value name="YVU420_2PLANE" value="41"/>
<value name="YUV420_3PLANE" value="42"/>
<value name="YVU420_3PLANE" value="43"/>
<value name="U8U8U8" value="44"/>
<value name="S8S8S8" value="45"/>
<value name="A2F10F10F10" value="46"/>
<value name="F32F32F32F32" value="47"/>
<value name="U32U32U32U32" value="48"/>
<value name="S32S32S32S32" value="49"/>
<value name="F32F32F32" value="50"/>
<value name="U32U32U32" value="51"/>
<value name="S32S32S32" value="52"/>
<value name="R5G5B5A1" value="53"/>
<value name="B6G5sR5s" value="54"/>
<value name="R10B10G10A2" value="55"/>
<value name="X8S8S8U8" value="56"/>
<value name="U24ST8" value="57"/>
<value name="F10F11F11" value="58"/>
<value name="VYUY" value="59"/>
<value name="UYVY" value="60"/>
<value name="YVYU" value="61"/>
<value name="YUYV" value="62"/>
<value name="F10F10F10A2" value="63"/>
<value name="YUV420_2PLANE_MACRO_BLOCK" value="64"/>
<value name="YVU420_2PLANE_MACRO_BLOCK" value="65"/>
<value name="YVU8_422_2PLANE_PACK8" value="66"/>
<value name="YVU8_444_2PLANE_PACK8" value="67"/>
<value name="YVU10_444_1PLANE_PACK10" value="68"/>
<value name="YVU10_422_2PLANE_PACK16" value="69"/>
<value name="YVU10_420_2PLANE_PACK16" value="70"/>
<value name="YVU10_444_2PLANE_PACK16" value="71"/>
<value name="YUV8_422_2PLANE_PACK8" value="72"/>
<value name="YUV8_444_3PLANE_PACK8" value="73"/>
<value name="YUV10_444_3PLANE_PACK16" value="74"/>
<value name="YVU10_420_2PLANE_PACK10" value="75"/>
<value name="YUV10_420_2PLANE_PACK10" value="76"/>
<value name="YVU10_422_2PLANE_PACK10" value="77"/>
<value name="YUV10_422_2PLANE_PACK10" value="78"/>
<value name="YUV10_444_3PLANE_PACK10" value="79"/>
<value name="R8G8_B8G8" value="80"/>
<value name="G8R8_G8B8" value="81"/>
<value name="YVYU_IMPLIED_CSC" value="82"/>
<value name="VYUY_IMPLIED_CSC" value="83"/>
<!-- 84..85 -->
<value name="YUV10_420_2PLANE_PACK10_T" value="86"/>
<value name="YVU10_420_2PLANE_PACK10_T" value="87"/>
<value name="YUV8_420_2PLANE_PACK8_P" value="88"/>
<value name="YVU8_420_2PLANE_PACK8_P" value="89"/>
<value name="YUV8_420_2PLANE_PACK8_F" value="90"/>
<value name="YVU8_420_2PLANE_PACK8_F" value="91"/>
<!-- 92..93 -->
<value name="ASTC_4x4" value="94"/>
<value name="ASTC_5x4" value="95"/>
<value name="ASTC_5x5" value="96"/>
<value name="ASTC_6x5" value="97"/>
<value name="ASTC_6x6" value="98"/>
<value name="ASTC_8x5" value="99"/>
<value name="ASTC_8x6" value="100"/>
<value name="ASTC_8x8" value="101"/>
<value name="ASTC_10x5" value="102"/>
<value name="ASTC_10x6" value="103"/>
<value name="ASTC_10x8" value="104"/>
<value name="ASTC_10x10" value="105"/>
<value name="ASTC_12x10" value="106"/>
<value name="ASTC_12x12" value="107"/>
<value name="UBC1" value="108"/>
<value name="UBC2" value="109"/>
<value name="UBC3" value="110"/>
<value name="UBC4" value="111"/>
<value name="SBC4" value="112"/>
<value name="UBC5" value="113"/>
<value name="SBC5" value="114"/>
<value name="UBC6" value="115"/>
<value name="SBC6" value="116"/>
<value name="UBC7" value="117"/>
<value name="ETC2_RGB" value="118"/>
<value name="ETC2A_RGBA" value="119"/>
<value name="ETC2_PUNCHTHROUGHA" value="120"/>
<value name="EAC_R11_UNSIGNED" value="121"/>
<value name="EAC_R11_SIGNED" value="122"/>
<value name="EAC_RG11_UNSIGNED" value="123"/>
<value name="EAC_RG11_SIGNED" value="124"/>
<!-- 125..138 -->
</enum>
<enum name="SWIZ">
<value name="SRCCHAN_0" value="0"/>
<value name="SRCCHAN_1" value="1"/>
<value name="SRCCHAN_2" value="2"/>
<value name="SRCCHAN_3" value="3"/>
<value name="SRC_ONE" value="4"/>
<value name="SRC_ZERO" value="5"/>
</enum>
<enum name="TEXTYPE">
<value name="1D" value="0"/>
<value name="2D" value="1"/>
<value name="3D" value="2"/>
<value name="CUBE" value="3"/>
<value name="STRIDE" value="4"/>
<value name="BUFFER_LOOKUP" value="5"/>
</enum>
<enum name="TWOCOMP_GAMMA">
<value name="OFF" value="0"/>
<value name="R" value="1"/>
<value name="RG" value="3"/>
</enum>
<struct name="IMAGE_WORD0" length="2">
<field name="height" start="49" end="62" type="uint"/>
<field name="width" start="35" end="48" type="uint"/>
<field name="texformat" start="15" end="22" type="FORMAT"/>
<field name="minlod" start="23" end="34" type="uint"/>
<field name="swiz0" start="12" end="14" type="SWIZ"/>
<field name="swiz1" start="9" end="11" type="SWIZ"/>
<field name="swiz2" start="6" end="8" type="SWIZ"/>
<field name="swiz3" start="3" end="5" type="SWIZ"/>
<field name="textype" start="0" end="2" type="TEXTYPE"/>
</struct>
<struct name="IMAGE_WORD1" length="2">
<field name="alpha_msb" start="62" end="62" type="bool"/>
<field name="mipmaps_present" start="61" end="61" type="bool"/>
<field name="depth" start="48" end="58" type="uint"/>
<field name="border" start="46" end="46" type="bool"/>
<field name="texaddr" start="0" end="45" shift="2" type="address"/>
</struct>
<struct name="IMAGE_WORD2" length="2">
<field name="num_mip_levels" start="10" end="13" type="uint"/>
<field name="twocomp_gamma" start="4" end="5" type="TWOCOMP_GAMMA"/>
<field name="baselevel" start="0" end="3" type="uint"/>
</struct>
<struct name="STRIDE_IMAGE_WORD1" length="2">
<field name="alpha_msb" start="62" end="62" type="bool"/>
<field name="mipmaps_present" start="61" end="61" type="bool"/>
<field name="stride" start="46" end="60" type="uint"/>
<field name="texaddr" start="0" end="45" shift="2" type="address"/>
</struct>
<struct name="SAMPLER_WORD0" length="2">
<field name="cemedge_dontfilter" start="63" end="63" type="bool"/>
<field name="cmp_mode" start="57" end="59" type="CMP_MODE"/>
<field name="non_normalized_coords" start="56" end="56" type="bool"/>
<field name="lumakey_alphamult" start="55" end="55" type="bool"/>
<field name="lumakey" start="54" end="54" type="bool"/>
<field name="addrmode_w" start="51" end="53" type="ADDRMODE"/>
<field name="addrmode_v" start="48" end="50" type="ADDRMODE"/>
<field name="addrmode_u" start="45" end="47" type="ADDRMODE"/>
<field name="mipfilter" start="44" end="44" type="bool"/>
<field name="minfilter" start="42" end="43" type="FILTER"/>
<field name="magfilter" start="40" end="41" type="FILTER"/>
<field name="anisoctl" start="37" end="39" type="ANISOCTL"/>
<field name="maxlod" start="25" end="36" type="CLAMP"/>
<field name="minlod" start="13" end="24" type="CLAMP"/>
<field name="dadjust" start="0" end="12" type="DADJUST"/>
</struct>
</csbgen>
+13
View File
@@ -0,0 +1,13 @@
# Copyright © 2026 Imagination Technologies Ltd.
# Copyright 2019 Broadcom
# SPDX-License-Identifier: MIT
libpowervr_noop_drm_shim = shared_library(
'powervr_noop_drm_shim',
'pvr_noop.c',
link_with : [libpowervr_common],
include_directories: [inc_imagination, inc_include, inc_src],
dependencies: [dep_drm_shim, dep_valgrind, dep_csbgen],
gnu_symbol_visibility : 'hidden',
install : true,
)
+567
View File
@@ -0,0 +1,567 @@
/*
* Copyright © 2026 Imagination Technologies Ltd.
* Copyright 2018 Broadcom
* SPDX-License-Identifier: MIT
*/
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "common/pvr_device_info.h"
#include "drm-shim/drm_shim.h"
#include "drm-uapi/pvr_drm.h"
#include "hwdef/rogue_hw_utils.h"
#include "util/macros.h"
#include "util/u_debug.h"
bool drm_shim_driver_prefers_first_render_node = true;
#define DEFAULT_DEVICE_BVNC PVR_BVNC_PACK(36, 53, 104, 796)
static struct pvr_device_info device_info;
static bool musthave_quirks = false;
static unsigned num_quirks = 0;
static uint32_t *quirks = NULL;
static unsigned num_enhancements = 0;
static uint32_t *enhancements = NULL;
static int
pvr_ioctl_noop(UNUSED int fd, UNUSED unsigned long request, UNUSED void *arg)
{
return 0;
}
static inline uint32_t
rogue_num_phantoms(const struct pvr_device_info *dev_info)
{
return DIV_ROUND_UP(PVR_GET_FEATURE_VALUE(&device_info, num_clusters, 1U),
4U);
}
static inline uint32_t
rogue_common_store_partition_space_size(const struct pvr_device_info *dev_info)
{
const uint32_t max_partitions =
PVR_GET_FEATURE_VALUE(dev_info, max_partitions, 0U);
const uint32_t tile_size_x =
PVR_GET_FEATURE_VALUE(dev_info, tile_size_x, 0U);
const uint32_t tile_size_y =
PVR_GET_FEATURE_VALUE(dev_info, tile_size_y, 0U);
if (tile_size_x == 16U && tile_size_y == 16U) {
uint32_t usc_min_output_registers_per_pix =
PVR_GET_FEATURE_VALUE(dev_info, usc_min_output_registers_per_pix, 0U);
return tile_size_x * tile_size_y * max_partitions *
usc_min_output_registers_per_pix;
}
return max_partitions * 1024U;
}
static inline uint32_t
rogue_common_store_alloc_region_size(const struct pvr_device_info *dev_info)
{
uint32_t alloc_region_size;
const uint32_t common_store_size_in_dwords =
PVR_GET_FEATURE_VALUE(dev_info,
common_store_size_in_dwords,
512U * 4U * 4U);
alloc_region_size = common_store_size_in_dwords - (256U * 4U) -
rogue_common_store_partition_space_size(dev_info);
if (PVR_HAS_QUIRK(dev_info, 44079)) {
uint32_t common_store_split_point = (768U * 4U * 4U);
return MIN2(common_store_split_point - (256U * 4U), alloc_region_size);
}
return alloc_region_size;
}
static inline uint32_t rogue_max_coeffs(const struct pvr_device_info *dev_info)
{
uint32_t max_coeff_additional_portion = ROGUE_MAX_VERTEX_SHARED_REGISTERS;
uint32_t pending_allocation_shared_regs = 2U * 1024U;
uint32_t pending_allocation_coeff_regs = 0U;
uint32_t num_phantoms = rogue_num_phantoms(dev_info);
uint32_t tiles_in_flight =
PVR_GET_FEATURE_VALUE(dev_info, isp_max_tiles_in_flight, 0U);
uint32_t max_coeff_pixel_portion =
DIV_ROUND_UP(tiles_in_flight, num_phantoms);
max_coeff_pixel_portion *= ROGUE_MAX_PIXEL_SHARED_REGISTERS;
/*
* Compute tasks on cores with BRN48492 and without compute overlap may lock
* up without two additional lines of coeffs.
*/
if (PVR_HAS_QUIRK(dev_info, 48492) &&
!PVR_HAS_FEATURE(dev_info, compute_overlap))
pending_allocation_coeff_regs = 2U * 1024U;
if (PVR_HAS_ENHANCEMENT(dev_info, 38748))
pending_allocation_shared_regs = 0;
if (PVR_HAS_ENHANCEMENT(dev_info, 38020))
max_coeff_additional_portion += ROGUE_MAX_COMPUTE_SHARED_REGISTERS;
return rogue_common_store_alloc_region_size(dev_info) +
pending_allocation_coeff_regs -
(max_coeff_pixel_portion + max_coeff_additional_portion +
pending_allocation_shared_regs);
}
static inline uint32_t
rogue_cdm_max_local_mem_size_regs(const struct pvr_device_info *dev_info)
{
uint32_t available_coeffs_in_dwords = rogue_max_coeffs(dev_info);
if (PVR_HAS_QUIRK(dev_info, 48492) && PVR_HAS_FEATURE(dev_info, roguexe) &&
!PVR_HAS_FEATURE(dev_info, compute_overlap)) {
/* Driver must not use the 2 reserved lines. */
available_coeffs_in_dwords -= ROGUE_CSRM_LINE_SIZE_IN_DWORDS * 2U;
}
/*
* The maximum amount of local memory available to a kernel is the minimum
* of the total number of coefficient registers available and the max common
* store allocation size which can be made by the CDM.
*
* If any coeff lines are reserved for tessellation or pixel then we need to
* subtract those too.
*/
return MIN2(available_coeffs_in_dwords,
ROGUE_MAX_PER_KERNEL_LOCAL_MEM_SIZE_REGS);
}
static int pvr_dev_query_gpu_info_get(struct drm_pvr_ioctl_dev_query_args *args)
{
struct drm_pvr_dev_query_gpu_info *gpu_info =
(struct drm_pvr_dev_query_gpu_info *)args->pointer;
if (!gpu_info)
goto dev_query_gpu_info_set_size;
gpu_info->gpu_id = pvr_get_packed_bvnc(&device_info);
gpu_info->num_phantoms = rogue_num_phantoms(&device_info);
dev_query_gpu_info_set_size:
args->size = sizeof(*gpu_info);
return 0;
}
static int
pvr_dev_query_runtime_info_get(struct drm_pvr_ioctl_dev_query_args *args)
{
struct drm_pvr_dev_query_runtime_info *runtime_info =
(struct drm_pvr_dev_query_runtime_info *)args->pointer;
if (!runtime_info)
goto dev_query_runtime_info_set_size;
if (PVR_HAS_FEATURE(&device_info, roguexe)) {
if (PVR_HAS_QUIRK(&device_info, 66011))
runtime_info->free_list_min_pages = 40;
else
runtime_info->free_list_min_pages = 25;
} else {
runtime_info->free_list_min_pages = 50;
}
runtime_info->free_list_max_pages = 0x80000;
runtime_info->common_store_alloc_region_size =
rogue_common_store_alloc_region_size(&device_info);
runtime_info->common_store_partition_space_size =
rogue_common_store_partition_space_size(&device_info);
runtime_info->max_coeffs = rogue_max_coeffs(&device_info);
runtime_info->cdm_max_local_mem_size_regs =
rogue_cdm_max_local_mem_size_regs(&device_info);
dev_query_runtime_info_set_size:
args->size = sizeof(*runtime_info);
return 0;
}
static int pvr_dev_query_quirks_get(struct drm_pvr_ioctl_dev_query_args *args)
{
struct drm_pvr_dev_query_quirks *query_quirks =
(struct drm_pvr_dev_query_quirks *)args->pointer;
if (!query_quirks)
goto dev_query_quirks_set_size;
if (!query_quirks->quirks) {
query_quirks->count = num_quirks;
query_quirks->musthave_count = musthave_quirks ? num_quirks : 0;
goto dev_query_quirks_set_size;
}
if (query_quirks->count > num_quirks)
query_quirks->count = num_quirks;
memcpy((void *)query_quirks->quirks,
quirks,
sizeof(*quirks) * query_quirks->count);
dev_query_quirks_set_size:
args->size = sizeof(*query_quirks);
return 0;
}
static int
pvr_dev_query_enhancements_get(struct drm_pvr_ioctl_dev_query_args *args)
{
struct drm_pvr_dev_query_enhancements *query_enhancements =
(struct drm_pvr_dev_query_enhancements *)args->pointer;
if (!query_enhancements)
goto dev_query_enhancements_set_size;
if (!query_enhancements->enhancements) {
query_enhancements->count = num_enhancements;
goto dev_query_enhancements_set_size;
}
if (query_enhancements->count > num_enhancements)
query_enhancements->count = num_enhancements;
memcpy((void *)query_enhancements->enhancements,
enhancements,
sizeof(*enhancements) * query_enhancements->count);
dev_query_enhancements_set_size:
args->size = sizeof(*query_enhancements);
return 0;
}
static const struct drm_pvr_heap pvr_heaps[DRM_PVR_HEAP_COUNT] = {
[DRM_PVR_HEAP_GENERAL] = {
.base = UINT64_C(0x8000000000),
.size = UINT64_C(0x2000000000),
.flags = 0,
.page_size_log2 = 12,
},
[DRM_PVR_HEAP_PDS_CODE_DATA] = {
.base = UINT64_C(0xda00000000),
.size = UINT64_C(0x100000000),
.flags = 0,
.page_size_log2 = 12,
},
[DRM_PVR_HEAP_USC_CODE] = {
.base = UINT64_C(0xe000000000),
.size = UINT64_C(0x100000000),
.flags = 0,
.page_size_log2 = 12,
},
[DRM_PVR_HEAP_RGNHDR] = {
.base = UINT64_C(0xdbf0000000),
.size = 0x10000000,
.flags = 0,
.page_size_log2 = 12,
},
[DRM_PVR_HEAP_VIS_TEST] = {
.base = UINT64_C(0xf200000000),
.size = 0x00200000,
.flags = 0,
.page_size_log2 = 12,
},
[DRM_PVR_HEAP_TRANSFER_FRAG] = {
.base = UINT64_C(0xe400000000),
.size = UINT64_C(0x400000000),
.flags = 0,
.page_size_log2 = 12,
},
};
static int
pvr_dev_query_heap_info_get(struct drm_pvr_ioctl_dev_query_args *args)
{
struct drm_pvr_dev_query_heap_info *heap_info =
(struct drm_pvr_dev_query_heap_info *)args->pointer;
if (!heap_info)
goto dev_query_heap_info_set_size;
if (!heap_info->heaps.array) {
heap_info->heaps.count = ARRAY_SIZE(pvr_heaps);
heap_info->heaps.stride = sizeof(struct drm_pvr_heap);
goto dev_query_heap_info_set_size;
}
if (heap_info->heaps.count > ARRAY_SIZE(pvr_heaps))
heap_info->heaps.count = ARRAY_SIZE(pvr_heaps);
memcpy((void *)heap_info->heaps.array,
pvr_heaps,
heap_info->heaps.stride * heap_info->heaps.count);
dev_query_heap_info_set_size:
args->size = sizeof(*heap_info);
return 0;
}
static const struct drm_pvr_static_data_area pvr_static_data_areas[] = {
{
.area_usage = DRM_PVR_STATIC_DATA_AREA_FENCE,
.location_heap_id = DRM_PVR_HEAP_GENERAL,
.offset = 0,
.size = 128,
},
{
.area_usage = DRM_PVR_STATIC_DATA_AREA_YUV_CSC,
.location_heap_id = DRM_PVR_HEAP_GENERAL,
.offset = 128,
.size = 1024,
},
{
.area_usage = DRM_PVR_STATIC_DATA_AREA_VDM_SYNC,
.location_heap_id = DRM_PVR_HEAP_PDS_CODE_DATA,
.offset = 0,
.size = 128,
},
{
.area_usage = DRM_PVR_STATIC_DATA_AREA_EOT,
.location_heap_id = DRM_PVR_HEAP_PDS_CODE_DATA,
.offset = 128,
.size = 128,
},
{
.area_usage = DRM_PVR_STATIC_DATA_AREA_VDM_SYNC,
.location_heap_id = DRM_PVR_HEAP_USC_CODE,
.offset = 0,
.size = 128,
},
};
static int
pvr_dev_query_static_data_areas_get(struct drm_pvr_ioctl_dev_query_args *args)
{
struct drm_pvr_dev_query_static_data_areas *static_data_areas =
(struct drm_pvr_dev_query_static_data_areas *)args->pointer;
if (!static_data_areas)
goto dev_query_static_data_areas_set_size;
if (!static_data_areas->static_data_areas.array) {
static_data_areas->static_data_areas.count =
ARRAY_SIZE(pvr_static_data_areas);
static_data_areas->static_data_areas.stride =
sizeof(struct drm_pvr_static_data_area);
goto dev_query_static_data_areas_set_size;
}
if (static_data_areas->static_data_areas.count >
ARRAY_SIZE(pvr_static_data_areas)) {
static_data_areas->static_data_areas.count =
ARRAY_SIZE(pvr_static_data_areas);
}
memcpy((void *)static_data_areas->static_data_areas.array,
pvr_static_data_areas,
static_data_areas->static_data_areas.stride *
static_data_areas->static_data_areas.count);
dev_query_static_data_areas_set_size:
args->size = sizeof(*static_data_areas);
return 0;
}
static int
pvr_ioctl_dev_query(UNUSED int fd, UNUSED unsigned long request, void *arg)
{
struct drm_pvr_ioctl_dev_query_args *args = arg;
switch ((enum drm_pvr_dev_query)args->type) {
case DRM_PVR_DEV_QUERY_GPU_INFO_GET:
return pvr_dev_query_gpu_info_get(args);
case DRM_PVR_DEV_QUERY_RUNTIME_INFO_GET:
return pvr_dev_query_runtime_info_get(args);
case DRM_PVR_DEV_QUERY_QUIRKS_GET:
return pvr_dev_query_quirks_get(args);
case DRM_PVR_DEV_QUERY_ENHANCEMENTS_GET:
return pvr_dev_query_enhancements_get(args);
case DRM_PVR_DEV_QUERY_HEAP_INFO_GET:
return pvr_dev_query_heap_info_get(args);
case DRM_PVR_DEV_QUERY_STATIC_DATA_AREAS_GET:
return pvr_dev_query_static_data_areas_get(args);
default:
break;
}
return -EINVAL;
}
static int pvr_ioctl_create_bo(int fd, UNUSED unsigned long request, void *arg)
{
struct drm_pvr_ioctl_create_bo_args *args = arg;
struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
struct shim_bo *bo = calloc(1, sizeof(*bo));
drm_shim_bo_init(bo, args->size);
args->handle = drm_shim_bo_get_handle(shim_fd, bo);
drm_shim_bo_put(bo);
return 0;
}
static int
pvr_ioctl_get_bo_mmap_offset(int fd, UNUSED unsigned long request, void *arg)
{
struct drm_pvr_ioctl_get_bo_mmap_offset_args *args = arg;
struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
struct shim_bo *bo = drm_shim_bo_lookup(shim_fd, args->handle);
args->offset = drm_shim_bo_get_mmap_offset(shim_fd, bo);
return 0;
}
#define PVR_IOC_NR(_name) (_IOC_NR(DRM_IOCTL_PVR_##_name) - DRM_COMMAND_BASE)
static ioctl_fn_t driver_ioctls[] = {
[PVR_IOC_NR(DEV_QUERY)] = pvr_ioctl_dev_query,
[PVR_IOC_NR(CREATE_BO)] = pvr_ioctl_create_bo,
[PVR_IOC_NR(GET_BO_MMAP_OFFSET)] = pvr_ioctl_get_bo_mmap_offset,
[PVR_IOC_NR(CREATE_VM_CONTEXT)] = pvr_ioctl_noop,
[PVR_IOC_NR(DESTROY_VM_CONTEXT)] = pvr_ioctl_noop,
[PVR_IOC_NR(VM_MAP)] = pvr_ioctl_noop,
[PVR_IOC_NR(VM_UNMAP)] = pvr_ioctl_noop,
[PVR_IOC_NR(CREATE_CONTEXT)] = pvr_ioctl_noop,
[PVR_IOC_NR(DESTROY_CONTEXT)] = pvr_ioctl_noop,
[PVR_IOC_NR(CREATE_FREE_LIST)] = pvr_ioctl_noop,
[PVR_IOC_NR(DESTROY_FREE_LIST)] = pvr_ioctl_noop,
[PVR_IOC_NR(CREATE_HWRT_DATASET)] = pvr_ioctl_noop,
[PVR_IOC_NR(DESTROY_HWRT_DATASET)] = pvr_ioctl_noop,
[PVR_IOC_NR(SUBMIT_JOBS)] = pvr_ioctl_noop,
};
static unsigned count_elems(const char *str, const char *delims)
{
if (!str || !strlen(str))
return 0;
unsigned count = 1;
for (unsigned u = 0; u < strlen(str); ++u) {
for (unsigned d = 0; d < strlen(delims); ++d) {
if (str[u] == delims[d]) {
++count;
break;
}
}
}
return count;
}
static void u32_str_list_to_array(const char *str_list,
const char *delims,
unsigned num_elems,
uint32_t *array)
{
for (unsigned u = 0; u < num_elems; ++u) {
array[u] = strtol(str_list, NULL, 10);
str_list += strcspn(str_list, delims) + 1;
}
}
static void init_overrides(void)
{
const char *device_bvnc = debug_get_option("PVR_SHIM_DEVICE_BVNC", NULL);
static const char *delims = ",;";
unsigned b, v, n, c;
uint64_t bvnc = DEFAULT_DEVICE_BVNC;
int ret;
if (device_bvnc) {
ret = sscanf(device_bvnc, "%u.%u.%u.%u", &b, &v, &n, &c);
if (ret != 4) {
fprintf(stderr,
"pvr-drm-shim: Warning: Invalid device BVNC format \"%s\"; "
"reverting to default device BVNC.\n",
device_bvnc);
bvnc = DEFAULT_DEVICE_BVNC;
} else {
bvnc = PVR_BVNC_PACK(b, v, n, c);
}
}
ret = pvr_device_info_init(&device_info, bvnc);
if (ret) {
fprintf(stderr,
"pvr-drm-shim: Warning: Device BVNC provided \"%s\" not found; "
"reverting to default device BVNC.\n",
device_bvnc);
ret = pvr_device_info_init(&device_info, DEFAULT_DEVICE_BVNC);
assert(!ret);
}
musthave_quirks = debug_get_bool_option("PVR_SHIM_MUSTHAVE_QUIRKS", false);
const char *quirk_list = debug_get_option("PVR_SHIM_QUIRKS", NULL);
if (quirk_list) {
num_quirks = count_elems(quirk_list, delims);
quirks = malloc(num_quirks * sizeof(*quirks));
u32_str_list_to_array(quirk_list, delims, num_quirks, quirks);
}
const char *enhancement_list =
debug_get_option("PVR_SHIM_ENHANCEMENTS", NULL);
if (enhancement_list) {
num_enhancements = count_elems(enhancement_list, delims);
enhancements = malloc(num_enhancements * sizeof(*enhancements));
u32_str_list_to_array(enhancement_list,
delims,
num_enhancements,
enhancements);
}
}
static void drm_shim_driver_fini(void)
{
free(enhancements);
free(quirks);
}
void drm_shim_driver_init(void)
{
init_overrides();
shim_device.bus_type = DRM_BUS_PLATFORM;
shim_device.driver_name = "powervr";
shim_device.driver_ioctls = driver_ioctls;
shim_device.driver_ioctl_count = ARRAY_SIZE(driver_ioctls);
shim_device.version_major = 1;
shim_device.version_minor = 0;
shim_device.version_patchlevel = 0;
drm_shim_override_file("DRIVER=powervr\n"
"OF_FULLNAME=/soc/pvr\n"
"OF_COMPATIBLE_0=img,img-rogue\n"
"OF_COMPATIBLE_N=1\n",
"/sys/dev/char/%d:%d/device/uevent",
DRM_MAJOR,
render_node_minor);
atexit(drm_shim_driver_fini);
}
@@ -0,0 +1,47 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef PVR_HW_UTILS_H
#define PVR_HW_UTILS_H
#include <stdint.h>
#include <assert.h>
#include "util/macros.h"
#include "pvr_device_info.h"
static inline uint32_t
pvr_get_slc_cache_line_size(const struct pvr_device_info *dev_info)
{
return PVR_GET_FEATURE_VALUE(dev_info, slc_cache_line_size_bits, 8U) / 8U;
}
static inline uint32_t pvr_get_max_user_vertex_output_components(
const struct pvr_device_info *dev_info)
{
/* Default value based on the minimum value found in all existing cores. */
const uint32_t uvs_pba_entries =
PVR_GET_FEATURE_VALUE(dev_info, uvs_pba_entries, 160U);
/* Default value based on the minimum value found in all existing cores. */
const uint32_t uvs_banks = PVR_GET_FEATURE_VALUE(dev_info, uvs_banks, 2U);
if (uvs_banks <= 8U && uvs_pba_entries == 160U) {
ASSERTED const uint32_t tpu_parallel_instances =
PVR_GET_FEATURE_VALUE(dev_info, tpu_parallel_instances, 1U);
/* Cores with > 2 ppc support vertex sizes of >= 128 dwords */
assert(tpu_parallel_instances <= 2 ||
(dev_info->ident.b <= 36 || dev_info->ident.b == 46));
return 64U;
}
return 128U;
}
#endif /* PVR_HW_UTILS_H */
@@ -0,0 +1,207 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* This file is based on rgxdefs.h and should only contain object-like macros.
* Any function-like macros or inline functions should instead appear in
* rogue_hw_utils.h.
*/
#ifndef ROGUE_HW_DEFS_H
#define ROGUE_HW_DEFS_H
#include <stdint.h>
#include "util/macros.h"
#define ROGUE_BIF_PM_PHYSICAL_PAGE_SHIFT 12U
#define ROGUE_BIF_PM_PHYSICAL_PAGE_SIZE \
BITFIELD_BIT(ROGUE_BIF_PM_PHYSICAL_PAGE_SHIFT)
/* ISP triangle merging constants. */
/* tan(15) (0x3E8930A3) */
#define ROGUE_ISP_MERGE_LOWER_LIMIT_NUMERATOR 0.267949f
/* tan(60) (0x3FDDB3D7) */
#define ROGUE_ISP_MERGE_UPPER_LIMIT_NUMERATOR 1.732051f
#define ROGUE_ISP_MERGE_SCALE_FACTOR 16.0f
#define ROGUE_MAX_INSTR_BYTES 32U
#define ROGUE_ICACHE_ALIGN 8U
#define ROGUE_OQUERY_ALIGN 16U
#define ROGUE_MAX_ALU_INPUTS 6U
#define ROGUE_ALU_INPUT_GROUP_SIZE (ROGUE_MAX_ALU_INPUTS / 2)
#define ROGUE_MAX_ALU_OUTPUTS 2U
#define ROGUE_MAX_ALU_INTERNAL_SOURCES 6U
/* MList entry stride in bytes */
#define ROGUE_MLIST_ENTRY_STRIDE 4U
/* VCE & TE share virtual space and Alist. */
#define ROGUE_NUM_PM_ADDRESS_SPACES 2U
/* PM Maximum addressable limit (as determined by the size field of the
* PM_*_FSTACK registers).
*/
#define ROGUE_PM_MAX_PB_VIRT_ADDR_SPACE UINT64_C(0x400000000)
/* Vheap entry size in bytes. */
#define ROGUE_PM_VHEAP_ENTRY_SIZE 4U
#define ROGUE_RTC_SIZE_IN_BYTES 256U
#define ROGUE_NUM_VCE 1U
#define ROGUE_NUM_TEAC 1U
#define ROGUE_NUM_TE 1U
/* Tail pointer size in bytes. */
#define ROGUE_TAIL_POINTER_SIZE 8U
/* Tail pointer cache line size. */
#define ROGUE_TE_TPC_CACHE_LINE_SIZE 64U
#define ROGUE_MAX_VERTEX_SHARED_REGISTERS 1024U
#define ROGUE_MAX_PIXEL_SHARED_REGISTERS 1024U
#define ROGUE_MAX_COMPUTE_SHARED_REGISTERS (2U * 1024U)
/* Number of CR_PDS_BGRND values that need setting up. */
#define ROGUE_NUM_CR_PDS_BGRND_WORDS 3U
/* Number of PBESTATE_REG_WORD values that need setting up. */
#define ROGUE_NUM_PBESTATE_REG_WORDS 3U
/* Number of PBESTATE_REG_WORD used in transfer.
* The last word is not used.
*/
#define ROGUE_NUM_PBESTATE_REG_WORDS_FOR_TRANSFER 2U
/* Number of PBESTATE_STATE_WORD values that need setting up. */
#define ROGUE_NUM_PBESTATE_STATE_WORDS 2U
/* Number of TEXSTATE_IMAGE_WORD values that need setting up. */
#define ROGUE_NUM_TEXSTATE_IMAGE_WORDS 2U
/* Number of TEXSTATE_SAMPLER state words that need setting up. */
#define ROGUE_NUM_TEXSTATE_SAMPLER_WORDS 2U
#define ROGUE_NUM_TEXSTATE_DWORDS 4U
/* 12 dwords reserved for shared register management. The first dword is the
* number of shared register blocks to reload. Should be a multiple of 4 dwords,
* size in bytes.
*/
#define ROGUE_LLS_SHARED_REGS_RESERVE_SIZE 48U
#define ROGUE_CSRM_LINE_SIZE_IN_DWORDS (64U * 4U * 4U)
/* The maximum amount of local memory which can be allocated by a single kernel
* (in dwords/32-bit registers).
*
* ROGUE_CDMCTRL_USC_COMMON_SIZE_UNIT_SIZE is in bytes so we divide by four.
*/
#define ROGUE_MAX_PER_KERNEL_LOCAL_MEM_SIZE_REGS \
((ROGUE_CDMCTRL_KERNEL0_USC_COMMON_SIZE_UNIT_SIZE * \
ROGUE_CDMCTRL_KERNEL0_USC_COMMON_SIZE_MAX_SIZE) >> \
2)
#define ROGUE_MAX_INSTANCES_PER_TASK \
(ROGUE_CDMCTRL_KERNEL8_MAX_INSTANCES_MAX_SIZE + 1U)
/* Optimal number for packing work groups into a slot. */
#define ROGUE_CDM_MAX_PACKED_WORKGROUPS_PER_TASK 8U
/* The maximum number of pixel task instances which might be running overlapped
* with compute. Once we have 8 pixel task instances we have a complete set and
* task will be able to run and allocations will be freed.
*/
#define ROGUE_MAX_OVERLAPPED_PIXEL_TASK_INSTANCES 7U
/* Size of the image state in 64-bit units. */
#define ROGUE_MAXIMUM_IMAGE_STATE_SIZE_IN_ULONGLONGS 2U
/* Size of the image state in dwords. The last 64-bit word is optional for
* non-YUV textures.
*/
#define ROGUE_MAXIMUM_IMAGE_STATE_SIZE \
(ROGUE_MAXIMUM_IMAGE_STATE_SIZE_IN_ULONGLONGS * \
(sizeof(uint64_t) / sizeof(uint32_t)))
#define PVR_NUM_PBE_EMIT_REGS 8U
#define ROGUE_USRM_GRANULARITY_IN_REGISTERS 4U
#define ROGUE_RESERVED_USRM_LINES 2U
#define ROGUE_USC_NUM_UNIFIED_STORE_BANKS 8U
#define ROGUE_PDS_US_REGISTER_ALLOCATION_GRANULARITY 8U
#define ROGUE_PDS_US_TEMP_ALLOCATION_GRANULARITY \
ROGUE_PDS_US_REGISTER_ALLOCATION_GRANULARITY
#define ROGUE_USRM_LINE_SIZE 16U
#define ROGUE_USRM_LINE_SIZE_PER_INSTANCE \
(ROGUE_PDS_US_TEMP_ALLOCATION_GRANULARITY * ROGUE_USRM_LINE_SIZE)
enum {
ROGUE_USC_COEFFICIENT_SET_A = 0,
ROGUE_USC_COEFFICIENT_SET_B,
ROGUE_USC_COEFFICIENT_SET_C,
ROGUE_USC_COEFFICIENT_SET_PAD,
ROGUE_USC_COEFFICIENT_SET_SIZE,
};
enum {
ROGUE_SMP_COEFF_UFRAC = 0,
ROGUE_SMP_COEFF_VFRAC,
ROGUE_SMP_COEFF_SFRAC,
ROGUE_SMP_COEFF_LOD_DVAL_POST_CLAMP,
ROGUE_SMP_COEFF_LOD_DVAL_PRE_CLAMP,
ROGUE_SMP_COEFF_TFRAC_POST_CLAMP,
ROGUE_SMP_COEFF_TFRAC_PRE_CLAMP,
ROGUE_SMP_COEFF_COUNT,
};
#define ROGUE_SMP_MAX_DATA_WORDS 18U
#define ROGUE_SMP_LOOKUP_MS_NUM_START 16U
#define ROGUE_SMP_LOOKUP_MS_NUM_BITS 3U
#define ROGUE_SMP_LOOKUP_W_OFF_START 12U
#define ROGUE_SMP_LOOKUP_W_OFF_BITS 4U
#define ROGUE_SMP_LOOKUP_V_OFF_START 6U
#define ROGUE_SMP_LOOKUP_V_OFF_BITS 6U
#define ROGUE_SMP_LOOKUP_U_OFF_START 0U
#define ROGUE_SMP_LOOKUP_U_OFF_BITS 6U
#define ROGUE_REG_SIZE_BYTES 4U
#endif /* ROGUE_HW_DEFS_H */
@@ -0,0 +1,517 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* This file is based on rgxdefs.h and should only contain function-like macros
* and inline functions. Any object-like macros should instead appear in
* rogue_hw_defs.h.
*/
#ifndef ROGUE_HW_UTILS_H
#define ROGUE_HW_UTILS_H
#include <stdint.h>
#include "pvr_types.h"
#define __pvr_address_type pvr_dev_addr_t
#define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr).addr
/* clang-format off */
#define __pvr_make_address(addr_u64) PVR_DEV_ADDR(addr_u64)
/* clang-format on */
#include "csbgen/rogue/cdm.h"
#include "csbgen/rogue/lls.h"
#undef __pvr_make_address
#undef __pvr_get_address
#undef __pvr_address_type
#include "rogue_hw_defs.h"
#include "pvr_device_info.h"
#include "util/compiler.h"
#include "util/macros.h"
#include "pvr_hw_utils.h"
static inline void
rogue_get_isp_samples_per_tile_xy(const struct pvr_device_info *dev_info,
uint32_t samples,
uint32_t *const x_out,
uint32_t *const y_out)
{
const uint32_t tile_size_x =
PVR_GET_FEATURE_VALUE(dev_info, tile_size_x, 0U);
const uint32_t tile_size_y =
PVR_GET_FEATURE_VALUE(dev_info, tile_size_y, 0U);
const uint32_t samples_per_pixel =
PVR_GET_FEATURE_VALUE(dev_info, isp_samples_per_pixel, 0U);
#if !defined(NDEBUG)
switch (samples_per_pixel) {
case 1:
case 2:
case 4:
break;
default:
assert(!"Unsupported ISP samples per pixel");
}
#endif
*x_out = tile_size_x;
*y_out = tile_size_y;
switch (samples) {
case 1:
break;
case 2:
if (samples_per_pixel == 2 || samples_per_pixel == 4)
*y_out *= 2;
break;
case 4:
if (samples_per_pixel == 2 || samples_per_pixel == 4)
*x_out *= 2;
if (samples_per_pixel == 4)
*y_out *= 2;
break;
case 8:
if (samples_per_pixel == 2)
*y_out *= 2;
break;
default:
assert(!"Unsupported number of samples");
}
}
static void rogue_get_isp_scale_xy_from_samples(const uint32_t samples,
uint32_t *const x_scale_out,
uint32_t *const y_scale_out)
{
switch (samples) {
case 1:
*x_scale_out = 1;
*y_scale_out = 1;
break;
case 2:
*x_scale_out = 1;
*y_scale_out = 2;
break;
case 4:
*x_scale_out = 2;
*y_scale_out = 2;
break;
case 8:
*x_scale_out = 2;
*y_scale_out = 4;
break;
default:
UNREACHABLE("Unsupported number of samples");
}
}
static inline void
rogue_get_isp_num_tiles_xy(const struct pvr_device_info *dev_info,
uint32_t samples,
uint32_t width,
uint32_t height,
uint32_t *const x_out,
uint32_t *const y_out)
{
uint32_t tile_samples_x;
uint32_t tile_samples_y;
uint32_t scale_x;
uint32_t scale_y;
rogue_get_isp_samples_per_tile_xy(dev_info,
samples,
&tile_samples_x,
&tile_samples_y);
rogue_get_isp_scale_xy_from_samples(samples, &scale_x, &scale_y);
*x_out = DIV_ROUND_UP(width * scale_x, tile_samples_x);
*y_out = DIV_ROUND_UP(height * scale_y, tile_samples_y);
if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) {
assert(PVR_GET_FEATURE_VALUE(dev_info,
simple_parameter_format_version,
0U) == 2U);
/* Align to a 2x2 tile block. */
*x_out = ALIGN_POT(*x_out, 2);
*y_out = ALIGN_POT(*y_out, 2);
}
}
static inline void
rogue_get_zls_tile_size_xy(const struct pvr_device_info *dev_info,
uint32_t *const x_out,
uint32_t *const y_out)
{
uint32_t version = 0;
bool has_version;
has_version =
!PVR_FEATURE_VALUE(dev_info, simple_parameter_format_version, &version);
*x_out = PVR_GET_FEATURE_VALUE(dev_info, tile_size_x, 0U);
*y_out = PVR_GET_FEATURE_VALUE(dev_info, tile_size_y, 0U);
if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format) &&
has_version && version == 2) {
*x_out *= 2;
*y_out *= 2;
}
}
static inline uint32_t
rogue_get_max_output_regs_per_pixel(const struct pvr_device_info *dev_info)
{
if (PVR_HAS_FEATURE(dev_info, eight_output_registers))
return 8U;
return 4U;
}
static inline void
rogue_get_num_macrotiles_xy(const struct pvr_device_info *dev_info,
uint32_t *const x_out,
uint32_t *const y_out)
{
uint32_t version;
if (PVR_FEATURE_VALUE(dev_info, simple_parameter_format_version, &version))
version = 0;
if (!PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format) ||
version == 2) {
*x_out = 4;
*y_out = 4;
} else {
*x_out = 1;
*y_out = 1;
}
}
static inline uint32_t
rogue_get_macrotile_array_size(const struct pvr_device_info *dev_info)
{
uint32_t num_macrotiles_x;
uint32_t num_macrotiles_y;
if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format))
return 0;
rogue_get_num_macrotiles_xy(dev_info, &num_macrotiles_x, &num_macrotiles_y);
return num_macrotiles_x * num_macrotiles_y * 8U;
}
/* Region header size in bytes. */
static inline uint32_t
rogue_get_region_header_size(const struct pvr_device_info *dev_info)
{
uint32_t version;
if (PVR_FEATURE_VALUE(dev_info, simple_parameter_format_version, &version))
version = 0;
if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format) &&
version == 2) {
return 6;
}
return 5;
}
static inline uint32_t
rogue_get_render_size_max(const struct pvr_device_info *dev_info)
{
if (PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format))
if (!PVR_HAS_FEATURE(dev_info, screen_size8K))
return 4096U;
return 8192U;
}
#define rogue_get_render_size_max_x(dev_info) \
rogue_get_render_size_max(dev_info)
#define rogue_get_render_size_max_y(dev_info) \
rogue_get_render_size_max(dev_info)
static inline uint32_t
rogue_get_render_size_max_z(const struct pvr_device_info *dev_info)
{
switch (dev_info->ident.arch) {
case PVR_DEVICE_ARCH_ROGUE:
return 2048;
default:
UNREACHABLE("unexpected arch");
}
}
static inline uint32_t
rogue_get_texture_extent_max(const struct pvr_device_info *dev_info)
{
switch (dev_info->ident.arch) {
case PVR_DEVICE_ARCH_ROGUE:
return 16384;
default:
UNREACHABLE("unexpected arch");
}
}
static inline uint32_t
rogue_max_compute_shared_registers(const struct pvr_device_info *dev_info)
{
if (PVR_HAS_FEATURE(dev_info, compute))
return 1024U;
return 0U;
}
static inline uint32_t
rogue_get_max_num_cores(const struct pvr_device_info *dev_info)
{
if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support) &&
PVR_HAS_FEATURE(dev_info, xpu_max_slaves)) {
return PVR_GET_FEATURE_VALUE(dev_info, xpu_max_slaves, 0U) + 1U;
}
return 1U;
}
static inline uint32_t
rogue_get_cdm_context_resume_buffer_size(const struct pvr_device_info *dev_info)
{
if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) {
const uint32_t max_num_cores = rogue_get_max_num_cores(dev_info);
const uint32_t cache_line_size = pvr_get_slc_cache_line_size(dev_info);
const uint32_t cdm_context_resume_buffer_stride =
ALIGN_POT(ROGUE_LLS_CDM_CONTEXT_RESUME_BUFFER_SIZE, cache_line_size);
/*
* TODO: Optimise buffer size based on the core_count,
* not max_num_cores
*/
return cdm_context_resume_buffer_stride * max_num_cores;
}
return ROGUE_LLS_CDM_CONTEXT_RESUME_BUFFER_SIZE;
}
static inline uint32_t rogue_get_cdm_context_resume_buffer_alignment(
const struct pvr_device_info *dev_info)
{
if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support))
return pvr_get_slc_cache_line_size(dev_info);
return ROGUE_LLS_CDM_CONTEXT_RESUME_BUFFER_ALIGNMENT;
}
static inline uint32_t
rogue_get_compute_max_work_group_size(const struct pvr_device_info *dev_info)
{
/* The number of tasks which can be executed per USC - Limited to 16U by the
* CDM.
*/
const uint32_t max_tasks_per_usc = 16U;
if (!PVR_HAS_ENHANCEMENT(dev_info, 35421)) {
/* Barriers on work-groups > 32 instances aren't supported. */
return ROGUE_MAX_INSTANCES_PER_TASK;
}
return ROGUE_MAX_INSTANCES_PER_TASK * max_tasks_per_usc;
}
/* Don't use this directly. Use the x and y define macros. */
static inline uint32_t
__rogue_get_param_vf_max(const struct pvr_device_info *dev_info)
{
return (rogue_get_render_size_max(dev_info) * 3 / 2) - 1;
}
#define rogue_get_param_vf_max_x(dev_info) __rogue_get_param_vf_max(dev_info)
#define rogue_get_param_vf_max_y(dev_info) __rogue_get_param_vf_max(dev_info)
static inline uint32_t
rogue_get_max_total_instances(const struct pvr_device_info *dev_info)
{
const uint32_t usc_slots = PVR_GET_FEATURE_VALUE(dev_info, usc_slots, 0U);
assert(usc_slots);
return usc_slots * ROGUE_MAX_INSTANCES_PER_TASK;
}
static inline uint32_t rogue_get_unified_store_size_per_instance(
const struct pvr_device_info *dev_info)
{
const uint32_t unified_store_depth =
PVR_GET_FEATURE_VALUE(dev_info, unified_store_depth, 0U);
assert(unified_store_depth);
return unified_store_depth * ROGUE_USC_NUM_UNIFIED_STORE_BANKS;
}
static inline uint32_t
rogue_get_min_attr_in_usrm_lines(const struct pvr_device_info *dev_info)
{
const uint32_t unified_store_size_per_instance =
rogue_get_unified_store_size_per_instance(dev_info);
assert(unified_store_size_per_instance);
return (unified_store_size_per_instance /
ROGUE_USRM_LINE_SIZE_PER_INSTANCE) -
ROGUE_RESERVED_USRM_LINES;
}
static inline uint32_t
rogue_get_parallel_instances(const struct pvr_device_info *dev_info)
{
return ROGUE_MAX_INSTANCES_PER_TASK / 2;
}
static inline uint32_t rogue_get_unified_store_temps_per_instance(
const struct pvr_device_info *dev_info)
{
return rogue_get_min_attr_in_usrm_lines(dev_info) *
ROGUE_USRM_LINE_SIZE_PER_INSTANCE;
}
static inline uint32_t
rogue_get_unified_store_total_temps(const struct pvr_device_info *dev_info)
{
return rogue_get_unified_store_temps_per_instance(dev_info) *
rogue_get_parallel_instances(dev_info);
}
static inline uint32_t
rogue_get_instance_groups_per_slot(const struct pvr_device_info *dev_info)
{
return ROGUE_MAX_INSTANCES_PER_TASK / rogue_get_parallel_instances(dev_info);
}
static inline uint32_t
rogue_get_optimal_temps(const struct pvr_device_info *dev_info)
{
const uint32_t usc_slots = PVR_GET_FEATURE_VALUE(dev_info, usc_slots, 0U);
assert(usc_slots);
uint32_t max_temps_full_slot_use =
rogue_get_unified_store_temps_per_instance(dev_info) /
(rogue_get_instance_groups_per_slot(dev_info) * usc_slots);
max_temps_full_slot_use &= ~(ROGUE_PDS_US_TEMP_ALLOCATION_GRANULARITY - 1);
return MAX2(max_temps_full_slot_use, 24U);
}
static inline uint32_t rogue_get_temps(const struct pvr_device_info *dev_info)
{
uint32_t temps = rogue_get_unified_store_temps_per_instance(dev_info) / 2;
return MIN2(temps, 248U);
}
static inline uint32_t
rogue_max_wg_temps(const struct pvr_device_info *dev_info,
unsigned temps,
unsigned wg_size,
bool has_barrier)
{
assert(wg_size <= rogue_get_max_total_instances(dev_info));
if (!wg_size)
wg_size = rogue_get_compute_max_work_group_size(dev_info);
if (wg_size > ROGUE_MAX_INSTANCES_PER_TASK && has_barrier) {
/* Number of slots allocated for each workgroup. */
unsigned slots_per_wg =
DIV_ROUND_UP(wg_size, ROGUE_MAX_INSTANCES_PER_TASK);
/* Lines of USRM lines available for each slot
* (+1 for fragmentation / coarse checking).
*/
unsigned lines_per_slot =
rogue_get_min_attr_in_usrm_lines(dev_info) / (slots_per_wg + 1);
unsigned max_allocs;
if (lines_per_slot != 0) {
/* Convert lines to USRM allocs. */
max_allocs = lines_per_slot * ROGUE_USRM_LINE_SIZE;
} else {
max_allocs = (rogue_get_min_attr_in_usrm_lines(dev_info) *
ROGUE_USRM_LINE_SIZE) /
(slots_per_wg + 1);
}
/* Convert USRM allocs to temporary registers. */
unsigned max_temps_for_barrier =
max_allocs * ROGUE_USRM_GRANULARITY_IN_REGISTERS;
/* Clamp to provided limit */
temps = MIN2(temps, max_temps_for_barrier);
}
return temps;
}
static inline uint32_t rogue_get_vtxins(void)
{
/* TODO: use highest safe number of vertex input registers. */
return 12;
}
static inline uint32_t
rogue_num_uscs_per_tile(const struct pvr_device_info *dev_info)
{
if (PVR_HAS_FEATURE(dev_info, tile_per_usc) ||
PVR_HAS_FEATURE(dev_info, pbe2_in_xe))
return 1;
return 4;
}
static inline uint32_t rogue_usc_indexed_pixel_output_index_scale(
const struct pvr_device_info *dev_info)
{
if (PVR_HAS_FEATURE(dev_info, tile_per_usc))
return 4;
return 1;
}
static inline uint32_t
rogue_get_total_instance_count(const struct pvr_device_info *dev_info)
{
/* Number of instances calculated as such:
* USC_SLOTS * INSTANCES_PER_SLOT * MAX_NUM_CORES * NUM_CLUSTERS
*/
/* TODO: Optimise tile buffer size to use core_count, not max_num_cores. */
return rogue_get_max_total_instances(dev_info) *
rogue_get_max_num_cores(dev_info) *
PVR_GET_FEATURE_VALUE(dev_info, num_clusters, 1);
}
#endif /* ROGUE_HW_UTILS_H */
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* This file is based on rgx_fwif_shared.h and rgx_fwif_client.h. It contains
* information about the firmware that is needed by the driver.
*/
#ifndef PVR_ROGUE_FW_H
#define PVR_ROGUE_FW_H
/* FIXME: This will change based on the firmware configuration, which will vary
* depending on the BVNC and firmware version. The powervr KM driver allows this
* information to be queried, but the pvrsrvkm KM driver doesn't. This
* information should really be queried from the winsys.
*/
/* Indicates the number of Render Target Datas in a Render Target Dataset. */
#define ROGUE_NUM_RTDATAS 2U
#endif /* PVR_ROGUE_FW_H */
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef PVR_TYPES_H
#define PVR_TYPES_H
#include <inttypes.h>
#include <stdint.h>
/**
* \brief Convert dwords to bytes.
*
* Throughout the code base we keep sizes in dwords (e.g. code_size and
* data_size returned by the pds api) and in some cases we need to convert those
* to be in bytes.
*
* This macro makes the conversion more obvious.
*/
/* clang-format off */
#define PVR_DW_TO_BYTES(_value) ((_value) * 4)
/* clang-format on */
/*****************************************************************************
Device virtual addresses
*****************************************************************************/
typedef struct pvr_dev_addr {
uint64_t addr;
} pvr_dev_addr_t;
#define PVR_DEV_ADDR(addr_) ((pvr_dev_addr_t){ .addr = (addr_) })
#define PVR_DEV_ADDR_OFFSET(base, offset) PVR_DEV_ADDR((base).addr + (offset))
#define PVR_DEV_ADDR_INVALID PVR_DEV_ADDR(0)
/* All currently supported devices use a 40-bit virtual address space. */
#define PVR_DEV_ADDR_FMT "0x%010" PRIx64
#endif /* PVR_TYPES_H */
+26
View File
@@ -0,0 +1,26 @@
# Copyright © 2022 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
imagination_c_args = cc.get_supported_arguments(
'-Werror=pointer-arith',
)
inc_imagination = include_directories([
'.',
'common',
'include',
])
if with_imagination_vk or with_tools.contains('imagination')
subdir('common')
subdir('csbgen')
subdir('pco')
endif
if with_imagination_vk
subdir('vulkan')
if with_tools.contains('drm-shim')
subdir('drm-shim')
endif
endif
+136
View File
@@ -0,0 +1,136 @@
# Copyright © 2024 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
inc_powervr_compiler = include_directories(['.'])
libpowervr_compiler_files = files(
'pco.c',
'pco_binary.c',
'pco_bool.c',
'pco_cf.c',
'pco_const_imms.c',
'pco_debug.c',
'pco_end.c',
'pco_group_instrs.c',
'pco_index.c',
'pco_ir.c',
'pco_legalize.c',
'pco_nir.c',
'pco_nir_compute.c',
'pco_nir_io.c',
'pco_nir_lower_null_descriptors.c',
'pco_nir_pvfio.c',
'pco_nir_sync.c',
'pco_nir_tex.c',
'pco_nir_vk.c',
'pco_opt.c',
'pco_print.c',
'pco_ra.c',
'pco_schedule.c',
'pco_trans_nir.c',
'pco_validate.c',
)
pco_pygen_dep_files = files('pco_pygen_common.py', 'pco_isa.py', 'pco_ops.py', 'pco_map.py')
pco_builder_ops_h = custom_target(
'pco_builder_ops.h',
input : ['pco_builder_ops.h.py'],
output : 'pco_builder_ops.h',
command : [prog_python, '@INPUT@'],
capture : true,
depend_files : pco_pygen_dep_files,
)
pco_common_h = custom_target(
'pco_common.h',
input : ['pco_common.h.py'],
output : 'pco_common.h',
command : [prog_python, '@INPUT@'],
capture : true,
depend_files : pco_pygen_dep_files,
)
pco_info_c = custom_target(
'pco_info.c',
input : ['pco_info.c.py'],
output : 'pco_info.c',
command : [prog_python, '@INPUT@'],
capture : true,
depend_files : pco_pygen_dep_files,
)
pco_isa_h = custom_target(
'pco_isa.h',
input : ['pco_isa.h.py'],
output : 'pco_isa.h',
command : [prog_python, '@INPUT@'],
capture : true,
depend_files : pco_pygen_dep_files,
)
pco_map_h = custom_target(
'pco_map.h',
input : ['pco_map.h.py'],
output : 'pco_map.h',
command : [prog_python, '@INPUT@'],
capture : true,
depend_files : pco_pygen_dep_files,
)
pco_ops_h = custom_target(
'pco_ops.h',
input : ['pco_ops.h.py'],
output : 'pco_ops.h',
command : [prog_python, '@INPUT@'],
capture : true,
depend_files : pco_pygen_dep_files,
)
pco_pygen_sources = [
pco_builder_ops_h,
pco_common_h,
pco_info_c,
pco_isa_h,
pco_map_h,
pco_ops_h,
]
idep_pco_pygen = declare_dependency(
sources : pco_pygen_sources,
include_directories : inc_powervr_compiler,
)
pco_pygen_c_files = [pco_info_c]
subdir('usclib')
pco_nir_algebraic_c = custom_target(
'pco_nir_algebraic.c',
input : 'pco_nir_algebraic.py',
output : 'pco_nir_algebraic.c',
command : [
prog_python, '@INPUT@', '-p', dir_compiler_nir,
],
capture : true,
depend_files : nir_algebraic_depends,
)
libpowervr_compiler = static_library(
'powervr_compiler',
[libpowervr_compiler_files, pco_pygen_c_files, pco_nir_algebraic_c],
include_directories : [
inc_imagination,
inc_powervr_compiler,
inc_include,
inc_compiler,
inc_src,
],
# Suppress 'parameter passing for argument of type ... changed in GCC ...' warnings.
c_args : [imagination_c_args, no_override_init_args, '-Wno-psabi'],
dependencies : [dep_csbgen, idep_mesautil, idep_nir, idep_pco_pygen, idep_pco_usclib],
gnu_symbol_visibility : 'hidden',
install : false,
)
subdir('uscgen')
+461
View File
@@ -0,0 +1,461 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco.c
*
* \brief Main compiler interface.
*/
#include "compiler/glsl_types.h"
#include "nir_serialize.h"
#include "pco.h"
#include "pco_internal.h"
#include "util/blob.h"
#include "util/hash_table.h"
#include "util/list.h"
#include "util/macros.h"
#include "util/ralloc.h"
#include "util/shader_stats.h"
#include <assert.h>
#include <stdbool.h>
/**
* \brief PCO compiler context destructor.
*
* \param[in,out] ptr PCO compiler context pointer.
*/
static void pco_ctx_destructor(UNUSED void *ptr)
{
glsl_type_singleton_decref();
}
/**
* \brief Allocates and sets up a PCO compiler context.
*
* \param[in] dev_info Device info.
* \param[in] dev_runtime_info Device runtime info.
* \param[in] mem_ctx Ralloc memory allocation context.
* \return The PCO compiler context, or NULL on failure.
*/
pco_ctx *pco_ctx_create(const struct pvr_device_info *dev_info,
const struct pvr_device_runtime_info *dev_runtime_info,
void *mem_ctx)
{
pco_ctx *ctx = rzalloc_size(mem_ctx, sizeof(*ctx));
ctx->dev_info = dev_info;
ctx->dev_runtime_info = dev_runtime_info;
pco_debug_init();
#ifndef NDEBUG
/* Ensure NIR debug variables are processed. */
nir_process_debug_variable();
#endif /* NDEBUG */
glsl_type_singleton_init_or_ref();
ralloc_set_destructor(ctx, pco_ctx_destructor);
return ctx;
}
void pco_ctx_setup_usclib(pco_ctx *ctx, const void *data, unsigned size)
{
struct blob_reader blob_reader;
blob_reader_init(&blob_reader, data, size);
ctx->usclib = nir_deserialize(ctx, pco_nir_options(), &blob_reader);
}
/**
* \brief Updates the device info for a PCO compiler context.
*
* \param[in,out] ctx PCO compiler context.
* \param[in] dev_info Device info.
*/
void pco_ctx_update_dev_info(pco_ctx *ctx,
const struct pvr_device_info *dev_info)
{
ctx->dev_info = dev_info;
}
/**
* \brief Allocates and sets up a PCO shader from a NIR shader.
*
* \param[in] ctx PCO compiler context.
* \param[in] nir The NIR shader.
* \return The PCO shader, or NULL on failure.
*/
pco_shader *pco_shader_create(pco_ctx *ctx, nir_shader *nir, void *mem_ctx)
{
pco_shader *shader = rzalloc_size(mem_ctx, sizeof(*shader));
shader->ctx = ctx;
shader->nir = nir;
shader->stage = nir->info.stage;
shader->name = ralloc_strdup(shader, nir->info.name);
shader->is_internal = nir->info.internal;
shader->is_grouped = false;
list_inithead(&shader->funcs);
return shader;
}
/**
* \brief Sets up a PCO cf node.
*
* \param[in,out] cf_node PCO cf node.
* \param[in] type CF node type.
*/
static inline void init_cf_node(pco_cf_node *cf_node,
enum pco_cf_node_type type)
{
cf_node->type = type;
cf_node->parent = NULL;
}
/**
* \brief Allocates and sets up a PCO function.
*
* \param[in,out] shader PCO shader.
* \param[in] type The function type.
* \param[in] num_params The number of parameters.
* \return The PCO function, or NULL on failure.
*/
pco_func *pco_func_create(pco_shader *shader,
enum pco_func_type type,
unsigned num_params)
{
pco_func *func = rzalloc_size(shader, sizeof(*func));
pco_func *preamble = pco_preamble(shader);
/* Add the function to the shader; preamble goes first, then entrypoint.
* The rest of the functions will get appended.
*/
if (type == PCO_FUNC_TYPE_PREAMBLE) {
assert(!preamble);
list_add(&func->link, &shader->funcs);
} else if (type == PCO_FUNC_TYPE_ENTRYPOINT) {
assert(!pco_entrypoint(shader));
if (!preamble)
list_add(&func->link, &shader->funcs);
else
list_add(&func->link, &preamble->link);
} else {
list_addtail(&func->link, &shader->funcs);
}
init_cf_node(&func->cf_node, PCO_CF_NODE_TYPE_FUNC);
func->parent_shader = shader;
func->type = type;
func->index = shader->next_func++;
list_inithead(&func->body);
func->num_params = num_params;
if (num_params) {
func->params =
rzalloc_array_size(func, sizeof(*func->params), num_params);
}
func->vec_infos = _mesa_hash_table_u64_create(func);
func->enc_offset = ~0U;
return func;
}
/**
* \brief Allocates and sets up a PCO block.
*
* \param[in,out] func Parent function.
* \return The PCO block, or NULL on failure.
*/
pco_block *pco_block_create(pco_func *func)
{
pco_block *block = rzalloc_size(func, sizeof(*block));
init_cf_node(&block->cf_node, PCO_CF_NODE_TYPE_BLOCK);
block->parent_func = func;
list_inithead(&block->instrs);
block->index = func->next_block++;
return block;
}
/**
* \brief Allocates and sets up a PCO if construct.
*
* \param[in,out] func Parent function.
* \return The PCO if construct, or NULL on failure.
*/
pco_if *pco_if_create(pco_func *func)
{
pco_if *pif = rzalloc_size(func, sizeof(*pif));
init_cf_node(&pif->cf_node, PCO_CF_NODE_TYPE_IF);
pif->parent_func = func;
list_inithead(&pif->prologue);
list_inithead(&pif->then_body);
list_inithead(&pif->interlogue);
list_inithead(&pif->else_body);
list_inithead(&pif->epilogue);
pif->index = func->next_if++;
return pif;
}
/**
* \brief Allocates and sets up a PCO loop.
*
* \param[in,out] func Parent function.
* \return The PCO loop, or NULL on failure.
*/
pco_loop *pco_loop_create(pco_func *func)
{
pco_loop *loop = rzalloc_size(func, sizeof(*loop));
init_cf_node(&loop->cf_node, PCO_CF_NODE_TYPE_LOOP);
loop->parent_func = func;
list_inithead(&loop->prologue);
list_inithead(&loop->body);
list_inithead(&loop->interlogue);
list_inithead(&loop->epilogue);
loop->index = func->next_loop++;
return loop;
}
/**
* \brief Allocates and sets up a PCO instruction.
*
* \param[in,out] func Parent function.
* \param[in] num_dests Number of destinations.
* \param[in] num_srcs Number of sources.
* \return The PCO instruction, or NULL on failure.
*/
pco_instr *
pco_instr_create(pco_func *func, unsigned num_dests, unsigned num_srcs)
{
pco_instr *instr;
unsigned size = sizeof(*instr);
size += num_dests * sizeof(*instr->dest);
size += num_srcs * sizeof(*instr->src);
instr = rzalloc_size(func, size);
instr->parent_func = func;
instr->num_dests = num_dests;
instr->dest = (pco_ref *)(instr + 1);
instr->num_srcs = num_srcs;
instr->src = instr->dest + num_dests;
list_inithead(&instr->phi_srcs);
instr->index = func->next_instr++;
return instr;
}
/**
* \brief Allocates and sets up a PCO instruction group.
*
* \param[in,out] func Parent function.
* \return The PCO instruction group, or NULL on failure.
*/
pco_igrp *pco_igrp_create(pco_func *func)
{
pco_igrp *igrp = rzalloc_size(func, sizeof(*igrp));
igrp->parent_func = func;
igrp->index = func->next_igrp++;
return igrp;
}
/**
* \brief Deletes a PCO instruction.
*
* \param[in,out] instr PCO instruction.
*/
void pco_instr_delete(pco_instr *instr)
{
list_del(&instr->link);
ralloc_free(instr);
}
/**
* \brief Returns the shader data.
*
* \param[in] shader PCO shader.
*/
pco_data *pco_shader_data(pco_shader *shader)
{
return &shader->data;
}
/**
* \brief Returns precompilation data for a shader.
*
* \param[in] shader PCO shader.
* \return The precompilation data.
*/
pco_precomp_data pco_get_precomp_data(pco_shader *shader)
{
assert(pco_shader_binary_size(shader));
unsigned size_dwords = pco_shader_binary_size(shader) / sizeof(uint32_t);
assert(size_dwords <= UINT16_MAX);
return (pco_precomp_data){
.temps = shader->data.common.temps,
.vtxins = shader->data.common.vtxins,
.coeffs = shader->data.common.coeffs,
.shareds = shader->data.common.shareds,
.size_dwords = size_dwords,
};
}
/**
* \brief Returns statistics for a shader.
*
* \param[in] shader PCO shader.
* \return The shader statistics.
*/
struct pvr_stats pco_get_pvr_stats(pco_shader *shader)
{
assert(shader->is_grouped);
unsigned shader_size = pco_shader_binary_size(shader);
assert(shader_size > 0);
unsigned loop_count = 0;
unsigned igrp_count = 0;
unsigned main_count = 0;
unsigned bitwise_count = 0;
unsigned control_count = 0;
pco_foreach_func_in_shader (func, shader) {
pco_foreach_loop_in_func (loop, func) {
loop_count++;
}
pco_foreach_igrp_in_func (igrp, func) {
igrp_count++;
switch (igrp->hdr.alutype) {
case PCO_ALUTYPE_MAIN:
main_count++;
break;
case PCO_ALUTYPE_BITWISE:
bitwise_count++;
break;
case PCO_ALUTYPE_CONTROL:
control_count++;
break;
default:
UNREACHABLE("Invalid pco_alutype");
}
}
}
return (struct pvr_stats){
.isa = PVR_STAT_ROGUE,
.rogue = (struct rogue_stats) {
.code_size = shader_size,
.scratch_size = shader->data.common.scratch,
.spill_count = shader->data.common.spilled_temps,
.temp_count = shader->data.common.temps,
.vtxin_count = shader->data.common.vtxins,
.loop_count = loop_count,
.inst_group_count = igrp_count,
.main_inst_group_count = main_count,
.bitwise_inst_group_count = bitwise_count,
.control_inst_group_count = control_count,
},
};
}
enum pco_pck_format pco_pipe_to_pck_format(enum pipe_format format,
bool *scale,
bool *roundzero,
bool *split)
{
enum pco_pck_format pck_format = ~0;
*scale = false;
*roundzero = false;
*split = false;
switch (format) {
case PIPE_FORMAT_R8_UNORM:
case PIPE_FORMAT_R8G8_UNORM:
case PIPE_FORMAT_R8G8B8_UNORM:
case PIPE_FORMAT_R8G8B8A8_UNORM:
pck_format = PCO_PCK_FORMAT_U8888;
*scale = true;
break;
case PIPE_FORMAT_R8_SNORM:
case PIPE_FORMAT_R8G8_SNORM:
case PIPE_FORMAT_R8G8B8_SNORM:
case PIPE_FORMAT_R8G8B8A8_SNORM:
pck_format = PCO_PCK_FORMAT_S8888;
*scale = true;
break;
case PIPE_FORMAT_R11G11B10_FLOAT:
pck_format = PCO_PCK_FORMAT_F111110;
break;
/* TODO: better way to do the 1x2 component. */
case PIPE_FORMAT_R10G10B10A2_UNORM:
pck_format = PCO_PCK_FORMAT_U1010102;
*scale = true;
break;
/* TODO: better way to do the 1x2 component. */
case PIPE_FORMAT_R10G10B10A2_SNORM:
pck_format = PCO_PCK_FORMAT_S1010102;
*scale = true;
break;
case PIPE_FORMAT_R16_FLOAT:
case PIPE_FORMAT_R16G16_FLOAT:
case PIPE_FORMAT_R16G16B16_FLOAT:
case PIPE_FORMAT_R16G16B16A16_FLOAT:
pck_format = PCO_PCK_FORMAT_F16F16;
*split = true;
break;
case PIPE_FORMAT_R16_UNORM:
case PIPE_FORMAT_R16G16_UNORM:
case PIPE_FORMAT_R16G16B16_UNORM:
case PIPE_FORMAT_R16G16B16A16_UNORM:
pck_format = PCO_PCK_FORMAT_U1616;
*scale = true;
*split = true;
break;
case PIPE_FORMAT_R16_SNORM:
case PIPE_FORMAT_R16G16_SNORM:
case PIPE_FORMAT_R16G16B16_SNORM:
case PIPE_FORMAT_R16G16B16A16_SNORM:
pck_format = PCO_PCK_FORMAT_S1616;
*scale = true;
*split = true;
break;
default:
break;
}
return pck_format;
}
+106
View File
@@ -0,0 +1,106 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef PCO_H
#define PCO_H
/**
* \file pco.h
*
* \brief Main compiler interface header.
*/
#include "compiler/nir/nir.h"
/* Defines. */
#define PCO_REG_UNUSED (~0U)
/* Driver-specific forward-declarations. */
struct pvr_device_info;
struct pvr_device_runtime_info;
/* Compiler-specific forward-declarations. */
typedef struct _pco_shader pco_shader;
typedef struct _pco_ctx pco_ctx;
typedef struct _pco_data pco_data;
pco_ctx *pco_ctx_create(const struct pvr_device_info *dev_info,
const struct pvr_device_runtime_info *dev_runtime_info,
void *mem_ctx);
void pco_ctx_setup_usclib(pco_ctx *ctx, const void *data, unsigned size);
void pco_ctx_update_dev_info(pco_ctx *ctx,
const struct pvr_device_info *dev_info);
const struct spirv_to_nir_options *pco_spirv_options(void);
const nir_shader_compiler_options *pco_nir_options(void);
void pco_preprocess_nir(pco_ctx *ctx, nir_shader *nir);
void pco_link_nir(pco_ctx *ctx,
nir_shader *producer,
nir_shader *consumer,
pco_data *producer_data,
pco_data *consumer_data);
void pco_rev_link_nir(pco_ctx *ctx, nir_shader *producer, nir_shader *consumer);
void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data);
void pco_postprocess_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data);
pco_shader *
pco_trans_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data, void *mem_ctx);
void pco_process_ir(pco_ctx *ctx, pco_shader *shader);
void pco_encode_ir(pco_ctx *ctx, pco_shader *shader);
pco_data *pco_shader_data(pco_shader *shader);
unsigned pco_shader_binary_size(pco_shader *shader);
const void *pco_shader_binary_data(pco_shader *shader);
void pco_validate_shader(pco_shader *shader, const char *when);
void pco_print_shader_stats(pco_shader *shader, FILE *fp);
void pco_print_shader(pco_shader *shader, FILE *fp, const char *when);
void pco_print_binary(pco_shader *shader, FILE *fp, const char *when);
#include "compiler/nir/nir_builder.h"
typedef struct _pco_smp_params {
nir_def *tex_state;
nir_def *smp_state;
nir_alu_type dest_type;
enum glsl_sampler_dim sampler_dim;
bool nncoords;
nir_def *coords;
nir_def *array_index;
nir_def *proj;
nir_def *lod_bias;
nir_def *lod_replace;
nir_def *lod_ddx;
nir_def *lod_ddy;
nir_def *addr_lo;
nir_def *addr_hi;
nir_def *offset;
nir_def *ms_index;
nir_def *write_data;
bool sample_coeffs;
bool sample_raw;
unsigned sample_components;
bool int_mode;
} pco_smp_params;
nir_intrinsic_instr *pco_emit_nir_smp(nir_builder *b, pco_smp_params *params);
enum pco_pck_format pco_pipe_to_pck_format(enum pipe_format format,
bool *scale,
bool *roundzero,
bool *split);
#endif /* PCO_H */
+160
View File
@@ -0,0 +1,160 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_binary.c
*
* \brief PCO binary-specific functions.
*/
#include "pco.h"
#include "pco_internal.h"
#include "pco_isa.h"
#include "pco_map.h"
#include "util/u_dynarray.h"
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
/**
* \brief Encodes instruction group alignment.
*
* \param[in,out] buf Binary buffer.
* \param[in] igrp PCO instruction group.
*/
static inline unsigned pco_encode_align(struct util_dynarray *buf,
pco_igrp *igrp)
{
unsigned bytes_encoded = 0;
if (igrp->enc.len.word_padding) {
util_dynarray_append_typed(buf, uint8_t, 0xff);
bytes_encoded += 1;
}
if (igrp->enc.len.align_padding) {
assert(!(igrp->enc.len.align_padding % 2));
unsigned align_words = igrp->enc.len.align_padding / 2;
util_dynarray_append_typed(buf, uint8_t, 0xf0 | align_words);
bytes_encoded += 1;
for (unsigned u = 0; u < igrp->enc.len.align_padding - 1; ++u) {
util_dynarray_append_typed(buf, uint8_t, 0xff);
bytes_encoded += 1;
}
}
return bytes_encoded;
}
/**
* \brief Encodes a PCO instruction group into binary.
*
* \param[in,out] buf Binary buffer.
* \param[in] igrp PCO instruction group.
* \return The number of bytes encoded.
*/
static unsigned pco_encode_igrp(struct util_dynarray *buf, pco_igrp *igrp)
{
uint8_t *ptr;
unsigned bytes_encoded = 0;
/* Header. */
ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.hdr);
bytes_encoded += pco_igrp_hdr_map_encode(ptr, igrp);
/* Instructions. */
pco_foreach_phase_in_igrp_rev (igrp, p) {
ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.instrs[p]);
bytes_encoded += pco_instr_map_encode(ptr, igrp, p);
}
/* I/O. */
if (igrp->enc.len.lower_srcs) {
ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.lower_srcs);
bytes_encoded += pco_srcs_map_encode(ptr, igrp, false);
}
if (igrp->enc.len.upper_srcs) {
ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.upper_srcs);
bytes_encoded += pco_srcs_map_encode(ptr, igrp, true);
}
if (igrp->enc.len.iss) {
ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.iss);
bytes_encoded += pco_iss_map_encode(ptr, igrp);
}
if (igrp->enc.len.dests) {
ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.dests);
bytes_encoded += pco_dests_map_encode(ptr, igrp);
}
/* Word/alignment padding. */
bytes_encoded += pco_encode_align(buf, igrp);
assert(bytes_encoded == igrp->enc.len.total);
return bytes_encoded;
}
/**
* \brief Encodes a PCO shader into binary.
*
* \param[in] ctx PCO compiler context.
* \param[in,out] shader PCO shader.
*/
void pco_encode_ir(pco_ctx *ctx, pco_shader *shader)
{
assert(shader->is_grouped);
util_dynarray_init(&shader->binary, shader);
unsigned bytes_encoded = 0;
pco_foreach_func_in_shader (func, shader) {
func->enc_offset = bytes_encoded;
pco_foreach_block_in_func (block, func) {
pco_foreach_igrp_in_block (igrp, block) {
bytes_encoded += pco_encode_igrp(&shader->binary, igrp);
}
}
}
if (pco_should_print_binary(shader))
pco_print_binary(shader, stdout, "after encoding");
if (pco_should_print_stats(shader))
pco_print_shader_stats(shader, stdout);
}
/**
* \brief Returns the size in bytes of a PCO shader binary.
*
* \param[in] shader PCO shader.
* \return The size in bytes of the PCO shader binary.
*/
unsigned pco_shader_binary_size(pco_shader *shader)
{
if (!shader)
return 0;
return shader->binary.size;
}
/**
* \brief Returns the PCO shader binary data.
*
* \param[in] shader PCO shader.
* \return The PCO shader binary data.
*/
const void *pco_shader_binary_data(pco_shader *shader)
{
if (!shader)
return NULL;
return shader->binary.data;
}
+73
View File
@@ -0,0 +1,73 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_bool.c
*
* \brief PCO bool passes.
*/
#include "pco.h"
#include "pco_builder.h"
#include "util/bitscan.h"
#include "util/bitset.h"
#include "util/macros.h"
#include "util/ralloc.h"
#include "util/u_dynarray.h"
#include <assert.h>
#include <stdbool.h>
static bool lower_bools(pco_func *func)
{
bool progress = false;
/* Update to 32-bit. */
pco_foreach_instr_in_func (instr, func) {
pco_foreach_instr_dest_vreg_ssa (pdest, instr) {
if (pco_ref_get_bits(*pdest) != 1)
continue;
*pdest = pco_ref_bits(*pdest, 32);
progress = true;
}
pco_foreach_instr_src_vreg_ssa (psrc, instr) {
if (pco_ref_get_bits(*psrc) != 1)
continue;
*psrc = pco_ref_bits(*psrc, 32);
progress = true;
}
}
pco_foreach_ssa_bool_if_in_func (pif, func) {
pif->cond = pco_ref_bits(pif->cond, 32);
progress = true;
}
return progress;
}
/**
* \brief Bool lowering pass.
*
* \param[in,out] shader PCO shader.
* \return True if the pass made progress.
*/
bool pco_bool(pco_shader *shader)
{
bool progress = false;
pco_foreach_func_in_shader (func, shader) {
progress |= lower_bools(func);
}
return progress;
}
+473
View File
@@ -0,0 +1,473 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef PCO_BUILDER_H
#define PCO_BUILDER_H
/**
* \\file pco_builder.h
*
* \\brief PCO builder header.
*/
#include "pco.h"
#include "pco_internal.h"
#include "util/list.h"
#include "util/macros.h"
#include <stdbool.h>
/** Cursor pointer. */
enum pco_cursor_option {
PCO_CURSOR_BEFORE_CF_NODE,
PCO_CURSOR_AFTER_CF_NODE,
PCO_CURSOR_BEFORE_INSTR,
PCO_CURSOR_AFTER_INSTR,
PCO_CURSOR_BEFORE_IGRP,
PCO_CURSOR_AFTER_IGRP,
};
/** Cursor for PCO instructions/groups and basic blocks. */
typedef struct pco_cursor {
enum pco_cursor_option option; /** Cursor pointer option. */
union {
pco_cf_node *cf_node;
pco_instr *instr;
pco_igrp *igrp;
};
} pco_cursor;
/** PCO builder context. */
typedef struct pco_builder {
pco_func *func; /** Target function. */
pco_cursor cursor; /** Current position in the function. */
} pco_builder;
/* Cursor position setters. */
/**
* \brief Returns a cursor set to before a cf node.
*
* \param[in] cf_node The cf node.
* \return The cursor.
*/
static inline pco_cursor pco_cursor_before_cf_node(pco_cf_node *cf_node)
{
return (pco_cursor){
.option = PCO_CURSOR_BEFORE_CF_NODE,
.cf_node = cf_node,
};
}
/**
* \brief Returns a cursor set to after a cf node.
*
* \param[in] cf_node The cf node.
* \return The cursor.
*/
static inline pco_cursor pco_cursor_after_cf_node(pco_cf_node *cf_node)
{
return (pco_cursor){
.option = PCO_CURSOR_AFTER_CF_NODE,
.cf_node = cf_node,
};
}
/**
* \brief Returns a cursor set to before a block.
*
* \param[in] block The block.
* \return The cursor.
*/
static inline pco_cursor pco_cursor_before_block(pco_block *block)
{
return pco_cursor_before_cf_node(&block->cf_node);
}
/**
* \brief Returns a cursor set to after a block.
*
* \param[in] block The block.
* \return The cursor.
*/
static inline pco_cursor pco_cursor_after_block(pco_block *block)
{
return pco_cursor_after_cf_node(&block->cf_node);
}
/**
* \brief Returns a cursor set to before a list.
*
* \param[in] list The list.
* \return The cursor.
*/
static inline pco_cursor pco_cursor_before_list(struct list_head *list)
{
return pco_cursor_before_cf_node(pco_cf_node_head(list));
}
/**
* \brief Returns a cursor set to after an exec_list.
*
* \param[in] list The list.
* \return The list.
*/
static inline pco_cursor pco_cursor_after_list(struct list_head *list)
{
return pco_cursor_after_cf_node(pco_cf_node_tail(list));
}
/**
* \brief Returns a cursor set to before an instruction.
*
* \param[in] instr The instruction.
* \return The cursor.
*/
static inline pco_cursor pco_cursor_before_instr(pco_instr *instr)
{
return (pco_cursor){
.option = PCO_CURSOR_BEFORE_INSTR,
.instr = instr,
};
}
/**
* \brief Returns a cursor set to after an instruction.
*
* \param[in] instr The instruction.
* \return The cursor.
*/
static inline pco_cursor pco_cursor_after_instr(pco_instr *instr)
{
return (pco_cursor){
.option = PCO_CURSOR_AFTER_INSTR,
.instr = instr,
};
}
/**
* \brief Returns a cursor set to before an instruction group.
*
* \param[in] igrp The instruction group.
* \return The cursor.
*/
static inline pco_cursor pco_cursor_before_igrp(pco_igrp *igrp)
{
return (pco_cursor){
.option = PCO_CURSOR_BEFORE_IGRP,
.igrp = igrp,
};
}
/**
* \brief Returns a cursor set to after an instruction group.
*
* \param[in] igrp The instruction group.
* \return The cursor.
*/
static inline pco_cursor pco_cursor_after_igrp(pco_igrp *igrp)
{
return (pco_cursor){
.option = PCO_CURSOR_AFTER_IGRP,
.igrp = igrp,
};
}
/**
* \brief Returns whether a cursor is set to before a construct.
*
* \param[in] cursor The cursor.
* \return True if the cursor is set to before a construct.
*/
static inline bool pco_cursor_is_before(pco_cursor cursor)
{
return cursor.option == PCO_CURSOR_BEFORE_CF_NODE ||
cursor.option == PCO_CURSOR_BEFORE_INSTR ||
cursor.option == PCO_CURSOR_BEFORE_IGRP;
}
/* Cursor get functions. */
/**
* \brief Returns the function being pointed to by the cursor.
*
* \param[in] cursor The cursor.
* \return The function being pointed to.
*/
static inline pco_func *pco_cursor_func(pco_cursor cursor)
{
switch (cursor.option) {
case PCO_CURSOR_BEFORE_CF_NODE:
case PCO_CURSOR_AFTER_CF_NODE:
switch (cursor.cf_node->type) {
case PCO_CF_NODE_TYPE_BLOCK:
return pco_cf_node_as_block(cursor.cf_node)->parent_func;
case PCO_CF_NODE_TYPE_IF:
return pco_cf_node_as_if(cursor.cf_node)->parent_func;
case PCO_CF_NODE_TYPE_LOOP:
return pco_cf_node_as_loop(cursor.cf_node)->parent_func;
case PCO_CF_NODE_TYPE_FUNC:
return pco_cf_node_as_func(cursor.cf_node);
default:
break;
}
break;
case PCO_CURSOR_BEFORE_INSTR:
case PCO_CURSOR_AFTER_INSTR:
return cursor.instr->parent_func;
case PCO_CURSOR_BEFORE_IGRP:
case PCO_CURSOR_AFTER_IGRP:
return cursor.igrp->parent_func;
default:
break;
}
UNREACHABLE("");
}
/**
* \brief Returns the cf node being pointed to by the cursor.
*
* \param[in] cursor The cursor.
* \return The cf node being pointed to.
*/
static inline pco_cf_node *pco_cursor_cf_node(pco_cursor cursor)
{
switch (cursor.option) {
case PCO_CURSOR_BEFORE_CF_NODE:
case PCO_CURSOR_AFTER_CF_NODE:
return cursor.cf_node;
case PCO_CURSOR_BEFORE_INSTR:
case PCO_CURSOR_AFTER_INSTR:
return &cursor.instr->parent_block->cf_node;
case PCO_CURSOR_BEFORE_IGRP:
case PCO_CURSOR_AFTER_IGRP:
return &cursor.igrp->parent_block->cf_node;
default:
break;
}
UNREACHABLE("");
}
/**
* \brief Returns the block being pointed to by the cursor.
*
* \param[in] cursor The cursor.
* \return The block being pointed to.
*/
static inline pco_block *pco_cursor_block(pco_cursor cursor)
{
switch (cursor.option) {
case PCO_CURSOR_BEFORE_CF_NODE:
case PCO_CURSOR_AFTER_CF_NODE:
switch (cursor.cf_node->type) {
case PCO_CF_NODE_TYPE_BLOCK:
return pco_cf_node_as_block(cursor.cf_node);
/* TODO: other cf node types? */
default:
break;
}
break;
case PCO_CURSOR_BEFORE_INSTR:
case PCO_CURSOR_AFTER_INSTR:
return cursor.instr->parent_block;
case PCO_CURSOR_BEFORE_IGRP:
case PCO_CURSOR_AFTER_IGRP:
return cursor.igrp->parent_block;
default:
break;
}
UNREACHABLE("");
}
/**
* \brief Returns the instruction being pointed to by the cursor.
*
* \param[in] cursor The cursor.
* \return The instruction being pointed to.
*/
static inline pco_instr *pco_cursor_instr(pco_cursor cursor)
{
bool before = pco_cursor_is_before(cursor);
switch (cursor.option) {
case PCO_CURSOR_BEFORE_CF_NODE:
case PCO_CURSOR_AFTER_CF_NODE: {
pco_block *block = NULL;
switch (cursor.cf_node->type) {
case PCO_CF_NODE_TYPE_BLOCK:
block = pco_cf_node_as_block(cursor.cf_node);
return before ? pco_first_instr(block) : pco_last_instr(block);
/* TODO: other cf node types? */
default:
break;
}
break;
}
case PCO_CURSOR_BEFORE_INSTR:
case PCO_CURSOR_AFTER_INSTR:
return cursor.instr;
default:
break;
}
UNREACHABLE("");
}
/**
* \brief Returns the instruction group being pointed to by the cursor.
*
* \param[in] cursor The cursor.
* \return The instruction group being pointed to.
*/
static inline pco_igrp *pco_cursor_igrp(pco_cursor cursor)
{
bool before = pco_cursor_is_before(cursor);
switch (cursor.option) {
case PCO_CURSOR_BEFORE_CF_NODE:
case PCO_CURSOR_AFTER_CF_NODE: {
pco_block *block = NULL;
switch (cursor.cf_node->type) {
case PCO_CF_NODE_TYPE_BLOCK:
block = pco_cf_node_as_block(cursor.cf_node);
/* Special case: we're in pco_group_instrs and want to go from
* the start.
*/
if (!block->parent_func->parent_shader->is_grouped)
return NULL;
return before ? pco_first_igrp(block) : pco_last_igrp(block);
/* TODO: other cf node types? */
default:
break;
}
break;
}
case PCO_CURSOR_BEFORE_IGRP:
case PCO_CURSOR_AFTER_IGRP:
return cursor.igrp;
default:
break;
}
UNREACHABLE("");
}
/* Builder functions. */
/**
* \brief Creates a builder.
*
* \param[in] func The function being targeted.
* \param[in] cursor The cursor.
* \return The builder.
*/
static pco_builder pco_builder_create(pco_func *func, pco_cursor cursor)
{
return (pco_builder){
.func = func,
.cursor = cursor,
};
}
/**
* \brief Inserts a instruction at a position specified by the builder.
*
* \param[in] b The builder.
* \param[in] instr The instruction.
*/
static inline void pco_builder_insert_instr(pco_builder *b, pco_instr *instr)
{
pco_block *block = pco_cursor_block(b->cursor);
instr->parent_block = block;
pco_instr *cursor_instr = pco_cursor_instr(b->cursor);
bool before = pco_cursor_is_before(b->cursor);
if (cursor_instr) {
if (before)
list_add(&instr->link, cursor_instr->link.prev);
else
list_add(&instr->link, &cursor_instr->link);
} else {
if (before)
list_add(&instr->link, &block->instrs);
else
list_addtail(&instr->link, &block->instrs);
}
b->cursor = pco_cursor_after_instr(instr);
}
/**
* \brief Inserts a instruction group at a position specified by the builder.
*
* \param[in] b The builder.
* \param[in] igrp The instruction group.
*/
static inline void pco_builder_insert_igrp(pco_builder *b, pco_igrp *igrp)
{
pco_block *block = pco_cursor_block(b->cursor);
igrp->parent_block = block;
pco_igrp *cursor_igrp = pco_cursor_igrp(b->cursor);
bool before = pco_cursor_is_before(b->cursor);
if (cursor_igrp) {
if (before)
list_add(&igrp->link, cursor_igrp->link.prev);
else
list_add(&igrp->link, &cursor_igrp->link);
} else {
if (before)
list_add(&igrp->link, &block->instrs);
else
list_addtail(&igrp->link, &block->instrs);
}
b->cursor = pco_cursor_after_igrp(igrp);
}
/* Generated op building functions. */
#include "pco_builder_ops.h"
/**
* \brief Returns whether the instruction has the default execution condition.
*
* \param[in] instr The instruction.
* \return True if the instruction has the default execution condition.
*/
static inline bool pco_instr_has_default_exec(pco_instr *instr)
{
if (!pco_instr_has_exec_cnd(instr))
return true;
return pco_instr_get_exec_cnd(instr) == PCO_EXEC_CND_E1_ZX;
}
#endif /* PCO_BUILDER_H */
+194
View File
@@ -0,0 +1,194 @@
# Copyright © 2024 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
from mako.template import Template, exceptions
from pco_ops import *
template = """/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef PCO_BUILDER_OPS_H
#define PCO_BUILDER_OPS_H
/**
* \\file pco_builder_ops.h
*
* \\brief PCO op building functions.
*/
#include "pco_internal.h"
#include "pco_common.h"
#include "pco_ops.h"
#include "util/macros.h"
#include <assert.h>
#include <stdbool.h>
/** Ref mod info. */
static inline
bool pco_instr_dest_has_mod(const pco_instr *instr, unsigned dest, enum pco_ref_mod mod)
{
const struct pco_op_info *info = &pco_op_info[instr->op];
if (info->num_dests == ~0)
return false;
assert(dest < info->num_dests);
assert(mod < _PCO_REF_MOD_COUNT);
return (info->dest_mods[dest] & (1ULL << mod)) != 0;
}
static inline
bool pco_instr_src_has_mod(const pco_instr *instr, unsigned src, enum pco_ref_mod mod)
{
const struct pco_op_info *info = &pco_op_info[instr->op];
if (info->num_srcs == ~0)
return false;
assert(src < info->num_srcs);
assert(mod < _PCO_REF_MOD_COUNT);
return (info->src_mods[src] & (1ULL << mod)) != 0;
}
% for ref_mod in ref_mods.values():
static inline
bool pco_instr_dest_has_${ref_mod.t.tname}(const pco_instr *instr, unsigned dest)
{
return pco_instr_dest_has_mod(instr, dest, ${ref_mod.cname});
}
static inline
bool pco_instr_src_has_${ref_mod.t.tname}(const pco_instr *instr, unsigned src)
{
return pco_instr_src_has_mod(instr, src, ${ref_mod.cname});
}
% endfor
/** Op mod getting/setting. */
static inline
bool pco_instr_has_mod(const pco_instr *instr, enum pco_op_mod mod)
{
assert(mod < _PCO_OP_MOD_COUNT);
return (pco_op_info[instr->op].mods & (1ULL << mod)) != 0;
}
static inline
void pco_instr_set_mod(pco_instr *instr, enum pco_op_mod mod, uint32_t val)
{
assert(mod < _PCO_OP_MOD_COUNT);
unsigned mod_index = pco_op_info[instr->op].mod_map[mod];
assert(mod_index > 0);
instr->mod[mod_index - 1] = val;
}
static inline
uint32_t pco_instr_get_mod(const pco_instr *instr, enum pco_op_mod mod)
{
assert(mod < _PCO_OP_MOD_COUNT);
unsigned mod_index = pco_op_info[instr->op].mod_map[mod];
assert(mod_index > 0);
return instr->mod[mod_index - 1];
}
static inline
bool pco_instr_mod_is_set(const pco_instr *instr, enum pco_op_mod mod)
{
const struct pco_op_mod_info *info = &pco_op_mod_info[mod];
return pco_instr_get_mod(instr, mod) != (info->nzdefault ? info->nzdefault : 0);
}
% for op_mod in op_mods.values():
static inline
bool pco_instr_has_${op_mod.t.tname}(const pco_instr *instr)
{
return pco_instr_has_mod(instr, ${op_mod.cname});
}
static inline
void pco_instr_set_${op_mod.t.tname}(pco_instr *instr, ${op_mod.t.name} val)
{
return pco_instr_set_mod(instr, ${op_mod.cname}, val);
}
static inline
${op_mod.t.name} pco_instr_get_${op_mod.t.tname}(const pco_instr *instr)
{
return pco_instr_get_mod(instr, ${op_mod.cname});
}
% endfor
% for op in ops.values():
% if bool(op.op_mods):
struct ${op.bname}_mods {
% for op_mod in op.op_mods:
${op_mod.t.name} ${op_mod.t.tname};
% endfor
};
% endif
#define ${op.bname}_(${op.builder_params[2]}${op.builder_params[4]}) _${op.bname}_(${op.builder_params[2]}${op.builder_params[5]})
static
pco_instr *_${op.bname}_(${op.builder_params[0]})
{
pco_instr *instr = pco_instr_create(func,
${'num_dests' if op.num_dests == VARIABLE else op.num_dests},
${'num_srcs' if op.num_srcs == VARIABLE else op.num_srcs});
instr->op = ${op.cname.upper()};
% if op.has_target_cf_node:
instr->target_cf_node = target_cf_node;
% endif
% if op.num_dests == VARIABLE:
for (unsigned d = 0; d < num_dests; ++d)
instr->dest[d] = dest[d];
% else:
% for d in range(op.num_dests):
instr->dest[${d}] = dest${d};
% endfor
% endif
% if op.num_srcs == VARIABLE:
for (unsigned s = 0; s < num_srcs; ++s)
instr->src[s] = src[s];
% else:
% for s in range(op.num_srcs):
instr->src[${s}] = src${s};
% endfor
% endif
% for op_mod in op.op_mods:
% if op_mod.t.nzdefault is None:
pco_instr_set_${op_mod.t.tname}(instr, mods.${op_mod.t.tname});
% else:
pco_instr_set_${op_mod.t.tname}(instr, !mods.${op_mod.t.tname} ? ${op_mod.t.nzdefault} : mods.${op_mod.t.tname});
% endif
% endfor
return instr;
}
% if op.op_type != 'hw_direct':
#define ${op.bname}(${op.builder_params[3]}${op.builder_params[4]}) _${op.bname}(${op.builder_params[3]}${op.builder_params[5]})
static inline
pco_instr *_${op.bname}(${op.builder_params[1]})
{
pco_func *func = pco_cursor_func(b->cursor);
pco_instr *instr = _${op.bname}_(${op.builder_params[2]}${op.builder_params[6]});
pco_builder_insert_instr(b, instr);
return instr;
}
% endif
% endfor
#endif /* PCO_BUILDER_OPS_H */"""
def main():
try:
print(Template(template).render(ops=ops, op_mods=op_mods, ref_mods=ref_mods, VARIABLE=VARIABLE))
except:
raise Exception(exceptions.text_error_template().render())
if __name__ == '__main__':
main()
+512
View File
@@ -0,0 +1,512 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_cf.c
*
* \brief PCO control-flow passes.
*/
#include "pco.h"
#include "pco_builder.h"
#include "util/bitscan.h"
#include "util/bitset.h"
#include "util/list.h"
#include "util/macros.h"
#include "util/ralloc.h"
#include "util/u_dynarray.h"
#include <assert.h>
#include <stdbool.h>
static pco_ref emc_ref(pco_func *func, pco_builder *b)
{
if (pco_ref_is_null(func->emc)) {
/* Allocate and initialize the emc. */
func->emc = pco_ref_new_vreg(func);
pco_cndst(b,
pco_ref_pred(PCO_PRED_PE),
func->emc,
pco_zero,
pco_ref_imm8(1),
.exec_cnd = PCO_EXEC_CND_EX_ZX,
.cnd = PCO_CND_ALWAYS);
}
return func->emc;
}
static inline pco_block *cf_section_create(pco_func *func,
pco_cf_node *parent_cf_node,
struct list_head *cf_node_list,
enum pco_cf_node_flag flag)
{
assert(flag == PCO_CF_NODE_FLAG_PROLOGUE ||
flag == PCO_CF_NODE_FLAG_INTERLOGUE ||
flag == PCO_CF_NODE_FLAG_EPILOGUE);
pco_block *block = pco_block_create(func);
block->cf_node.parent = parent_cf_node;
block->cf_node.flag = flag;
list_addtail(&block->cf_node.link, cf_node_list);
return block;
}
static inline bool body_has_non_preds(struct list_head *body)
{
if (list_is_empty(body))
return false;
pco_block *block = pco_cf_node_as_block(pco_cf_node_head(body));
pco_instr *last_instr = NULL;
pco_foreach_instr_in_block (instr, block) {
/* Make sure there are no instructions that read/write predicates. */
pco_foreach_instr_src (psrc, instr) {
if (pco_ref_is_pred(*psrc))
return true;
}
pco_foreach_instr_dest (pdest, instr) {
if (pco_ref_is_pred(*pdest))
return true;
}
if (!pco_instr_has_exec_cnd(instr))
return true;
if (!pco_instr_has_default_exec(instr))
return true;
last_instr = instr;
}
assert(last_instr);
return last_instr->op == PCO_OP_BR;
}
static inline bool can_pred_exec(pco_if *pif)
{
if (PCO_DEBUG(NO_PRED_CF))
return false;
/* Skip if there is any nesting. */
if (list_length(&pif->then_body) > 1 || list_length(&pif->else_body) > 1)
return false;
/* Skip if then/else blocks end with a branch, or contain non-predicatable
* instructions.
* Note: WDFs can't be predicated and won't be inserted until the scheduling
* pass which comes after this one, but we don't have to worry about it as if
* there are no outstanding data fences it'll simply NOP.
*/
if (body_has_non_preds(&pif->then_body) ||
body_has_non_preds(&pif->else_body))
return false;
return true;
}
static inline void set_body_exec_cnd(struct list_head *body,
enum pco_exec_cnd exec_cnd)
{
assert(!list_is_empty(body));
pco_block *block = pco_cf_node_as_block(pco_cf_node_head(body));
pco_foreach_instr_in_block (instr, block) {
pco_instr_set_exec_cnd(instr, exec_cnd);
}
}
static inline void
lower_if_pred_exec(pco_if *pif, pco_func *func, bool has_else, bool invert_cond)
{
pco_block *prologue = cf_section_create(func,
&pif->cf_node,
&pif->prologue,
PCO_CF_NODE_FLAG_PROLOGUE);
/* Setup the prologue. */
pco_builder b = pco_builder_create(func, pco_cursor_after_block(prologue));
/* TODO: see if the cond producer can set p0 directly. */
pco_tstz(&b,
pco_ref_null(),
pco_ref_pred(PCO_PRED_P0),
pif->cond,
.tst_type_main = PCO_TST_TYPE_MAIN_U32);
set_body_exec_cnd(&pif->then_body,
invert_cond ? PCO_EXEC_CND_E1_Z1 : PCO_EXEC_CND_E1_Z0);
if (has_else) {
set_body_exec_cnd(&pif->else_body,
invert_cond ? PCO_EXEC_CND_E1_Z0 : PCO_EXEC_CND_E1_Z1);
}
}
static inline void
lower_if_cond_exec(pco_if *pif, pco_func *func, bool has_else, bool invert_cond)
{
pco_block *prologue = cf_section_create(func,
&pif->cf_node,
&pif->prologue,
PCO_CF_NODE_FLAG_PROLOGUE);
pco_block *interlogue = has_else
? cf_section_create(func,
&pif->cf_node,
&pif->interlogue,
PCO_CF_NODE_FLAG_INTERLOGUE)
: NULL;
pco_block *epilogue = cf_section_create(func,
&pif->cf_node,
&pif->epilogue,
PCO_CF_NODE_FLAG_EPILOGUE);
/* Setup the prologue. */
pco_builder b = pco_builder_create(func, pco_cursor_after_block(prologue));
pco_ref emc = emc_ref(func, &b);
/* TODO: see if the cond producer can set p0 directly. */
pco_tstz(&b,
pco_ref_null(),
pco_ref_pred(PCO_PRED_P0),
pif->cond,
.tst_type_main = PCO_TST_TYPE_MAIN_U32);
pco_cndst(&b,
pco_ref_pred(PCO_PRED_PE),
emc,
emc,
pco_ref_imm8(1),
.exec_cnd = PCO_EXEC_CND_EX_ZX,
.cnd = invert_cond ? PCO_CND_P0_TRUE : PCO_CND_P0_FALSE);
pco_br(&b,
has_else ? &interlogue->cf_node : &epilogue->cf_node,
.branch_cnd = PCO_BRANCH_CND_ALLINST);
/* Setup the interlogue (if needed). */
if (has_else) {
b.cursor = pco_cursor_after_block(interlogue);
pco_cndef(&b,
pco_ref_pred(PCO_PRED_PE),
emc,
emc,
pco_ref_imm8(1),
.exec_cnd = PCO_EXEC_CND_EX_ZX,
.cnd = PCO_CND_ALWAYS);
pco_br(&b, &epilogue->cf_node, .branch_cnd = PCO_BRANCH_CND_ALLINST);
}
/* Setup the epilogue. */
b.cursor = pco_cursor_after_block(epilogue);
pco_cndend(&b,
pco_ref_pred(PCO_PRED_PE),
emc,
emc,
pco_ref_imm8(1),
.exec_cnd = PCO_EXEC_CND_EX_ZX);
}
static inline void lower_if(pco_if *pif, pco_func *func)
{
assert(!pco_ref_is_null(pif->cond));
assert(list_is_empty(&pif->prologue));
assert(list_is_empty(&pif->interlogue));
assert(list_is_empty(&pif->epilogue));
bool has_then = !list_is_empty(&pif->then_body);
bool has_else = !list_is_empty(&pif->else_body);
assert(has_then || has_else);
/* If we only have an else body, invert the condition and bodies. */
bool invert_cond = false;
if (!has_then && has_else) {
struct list_head temp;
memcpy(&temp, &pif->then_body, sizeof(pif->then_body));
memcpy(&pif->then_body, &pif->else_body, sizeof(pif->else_body));
memcpy(&pif->else_body, &pif->then_body, sizeof(pif->then_body));
invert_cond = true;
has_then = true;
has_else = false;
}
assert(has_then);
if (pif->pred_exec)
lower_if_pred_exec(pif, func, has_else, invert_cond);
else
lower_if_cond_exec(pif, func, has_else, invert_cond);
pif->cond = pco_ref_null();
}
static inline void lower_loop(pco_loop *loop, pco_func *func)
{
assert(list_is_empty(&loop->prologue));
assert(list_is_empty(&loop->interlogue));
assert(list_is_empty(&loop->epilogue));
pco_block *prologue = cf_section_create(func,
&loop->cf_node,
&loop->prologue,
PCO_CF_NODE_FLAG_PROLOGUE);
pco_block *interlogue = cf_section_create(func,
&loop->cf_node,
&loop->interlogue,
PCO_CF_NODE_FLAG_INTERLOGUE);
pco_block *epilogue = cf_section_create(func,
&loop->cf_node,
&loop->epilogue,
PCO_CF_NODE_FLAG_EPILOGUE);
/* Setup the prologue. */
pco_builder b = pco_builder_create(func, pco_cursor_after_block(prologue));
pco_ref emc = emc_ref(func, &b);
pco_cndst(&b,
pco_ref_pred(PCO_PRED_PE),
emc,
emc,
pco_ref_imm8(2), /* TODO: make this a define */
.exec_cnd = PCO_EXEC_CND_EX_ZX,
.cnd = PCO_CND_ALWAYS);
pco_br(&b, &epilogue->cf_node, .branch_cnd = PCO_BRANCH_CND_ALLINST);
/* Setup the interlogue. */
b.cursor = pco_cursor_after_block(interlogue);
pco_cndend(&b,
pco_ref_pred(PCO_PRED_PE),
emc,
emc,
pco_ref_imm8(1), /* TODO: make this a define */
.exec_cnd = PCO_EXEC_CND_EX_ZX);
pco_cndst(&b,
pco_ref_pred(PCO_PRED_PE),
emc,
emc,
pco_ref_imm8(1), /* TODO: make this a define */
.exec_cnd = PCO_EXEC_CND_EX_ZX,
.cnd = PCO_CND_ALWAYS);
/* Setup the epilogue. */
b.cursor = pco_cursor_after_block(epilogue);
pco_cndlt(&b,
pco_ref_pred(PCO_PRED_PE),
emc,
pco_ref_pred(PCO_PRED_P0),
emc,
pco_ref_imm8(2), /* TODO: make this a define */
.exec_cnd = PCO_EXEC_CND_EX_ZX,
.cnd = PCO_CND_ALWAYS);
pco_br(&b,
pco_cf_node_head(&loop->body),
.exec_cnd = PCO_EXEC_CND_E1_Z1,
.branch_cnd = PCO_BRANCH_CND_EXEC_COND);
}
static inline void lower_break_continue(pco_instr *instr,
pco_func *func,
pco_if *pif,
pco_loop *loop,
unsigned loop_nestings,
bool is_continue)
{
pco_builder b = pco_builder_create(func, pco_cursor_before_instr(instr));
pco_ref emc = emc_ref(func, &b);
enum pco_exec_cnd exec_cnd = pco_instr_get_exec_cnd(instr);
pco_ref val = pco_ref_new_ssa32(func);
pco_movi32(&b,
val,
pco_ref_imm32(loop_nestings + (is_continue ? 1 : 2)),
.exec_cnd = exec_cnd);
enum pco_cnd cnd;
switch (exec_cnd) {
case PCO_CC_E1_ZX:
assert(!pif || !pif->pred_exec);
cnd = PCO_CND_ALWAYS;
break;
case PCO_CC_E1_Z1:
assert(!pif || pif->pred_exec);
cnd = PCO_CND_P0_TRUE;
break;
case PCO_CC_E1_Z0:
assert(!pif || pif->pred_exec);
cnd = PCO_CND_P0_FALSE;
break;
default:
UNREACHABLE("");
}
pco_cndsm(&b,
pco_ref_pred(PCO_PRED_PE),
emc,
emc,
val,
.exec_cnd = PCO_EXEC_CND_EX_ZX,
.cnd = cnd);
pco_instr_delete(instr);
}
static inline bool pco_lower_cf(pco_func *func)
{
bool progress = false;
void *mem_ctx = ralloc_context(NULL);
unsigned loop_nestings = 0;
struct util_dynarray loop_nestings_stack;
struct util_dynarray pif_stack;
struct util_dynarray loop_stack;
util_dynarray_init(&loop_nestings_stack, mem_ctx);
util_dynarray_init(&pif_stack, mem_ctx);
util_dynarray_init(&loop_stack, mem_ctx);
pco_foreach_cf_node_in_func_structured (cf_node, cf_node_completed, func) {
/* Handle the end of an if/loop. */
if (cf_node_completed) {
switch (cf_node_completed->type) {
case PCO_CF_NODE_TYPE_IF: {
pco_if *pif = pco_cf_node_as_if(cf_node_completed);
ASSERTED pco_if *last_pif = util_dynarray_pop(&pif_stack, pco_if *);
assert(pif == last_pif);
if (!pif->pred_exec)
--loop_nestings;
break;
}
case PCO_CF_NODE_TYPE_LOOP: {
ASSERTED pco_loop *loop = pco_cf_node_as_loop(cf_node_completed);
ASSERTED pco_loop *last_loop =
util_dynarray_pop(&loop_stack, pco_loop *);
assert(loop == last_loop);
assert(loop_nestings == 0);
loop_nestings = util_dynarray_pop(&loop_nestings_stack, unsigned);
break;
}
default:
break;
}
}
/* Handle the start of an if/loop, or lower break/continue for blocks. */
switch (cf_node->type) {
case PCO_CF_NODE_TYPE_IF: {
pco_if *pif = pco_cf_node_as_if(cf_node);
pif->pred_exec = can_pred_exec(pif);
util_dynarray_append(&pif_stack, pif);
if (!pif->pred_exec)
++loop_nestings;
lower_if(pif, func);
progress = true;
break;
}
case PCO_CF_NODE_TYPE_LOOP: {
util_dynarray_append(&loop_nestings_stack, loop_nestings);
loop_nestings = 0;
pco_loop *loop = pco_cf_node_as_loop(cf_node);
util_dynarray_append(&loop_stack, loop);
lower_loop(loop, func);
progress = true;
break;
}
case PCO_CF_NODE_TYPE_BLOCK: {
pco_block *block = pco_cf_node_as_block(cf_node);
pco_foreach_instr_in_block_safe (instr, block) {
if (instr->op != PCO_OP_BREAK && instr->op != PCO_OP_CONTINUE)
continue;
/* This has to be the last instruction in the block. */
assert(instr == pco_last_instr(block));
pco_if *current_pif = NULL;
if (instr->parent_block->cf_node.parent->type ==
PCO_CF_NODE_TYPE_IF) {
current_pif = util_dynarray_top(&pif_stack, pco_if *);
assert(current_pif ==
pco_cf_node_as_if(instr->parent_block->cf_node.parent));
}
pco_loop *current_loop = util_dynarray_top(&loop_stack, pco_loop *);
lower_break_continue(instr,
func,
current_pif,
current_loop,
loop_nestings,
instr->op == PCO_OP_CONTINUE);
progress = true;
}
break;
}
default:
break;
}
}
assert(!util_dynarray_num_elements(&loop_stack, pco_loop *));
assert(!util_dynarray_num_elements(&pif_stack, pco_if *));
assert(!util_dynarray_num_elements(&loop_nestings_stack, unsigned));
assert(loop_nestings == 0);
ralloc_free(mem_ctx);
return progress;
}
/**
* \brief Control-flow pass.
*
* \param[in,out] shader PCO shader.
* \return True if the pass made progress.
*/
bool pco_cf(pco_shader *shader)
{
bool progress = false;
pco_foreach_func_in_shader (func, shader) {
progress |= pco_lower_cf(func);
}
return progress;
}
+92
View File
@@ -0,0 +1,92 @@
# Copyright © 2024 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
from mako.template import Template, exceptions
from pco_pygen_common import *
from pco_ops import *
from pco_isa import *
from pco_map import *
template = """/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef PCO_COMMON_H
#define PCO_COMMON_H
/**
* \\file pco_common.h
*
* \\brief PCO common definitions.
*/
#include "util/macros.h"
#include <stdbool.h>
#ifndef __OPENCL_VERSION__
#define __constant
#endif
/** Enums. */
% for enum in [enum for enum in enums.values() if enum.parent is None]:
#define _${enum.name.upper()}_COUNT ${enum.unique_count}U
enum ${enum.name} {
% for elem in enum.elems.values():
${elem.cname} = ${hex(elem.value) if enum.is_bitset else elem.value},
% endfor
};
static inline
__constant const char *${enum.name}_str(uint64_t val) {
switch (val) {
% for elem in enum.elems.values():
% if elem.string is not None:
case ${elem.cname}:
return "${elem.string}";
% endif
% endfor
default:
break;
}
UNREACHABLE("");
}
% endfor
/** Enum validation. */
% for enum in enums.values():
static bool ${enum.name}_valid(uint64_t val)
{
% if enum.is_bitset:
return !(val & ~(${enum.valid}ULL));
% else:
return ${' || '.join([f'val == {val}' for val in enum.valid])};
% endif
}
% endfor
/** Bit set variants. */
% for bit_set in bit_sets.values():
#define _${bit_set.name.upper()}_VARIANT_COUNT ${len(bit_set.variants) + 1}U
enum ${bit_set.name}_variant {
${bit_set.name.upper()}_NONE,
% for variant in bit_set.variants:
${variant.cname},
% endfor
};
% endfor
#endif /* PCO_COMMON_H */"""
def main():
try:
print(Template(template).render(enums=enums, bit_sets=bit_sets))
except:
raise Exception(exceptions.text_error_template().render())
if __name__ == '__main__':
main()
+214
View File
@@ -0,0 +1,214 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_const_imms.c
*
* \brief PCO constant immediates lowering pass.
*/
#include "pco.h"
#include "pco_builder.h"
#include "pco_internal.h"
#include "util/macros.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/** Mapping of constant register values and their indices. */
struct const_reg_def {
uint32_t val;
uint8_t idx;
bool flr : 1;
bool neg : 1;
};
/** Constant register values (sorted for bsearch). */
static const struct const_reg_def const_reg_defs[] = {
{ 0x00000000, 0, false, false }, /* */
{ 0x00000001, 1, false, false }, /* */
{ 0x00000002, 2, false, false }, /* */
{ 0x00000003, 3, false, false }, /* */
{ 0x00000004, 4, false, false }, /* */
{ 0x00000005, 5, false, false }, /* */
{ 0x00000006, 6, false, false }, /* */
{ 0x00000007, 7, false, false }, /* */
{ 0x00000008, 8, false, false }, /* */
{ 0x00000009, 9, false, false }, /* */
{ 0x0000000a, 10, false, false }, /* */
{ 0x0000000b, 11, false, false }, /* */
{ 0x0000000c, 12, false, false }, /* */
{ 0x0000000d, 13, false, false }, /* */
{ 0x0000000e, 14, false, false }, /* */
{ 0x0000000f, 15, false, false }, /* */
{ 0x00000010, 16, false, false }, /* */
{ 0x00000011, 17, false, false }, /* */
{ 0x00000012, 18, false, false }, /* */
{ 0x00000013, 19, false, false }, /* */
{ 0x00000014, 20, false, false }, /* */
{ 0x00000015, 21, false, false }, /* */
{ 0x00000016, 22, false, false }, /* */
{ 0x00000017, 23, false, false }, /* */
{ 0x00000018, 24, false, false }, /* */
{ 0x00000019, 25, false, false }, /* */
{ 0x0000001a, 26, false, false }, /* */
{ 0x0000001b, 27, false, false }, /* */
{ 0x0000001c, 28, false, false }, /* */
{ 0x0000001d, 29, false, false }, /* */
{ 0x0000001e, 30, false, false }, /* */
{ 0x0000001f, 31, false, false }, /* */
{ 0x0000007f, 147, false, false }, /* */
{ 0x37800000, 134, false, false }, /* */
{ 0x38000000, 135, false, false }, /* */
{ 0x38800000, 88, false, false }, /* */
{ 0x39000000, 87, false, false }, /* */
{ 0x39800000, 86, false, false }, /* */
{ 0x3a000000, 85, false, false }, /* */
{ 0x3a800000, 84, false, false }, /* */
{ 0x3b000000, 83, false, false }, /* */
{ 0x3b4d2e1c, 136, false, false }, /* */
{ 0x3b800000, 82, false, false }, /* */
{ 0x3c000000, 81, false, false }, /* */
{ 0x3c800000, 80, false, false }, /* */
{ 0x3d000000, 79, false, false }, /* */
{ 0x3d25aee6, 156, false, false }, /* */
{ 0x3d6147ae, 140, false, false }, /* */
{ 0x3d800000, 78, false, false }, /* */
{ 0x3d9e8391, 157, false, false }, /* */
{ 0x3e000000, 77, false, false }, /* */
{ 0x3e2aaaab, 153, false, false }, /* */
{ 0x3e800000, 76, false, false }, /* */
{ 0x3e9a209b, 145, false, false }, /* */
{ 0x3ea2f983, 128, false, false }, /* */
{ 0x3eaaaaab, 152, false, false }, /* */
{ 0x3ebc5ab2, 90, false, false }, /* */
{ 0x3ed55555, 138, false, false }, /* */
{ 0x3f000000, 75, false, false }, /* */
{ 0x3f22f983, 129, false, false }, /* */
{ 0x3f317218, 146, false, false }, /* */
{ 0x3f3504f3, 92, false, false }, /* */
{ 0x3f490fdb, 93, false, false }, /* */
{ 0x3f72a76f, 158, false, false }, /* */
{ 0x3f800000, 64, false, false }, /* */
{ 0x3f860a92, 151, false, false }, /* */
{ 0x3f870a3d, 139, false, false }, /* */
{ 0x3fa2f983, 130, false, false }, /* */
{ 0x3fb504f3, 91, false, false }, /* */
{ 0x3fb8aa3b, 155, false, false }, /* */
{ 0x3fc90fdb, 94, false, false }, /* */
{ 0x40000000, 65, false, false }, /* */
{ 0x4019999a, 159, false, false }, /* */
{ 0x402df854, 89, false, false }, /* */
{ 0x40490fdb, 95, false, false }, /* */
{ 0x40549a78, 154, false, false }, /* */
{ 0x40800000, 66, false, false }, /* */
{ 0x40c90fdb, 131, false, false }, /* */
{ 0x41000000, 67, false, false }, /* */
{ 0x41490fdb, 132, false, false }, /* */
{ 0x414eb852, 137, false, false }, /* */
{ 0x41800000, 68, false, false }, /* */
{ 0x41c90fdb, 133, false, false }, /* */
{ 0x42000000, 69, false, false }, /* */
{ 0x42800000, 70, false, false }, /* */
{ 0x43000000, 71, false, false }, /* */
{ 0x43800000, 72, false, false }, /* */
{ 0x44000000, 73, false, false }, /* */
{ 0x44800000, 74, false, false }, /* */
{ 0x4b000000, 149, false, false }, /* */
{ 0x4b800000, 150, false, false }, /* */
{ 0x7f7fffff, 148, false, false }, /* */
{ 0x7f800000, 142, false, false }, /* */
{ 0x7fff7fff, 144, false, false }, /* */
{ 0x80000000, 141, false, false }, /* */
{ 0xffffffff, 143, false, false }, /* */
};
/**
* \brief Comparison function for bsearch() to support rogue_const_reg_def.
*
* \param[in] lhs The left hand side of the comparison.
* \param[in] rhs The right hand side of the comparison.
* \return 0 if (lhs == rhs), -1 if (lhs < rhs), 1 if (lhs > rhs).
*/
static int constreg_cmp(const void *lhs, const void *rhs)
{
const struct const_reg_def *l = lhs;
const struct const_reg_def *r = rhs;
if (l->val < r->val)
return -1;
else if (l->val > r->val)
return 1;
return 0;
}
/**
* \brief Looks up an immediate in constant registers.
*
* \param[in] imm The immediate to lookup.
* \return A pointer to the constant register definition,
* or NULL if no constant register was found.
*/
inline static const struct const_reg_def *constreg_lookup(uint32_t imm)
{
return bsearch(&(struct const_reg_def){ .val = imm },
const_reg_defs,
ARRAY_SIZE(const_reg_defs),
sizeof(*const_reg_defs),
constreg_cmp);
}
/**
* \brief Converts immediates into constant register lookups where possible.
*
* \param[in,out] shader PCO shader.
* \return True if the pass made progress.
*/
bool pco_const_imms(pco_shader *shader)
{
bool progress = false;
pco_foreach_func_in_shader (func, shader) {
pco_foreach_instr_in_func_safe (instr, func) {
if (instr->op != PCO_OP_MOVI32)
continue;
const struct const_reg_def *const_reg_def =
constreg_lookup(pco_ref_get_imm(instr->src[0]));
if (!const_reg_def)
continue;
pco_builder b =
pco_builder_create(func, pco_cursor_before_instr(instr));
pco_ref dest = instr->dest[0];
pco_ref const_reg =
pco_ref_hwreg(const_reg_def->idx, PCO_REG_CLASS_CONST);
if (!const_reg_def->flr && !const_reg_def->neg) {
pco_mov(&b, dest, const_reg);
} else if (!const_reg_def->flr && const_reg_def->neg) {
pco_fneg(&b, dest, const_reg);
} else if (const_reg_def->flr && !const_reg_def->neg) {
pco_fflr(&b, dest, const_reg);
} else {
/* TODO: use floor and neg mods when support for > 1 is added. */
const_reg = pco_ref_flr(const_reg);
const_reg = pco_ref_neg(const_reg);
pco_fadd(&b, dest, const_reg, pco_zero);
}
pco_instr_delete(instr);
progress = true;
}
}
return progress;
}
+262
View File
@@ -0,0 +1,262 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef PCO_DATA_H
#define PCO_DATA_H
/**
* \file pco_data.h
*
* \brief PCO shader-specific data/compiler-driver interface.
*/
#include "common/pvr_limits.h"
#include "compiler/shader_enums.h"
#include "nir/nir_lower_blend.h"
#include "util/format/u_format.h"
#include <stdbool.h>
#define PCO_POINT_SAMPLER 0xffff
#define PCO_IA_SAMPLER 0xfffe
/* Compiler-specific forward-declarations. */
typedef struct _pco_shader pco_shader;
/** Generic range struct. */
typedef struct _pco_range {
unsigned start;
unsigned count;
union {
unsigned stride;
unsigned offset;
};
} pco_range;
/** PCO vertex shader-specific data. */
typedef struct _pco_vs_data {
/** Attributes/input mappings. */
pco_range attribs[VERT_ATTRIB_MAX];
enum pipe_format attrib_formats[VERT_ATTRIB_MAX];
/** Varyings/output mappings. */
pco_range varyings[VARYING_SLOT_MAX];
unsigned clip_count;
unsigned cull_count;
unsigned f32_smooth; /** Number of F32 linear varyings. */
unsigned f32_flat; /** Number of F32 flat varyings. */
unsigned f32_npc; /** Number of F32 NPC varyings. */
unsigned f16_smooth; /** Number of F16 linear varyings. */
unsigned f16_flat; /** Number of F16 flat varyings. */
unsigned f16_npc; /** Number of F16 NPC varyings. */
unsigned vtxouts; /** How many vertex outputs are written to. */
} pco_vs_data;
enum pco_front_face_op {
PCO_FRONT_FACE_OP_NOP,
PCO_FRONT_FACE_OP_SWAP,
PCO_FRONT_FACE_OP_TRUE,
};
/** PCO fragment shader-specific data. */
typedef struct _pco_fs_data {
/** Varyings/input mappings. */
pco_range varyings[VARYING_SLOT_MAX];
/** Results/output mappings. */
pco_range outputs[FRAG_RESULT_MAX];
/** If outputs are to be placed in tile buffers. */
uint8_t output_tile_buffers;
/** Fragment output formats. */
enum pipe_format output_formats[FRAG_RESULT_MAX];
/** On-chip input attachment mappings. */
pco_range ias_onchip[8];
/** On-chip input attachment formats. */
enum pipe_format ia_formats[8];
uint8_t ia_tile_buffers;
uint8_t ia_has_stencil;
unsigned num_tile_buffers;
pco_range meta;
gl_frag_result z_replicate;
/* Blend options. */
nir_lower_blend_options blend_opts;
pco_range blend_consts;
uint8_t blend_consts_needed;
uint16_t rasterization_samples;
pco_range tile_buffers;
pco_range sample_locations;
gl_varying_slot view_index_slot;
struct {
bool w; /** Whether the shader uses pos.w. */
bool z; /** Whether the shader uses pos.z */
bool pntc; /** Whether the shader uses point coord. */
bool phase_change; /** Whether the shader does a phase change. */
bool fbfetch; /** Whether the shader fetches from the framebuffer. */
bool depth_feedback;
bool discard;
bool early_frag;
bool sample_shading;
bool sample_locations;
bool alpha_to_coverage;
bool olchk_skip;
} uses;
struct {
bool color_write_enable;
} meta_present;
} pco_fs_data;
/** PCO compute shader-specific data. */
typedef struct _pco_cs_data {
unsigned workgroup_size[3]; /** Workgroup size. */
pco_range shmem;
bool zero_shmem;
bool global_shmem;
} pco_cs_data;
/** PCO image descriptor metadata. */
enum pco_image_meta {
PCO_IMAGE_META_LAYER_SIZE,
PCO_IMAGE_META_BUFFER_ELEMS,
PCO_IMAGE_META_Z_SLICE,
PCO_IMAGE_META_PCK_INFO,
PCO_IMAGE_META_COUNT,
};
/** PCO sampler descriptor metadata. */
enum pco_sampler_meta {
PCO_SAMPLER_META_COMPARE_OP,
PCO_SAMPLER_META_RSVD0,
PCO_SAMPLER_META_RSVD1,
PCO_SAMPLER_META_RSVD2,
PCO_SAMPLER_META_COUNT,
};
/** PCO descriptor binding data. */
typedef struct _pco_binding_data {
pco_range range; /** Descriptor location range. */
bool used; /** Whether the descriptor binding is used by the shader. */
/** Whether the descriptor binding is a combined image sampler. */
bool is_img_smp;
} pco_binding_data;
/** PCO descriptor set data. */
typedef struct _pco_descriptor_set_data {
pco_range range; /** Descriptor location range. */
pco_range dynamic_range; /** Dynamic descriptor location range. */
unsigned binding_count; /** Number of bindings. */
pco_binding_data *bindings; /** Descriptor set bindings. */
bool used; /** Whether the descriptor set is used by the shader. */
} pco_descriptor_set_data;
/** PCO push constant data. */
typedef struct _pco_push_const_data {
pco_range range; /** Push constant range. */
unsigned used;
} pco_push_const_data;
/** PCO common data. */
typedef struct _pco_common_data {
/** System value mappings. */
pco_range sys_vals[SYSTEM_VALUE_MAX];
/** Descriptor set data. */
pco_descriptor_set_data desc_sets[PVR_MAX_DESCRIPTOR_SETS];
/** Push constant data. */
pco_push_const_data push_consts;
pco_range point_sampler;
pco_range ia_sampler;
unsigned temps; /** Number of allocated temp registers. */
unsigned vtxins; /** Number of allocated vertex input registers. */
unsigned interns; /** Number of allocated internal registers. */
unsigned spilled_temps;
pco_range spill_info; /* addr_lo, addr_hi, block_size */
unsigned scratch;
pco_range scratch_info; /* addr_lo, addr_hi, block_size */
unsigned coeffs; /** Number of allocated coefficient registers. */
unsigned shareds; /** Number of allocated shared registers. */
unsigned entry_offset; /** Offset of the shader entrypoint. */
struct {
bool atomics; /** Whether the shader uses atomics. */
bool barriers; /** Whether the shader uses barriers. */
bool side_effects; /** Whether the shader has side effects. */
bool empty; /** Whether the shader is empty. */
bool point_sampler; /** Whether the shader uses a point sampler. */
bool ia_sampler; /** Does the shader use an input attachment sampler? */
bool usclib; /** Does the shader use usclib functions? */
} uses;
bool robust_buffer_access;
bool null_descriptor;
bool image_2d_view_of_3d;
bool multiview;
} pco_common_data;
/** PCO shader data. */
typedef struct _pco_data {
union {
pco_vs_data vs;
pco_fs_data fs;
pco_cs_data cs;
};
pco_common_data common;
} pco_data;
/** PCO precompiled shader data. */
typedef struct PACKED _pco_precomp_data {
uint8_t temps;
uint8_t vtxins;
uint16_t coeffs : 12;
uint16_t shareds : 12;
uint16_t size_dwords;
uint8_t pad[1];
uint32_t binary[];
} pco_precomp_data;
static_assert(sizeof(pco_precomp_data) == 8, "sizeof(pco_precomp_data) != 8");
pco_precomp_data pco_get_precomp_data(pco_shader *shader);
struct pvr_stats pco_get_pvr_stats(pco_shader *shader);
#endif /* PCO_DATA_H */
+94
View File
@@ -0,0 +1,94 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_debug.c
*
* \brief Debug-related functions.
*/
#include "pco.h"
#include "pco_internal.h"
#include "util/macros.h"
#include "util/u_call_once.h"
#include "util/u_debug.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static const struct debug_named_value pco_debug_options[] = {
{ "val_skip", PCO_DEBUG_VAL_SKIP, "Skip IR validation." },
{ "reindex", PCO_DEBUG_REINDEX, "Reindex IR at the end of each pass." },
{ "no_pred_cf", PCO_DEBUG_NO_PRED_CF, "No predicated execution in CF." },
{ "alloc_extra_vtxins",
PCO_DEBUG_ALLOC_EXTRA_VTXINS,
"Allocates additional vertex input registers." },
{ "int_smp",
PCO_DEBUG_INT_SMP,
"Enable integer coordinate support for sampler instructions." },
{ "global_shmem",
PCO_DEBUG_GLOBAL_SHMEM,
"Force spill shared memory to global memory." },
DEBUG_NAMED_VALUE_END,
};
static const struct debug_named_value pco_debug_print_options[] = {
{ "vs", PCO_DEBUG_PRINT_VS, "Print the IR for vertex shaders." },
{ "fs", PCO_DEBUG_PRINT_FS, "Print the IR for fragment shaders." },
{ "cs", PCO_DEBUG_PRINT_CS, "Print the IR for compute shaders." },
{ "all", PCO_DEBUG_PRINT_ALL, "Print the IR for all shaders." },
{ "internal",
PCO_DEBUG_PRINT_INTERNAL,
"Print the IR for internal shader types." },
{ "passes", PCO_DEBUG_PRINT_PASSES, "Print the IR after each pass." },
{ "nir", PCO_DEBUG_PRINT_NIR, "Print the resulting NIR." },
{ "binary", PCO_DEBUG_PRINT_BINARY, "Print the resulting binary." },
{ "verbose", PCO_DEBUG_PRINT_VERBOSE, "Print verbose IR." },
{ "ra", PCO_DEBUG_PRINT_RA, "Print register alloc info." },
{ "stats", PCO_DEBUG_PRINT_STATS, "Print shader stats." },
DEBUG_NAMED_VALUE_END,
};
DEBUG_GET_ONCE_FLAGS_OPTION(pco_debug, "PCO_DEBUG", pco_debug_options, 0U)
uint64_t pco_debug = 0U;
DEBUG_GET_ONCE_FLAGS_OPTION(pco_debug_print,
"PCO_DEBUG_PRINT",
pco_debug_print_options,
0U)
uint64_t pco_debug_print = 0U;
DEBUG_GET_ONCE_OPTION(pco_skip_passes, "PCO_SKIP_PASSES", "")
const char *pco_skip_passes = "";
DEBUG_GET_ONCE_OPTION(pco_color, "PCO_COLOR", NULL)
bool pco_color = false;
static void pco_debug_init_once(void)
{
/* Get debug flags. */
pco_debug = debug_get_option_pco_debug();
pco_debug_print = debug_get_option_pco_debug_print();
pco_skip_passes = debug_get_option_pco_skip_passes();
/* Get/parse color option. */
const char *color_opt = debug_get_option_pco_color();
if (!color_opt || !strcmp(color_opt, "auto") || !strcmp(color_opt, "a"))
pco_color = isatty(fileno(stdout));
else if (!strcmp(color_opt, "on") || !strcmp(color_opt, "1"))
pco_color = true;
else if (!strcmp(color_opt, "off") || !strcmp(color_opt, "0"))
pco_color = false;
}
void pco_debug_init(void)
{
static util_once_flag flag = UTIL_ONCE_FLAG_INIT;
util_call_once(&flag, pco_debug_init_once);
}
+59
View File
@@ -0,0 +1,59 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_end.c
*
* \brief PCO shader ending pass.
*/
#include "pco.h"
#include "pco_builder.h"
#include "pco_internal.h"
#include "util/macros.h"
#include <stdbool.h>
/**
* \brief Processes end of shader instruction(s).
*
* \param[in,out] shader PCO shader.
* \return True if the pass made progress.
*/
bool pco_end(pco_shader *shader)
{
/* TODO: Support for multiple end points. */
pco_func *entry = pco_entrypoint(shader);
pco_block *last_block = pco_func_last_block(entry);
pco_instr *last_instr = pco_last_instr(last_block);
pco_builder b =
pco_builder_create(entry, pco_cursor_after_block(last_block));
if (shader->stage == MESA_SHADER_VERTEX) {
if (last_instr && last_instr->op == PCO_OP_UVSW_WRITE &&
pco_instr_has_default_exec(last_instr) &&
pco_instr_get_rpt(last_instr) == 1) {
pco_instr *new_last_instr =
pco_uvsw_write_emit_endtask(&b,
last_instr->src[0],
last_instr->src[1]);
pco_instr_delete(last_instr);
last_instr = new_last_instr;
} else {
last_instr = pco_uvsw_emit_endtask(&b);
}
}
if (last_instr && pco_instr_has_end(last_instr)) {
pco_instr_set_end(last_instr, true);
return true;
}
pco_nop(&b, .end = true);
return true;
}
+226
View File
@@ -0,0 +1,226 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_group_instrs.c
*
* \brief PCO instruction grouping pass.
*/
#include "hwdef/rogue_hw_defs.h"
#include "pco.h"
#include "pco_builder.h"
#include "pco_map.h"
#include "util/macros.h"
#include <stdbool.h>
/**
* \brief Calculates the decode-assist value for an instruction group.
*
* \param[in] igrp PCO instruction group.
* \return The decode-assist value.
*/
static inline unsigned calc_da(pco_igrp *igrp)
{
unsigned da = igrp->enc.len.hdr;
bool no_srcs_dests = !igrp->enc.len.lower_srcs &&
!igrp->enc.len.upper_srcs && !igrp->enc.len.dests;
switch (igrp->hdr.alutype) {
case PCO_ALUTYPE_MAIN:
case PCO_ALUTYPE_BITWISE: {
pco_foreach_phase_rev (p) {
if (igrp->hdr.alutype == PCO_ALUTYPE_BITWISE || p > PCO_OP_PHASE_1)
da += igrp->enc.len.instrs[p];
}
break;
}
case PCO_ALUTYPE_CONTROL:
if (no_srcs_dests)
return 0;
da += igrp->enc.len.instrs[PCO_OP_PHASE_CTRL];
break;
default:
UNREACHABLE("");
}
return da;
}
/**
* \brief Calculates the lengths for an instruction group.
*
* \param[in,out] igrp PCO instruction group.
* \param[in,out] offset_bytes The cumulative shader offset (in bytes).
*/
static inline void calc_lengths(pco_igrp *igrp, unsigned *offset_bytes)
{
unsigned total_length = 0;
igrp->enc.len.hdr = pco_igrp_hdr_bytes(igrp->variant.hdr);
total_length += igrp->enc.len.hdr;
igrp->enc.len.lower_srcs = pco_src_bytes(igrp->variant.lower_src);
total_length += igrp->enc.len.lower_srcs;
igrp->enc.len.upper_srcs = pco_src_bytes(igrp->variant.upper_src);
total_length += igrp->enc.len.upper_srcs;
igrp->enc.len.iss = pco_iss_bytes(igrp->variant.iss);
total_length += igrp->enc.len.iss;
igrp->enc.len.dests = pco_dst_bytes(igrp->variant.dest);
total_length += igrp->enc.len.dests;
pco_foreach_phase_in_igrp (igrp, phase) {
switch (igrp->hdr.alutype) {
case PCO_ALUTYPE_MAIN:
if (phase == PCO_OP_PHASE_BACKEND) {
igrp->enc.len.instrs[phase] =
pco_backend_bytes(igrp->variant.instr[phase].backend);
} else {
igrp->enc.len.instrs[phase] =
pco_main_bytes(igrp->variant.instr[phase].main);
}
break;
case PCO_ALUTYPE_BITWISE:
igrp->enc.len.instrs[phase] =
pco_bitwise_bytes(igrp->variant.instr[phase].bitwise);
break;
case PCO_ALUTYPE_CONTROL:
igrp->enc.len.instrs[phase] =
pco_ctrl_bytes(igrp->variant.instr[phase].control);
break;
default:
UNREACHABLE("");
}
total_length += igrp->enc.len.instrs[phase];
}
igrp->enc.len.word_padding = total_length % 2;
total_length += igrp->enc.len.word_padding;
igrp->enc.len.total = total_length;
/* Set igrp header length and decode-assist. */
igrp->hdr.length = igrp->enc.len.total / 2;
igrp->hdr.da = calc_da(igrp);
/* Set offset and update running offset byte count. */
igrp->enc.offset = *offset_bytes;
*offset_bytes += igrp->enc.len.total;
}
/**
* \brief Calculates the alignment padding to be applied to
* the last instruction group in the shader.
*
* \param[in,out] last_igrp The last instruction group.
* \param[in,out] offset_bytes The cumulative shader offset (in bytes).
*/
static inline void calc_align_padding(pco_igrp *last_igrp,
unsigned *offset_bytes)
{
/* We should never end up with a completely empty shader. */
assert(last_igrp);
unsigned total_align = last_igrp->enc.len.total % ROGUE_ICACHE_ALIGN;
unsigned offset_align = last_igrp->enc.offset % ROGUE_ICACHE_ALIGN;
if (total_align) {
unsigned padding = ROGUE_ICACHE_ALIGN - total_align;
*offset_bytes += padding;
/* Pad the size of the last igrp. */
last_igrp->enc.len.align_padding += padding;
last_igrp->enc.len.total += padding;
/* Update the last igrp header length. */
last_igrp->hdr.length = last_igrp->enc.len.total / 2;
}
if (offset_align) {
unsigned padding = ROGUE_ICACHE_ALIGN - offset_align;
*offset_bytes += padding;
/* Pad the size of the penultimate igrp. */
pco_igrp *penultimate_igrp = pco_prev_igrp(last_igrp);
/* If we only have one igrp then its offset will be zero. */
assert(penultimate_igrp);
penultimate_igrp->enc.len.align_padding += padding;
penultimate_igrp->enc.len.total += padding;
/* Update the penultimate igrp header length. */
penultimate_igrp->hdr.length = penultimate_igrp->enc.len.total / 2;
/* Update the offset of the last igrp. */
last_igrp->enc.offset += padding;
}
}
/**
* \brief Converts a PCO instruction to an instruction group.
*
* \param[in] b PCO builder.
* \param[in] instr PCO instruction.
* \param[out] igrp PCO instruction group.
* \param[in,out] offset_bytes The cumulative shader offset (in bytes).
*/
static void pco_instr_to_igrp(pco_builder *b,
pco_instr *instr,
pco_igrp *igrp,
unsigned *offset_bytes)
{
pco_map_igrp(igrp, instr);
calc_lengths(igrp, offset_bytes);
pco_builder_insert_igrp(b, igrp);
}
/**
* \brief Groups PCO instructions into instruction groups.
*
* \param[in,out] shader PCO shader.
* \return True if the pass made progress.
*/
bool pco_group_instrs(pco_shader *shader)
{
pco_builder b;
pco_igrp *igrp = NULL;
unsigned offset_bytes = 0;
assert(!shader->is_grouped);
pco_foreach_func_in_shader (func, shader) {
/* TODO: double check that *start* alignment is satisfied by
* calc_align_padding when having multiple functions?
*/
pco_foreach_block_in_func (block, func) {
b = pco_builder_create(func, pco_cursor_before_block(block));
pco_foreach_instr_in_block_safe (instr, block) {
igrp = pco_igrp_create(func);
pco_instr_to_igrp(&b, instr, igrp, &offset_bytes);
}
}
/* Ensure the final instruction group has a total size and offset
* that are a multiple of the icache alignment.
*/
calc_align_padding(igrp, &offset_bytes);
}
shader->is_grouped = true;
return true;
}
+110
View File
@@ -0,0 +1,110 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_index.c
*
* \brief PCO indexing pass.
*/
#include "pco.h"
#include "pco_internal.h"
#include "util/hash_table.h"
#include "util/macros.h"
#include "util/ralloc.h"
#include <assert.h>
#include <stdbool.h>
/**
* \brief Indexes all shader child structures.
*
* \param[in,out] shader PCO shader.
* \param[in] skip_ssa Whether to skip SSA indexing.
* \return True if the pass made progress.
*/
bool pco_index(pco_shader *shader, bool skip_ssa)
{
/* TODO */
if (shader->is_grouped)
return false;
shader->next_func = 0;
pco_foreach_func_in_shader (func, shader) {
unsigned *ssa_idx_map = NULL;
if (!skip_ssa) {
ssa_idx_map =
rzalloc_array_size(NULL, sizeof(*ssa_idx_map), func->next_ssa);
}
func->index = shader->next_func++;
func->next_instr = 0;
func->next_block = 0;
struct hash_table_u64 *vec_infos = NULL;
if (!skip_ssa) {
func->next_ssa = 0;
vec_infos = _mesa_hash_table_u64_create(func);
}
pco_foreach_block_in_func (block, func) {
block->index = func->next_block++;
pco_foreach_instr_in_block (instr, block) {
instr->index = func->next_instr++;
if (!skip_ssa) {
pco_foreach_instr_dest_ssa (pdest, instr) {
ssa_idx_map[pdest->val] = func->next_ssa++;
if (instr->op == PCO_OP_VEC) {
pco_vec_info *vec_info =
_mesa_hash_table_u64_search(func->vec_infos,
pdest->val);
ralloc_steal(vec_infos, vec_info);
_mesa_hash_table_u64_insert(vec_infos,
ssa_idx_map[pdest->val],
vec_info);
}
pdest->val = ssa_idx_map[pdest->val];
}
}
}
}
if (!skip_ssa) {
pco_foreach_instr_in_func (instr, func) {
pco_foreach_instr_src_ssa (psrc, instr) {
psrc->val = ssa_idx_map[psrc->val];
}
}
}
func->next_if = 0;
pco_foreach_if_in_func (pif, func) {
pif->index = func->next_if++;
if (!skip_ssa) {
if (!pco_ref_is_ssa(pif->cond))
continue;
pif->cond.val = ssa_idx_map[pif->cond.val];
}
}
func->next_loop = 0;
pco_foreach_loop_in_func (loop, func) {
loop->index = func->next_loop++;
}
if (!skip_ssa) {
_mesa_hash_table_u64_destroy(func->vec_infos);
func->vec_infos = vec_infos;
ralloc_free(ssa_idx_map);
}
}
return true;
}
+134
View File
@@ -0,0 +1,134 @@
# Copyright © 2024 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
from mako.template import Template, exceptions
from pco_ops import *
from pco_map import *
template = """/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \\file pco_info.c
*
* \\brief PCO info structures.
*/
#include "pco_common.h"
#include "pco_internal.h"
#include "pco_isa.h"
#include "pco_ops.h"
const struct pco_op_info pco_op_info[_PCO_OP_COUNT] = {
% for op in ops.values():
[${op.cname.upper()}] = {
.str = "${op.name}",
.num_dests = ${op.num_dests},
.num_srcs = ${op.num_srcs},
.mods = ${op.cop_mods},
.mod_map = {
% for mod, index in op.op_mod_map.items():
[${mod}] = ${index},
% endfor
},
.dest_mods = {
% for index, cdest_mods in op.cdest_mods.items():
[${index}] = ${cdest_mods},
% endfor
},
.src_mods = {
% for index, csrc_mods in op.csrc_mods.items():
[${index}] = ${csrc_mods},
% endfor
},
.type = PCO_OP_TYPE_${op.op_type.upper()},
.has_target_cf_node = ${str(op.has_target_cf_node).lower()},
% if op.bname in group_maps:
.dest_intrn_map = {
% for index, val in group_maps[op.bname].dest_intrn_map:
[${index}] = ${val},
% endfor
},
.src_intrn_map = {
% for index, val in group_maps[op.bname].src_intrn_map:
[${index}] = ${val},
% endfor
},
% endif
#ifndef NDEBUG
% if op.bname in encode_maps:
.grp_dest_maps = {
% for phase, dests, _ in encode_maps[op.bname].op_ref_maps:
[${phase}] = {
% for dest in dests:
[${loop.index}] = ${dest},
% endfor
},
% endfor
},
.grp_src_maps = {
% for phase, _, srcs in encode_maps[op.bname].op_ref_maps:
[${phase}] = {
% for src in srcs:
[${loop.index}] = ${src},
% endfor
},
% endfor
},
% endif
#endif /* NDEBUG */
},
% endfor
};
const struct pco_op_mod_info pco_op_mod_info[_PCO_OP_MOD_COUNT] = {
% for name, op_mod in op_mods.items():
[${op_mod.cname}] = {
.print_early = ${str(op_mod.t.print_early).lower()},
.type = ${op_mod.ctype},
% if op_mod.t.base_type == BaseType.enum:
.is_bitset = ${str(op_mod.t.enum.is_bitset).lower()},
.strs = (const char * []){
% for elem in op_mod.t.enum.elems.values():
[${elem.cname}] = "${elem.string}",
% endfor
},
% else:
.str = "${name}",
% endif
% if op_mod.t.nzdefault is not None:
.nzdefault = ${op_mod.t.nzdefault},
% endif
},
% endfor
};
const struct pco_ref_mod_info pco_ref_mod_info[_PCO_REF_MOD_COUNT] = {
% for name, ref_mod in ref_mods.items():
[${ref_mod.cname}] = {
.type = ${ref_mod.ctype},
% if ref_mod.t.base_type == BaseType.enum:
.is_bitset = ${str(ref_mod.t.enum.is_bitset).lower()},
.strs = (const char * []){
% for elem in ref_mod.t.enum.elems.values():
[${elem.cname}] = "${elem.string}",
% endfor
},
% else:
.str = "${name}",
% endif
},
% endfor
};"""
def main():
try:
print(Template(template).render(BaseType=BaseType, ops=ops, op_mods=op_mods, ref_mods=ref_mods, group_maps=group_maps, encode_maps=encode_maps))
except:
raise Exception(exceptions.text_error_template().render())
if __name__ == '__main__':
main()
File diff suppressed because it is too large. Load diff
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_ir.c
*
* \brief PCO IR-specific functions.
*/
#include "pco.h"
#include "pco_internal.h"
#include <stdbool.h>
#include <stdio.h>
/**
* \brief Runs passes on a PCO shader.
*
* \param[in] ctx PCO compiler context.
* \param[in,out] shader PCO shader.
*/
void pco_process_ir(pco_ctx *ctx, pco_shader *shader)
{
pco_validate_shader(shader, "before passes");
PCO_PASS(_, shader, pco_const_imms);
PCO_PASS(_, shader, pco_opt);
bool progress;
do {
progress = false;
PCO_PASS(progress, shader, pco_dce);
} while (progress);
PCO_PASS(_, shader, pco_bool);
PCO_PASS(_, shader, pco_cf);
PCO_PASS(_, shader, pco_shrink_vecs);
PCO_PASS(_, shader, pco_const_imms);
PCO_PASS(_, shader, pco_opt_comp_only_vecs);
PCO_PASS(_, shader, pco_opt);
do {
progress = false;
PCO_PASS(progress, shader, pco_dce);
} while (progress);
/* TODO: schedule after RA instead as e.g. vecs may no longer be the first
* time a drc result is used.
*/
PCO_PASS(_, shader, pco_schedule);
PCO_PASS(_, shader, pco_pre_ra_legalize);
PCO_PASS(_, shader, pco_ra);
PCO_PASS(_, shader, pco_post_ra_legalize);
PCO_PASS(_, shader, pco_end);
PCO_PASS(_, shader, pco_group_instrs);
pco_validate_shader(shader, "after passes");
if (pco_should_print_shader(shader))
pco_print_shader(shader, stdout, "after passes");
}
+114
View File
@@ -0,0 +1,114 @@
# Copyright © 2024 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
from mako.template import Template, exceptions
from pco_isa import *
template = """/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef PCO_ISA_H
#define PCO_ISA_H
/**
* \\file pco_isa.h
*
* \\brief PCO ISA definitions.
*/
#include "pco_common.h"
#include "util/macros.h"
#include <stdbool.h>
% for _bit_set_name, bit_set in bit_sets.items():
/** ${_bit_set_name} */
enum ${bit_set.name}_field {
% for field in bit_set.fields.values():
${field.cname},
% endfor
};
static unsigned ${bit_set.name}_bytes(enum ${bit_set.name}_variant variant)
{
switch (variant) {
case ${bit_set.name.upper()}_NONE: return 0;
% for variant in bit_set.variants:
case ${variant.cname}: return ${variant.bytes};
% endfor
default: break;
}
UNREACHABLE("");
}
static unsigned ${bit_set.name}_encode_field(uint8_t *bin, enum ${bit_set.name}_field field, uint64_t val)
{
uint64_t enc_val;
switch (field) {
% for field in bit_set.fields.values():
case ${field.cname}:
% if field.field_type.check is not None:
assert(${field.field_type.check.format('val')});
% endif
% if field.reserved is not None:
assert(val == ${field.reserved});
% endif
enc_val = ${field.field_type.encode.format('val') if field.field_type.encode is not None else 'val'};
assert(${field.validate.format('enc_val')});
% for encoding in field.encoding:
${encoding.clear.format('bin')};
${encoding.set.format('bin', 'enc_val')};
% endfor
return ${field.encoded_bits};
% endfor
default:
break;
}
UNREACHABLE("");
}
% for bit_struct in bit_set.bit_structs.values():
% if len(bit_struct.struct_fields) > 0:
struct ${bit_struct.name} {
% for struct_field in bit_struct.struct_fields.values():
${struct_field.type.name} ${struct_field.field} : ${struct_field.bits};
% endfor
};
% endif
% if len(bit_struct.struct_fields) > 0:
#define ${bit_struct.name}_encode(bin, ...) _${bit_struct.name}_encode(bin, (const struct ${bit_struct.name}){0, ##__VA_ARGS__})
static unsigned _${bit_struct.name}_encode(uint8_t *bin, const struct ${bit_struct.name} s)
% else:
static unsigned ${bit_struct.name}_encode(uint8_t *bin)
% endif
{
unsigned bits_encoded = 0;
% for encode_field in bit_struct.encode_fields:
bits_encoded += ${bit_set.name}_encode_field(bin, ${encode_field.name}, ${encode_field.value});
% endfor
assert(!(bits_encoded % 8));
return bits_encoded / 8;
}
% endfor
% endfor
#endif /* PCO_ISA_H */"""
def main():
try:
print(Template(template).render(bit_sets=bit_sets))
except:
raise Exception(exceptions.text_error_template().render())
if __name__ == '__main__':
main()
File diff suppressed because it is too large. Load diff
+517
View File
@@ -0,0 +1,517 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_legalize.c
*
* \brief PCO legalizing pass.
*/
#include "pco.h"
#include "pco_builder.h"
#include "pco_internal.h"
#include "util/macros.h"
#include <stdbool.h>
static inline bool ref_needs_olchk(pco_ref ref)
{
if (!pco_ref_is_reg(ref))
return false;
switch (pco_ref_get_reg_class(ref)) {
case PCO_REG_CLASS_PIXOUT:
return true;
case PCO_REG_CLASS_SPEC:
return ref.val == PCO_SR_OUTPUT_PART ||
(ref.val >= PCO_SR_TILED_LD_COMP0 &&
ref.val <= PCO_SR_TILED_ST_COMP3) ||
(ref.val >= PCO_SR_TILED_LD_COMP4 &&
ref.val <= PCO_SR_TILED_ST_COMP7);
default:
break;
}
return false;
}
/**
* \brief Insert a mov to legalize how a hardware register is referenced.
*
* \param[in,out] instr PCO instr.
* \param[in,out] ref Reference to be legalized.
* \param[in] needs_s124 Whether the mapping needs to use S{1,2,4}
* rather than S{0,2,3}.
* \return True if progress was made.
*/
static void insert_mov_ref(pco_instr *instr, pco_ref *ref, bool needs_s124)
{
if (instr->op == PCO_OP_MBYP && needs_s124 && !pco_ref_has_mods_set(*ref)) {
instr->op = PCO_OP_MOVS1;
return;
} else if (instr->op == PCO_OP_MOVS1 && !needs_s124) {
instr->op = PCO_OP_MBYP;
return;
}
assert(pco_ref_is_scalar(*ref));
pco_ref new_ref = pco_ref_new_ssa(instr->parent_func,
pco_ref_get_bits(*ref),
pco_ref_get_chans(*ref));
pco_ref_xfer_mods(&new_ref, ref, true);
pco_builder b =
pco_builder_create(instr->parent_func, pco_cursor_before_instr(instr));
enum pco_exec_cnd exec_cnd = pco_instr_get_exec_cnd(instr);
pco_instr *mov_instr;
if (needs_s124)
mov_instr = pco_movs1(&b, new_ref, *ref, .exec_cnd = exec_cnd);
else
mov_instr = pco_mbyp(&b, new_ref, *ref, .exec_cnd = exec_cnd);
if (pco_instr_has_olchk(instr) && pco_instr_get_olchk(instr) &&
ref_needs_olchk(*ref)) {
assert(pco_instr_has_olchk(mov_instr));
pco_instr_set_olchk(mov_instr, true);
pco_instr_set_olchk(instr, false);
}
*ref = new_ref;
}
/**
* \brief Try to legalize an instruction's hardware source mappings.
*
* \param[in,out] instr PCO instr.
* \param[in] info PCO op info.
* \return True if progress was made.
*/
static bool try_legalize_src_mappings(pco_instr *instr,
const struct pco_op_info *info)
{
bool progress = false;
bool needs_s124;
/* Check dests. */
pco_foreach_instr_dest (pdest, instr) {
unsigned dest_index = pdest - instr->dest;
if (!info->dest_intrn_map[dest_index])
continue;
enum pco_io mapped_src = PCO_IO_S0 + info->dest_intrn_map[dest_index] - 1;
if (ref_src_map_valid(*pdest, mapped_src, &needs_s124))
continue;
insert_mov_ref(instr, pdest, needs_s124);
progress = true;
}
/* Check srcs. */
pco_foreach_instr_src (psrc, instr) {
unsigned src_index = psrc - instr->src;
if (!info->src_intrn_map[src_index])
continue;
enum pco_io mapped_src = PCO_IO_S0 + info->src_intrn_map[src_index] - 1;
if (ref_src_map_valid(*psrc, mapped_src, &needs_s124))
continue;
insert_mov_ref(instr, psrc, needs_s124);
progress = true;
}
return progress;
}
static inline bool xfer_op_mods(pco_instr *dest, pco_instr *src)
{
bool all_xfered = true;
for (enum pco_op_mod mod = PCO_OP_MOD_NONE + 1; mod < _PCO_OP_MOD_COUNT;
++mod) {
bool dest_has_mod = pco_instr_has_mod(dest, mod);
bool src_has_mod = pco_instr_has_mod(src, mod);
if (!dest_has_mod && !src_has_mod)
continue;
if (dest_has_mod != src_has_mod) {
all_xfered = false;
continue;
}
pco_instr_set_mod(dest, mod, pco_instr_get_mod(src, mod));
}
return all_xfered;
}
/**
* \brief Legalize fence pseudo instruction.
*
* \param[in,out] instr PCO instr.
* \return True if progress was made.
*/
static bool legalize_fence(pco_instr *instr)
{
pco_builder b =
pco_builder_create(instr->parent_func, pco_cursor_before_instr(instr));
pco_flush_p0(&b);
pco_br_next(&b, .exec_cnd = PCO_EXEC_CND_E1_Z1);
pco_br_next(&b, .exec_cnd = PCO_EXEC_CND_E1_Z0);
pco_instr_delete(instr);
return true;
}
static bool legalize_pseudo(pco_instr *instr)
{
switch (instr->op) {
case PCO_OP_FENCE:
return legalize_fence(instr);
case PCO_OP_MOV:
if (pco_ref_is_reg(instr->src[0]) &&
pco_ref_get_reg_class(instr->src[0]) == PCO_REG_CLASS_SPEC)
instr->op = PCO_OP_MOVS1;
else
instr->op = PCO_OP_MBYP;
return true;
case PCO_OP_MOV_OFFSET: {
pco_builder b =
pco_builder_create(instr->parent_func, pco_cursor_before_instr(instr));
pco_ref dest = instr->dest[0];
pco_ref src = instr->src[0];
pco_ref offset = instr->src[1];
unsigned idx_reg_num = 0;
pco_ref idx_reg =
pco_ref_hwreg_idx(idx_reg_num, idx_reg_num, PCO_REG_CLASS_INDEX);
pco_mbyp(&b, idx_reg, offset, .exec_cnd = pco_instr_get_exec_cnd(instr));
if (pco_instr_get_offset_sd(instr) == PCO_OFFSET_SD_SRC)
src = pco_ref_hwreg_idx_from(idx_reg_num, src);
else
dest = pco_ref_hwreg_idx_from(idx_reg_num, dest);
pco_instr *mbyp = pco_mbyp(&b, dest, src);
xfer_op_mods(mbyp, instr);
pco_instr_delete(instr);
return true;
}
case PCO_OP_OP_ATOMIC_OFFSET: {
pco_builder b =
pco_builder_create(instr->parent_func, pco_cursor_before_instr(instr));
pco_ref dest = instr->dest[0];
pco_ref shmem_dest = instr->dest[1];
pco_ref shmem_src = instr->src[0];
pco_ref value = instr->src[1];
pco_ref value_swap = instr->src[2];
pco_ref offset = instr->src[3];
unsigned idx_reg_num = 0;
pco_ref idx_reg =
pco_ref_hwreg_idx(idx_reg_num, idx_reg_num, PCO_REG_CLASS_INDEX);
pco_mbyp(&b, idx_reg, offset, .exec_cnd = pco_instr_get_exec_cnd(instr));
shmem_dest = pco_ref_hwreg_idx_from(idx_reg_num, shmem_dest);
shmem_src = pco_ref_hwreg_idx_from(idx_reg_num, shmem_src);
pco_instr *repl;
enum pco_atom_op atom_op = pco_instr_get_atom_op(instr);
switch (atom_op) {
case PCO_ATOM_OP_ADD:
assert(pco_ref_is_null(value_swap));
repl = pco_iadd32_atomic(&b,
dest,
shmem_dest,
shmem_src,
value,
pco_ref_null(),
.s = true);
break;
case PCO_ATOM_OP_XCHG:
assert(pco_ref_is_null(value_swap));
repl = pco_xchg_atomic(&b, dest, shmem_dest, shmem_src, value);
break;
case PCO_ATOM_OP_CMPXCHG:
assert(!pco_ref_is_null(value_swap));
repl = pco_cmpxchg_atomic(&b,
dest,
shmem_dest,
shmem_src,
value,
value_swap,
.tst_type_main = PCO_TST_TYPE_MAIN_U32);
break;
case PCO_ATOM_OP_UMIN:
assert(pco_ref_is_null(value_swap));
repl = pco_min_atomic(&b,
dest,
shmem_dest,
shmem_src,
value,
.tst_type_main = PCO_TST_TYPE_MAIN_U32);
break;
case PCO_ATOM_OP_IMIN:
assert(pco_ref_is_null(value_swap));
repl = pco_min_atomic(&b,
dest,
shmem_dest,
shmem_src,
value,
.tst_type_main = PCO_TST_TYPE_MAIN_S32);
break;
case PCO_ATOM_OP_UMAX:
assert(pco_ref_is_null(value_swap));
repl = pco_max_atomic(&b,
dest,
shmem_dest,
shmem_src,
value,
.tst_type_main = PCO_TST_TYPE_MAIN_U32);
break;
case PCO_ATOM_OP_IMAX:
assert(pco_ref_is_null(value_swap));
repl = pco_max_atomic(&b,
dest,
shmem_dest,
shmem_src,
value,
.tst_type_main = PCO_TST_TYPE_MAIN_S32);
break;
case PCO_ATOM_OP_AND:
assert(pco_ref_is_null(value_swap));
repl = pco_logical_atomic(&b,
dest,
shmem_dest,
shmem_src,
value,
.logiop = PCO_LOGIOP_AND);
break;
case PCO_ATOM_OP_OR:
assert(pco_ref_is_null(value_swap));
repl = pco_logical_atomic(&b,
dest,
shmem_dest,
shmem_src,
value,
.logiop = PCO_LOGIOP_OR);
break;
case PCO_ATOM_OP_XOR:
assert(pco_ref_is_null(value_swap));
repl = pco_logical_atomic(&b,
dest,
shmem_dest,
shmem_src,
value,
.logiop = PCO_LOGIOP_XOR);
break;
default:
UNREACHABLE("");
}
xfer_op_mods(repl, instr);
pco_instr_delete(instr);
return true;
}
default:
break;
}
return false;
}
static bool try_legalize_large_hwreg_offsets(pco_instr *instr,
const struct pco_op_info *info)
{
unsigned large_hwreg_count = 0;
pco_ref *large_hwregs[_PCO_OP_MAX_SRCS + _PCO_OP_MAX_DESTS] = { 0 };
enum pco_reg_class hwreg_class = ~0;
unsigned min_large_offset = ~0;
ASSERTED unsigned max_large_offset = 0;
/* Check dests. */
pco_foreach_instr_dest_hwreg (pdest, instr) {
if (pco_ref_get_reg_index(*pdest) < 256)
continue;
large_hwregs[large_hwreg_count++] = pdest;
assert(hwreg_class == ~0 || hwreg_class == pco_ref_get_reg_class(*pdest));
hwreg_class = pco_ref_get_reg_class(*pdest);
min_large_offset = MIN2(min_large_offset, pco_ref_get_reg_index(*pdest));
max_large_offset = MAX2(max_large_offset, pco_ref_get_reg_index(*pdest));
}
/* Check srcs. */
pco_foreach_instr_src_hwreg (psrc, instr) {
if (pco_ref_get_reg_index(*psrc) < 256)
continue;
large_hwregs[large_hwreg_count++] = psrc;
assert(hwreg_class == ~0 || hwreg_class == pco_ref_get_reg_class(*psrc));
hwreg_class = pco_ref_get_reg_class(*psrc);
min_large_offset = MIN2(min_large_offset, pco_ref_get_reg_index(*psrc));
max_large_offset = MAX2(max_large_offset, pco_ref_get_reg_index(*psrc));
}
if (!large_hwreg_count)
return false;
/* We'd need more than one indexed register to support this. */
assert((max_large_offset - min_large_offset) < 256);
pco_builder b =
pco_builder_create(instr->parent_func, pco_cursor_before_instr(instr));
unsigned idx_reg_num = 0;
pco_ref idx_reg =
pco_ref_hwreg_idx(idx_reg_num, idx_reg_num, PCO_REG_CLASS_INDEX);
pco_ref imm = pco_ref_imm32(min_large_offset);
pco_movi32(&b, idx_reg, imm, .exec_cnd = pco_instr_get_exec_cnd(instr));
/* Remap the offset for each large hwreg and replace it with the indexed
* register.
*/
for (unsigned u = 0; u < large_hwreg_count; ++u) {
*large_hwregs[u] = pco_ref_offset(*large_hwregs[u], -min_large_offset);
*large_hwregs[u] = pco_ref_hwreg_idx_from(idx_reg_num, *large_hwregs[u]);
}
return true;
}
/**
* \brief Insert pseudo fences around DITR and DITRP instructions.
*
* \param[in,out] instr PCO instr.
* \return True if progress was made.
*/
static bool try_legalize_ditr_fence(pco_instr *instr)
{
if (instr->op != PCO_OP_DITR && instr->op != PCO_OP_DITRP)
return false;
pco_builder b =
pco_builder_create(instr->parent_func, pco_cursor_before_instr(instr));
pco_fence(&b);
b.cursor = pco_cursor_after_instr(instr);
pco_fence(&b);
return true;
}
/**
* \brief Try to legalizes an instruction.
*
* \param[in,out] instr PCO instr.
* \return True if progress was made.
*/
static bool try_legalize(pco_instr *instr)
{
const struct pco_op_info *info = &pco_op_info[instr->op];
bool progress = false;
progress |= try_legalize_large_hwreg_offsets(instr, info);
progress |= try_legalize_ditr_fence(instr);
return progress;
}
/**
* \brief Legalizes instructions where additional restrictions apply.
* This should be run after register allocation.
*
* \param[in,out] shader PCO shader.
* \return True if the pass made progress.
*/
bool pco_pre_ra_legalize(pco_shader *shader)
{
bool progress = false;
assert(!shader->is_grouped);
assert(!shader->is_legalized);
const struct pco_op_info *info;
pco_foreach_func_in_shader (func, shader) {
pco_foreach_instr_in_func_safe (instr, func) {
info = &pco_op_info[instr->op];
if (info->type != PCO_OP_TYPE_PSEUDO)
progress |= try_legalize_src_mappings(instr, info);
}
}
return progress;
}
/**
* \brief Post-RA legalization pass.
*
* \param[in,out] shader PCO shader.
* \return True if the pass made progress.
*/
bool pco_post_ra_legalize(pco_shader *shader)
{
assert(!shader->is_grouped);
bool progress = false;
pco_foreach_func_in_shader (func, shader) {
pco_foreach_instr_in_func_safe (instr, func) {
progress |= try_legalize(instr);
}
}
const struct pco_op_info *info;
pco_foreach_func_in_shader (func, shader) {
pco_foreach_instr_in_func_safe (instr, func) {
info = &pco_op_info[instr->op];
if (info->type == PCO_OP_TYPE_PSEUDO)
progress |= legalize_pseudo(instr);
}
}
shader->is_legalized = true;
return progress;
}
+553
View File
@@ -0,0 +1,553 @@
# Copyright © 2024 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
from mako.template import Template, exceptions
from pco_map import *
template = """/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef PCO_MAP_H
#define PCO_MAP_H
/**
* \\file pco_map.h
*
* \\brief PCO mapping definitions.
*/
#include "pco_builder.h"
#include "pco_common.h"
#include "pco_internal.h"
#include "pco_isa.h"
#include "pco_ops.h"
#include "util/macros.h"
#include <stdbool.h>
/* Enum mappings. */
% for enum_map in enum_maps.values():
static inline
${enum_map.type_to} ${enum_map.name}(${enum_map.type_from} val)
{
uint64_t to = 0;
% if enum_map.pass_zero_val is not None:
if (!val)
return ${enum_map.pass_zero_val};
% endif
% if enum_map.both_bitsets:
u_foreach_bit64 (b, val) {
switch (b) {
% for elem_from, elem_to in enum_map.mappings:
case ${elem_from}:
to |= ${elem_to};
break;
% endfor
default:
UNREACHABLE("");
}
}
% else:
switch (val) {
% for elem_from, elem_to in enum_map.mappings:
case ${elem_from}:
to = ${elem_to};
break;
% endfor
default:
UNREACHABLE("");
}
% endif
return to;
}
% endfor
static inline
enum pco_regbank pco_map_reg_bank(pco_ref ref)
{
if (pco_ref_is_idx_reg(ref)) {
return PCO_REGBANK_IDX0 + ref.idx_reg.num;
}
return pco_map_reg_class_to_regbank(pco_ref_get_reg_class(ref));
}
static inline
unsigned pco_map_reg_bank_bits(pco_ref ref)
{
return util_last_bit(pco_map_reg_bank(ref));
}
static inline
enum pco_idxbank pco_map_idx_bank(pco_ref ref)
{
assert(pco_ref_is_idx_reg(ref));
return pco_map_reg_class_to_idxbank(ref.reg_class);
}
static inline unsigned pco_map_reg_index(pco_ref ref)
{
if (pco_ref_is_reg(ref)) {
switch (ref.reg_class) {
case PCO_REG_CLASS_TEMP:
case PCO_REG_CLASS_VTXIN:
case PCO_REG_CLASS_COEFF:
case PCO_REG_CLASS_SHARED:
case PCO_REG_CLASS_SPEC:
case PCO_REG_CLASS_CONST:
return ref.val;
case PCO_REG_CLASS_INTERN:
return ref.val + PCO_SR_INTL0;
case PCO_REG_CLASS_PIXOUT:
if (ref.val >= 4)
return ref.val + PCO_SR_PIXOUT4 - 4;
else
return ref.val + PCO_SR_PIXOUT0;
case PCO_REG_CLASS_GLOBAL:
return ref.val + PCO_SR_GLOBAL0;
case PCO_REG_CLASS_SLOT:
return (7 - ref.val) + PCO_SR_SLOT7;
default:
break;
}
} else if (pco_ref_is_idx_reg(ref)) {
return pco_map_idx_bank(ref) | (ref.idx_reg.offset << 3);
}
UNREACHABLE("");
}
static inline unsigned pco_map_reg_index_bits(pco_ref ref)
{
if (pco_ref_is_reg(ref))
return util_last_bit(pco_map_reg_index(ref));
else if (pco_ref_is_idx_reg(ref))
return 11;
UNREACHABLE("");
}
static inline
enum pco_igrp_hdr_variant pco_igrp_hdr_variant(pco_igrp *igrp)
{
if (igrp->hdr.alutype == PCO_ALUTYPE_BITWISE)
return PCO_IGRP_HDR_BITWISE;
else if (igrp->hdr.alutype == PCO_ALUTYPE_CONTROL)
return PCO_IGRP_HDR_CONTROL;
else
assert(igrp->hdr.alutype == PCO_ALUTYPE_MAIN);
if (!igrp->hdr.end && !igrp->hdr.atom && !igrp->hdr.rpt && !igrp->hdr.cc)
return PCO_IGRP_HDR_MAIN_BRIEF;
return PCO_IGRP_HDR_MAIN;
}
static inline
enum pco_src_variant pco_igrp_src_variant(const pco_igrp *igrp,
bool is_upper)
{
unsigned offset = is_upper ? ROGUE_ALU_INPUT_GROUP_SIZE : 0;
pco_ref sA = igrp->srcs.s[0 + offset];
pco_ref sB = igrp->srcs.s[1 + offset];
pco_ref sC = igrp->srcs.s[2 + offset];
pco_ref mux = is_upper ? pco_ref_null() : igrp->iss.is[0];
bool sA_set = !pco_ref_is_null(sA);
bool sB_set = !pco_ref_is_null(sB);
bool sC_set = !pco_ref_is_null(sC);
bool mux_set = !pco_ref_is_null(mux);
int sbA_bits = sA_set ? pco_map_reg_bank_bits(sA) : -1;
int sA_bits = sA_set ? pco_map_reg_index_bits(sA) : -1;
int sbB_bits = sB_set ? pco_map_reg_bank_bits(sB) : -1;
int sB_bits = sB_set ? pco_map_reg_index_bits(sB) : -1;
int sbC_bits = sC_set ? pco_map_reg_bank_bits(sC) : -1;
int sC_bits = sC_set ? pco_map_reg_index_bits(sC) : -1;
int mux_bits = mux_set ? util_last_bit(pco_map_io_to_is0_sel(pco_ref_get_io(mux))) : -1;
bool is_ctrl = igrp->hdr.alutype == PCO_ALUTYPE_CONTROL;
bool no_srcs_set = !sA_set && !sB_set && !sC_set && !mux_set;
if (is_ctrl && no_srcs_set)
return PCO_SRC_NONE;
% for variant, spec in [(bs.name.upper(), bs.data) for bs in I_SRC.bit_structs.values()]:
${'else ' if not loop.first else ''}if (${'!' if not spec.is_upper else ''}is_upper &&
sbA_bits ${'==' if spec.sbA_bits == -1 else '<='} ${spec.sbA_bits} && sA_bits ${'==' if spec.sA_bits == -1 else '<='} ${spec.sA_bits} &&
sbB_bits ${'==' if spec.sbB_bits == -1 else '<='} ${spec.sbB_bits} && sB_bits ${'==' if spec.sB_bits == -1 else '<='} ${spec.sB_bits} &&
sbC_bits ${'==' if spec.sbC_bits == -1 else '<='} ${spec.sbC_bits} && sC_bits ${'==' if spec.sC_bits == -1 else '<='} ${spec.sC_bits} &&
mux_bits ${'==' if spec.mux_bits == -1 else '<='} ${spec.mux_bits}) {
return ${variant};
}
% endfor
UNREACHABLE("");
}
static inline
enum pco_iss_variant pco_igrp_iss_variant(const pco_igrp *igrp)
{
if (igrp->hdr.alutype == PCO_ALUTYPE_MAIN)
return PCO_ISS_ISS;
return PCO_ISS_NONE;
}
static inline
enum pco_dst_variant pco_igrp_dest_variant(pco_igrp *igrp)
{
pco_ref w0 = igrp->dests.w[0];
pco_ref w1 = igrp->dests.w[1];
bool w0_set = !pco_ref_is_null(w0);
bool w1_set = !pco_ref_is_null(w1);
bool no_dsts = !w0_set && !w1_set;
bool one_dest = w0_set != w1_set;
bool dual_dsts = w0_set && w1_set;
if (no_dsts)
return PCO_DST_NONE;
int db0_bits = w0_set ? pco_map_reg_bank_bits(w0) : -1;
int d0_bits = w0_set ? pco_map_reg_index_bits(w0) : -1;
int db1_bits = w1_set ? pco_map_reg_bank_bits(w1) : -1;
int d1_bits = w1_set ? pco_map_reg_index_bits(w1) : -1;
int dbN_bits = w0_set ? db0_bits : db1_bits;
int dN_bits = w0_set ? d0_bits : d1_bits;
if (one_dest) {
db0_bits = dbN_bits;
d0_bits = dN_bits;
db1_bits = -1;
d1_bits = -1;
}
% for variant, spec in [(bs.name.upper(), bs.data) for bs in I_DST.bit_structs.values()]:
${'else ' if not loop.first else ''}if (${'!' if not spec.dual_dsts else ''}dual_dsts &&
db0_bits ${'==' if spec.db0_bits == -1 else '<='} ${spec.db0_bits} && d0_bits ${'==' if spec.d0_bits == -1 else '<='} ${spec.d0_bits} &&
db1_bits ${'==' if spec.db1_bits == -1 else '<='} ${spec.db1_bits} && d1_bits ${'==' if spec.d1_bits == -1 else '<='} ${spec.d1_bits}) {
return ${variant};
}
% endfor
UNREACHABLE("");
}
% for encode_map in encode_maps.values():
static inline
unsigned ${encode_map.name}_variant(pco_instr *instr)
{
% if len(encode_map.variants) > 1:
% for variant, _, conds in encode_map.variants[1:]:
${conds.format('bin', 'instr', 'variant')}
return ${variant};
% endfor
% endif
return ${encode_map.variants[0][0]};
}
% endfor
/* Instruction group mappings. */
% for group_map in group_maps.values():
static inline
void ${group_map.name}_map_igrp(pco_igrp *igrp, pco_instr *instr)
{
% for mapping_set in group_map.mapping_sets:
% for mapping in mapping_set:
${mapping.format('igrp', 'instr')}
% endfor
% endfor
igrp->variant.hdr = pco_igrp_hdr_variant(igrp);
igrp->variant.lower_src = pco_igrp_src_variant(igrp, false);
igrp->variant.upper_src = pco_igrp_src_variant(igrp, true);
igrp->variant.iss = pco_igrp_iss_variant(igrp);
igrp->variant.dest = pco_igrp_dest_variant(igrp);
}
% endfor
static inline
void pco_map_igrp(pco_igrp *igrp, pco_instr *instr)
{
switch (instr->op) {
% for group_map in group_maps.values():
case ${group_map.cop_name}:
return ${group_map.name}_map_igrp(igrp, instr);
% endfor
default:
break;
}
const struct pco_op_info *info = &pco_op_info[instr->op];
printf("Instruction group mapping not defined for %s op '%s'.\\n",
info->type == PCO_OP_TYPE_PSEUDO ? "pseudo" : "hardware",
info->str);
UNREACHABLE("");
}
static inline unsigned pco_igrp_hdr_map_encode(uint8_t *bin, pco_igrp *igrp)
{
switch (igrp->variant.hdr) {
case PCO_IGRP_HDR_MAIN_BRIEF:
return pco_igrp_hdr_main_brief_encode(bin,
.da = igrp->hdr.da,
.length = igrp->hdr.length,
.oporg = igrp->hdr.oporg,
.olchk = igrp->hdr.olchk,
.w1p = igrp->hdr.w1p,
.w0p = igrp->hdr.w0p,
.cc = igrp->hdr.cc);
case PCO_IGRP_HDR_MAIN:
return pco_igrp_hdr_main_encode(bin,
.da = igrp->hdr.da,
.length = igrp->hdr.length,
.oporg = igrp->hdr.oporg,
.olchk = igrp->hdr.olchk,
.w1p = igrp->hdr.w1p,
.w0p = igrp->hdr.w0p,
.cc = igrp->hdr.cc,
.end = igrp->hdr.end,
.atom = igrp->hdr.atom,
.rpt = igrp->hdr.rpt);
case PCO_IGRP_HDR_BITWISE:
return pco_igrp_hdr_bitwise_encode(bin,
.da = igrp->hdr.da,
.length = igrp->hdr.length,
.opcnt = igrp->hdr.opcnt,
.olchk = igrp->hdr.olchk,
.w1p = igrp->hdr.w1p,
.w0p = igrp->hdr.w0p,
.cc = igrp->hdr.cc,
.end = igrp->hdr.end,
.atom = igrp->hdr.atom,
.rpt = igrp->hdr.rpt);
case PCO_IGRP_HDR_CONTROL:
return pco_igrp_hdr_control_encode(bin,
.da = igrp->hdr.da,
.length = igrp->hdr.length,
.olchk = igrp->hdr.olchk,
.w1p = igrp->hdr.w1p,
.w0p = igrp->hdr.w0p,
.cc = igrp->hdr.cc,
.miscctl = igrp->hdr.miscctl,
.ctrlop = igrp->hdr.ctrlop);
default:
break;
}
UNREACHABLE("");
}
% for encode_map in encode_maps.values():
static inline
% if len(encode_map.variants) > 1:
unsigned ${encode_map.name}_map_encode(uint8_t *bin, pco_instr *instr, unsigned variant)
{
switch (variant) {
% for variant, mapping, _ in encode_map.variants:
case ${variant}:
return ${mapping.format('bin', 'instr', 'variant')};
% endfor
default:
break;
}
UNREACHABLE("");
}
% else:
unsigned ${encode_map.name}_map_encode(uint8_t *bin, pco_instr *instr)
{
return ${encode_map.variants[0][1].format('bin', 'instr', 'variant')};
}
% endif
% endfor
static inline
unsigned pco_instr_map_encode(uint8_t *bin, pco_igrp *igrp, enum pco_op_phase phase)
{
pco_instr *instr = igrp->instrs[phase];
switch (instr->op) {
% for encode_map in encode_maps.values():
case ${encode_map.cop_name}:
% if len(encode_map.variants) > 1:
return ${encode_map.name}_map_encode(bin, instr, pco_igrp_variant(igrp, phase));
% else:
return ${encode_map.name}_map_encode(bin, instr);
% endif
% endfor
default:
break;
}
UNREACHABLE("");
}
static inline
unsigned pco_srcs_map_encode(uint8_t *bin, pco_igrp *igrp, bool is_upper)
{
unsigned offset = is_upper ? ROGUE_ALU_INPUT_GROUP_SIZE : 0;
pco_ref _sA = igrp->srcs.s[0 + offset];
pco_ref _sB = igrp->srcs.s[1 + offset];
pco_ref _sC = igrp->srcs.s[2 + offset];
pco_ref _mux = is_upper ? pco_ref_null() : igrp->iss.is[0];
bool sA_set = !pco_ref_is_null(_sA);
bool sB_set = !pco_ref_is_null(_sB);
bool sC_set = !pco_ref_is_null(_sC);
bool mux_set = !pco_ref_is_null(_mux);
unsigned sbA = sA_set ? pco_map_reg_bank(_sA) : 0;
unsigned sA = sA_set ? pco_map_reg_index(_sA) : 0;
unsigned sbB = sB_set ? pco_map_reg_bank(_sB) : 0;
unsigned sB = sB_set ? pco_map_reg_index(_sB) : 0;
unsigned sbC = sC_set ? pco_map_reg_bank(_sC) : 0;
unsigned sC = sC_set ? pco_map_reg_index(_sC) : 0;
unsigned mux = mux_set ? pco_map_io_to_is0_sel(pco_ref_get_io(_mux)) : 0;
enum pco_src_variant variant = is_upper ? igrp->variant.upper_src : igrp->variant.lower_src;
switch (variant) {
% for variant, encode_func, spec, offset in [(bs.name.upper(), f'{bs.name}_encode', bs.data, 3 if bs.data.is_upper else 0) for bs in I_SRC.bit_structs.values()]:
case ${variant}:
return ${encode_func}(bin,
% if spec.sbA_bits != -1:
.s${offset + 0} = sA,
.sb${offset + 0} = sbA,
% endif
% if spec.sbB_bits != -1:
.s${offset + 1} = sB,
.sb${offset + 1} = sbB,
% endif
% if spec.sbC_bits != -1:
.s${offset + 2} = sC,
.sb${offset + 2} = sbC,
% endif
% if spec.mux_bits != -1:
.is0 = mux,
% endif
);
% endfor
default:
break;
}
UNREACHABLE("");
}
static inline
unsigned pco_iss_map_encode(uint8_t *bin, pco_igrp *igrp)
{
bool is5_set = !pco_ref_is_null(igrp->iss.is[5]);
bool is4_set = !pco_ref_is_null(igrp->iss.is[4]);
bool is3_set = !pco_ref_is_null(igrp->iss.is[3]);
bool is2_set = !pco_ref_is_null(igrp->iss.is[2]);
bool is1_set = !pco_ref_is_null(igrp->iss.is[1]);
unsigned is5 = is5_set ? pco_map_io_to_is5_sel(pco_ref_get_io(igrp->iss.is[5])) : 0;
unsigned is4 = is4_set ? pco_map_io_to_is4_sel(pco_ref_get_io(igrp->iss.is[4])) : 0;
unsigned is3 = is3_set ? pco_map_io_to_is3_sel(pco_ref_get_io(igrp->iss.is[3])) : 0;
unsigned is2 = is2_set ? pco_map_io_to_is2_sel(pco_ref_get_io(igrp->iss.is[2])) : 0;
unsigned is1 = is1_set ? pco_map_io_to_is1_sel(pco_ref_get_io(igrp->iss.is[1])) : 0;
assert(igrp->variant.iss == PCO_ISS_ISS);
return pco_iss_iss_encode(bin, .is5 = is5, .is4 = is4, .is3 = is3, .is2 = is2, .is1 = is1);
}
static inline
unsigned pco_dests_map_encode(uint8_t *bin, pco_igrp *igrp)
{
pco_ref w0 = igrp->dests.w[0];
pco_ref w1 = igrp->dests.w[1];
bool w0_set = !pco_ref_is_null(w0);
bool w1_set = !pco_ref_is_null(w1);
bool one_dest = w0_set != w1_set;
int db0 = w0_set ? pco_map_reg_bank(w0) : 0;
int d0 = w0_set ? pco_map_reg_index(w0) : 0;
int db1 = w1_set ? pco_map_reg_bank(w1) : 0;
int d1 = w1_set ? pco_map_reg_index(w1) : 0;
int dbN = w0_set ? db0 : db1;
int dN = w0_set ? d0 : d1;
if (one_dest) {
db0 = dbN;
d0 = dN;
db1 = 0;
d1 = 0;
}
switch (igrp->variant.dest) {
% for variant, encode_func, spec in [(bs.name.upper(), f'{bs.name}_encode', bs.data) for bs in I_DST.bit_structs.values()]:
case ${variant}:
return ${encode_func}(bin,
% if spec.db0_bits != -1:
% if spec.dual_dsts:
.d0 = d0,
.db0 = db0,
% else:
.dN = d0,
.dbN = db0,
% endif
% endif
% if spec.db1_bits != -1:
.d1 = d1,
.db1 = db1,
% endif
);
% endfor
default:
break;
}
UNREACHABLE("");
}
#endif /* PCO_MAP_H */"""
def main():
try:
print(Template(template).render(enum_maps=enum_maps, group_maps=group_maps, encode_maps=encode_maps, I_SRC=I_SRC, I_DST=I_DST))
except:
raise Exception(exceptions.text_error_template().render())
if __name__ == '__main__':
main()
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+88
View File
@@ -0,0 +1,88 @@
# Copyright © 2025 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
import argparse
import sys
import math
a = 'a'
b = 'b'
lower_algebraic = []
lower_algebraic_late = []
def lowered_fround_even(src):
abs_src = ('fabs', src)
ffloor_temp = ('ffloor', abs_src)
ffract_temp = ('ffract', abs_src)
ceil_temp = ('fadd', ffloor_temp, 1.0)
even_temp = ('fmul', ffloor_temp, 0.5)
even_ffract_temp = ('ffract', even_temp)
ishalf_temp = ('feq', ffract_temp, 0.5)
ffract_temp = ('bcsel', ishalf_temp, even_ffract_temp, ffract_temp)
lesshalf_temp = ('flt', ffract_temp, 0.5)
result_temp = ('bcsel', lesshalf_temp, ffloor_temp, ceil_temp)
res = ('fcopysign_pco', result_temp, src)
return res
lower_algebraic.append((('fround_even', a), lowered_fround_even(a)))
lower_insert_extract = [
(('insert_u8', 'a@32', b), ('bitfield_insert', 0, a, ('imul', b, 8), 8)),
(('insert_u16', 'a@32', b), ('bitfield_insert', 0, a, ('imul', b, 16), 16)),
(('extract_u8', 'a@32', b), ('ubitfield_extract', a, ('imul', b, 8), 8)),
(('extract_i8', 'a@32', b), ('ibitfield_extract', a, ('imul', b, 8), 8)),
(('extract_u16', 'a@32', b), ('ubitfield_extract', a, ('imul', b, 16), 16)),
(('extract_i16', 'a@32', b), ('ibitfield_extract', a, ('imul', b, 16), 16)),
]
lower_algebraic_late.extend(lower_insert_extract)
lower_b2b = [
(('b2b32', a), ('ineg', ('b2i32', a))),
(('b2b1', a), ('ine', a, 0)),
]
lower_algebraic.extend(lower_b2b)
lower_scmp = [
# Float comparisons + bool conversions.
(('b2f32', ('flt', a, b)), ('slt', a, 'b@32'), '!options->lower_scmp'),
(('b2f32', ('fge', a, b)), ('sge', a, 'b@32'), '!options->lower_scmp'),
(('b2f32', ('feq', a, b)), ('seq', a, 'b@32'), '!options->lower_scmp'),
(('b2f32', ('fneu', a, b)), ('sne', a, 'b@32'), '!options->lower_scmp'),
# Float comparisons + bool conversions via bcsel.
(('bcsel@32', ('flt', a, b), 1.0, 0.0), ('slt', a, 'b@32'), '!options->lower_scmp'),
(('bcsel@32', ('fge', a, b), 1.0, 0.0), ('sge', a, 'b@32'), '!options->lower_scmp'),
(('bcsel@32', ('feq', a, b), 1.0, 0.0), ('seq', a, 'b@32'), '!options->lower_scmp'),
(('bcsel@32', ('fneu', a, b), 1.0, 0.0), ('sne', a, 'b@32'), '!options->lower_scmp'),
]
lower_algebraic_late.extend(lower_scmp)
# TODO: core-specific info.
params=[]
def run():
import nir_algebraic # pylint: disable=import-error
print('#include "pco_internal.h"')
print(nir_algebraic.AlgebraicPass('pco_nir_lower_algebraic', lower_algebraic, params=params).render())
print(nir_algebraic.AlgebraicPass('pco_nir_lower_algebraic_late', lower_algebraic_late, params=params).render())
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--import-path', required=True)
args = parser.parse_args()
sys.path.insert(0, args.import_path)
run()
if __name__ == '__main__':
main()
+86
View File
@@ -0,0 +1,86 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_nir_compute.c
*
* \brief PCO NIR compute-specific passes.
*/
#include "nir.h"
#include "nir_builder.h"
#include "pco.h"
#include "pco_builder.h"
#include "pco_internal.h"
#include "util/macros.h"
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
/**
* \brief Inserts the instance check.
*
* \param[in,out] entrypoint NIR shader entrypoint.
* \return The cursor position for where to re-insert the entrypoint.
*/
static nir_cursor insert_instance_check(nir_function_impl *entrypoint)
{
nir_builder b = nir_builder_at(nir_before_impl(entrypoint));
nir_cursor cursor;
/* If the current instance index is greater than the total workgroup size,
* we don't execute.
*/
nir_def *local_size = nir_load_workgroup_size(&b);
nir_def *size_x = nir_channel(&b, local_size, 0);
nir_def *size_y = nir_channel(&b, local_size, 1);
nir_def *size_z = nir_channel(&b, local_size, 2);
nir_def *flat_size = nir_imul(&b, nir_imul(&b, size_x, size_y), size_z);
nir_def *flat_id = nir_load_local_invocation_index(&b);
nir_def *cond_inst_valid = nir_ilt(&b, flat_id, flat_size);
nir_if *nif = nir_push_if(&b, cond_inst_valid);
{
cursor = b.cursor;
}
nir_pop_if(&b, nif);
return cursor;
}
/**
* \brief Inserts an instance check for compute shaders.
*
* \param[in,out] shader NIR shader.
* \return True if the pass made progress.
*/
bool pco_nir_compute_instance_check(nir_shader *shader)
{
assert(shader->info.stage == MESA_SHADER_COMPUTE);
if (shader->info.internal)
return false;
nir_function_impl *entrypoint = nir_shader_get_entrypoint(shader);
if (nir_cf_list_is_empty_block(&entrypoint->body))
return false;
/* Extract the entire entrypoint. */
nir_cf_list cf_list;
nir_cf_extract(&cf_list,
nir_before_impl(entrypoint),
nir_after_impl(entrypoint));
nir_cursor cursor = insert_instance_check(entrypoint);
/* Re-insert the entrypoint inside the instance check. */
nir_cf_reinsert(&cf_list, cursor);
return true;
}
+198
View File
@@ -0,0 +1,198 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_nir_io.c
*
* \brief PCO NIR I/O lowering pass.
*/
#include "nir.h"
#include "nir_builder.h"
#include "pco.h"
#include "pco_builder.h"
#include "pco_internal.h"
#include "util/macros.h"
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
/**
* \brief Lowers an I/O instruction.
*
* \param[in] b NIR builder.
* \param[in] intr NIR intrinsic instruction.
* \param[in] cb_data User callback data.
* \return True if progress was made.
*/
static bool
lower_io(nir_builder *b, nir_intrinsic_instr *intr, UNUSED void *cb_data)
{
b->cursor = nir_before_instr(&intr->instr);
switch (intr->intrinsic) {
case nir_intrinsic_load_push_constant:
case nir_intrinsic_load_shared:
case nir_intrinsic_shared_atomic:
case nir_intrinsic_shared_atomic_swap:
case nir_intrinsic_store_shared:
break;
default:
return false;
}
nir_src *offset_src = nir_get_io_offset_src(intr);
ASSERTED unsigned base = nir_intrinsic_base(intr);
assert(!base);
/* Byte offset to DWORD offset. */
nir_src_rewrite(offset_src, nir_ushr_imm(b, offset_src->ssa, 2));
return true;
}
/**
* \brief I/O lowering pass.
*
* \param[in,out] shader NIR shader.
* \return True if the pass made progress.
*/
bool pco_nir_lower_io(nir_shader *shader)
{
bool progress = false;
progress |= nir_shader_intrinsics_pass(shader,
lower_io,
nir_metadata_control_flow,
NULL);
return progress;
}
static bool lower_shared_io_to_global(nir_builder *b,
nir_intrinsic_instr *intr,
void *cb_data)
{
switch (intr->intrinsic) {
case nir_intrinsic_load_shared:
case nir_intrinsic_store_shared:
case nir_intrinsic_shared_atomic:
case nir_intrinsic_shared_atomic_swap:
break;
default:
return false;
}
struct shader_info *info = &b->shader->info;
unsigned local_size = info->workgroup_size[0] *
info->workgroup_size[1] *
info->workgroup_size[2];
unsigned usc_slots = *((unsigned *)cb_data);
assert(usc_slots);
b->cursor = nir_before_instr(&intr->instr);
/* If each wg fits inside a slot, then we run one wg per _slot_, so:
*
* wg_idx = (cluster_num * slots_per_cluster) + slot_num
*
* otherwise if > 1 slot is required, we run one wg per _cluster_:
*
* wg_idx = cluster_num
*/
nir_def *wg_idx = nir_load_cluster_num_pco(b);
if (local_size <= ROGUE_MAX_INSTANCES_PER_TASK) {
wg_idx = nir_imul_imm(b, wg_idx, usc_slots);
wg_idx = nir_iadd(b, wg_idx, nir_load_slot_num_pco(b));
}
nir_src *offset_src = nir_get_io_offset_src(intr);
nir_def *shmem_buf_offset = nir_imul_imm(b, wg_idx, info->shared_size);
nir_def *offset = nir_iadd(b, offset_src->ssa, shmem_buf_offset);
nir_def *shared_base_ptr = nir_load_shared_base_ptr(b, 2, 32);
nir_def *shared_base_ptr_lo = nir_channel(b, shared_base_ptr, 0);
nir_def *shared_base_ptr_hi = nir_channel(b, shared_base_ptr, 1);
nir_def *addr =
nir_uadd64_32(b, shared_base_ptr_lo, shared_base_ptr_hi, offset);
switch (intr->intrinsic) {
case nir_intrinsic_load_shared: {
nir_def *repl =
nir_load_global_2x32(b,
intr->def.num_components,
intr->def.bit_size,
addr,
.align_mul = nir_intrinsic_align_mul(intr),
.align_offset = nir_intrinsic_align_offset(intr));
nir_def_replace(&intr->def, repl);
nir_instr_free(&intr->instr);
break;
}
case nir_intrinsic_store_shared: {
nir_def *value = intr->src[0].ssa;
nir_store_global_2x32(b,
value,
addr,
.write_mask = nir_intrinsic_write_mask(intr),
.align_mul = nir_intrinsic_align_mul(intr),
.align_offset = nir_intrinsic_align_offset(intr));
nir_instr_remove(&intr->instr);
break;
}
case nir_intrinsic_shared_atomic: {
nir_def *data = intr->src[1].ssa;
nir_def *repl =
nir_global_atomic_2x32(b,
intr->def.bit_size,
addr,
data,
.atomic_op = nir_intrinsic_atomic_op(intr));
nir_def_replace(&intr->def, repl);
nir_instr_free(&intr->instr);
break;
}
case nir_intrinsic_shared_atomic_swap: {
nir_def *data = intr->src[1].ssa;
nir_def *data2 = intr->src[2].ssa;
nir_def *repl =
nir_global_atomic_swap_2x32(b,
intr->def.bit_size,
addr,
data,
data2,
.atomic_op = nir_intrinsic_atomic_op(intr));
nir_def_replace(&intr->def, repl);
nir_instr_free(&intr->instr);
break;
}
default:
UNREACHABLE("Unexpected intrinsic.");
}
return true;
}
bool pco_nir_lower_shared_io_to_global(nir_shader *shader, unsigned usc_slots)
{
return nir_shader_intrinsics_pass(shader,
lower_shared_io_to_global,
nir_metadata_control_flow,
&usc_slots);
}
@@ -0,0 +1,131 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
* Copyright (C) 2020-2021 Collabora, Ltd.
* Copyright © 2020 Valve Corporation
*
* SPDX-License-Identifier: MIT
*/
#include "compiler/nir/nir.h"
#include "compiler/nir/nir_builder.h"
#include "pco_internal.h"
static nir_def *get_is_null(nir_builder *b,
nir_instr *instr,
nir_def **def,
pco_nir_lower_null_descriptor_options options)
{
bool is_deref = false;
*def = NULL;
if (instr->type == nir_instr_type_intrinsic) {
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
switch (intr->intrinsic) {
case nir_intrinsic_image_deref_size:
case nir_intrinsic_image_deref_levels:
case nir_intrinsic_image_deref_samples:
case nir_intrinsic_image_deref_load:
case nir_intrinsic_image_deref_store:
case nir_intrinsic_image_deref_atomic:
case nir_intrinsic_image_deref_atomic_swap:
if (!(options & pco_nir_lower_null_descriptor_image))
return NULL;
is_deref = true;
break;
case nir_intrinsic_get_ubo_size:
case nir_intrinsic_load_ubo:
if (!(options & pco_nir_lower_null_descriptor_ubo))
return NULL;
break;
case nir_intrinsic_get_ssbo_size:
case nir_intrinsic_load_ssbo:
case nir_intrinsic_ssbo_atomic:
case nir_intrinsic_ssbo_atomic_swap:
case nir_intrinsic_store_ssbo:
if (!(options & pco_nir_lower_null_descriptor_ssbo))
return NULL;
break;
default:
return NULL;
}
nir_src *index = nir_get_io_index_src(intr);
assert(index || is_deref);
if (nir_intrinsic_infos[intr->intrinsic].has_dest)
*def = &intr->def;
return nir_is_null_descriptor(b,
is_deref ? intr->src[0].ssa : index->ssa);
}
if (instr->type == nir_instr_type_tex) {
if (!(options & pco_nir_lower_null_descriptor_texture))
return NULL;
nir_tex_instr *tex = nir_instr_as_tex(instr);
nir_def *deref_def = nir_get_tex_src(tex, nir_tex_src_texture_deref);
if (!deref_def)
return NULL;
*def = &tex->def;
return nir_is_null_descriptor(b, deref_def);
}
return NULL;
}
static bool lower(nir_builder *b, nir_instr *instr, void *data)
{
pco_nir_lower_null_descriptor_options *options = data;
b->cursor = nir_before_instr(instr);
nir_def *def;
nir_def *is_null = get_is_null(b, instr, &def, *options);
if (!is_null)
return false;
nir_def *zero = NULL;
nir_if *nif = nir_push_if(b, nir_inot(b, is_null));
nir_instr_remove(instr);
nir_builder_instr_insert(b, instr);
if (def) {
nir_push_else(b, nif);
zero = nir_imm_zero(b, def->num_components, def->bit_size);
}
nir_pop_if(b, nif);
if (def) {
nir_def *phi = nir_if_phi(b, def, zero);
/* We can't use nir_def_rewrite_uses_after on phis, so use the global
* version and fixup the phi manually
*/
nir_def_rewrite_uses(def, phi);
nir_instr *phi_instr = nir_def_instr(phi);
nir_phi_instr *phi_as_phi = nir_instr_as_phi(phi_instr);
nir_phi_src *phi_src =
nir_phi_get_src_from_block(phi_as_phi, instr->block);
nir_src_rewrite(&phi_src->src, def);
}
return true;
}
bool pco_nir_lower_null_descriptors(
nir_shader *shader,
pco_nir_lower_null_descriptor_options options)
{
return nir_shader_instructions_pass(shader,
lower,
nir_metadata_none,
&options);
}
File diff suppressed because it is too large. Load diff
+263
View File
@@ -0,0 +1,263 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_nir_sync.c
*
* \brief PCO NIR sync-related passes.
*/
#include "hwdef/rogue_hw_defs.h"
#include "nir.h"
#include "nir_builder.h"
#include "nir_builtin_builder.h"
#include "pco.h"
#include "pco_builder.h"
#include "pco_internal.h"
#include "pco_usclib.h"
#include "util/macros.h"
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
/**
* \brief Lowers a barrier instruction.
*
* \param[in] b NIR builder.
* \param[in] intr NIR intrinsic instruction.
* \param[in] cb_data User callback data.
* \return True if progress was made.
*/
static bool
lower_barrier(nir_builder *b, nir_intrinsic_instr *intr, void *cb_data)
{
if (intr->intrinsic != nir_intrinsic_barrier)
return false;
struct shader_info *info = &b->shader->info;
bool *uses_usclib = cb_data;
mesa_scope exec_scope = nir_intrinsic_execution_scope(intr);
unsigned wg_size = info->workgroup_size[0] * info->workgroup_size[1] *
info->workgroup_size[2];
if (wg_size <= ROGUE_MAX_INSTANCES_PER_TASK || exec_scope == SCOPE_NONE ||
exec_scope == SCOPE_SUBGROUP) {
nir_instr_remove(&intr->instr);
return true;
}
/* TODO: We might be able to re-use barrier counters. */
unsigned counter_offset = info->shared_size;
info->shared_size += sizeof(uint32_t);
info->zero_initialize_shared_memory = true;
*uses_usclib = true;
unsigned num_slots = DIV_ROUND_UP(wg_size, ROGUE_MAX_INSTANCES_PER_TASK);
b->cursor = nir_before_instr(&intr->instr);
usclib_barrier(b, nir_imm_int(b, num_slots), nir_imm_int(b, counter_offset));
nir_instr_remove(&intr->instr);
return true;
}
/**
* \brief Barrier lowering pass.
*
* \param[in,out] shader NIR shader.
* \return True if the pass made progress.
*/
bool pco_nir_lower_barriers(nir_shader *shader, pco_data *data)
{
bool progress = nir_shader_intrinsics_pass(shader,
lower_barrier,
nir_metadata_none,
&data->common.uses.usclib);
data->common.uses.barriers |= progress;
return progress;
}
static bool
lower_usclib_atomic(nir_builder *b, nir_intrinsic_instr *intr, void *cb_data)
{
if (intr->intrinsic != nir_intrinsic_ssbo_atomic_swap &&
intr->intrinsic != nir_intrinsic_global_atomic_swap_pco)
return false;
bool *uses_usclib = cb_data;
b->cursor = nir_before_instr(&intr->instr);
if (intr->intrinsic == nir_intrinsic_ssbo_atomic_swap) {
nir_def *buffer = intr->src[0].ssa;
nir_def *offset = intr->src[1].ssa;
nir_def *value = intr->src[2].ssa;
nir_def *value_swap = intr->src[3].ssa;
ASSERTED enum gl_access_qualifier access = nir_intrinsic_access(intr);
ASSERTED unsigned num_components = intr->def.num_components;
ASSERTED unsigned bit_size = intr->def.bit_size;
assert(access == ACCESS_COHERENT);
assert(num_components == 1 && bit_size == 32);
*uses_usclib = true;
nir_def *emulated =
usclib_emu_ssbo_atomic_comp_swap(b, buffer, offset, value, value_swap);
nir_def_rewrite_uses(&intr->def, emulated);
nir_instr_remove(&intr->instr);
return true;
}
nir_def *addr_data = intr->src[0].ssa;
nir_def *addr = nir_channels(b, addr_data, BITFIELD_RANGE(0, 2));
nir_def *value = nir_channel(b, addr_data, 2);
nir_def *value_swap = nir_channel(b, addr_data, 3);
ASSERTED unsigned num_components = intr->def.num_components;
ASSERTED unsigned bit_size = intr->def.bit_size;
assert(num_components == 1 && bit_size == 32);
*uses_usclib = true;
nir_def *emulated =
usclib_emu_global_atomic_comp_swap(b, addr, value, value_swap);
nir_def_rewrite_uses(&intr->def, emulated);
nir_instr_remove(&intr->instr);
return true;
}
static bool lower_global_atomic_intrinsic(nir_builder *b,
nir_intrinsic_instr *intrin,
UNUSED void *data)
{
nir_intrinsic_op op;
bool is_swap = false;
switch (intrin->intrinsic) {
case nir_intrinsic_global_atomic_2x32:
op = nir_intrinsic_global_atomic_pco;
break;
case nir_intrinsic_global_atomic_swap_2x32:
op = nir_intrinsic_global_atomic_swap_pco;
is_swap = true;
break;
default:
return false;
}
nir_src *addr_src = &intrin->src[0];
nir_src *data_src = &intrin->src[1];
nir_src *data2_src;
if (is_swap)
data2_src = &intrin->src[2];
b->cursor = nir_before_instr(&intrin->instr);
nir_def *new_src = nir_pad_vector(b, addr_src->ssa, is_swap ? 4 : 3);
new_src = nir_vector_insert_imm(b, new_src, data_src->ssa, 2);
if (is_swap)
new_src = nir_vector_insert_imm(b, new_src, data2_src->ssa, 3);
nir_intrinsic_instr *new_intrin = nir_intrinsic_instr_create(b->shader, op);
new_intrin->num_components = intrin->num_components;
nir_def_init(&new_intrin->instr,
&new_intrin->def,
intrin->def.num_components,
intrin->def.bit_size);
new_intrin->src[0] = nir_src_for_ssa(new_src);
assert(nir_intrinsic_has_atomic_op(intrin));
nir_intrinsic_set_atomic_op(new_intrin, nir_intrinsic_atomic_op(intrin));
nir_builder_instr_insert(b, &new_intrin->instr);
nir_def_rewrite_uses(&intrin->def, &new_intrin->def);
nir_instr_remove(&intrin->instr);
return true;
}
/**
* \brief Atomics lowering pass.
*
* \param[in,out] shader NIR shader.
* \return True if the pass made progress.
*/
bool pco_nir_lower_atomics(nir_shader *shader, pco_data *data)
{
bool progress = false;
progress |= nir_shader_intrinsics_pass(shader,
lower_global_atomic_intrinsic,
nir_metadata_none,
NULL);
progress |= nir_shader_intrinsics_pass(shader,
lower_usclib_atomic,
nir_metadata_none,
&data->common.uses.usclib);
return progress;
}
static bool lower_subgroup_intrinsic(nir_builder *b,
nir_intrinsic_instr *intr,
void *cb_data)
{
nir_def *new_def;
b->cursor = nir_before_instr(&intr->instr);
switch (intr->intrinsic) {
case nir_intrinsic_load_subgroup_size:
new_def = nir_imm_int(b, 1);
break;
case nir_intrinsic_load_subgroup_invocation:
new_def = nir_imm_int(b, 0);
break;
case nir_intrinsic_load_num_subgroups:
new_def = nir_imm_int(b,
b->shader->info.workgroup_size[0] *
b->shader->info.workgroup_size[1] *
b->shader->info.workgroup_size[2]);
break;
case nir_intrinsic_load_subgroup_id:
new_def = nir_load_local_invocation_index(b);
break;
case nir_intrinsic_first_invocation:
new_def = nir_imm_int(b, 0);
break;
case nir_intrinsic_elect:
new_def = nir_imm_true(b);
break;
default:
return false;
}
nir_def_rewrite_uses(&intr->def, new_def);
nir_instr_remove(&intr->instr);
assert(intr->def.num_components == 1);
return true;
}
bool pco_nir_lower_subgroups(nir_shader *shader)
{
shader->info.api_subgroup_size = 1;
shader->info.min_subgroup_size = 1;
shader->info.max_subgroup_size = 1;
return nir_shader_intrinsics_pass(shader,
lower_subgroup_intrinsic,
nir_metadata_control_flow,
NULL);
}
File diff suppressed because it is too large. Load diff
+332
View File
@@ -0,0 +1,332 @@
/*
* Copyright © 2025 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_nir_vk.c
*
* \brief PCO NIR Vulkan lowering pass.
*/
#include "nir.h"
#include "nir_builder.h"
#include "pco.h"
#include "pco_builder.h"
#include "pco_internal.h"
#include "util/macros.h"
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
static void
set_resource_used(pco_common_data *common, unsigned desc_set, unsigned binding)
{
assert(desc_set < ARRAY_SIZE(common->desc_sets));
pco_descriptor_set_data *desc_set_data = &common->desc_sets[desc_set];
desc_set_data->used = true;
assert(desc_set_data->bindings && binding < desc_set_data->binding_count);
pco_binding_data *binding_data = &desc_set_data->bindings[binding];
binding_data->used = true;
}
/**
* \brief Lowers load_vulkan_descriptor.
*
* Packs the descriptor set, binding, and array element.
*
* \param[in] b NIR builder.
* \param[in] intr NIR intrinsic instruction.
* \param[in] common Shader common data.
* \return True if progress was made.
*/
static bool lower_load_vulkan_descriptor(nir_builder *b,
nir_intrinsic_instr *intr,
pco_common_data *common)
{
nir_intrinsic_instr *vk_res_idx = nir_src_as_intrinsic(intr->src[0]);
assert(vk_res_idx->intrinsic == nir_intrinsic_vulkan_resource_index);
assert(nir_intrinsic_desc_type(intr) == nir_intrinsic_desc_type(vk_res_idx));
unsigned desc_set = nir_intrinsic_desc_set(vk_res_idx);
unsigned binding = nir_intrinsic_binding(vk_res_idx);
unsigned elem = nir_src_as_uint(vk_res_idx->src[0]);
set_resource_used(common, desc_set, binding);
b->cursor = nir_before_instr(&intr->instr);
uint32_t desc_set_binding = pco_pack_desc(desc_set, binding);
nir_def *desc_ref = nir_imm_ivec3(b, desc_set_binding, elem, 0);
nir_def_rewrite_uses(&intr->def, desc_ref);
nir_instr_remove(&intr->instr);
return true;
}
static nir_def *array_elem_from_deref(nir_builder *b, nir_deref_instr *deref)
{
unsigned array_elem = 0;
if (deref->deref_type != nir_deref_type_var) {
assert(deref->deref_type == nir_deref_type_array);
array_elem = nir_src_as_uint(deref->arr.index);
deref = nir_deref_instr_parent(deref);
}
assert(deref->deref_type == nir_deref_type_var);
return nir_imm_int(b, array_elem);
}
static inline bool is_comb_img_smp(unsigned desc_set,
unsigned binding,
const pco_common_data *common)
{
const pco_descriptor_set_data *desc_set_data = &common->desc_sets[desc_set];
assert(desc_set_data->bindings && binding < desc_set_data->binding_count);
const pco_binding_data *binding_data = &desc_set_data->bindings[binding];
return binding_data->is_img_smp;
}
static bool lower_tex_deref_to_binding(nir_builder *b,
nir_tex_instr *tex,
unsigned deref_index,
pco_common_data *common)
{
nir_tex_src *deref_src = &tex->src[deref_index];
nir_deref_instr *deref = nir_def_as_deref(deref_src->src.ssa);
b->cursor = nir_before_instr(&tex->instr);
nir_variable *var = nir_deref_instr_get_variable(deref);
assert(var);
unsigned desc_set = var->data.descriptor_set;
unsigned binding = var->data.binding;
nir_def *elem = array_elem_from_deref(b, deref);
set_resource_used(common, desc_set, binding);
uint32_t desc_set_binding = pco_pack_desc(desc_set, binding);
if (deref_src->src_type == nir_tex_src_texture_deref) {
tex->texture_index = desc_set_binding;
deref_src->src_type = nir_tex_src_backend1;
} else {
tex->sampler_index = desc_set_binding;
deref_src->src_type = nir_tex_src_backend2;
}
nir_src_rewrite(&deref_src->src, elem);
return true;
}
static bool
add_txf_sampler(nir_builder *b, nir_tex_instr *tex, pco_common_data *common)
{
int deref_index = nir_tex_instr_src_index(tex, nir_tex_src_backend1);
assert(deref_index >= 0);
nir_tex_src *deref_src = &tex->src[deref_index];
unsigned desc_set;
unsigned binding;
pco_unpack_desc(tex->texture_index, &desc_set, &binding);
nir_def *elem = deref_src->src.ssa;
/* If it's not a combined image/sampler, use the point sampler. */
if (!is_comb_img_smp(desc_set, binding, common)) {
desc_set = PCO_POINT_SAMPLER;
binding = PCO_POINT_SAMPLER;
elem = nir_imm_int(b, 0);
common->uses.point_sampler = true;
}
tex->sampler_index = pco_pack_desc(desc_set, binding);
nir_tex_instr_add_src(tex, nir_tex_src_backend2, elem);
return true;
}
static inline bool
lower_tex_derefs(nir_builder *b, nir_tex_instr *tex, pco_common_data *common)
{
int deref_index;
bool progress = false;
deref_index = nir_tex_instr_src_index(tex, nir_tex_src_texture_deref);
if (deref_index >= 0)
progress |= lower_tex_deref_to_binding(b, tex, deref_index, common);
deref_index = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref);
if (deref_index >= 0)
progress |= lower_tex_deref_to_binding(b, tex, deref_index, common);
else if (tex->op == nir_texop_txf || tex->op == nir_texop_txf_ms)
progress |= add_txf_sampler(b, tex, common);
return progress;
}
static bool
lower_image_derefs(nir_builder *b, nir_intrinsic_instr *intr, pco_data *data)
{
nir_src *deref_src = &intr->src[0];
nir_deref_instr *deref = nir_src_as_deref(*deref_src);
b->cursor = nir_before_instr(&intr->instr);
nir_variable *var = nir_deref_instr_get_variable(deref);
assert(var);
unsigned desc_set = var->data.descriptor_set;
unsigned binding = var->data.binding;
set_resource_used(&data->common, desc_set, binding);
if (nir_intrinsic_format(intr) == PIPE_FORMAT_NONE)
nir_intrinsic_set_format(intr, var->data.image.format);
enum glsl_sampler_dim image_dim = nir_intrinsic_image_dim(intr);
bool ia = image_dim == GLSL_SAMPLER_DIM_SUBPASS ||
image_dim == GLSL_SAMPLER_DIM_SUBPASS_MS;
if (ia) {
unsigned ia_idx = var->data.index;
bool onchip = data->fs.ia_formats[ia_idx] != PIPE_FORMAT_NONE;
bool is_stencil = data->fs.ia_has_stencil & BITFIELD_BIT(ia_idx);
is_stencil &= glsl_get_sampler_result_type(glsl_without_array_or_matrix(
var->type)) != GLSL_TYPE_FLOAT;
onchip &= !is_stencil;
if (onchip) {
nir_def *elem = array_elem_from_deref(b, deref);
nir_def *index = nir_vec4(b,
nir_imm_int(b, desc_set),
nir_imm_int(b, binding),
elem,
nir_imm_int(b, ia_idx));
nir_src_rewrite(deref_src, index);
return true;
}
/* Sampler not needed for on-chip input attachments. */
data->common.uses.ia_sampler = true;
} else if (intr->intrinsic == nir_intrinsic_image_deref_load ||
intr->intrinsic == nir_intrinsic_image_deref_store) {
/* Sampler not needed for other types of image accesses. */
data->common.uses.point_sampler = true;
}
nir_def *elem = array_elem_from_deref(b, deref);
nir_def *index =
nir_vec3(b, nir_imm_int(b, desc_set), nir_imm_int(b, binding), elem);
nir_src_rewrite(deref_src, index);
return true;
}
static bool lower_is_null_descriptor(nir_builder *b, nir_intrinsic_instr *intr)
{
nir_src *deref_src = &intr->src[0];
nir_deref_instr *deref = nir_src_as_deref(*deref_src);
/* Will be taken care of by lower_load_vulkan_descriptor. */
if (!deref)
return false;
b->cursor = nir_before_instr(&intr->instr);
nir_variable *var = nir_deref_instr_get_variable(deref);
assert(var);
unsigned desc_set = var->data.descriptor_set;
unsigned binding = var->data.binding;
nir_def *elem = array_elem_from_deref(b, deref);
uint32_t desc_set_binding = pco_pack_desc(desc_set, binding);
nir_def *index = nir_vec2(b, nir_imm_int(b, desc_set_binding), elem);
nir_src_rewrite(deref_src, index);
return true;
}
/**
* \brief Lowers a Vulkan-related texture instruction.
*
* \param[in] b NIR builder.
* \param[in] tex NIR texture instruction.
* \param[in] cb_data User callback data.
* \return True if progress was made.
*/
static bool lower_vk_tex(nir_builder *b, nir_tex_instr *tex, void *cb_data)
{
pco_data *data = cb_data;
pco_common_data *common = &data->common;
if (nir_tex_instr_src_index(tex, nir_tex_src_texture_deref) >= 0 ||
nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref) >= 0) {
return lower_tex_derefs(b, tex, common);
}
return false;
}
/**
* \brief Lowers a Vulkan-related intrinsic instruction.
*
* \param[in] b NIR builder.
* \param[in] intr NIR intrinsic instruction.
* \param[in] cb_data User callback data.
* \return True if progress was made.
*/
static bool
lower_vk_intr(nir_builder *b, nir_intrinsic_instr *intr, void *cb_data)
{
pco_data *data = cb_data;
pco_common_data *common = &data->common;
b->cursor = nir_before_instr(&intr->instr);
switch (intr->intrinsic) {
case nir_intrinsic_load_vulkan_descriptor:
return lower_load_vulkan_descriptor(b, intr, common);
case nir_intrinsic_image_deref_load:
case nir_intrinsic_image_deref_store:
case nir_intrinsic_image_deref_atomic:
case nir_intrinsic_image_deref_atomic_swap:
case nir_intrinsic_image_deref_size:
return lower_image_derefs(b, intr, data);
case nir_intrinsic_is_null_descriptor:
return lower_is_null_descriptor(b, intr);
default:
break;
}
return false;
}
/**
* \brief Vulkan lowering pass.
*
* \param[in,out] shader NIR shader.
* \param[in,out] data Shader data.
* \return True if the pass made progress.
*/
bool pco_nir_lower_vk(nir_shader *shader, pco_data *data)
{
bool progress = false;
progress |= nir_shader_intrinsics_pass(shader,
lower_vk_intr,
nir_metadata_control_flow,
data);
progress |= nir_shader_tex_pass(shader,
lower_vk_tex,
nir_metadata_control_flow,
data);
return progress;
}
+67
View File
@@ -0,0 +1,67 @@
# Copyright © 2024 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
from mako.template import Template, exceptions
from pco_ops import *
template = """/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
#ifndef PCO_OPS_H
#define PCO_OPS_H
/**
* \\file pco_ops.h
*
* \\brief PCO op definitions and functions.
*/
#include "util/macros.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#define _PCO_OP_MAX_DESTS ${max([op.num_dests for op in ops.values()])}U
#define _PCO_OP_MAX_SRCS ${max([op.num_srcs for op in ops.values()])}U
#define _PCO_OP_MAX_MODS ${max([len(op.op_mods) for op in ops.values()])}U
/** Ops. */
#define _PCO_OP_COUNT ${len(ops) + 1}U
enum pco_op {
PCO_OP_NONE,
% for op in ops.values():
${op.cname.upper()},
% endfor
};
/** Op mods. */
#define _PCO_OP_MOD_COUNT ${len(op_mods) + 1}U
enum pco_op_mod {
PCO_OP_MOD_NONE,
% for op_mod in op_mods.values():
${op_mod.cname},
% endfor
};
/** Ref mods. */
#define _PCO_REF_MOD_COUNT ${len(ref_mods) + 1}U
enum pco_ref_mod {
PCO_REF_MOD_NONE,
% for ref_mod in ref_mods.values():
${ref_mod.cname},
% endfor
};
#endif /* PCO_OPS_H */"""
def main():
try:
print(Template(template).render(ops=ops, op_mods=op_mods, ref_mods=ref_mods))
except:
raise Exception(exceptions.text_error_template().render())
if __name__ == '__main__':
main()
+529
View File
@@ -0,0 +1,529 @@
# Copyright © 2024 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
from pco_pygen_common import *
OP_TYPE = enum_type('op_type', [
'pseudo',
'hw',
'hw_direct',
])
MOD_TYPE = enum_type('mod_type', [
'bool',
'uint',
'enum',
])
REF_TYPE = enum_type('ref_type', [
('null', '_'),
('ssa', '%'),
('reg', ''),
('idx_reg', ''),
('imm', ''),
('io', ''),
('pred', ''),
('drc', 'drc'),
])
FUNC_TYPE = enum_type('func_type', [
'callable',
'preamble',
'entrypoint',
'phase_change',
])
DTYPE = enum_type('dtype', [
('any', ''),
('unsigned', 'u'),
('signed', 'i'),
('float', 'f'),
])
BITS = enum_type('bits', [
('1', '1'),
('8', '8'),
('16', '16'),
('32', '32'),
('64', '64'),
])
REG_CLASS = enum_type('reg_class', [
('virt', '$'),
('temp', 'r'),
('vtxin', 'vi'),
('coeff', 'cf'),
('shared', 'sh'),
('index', 'idx'),
('spec', 'sr'),
('intern', 'i'),
('const', 'sc'),
('pixout', 'po'),
('global', 'g'),
('slot', 'sl'),
])
IO = enum_type('io', [
('s0', 's0'),
('s1', 's1'),
('s2', 's2'),
('s3', 's3'),
('s4', 's4'),
('s5', 's5'),
('w0', 'w0'),
('w1', 'w1'),
('is0', 'is0'),
('is1', 'is1'),
('is2', 'is2'),
('is3', 'is3'),
('is4', 'is4'),
('is5', 'is5'),
('ft0', 'ft0'),
('ft1', 'ft1'),
('ft2', 'ft2'),
('fte', 'fte'),
('ft1_invert', '~ft1'),
('ft3', 'ft3'),
('ft4', 'ft4'),
('ft5', 'ft5'),
('ftt', 'ftt'),
('cout', 'cout'),
])
PRED = enum_type('pred', [
('pe', 'pe'),
('p0', 'p0'),
('always', 'if(1)'),
('p0_true', 'if(p0)'),
('never', 'if(0)'),
('p0_false', 'if(!p0)'),
])
DRC = enum_type('drc', [
('0', '0'),
('1', '1'),
('pending', '?'),
])
MUTEX_ID = enum_type('mutex_id', [
'atomic_emu',
'barrier',
'rsvd_2',
'rsvd_3',
'rsvd_4',
'rsvd_5',
'rsvd_6',
'rsvd_7',
'rsvd_8',
'rsvd_9',
'rsvd_a',
'rsvd_b',
'rsvd_c',
'rsvd_d',
'rsvd_e',
'rsvd_f'
])
# Ref mods.
RM_ONEMINUS = ref_mod('oneminus', BaseType.bool)
RM_CLAMP = ref_mod('clamp', BaseType.bool)
RM_ABS = ref_mod('abs', BaseType.bool)
RM_NEG = ref_mod('neg', BaseType.bool)
RM_FLR = ref_mod('flr', BaseType.bool)
RM_ELEM = ref_mod_enum('elem', [
'e0',
'e1',
'e2',
'e3',
], is_bitset=True)
# Op mods.
OM_EXEC_CND = op_mod_enum('exec_cnd', [
('e1_zx', ''),
('e1_z1', 'if(p0)'),
('ex_zx', '(ignorepe)'),
('e1_z0', 'if(!p0)'),
], print_early=True, unset=True)
OM_RPT = op_mod('rpt', BaseType.uint, print_early=True, nzdefault=1, unset=True)
OM_SAT = op_mod('sat', BaseType.bool)
OM_LP = op_mod('lp', BaseType.bool)
OM_SCALE = op_mod('scale', BaseType.bool)
OM_ROUNDZERO = op_mod('roundzero', BaseType.bool)
OM_S = op_mod('s', BaseType.bool)
OM_TST_TYPE_MAIN = op_mod_enum('tst_type_main', [
'f32',
'u16',
's16',
'u8',
's8',
'u32',
's32',
])
OM_TST_OP_MAIN = op_mod_enum('tst_op_main', [
('zero', 'z'),
('gzero', 'gz'),
('gezero', 'gez'),
('carry', 'c'),
('equal', 'e'),
('greater', 'g'),
('gequal', 'ge'),
('notequal', 'ne'),
('less', 'l'),
('lequal', 'le'),
])
OM_TST_OP_BITWISE = op_mod_enum('tst_op_bitwise', [
('zero', 'z'),
('nonzero', 'nz'),
])
OM_SIGNPOS = op_mod_enum('signpos', [
'twb',
'pwb',
'mtb',
'ftb',
])
OM_DIM = op_mod_enum('dim', [
'1d',
'2d',
'3d',
])
OM_PROJ = op_mod('proj', BaseType.bool)
OM_FCNORM = op_mod('fcnorm', BaseType.bool)
OM_NNCOORDS = op_mod('nncoords', BaseType.bool)
OM_LOD_MODE = op_mod_enum('lod_mode', [
('normal', ''),
('bias', 'bias'),
('replace', 'replace'),
('gradients', 'gradients'),
])
OM_PPLOD = op_mod('pplod', BaseType.bool)
OM_TAO = op_mod('tao', BaseType.bool)
OM_SOO = op_mod('soo', BaseType.bool)
OM_SNO = op_mod('sno', BaseType.bool)
OM_WRT = op_mod('wrt', BaseType.bool)
OM_SB_MODE = op_mod_enum('sb_mode', [
('none', ''),
('rawdata', 'rawdata'),
('coeffs', 'coeffs'),
('both', 'both'),
])
OM_ARRAY = op_mod('array', BaseType.bool)
OM_INTEGER = op_mod('integer', BaseType.bool)
OM_SCHEDSWAP = op_mod_enum('schedswap', [
('none', ''),
('swap', 'schedswap'),
])
OM_F16 = op_mod('f16', BaseType.bool)
OM_TILED = op_mod('tiled', BaseType.bool)
OM_FREEP = op_mod('freep', BaseType.bool)
OM_SM = op_mod('sm', BaseType.bool)
OM_SAVMSK_MODE = op_mod_enum('savmsk_mode', [
'vm',
'icm',
'icmoc',
'icmi',
'caxy',
])
OM_ATOM_OP = op_mod_enum('atom_op', [
'add',
'sub',
'xchg',
'cmpxchg',
'umin',
'imin',
'umax',
'imax',
'and',
'or',
'xor',
])
OM_MCU_CACHE_MODE_LD = op_mod_enum('mcu_cache_mode_ld', [
('normal', ''),
('bypass', 'bypass'),
('force_line_fill', 'forcelinefill'),
])
OM_MCU_CACHE_MODE_ST = op_mod_enum('mcu_cache_mode_st', [
('write_through', 'writethrough'),
('write_back', 'writeback'),
('lazy_write_back', 'lazywriteback'),
])
OM_BRANCH_CND = op_mod_enum('branch_cnd', [
('exec_cond', ''),
('allinst', 'allinst'),
('anyinst', 'anyinst'),
])
OM_LINK = op_mod('link', BaseType.bool)
OM_PCK_FMT = op_mod_enum('pck_fmt', [
'u8888',
's8888',
'o8888',
'u1616',
's1616',
'o1616',
'u32',
's32',
'u1010102',
's1010102',
'u111110',
's111110',
'f111110',
'f16f16',
'f32',
'cov',
'u565u565',
'd24s8',
's8d24',
'f32_mask',
'2f10f10f10',
's8888ogl',
's1616ogl',
'zero',
'one',
])
OM_PHASE2END = op_mod('phase2end', BaseType.bool)
OM_ITR_MODE = op_mod_enum('itr_mode', [
'pixel',
'sample',
'centroid',
])
OM_SCHED = op_mod_enum('sched', [
('none', ''),
('swap', 'schedswap'),
('wdf', 'schedwdf'),
])
OM_ATOM = op_mod('atom', BaseType.bool, unset=True)
OM_OLCHK = op_mod('olchk', BaseType.bool, unset=True)
OM_END = op_mod('end', BaseType.bool, unset=True)
OM_LOGIOP = op_mod_enum('logiop', [
'or',
'and',
'xor',
'nor',
'nand',
'xnor',
])
OM_SHIFTOP = op_mod_enum('shiftop', [
'lsl',
'shr',
'rol',
'cps',
'asr_twb',
'asr_pwb',
'asr_mtb',
'asr_ftb',
])
OM_CND = op_mod_enum('cnd', [
('always', 'if(1)'),
('p0_true', 'if(p0)'),
('never', 'if(0)'),
('p0_false', 'if(!p0)'),
])
OM_FRED_TYPE = op_mod_enum('fred_type', [
'sin',
'cos',
])
OM_FRED_PART = op_mod_enum('fred_part', [
'a',
'b',
])
OM_MUTEX_OP = op_mod_enum('mutex_op', [
('release', 'release'),
('release_sleep', 'release.sleep'),
('release_wakeup', 'release.wakeup'),
('lock', 'lock'),
])
OM_OFFSET_SD = op_mod_enum('offset_sd', [
'src',
'dest',
])
OM_IDF = op_mod('idf', BaseType.bool)
# Ops.
OM_ALU = [OM_OLCHK, OM_EXEC_CND, OM_END, OM_ATOM, OM_RPT]
OM_ALU_RPT1 = [OM_OLCHK, OM_EXEC_CND, OM_END, OM_ATOM]
OM_ALU_ATOMEXT = [OM_OLCHK, OM_EXEC_CND, OM_END, OM_RPT]
## Main.
O_FADD = hw_op('fadd', OM_ALU + [OM_SAT], 1, 2, [], [[RM_ABS, RM_NEG, RM_FLR], [RM_ABS]])
O_FMUL = hw_op('fmul', OM_ALU + [OM_SAT], 1, 2, [], [[RM_ABS, RM_NEG, RM_FLR], [RM_ABS]])
O_FMAD = hw_op('fmad', OM_ALU + [OM_SAT, OM_LP], 1, 3, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG], [RM_ABS, RM_NEG, RM_FLR]])
O_FRCP = hw_op('frcp', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]])
O_FRSQ = hw_op('frsq', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]])
O_FLOG = hw_op('flog', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]])
O_FLOGCN = hw_op('flogcn', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]])
O_FEXP = hw_op('fexp', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]])
O_FRED = hw_op('fred', OM_ALU + [OM_FRED_TYPE, OM_FRED_PART], 3, 3, [], [[RM_ABS, RM_NEG]])
O_FSINC = hw_op('fsinc', OM_ALU, 2, 1)
O_MBYP = hw_op('mbyp', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]])
O_FDSX = hw_op('fdsx', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]])
O_FDSXF = hw_op('fdsxf', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]])
O_FDSY = hw_op('fdsy', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]])
O_FDSYF = hw_op('fdsyf', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]])
O_PCK = hw_op('pck', OM_ALU + [OM_PCK_FMT, OM_ROUNDZERO, OM_SCALE], 1, 1)
O_PCK_PROG = hw_op('pck.prog', OM_ALU + [OM_ROUNDZERO, OM_SCALE], 1, 2)
O_ADD64_32 = hw_op('add64_32', OM_ALU + [OM_S], 2, 4, [], [[RM_ABS, RM_NEG], [], [RM_ABS, RM_NEG]])
O_IMADD64 = hw_op('imadd64', OM_ALU + [OM_S], 2, 5, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_IMADD32 = hw_op('imadd32', OM_ALU + [OM_S], 1, 4, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_UNPCK = hw_op('unpck', OM_ALU + [OM_PCK_FMT, OM_ROUNDZERO, OM_SCALE], 1, 1, [], [[RM_ELEM]])
O_TST = hw_direct_op('tst', [OM_TST_OP_MAIN, OM_PHASE2END, OM_TST_TYPE_MAIN], 2, 2, [], [[RM_ELEM], [RM_ELEM]])
O_MOVC = hw_direct_op('movc', [OM_PHASE2END], 2, 5, [[RM_ELEM]])
O_MOVWM = hw_op('movwm', OM_ALU + [OM_PHASE2END], 1, 2, [[RM_ELEM]])
O_MOVS1 = hw_op('movs1', OM_ALU, 1, 1)
# TODO
# O_PCK_ELEM = pseudo_op('pck.elem', OM_ALU_RPT1 + [OM_PCK_FMT, OM_ROUNDZERO, OM_SCALE], 1, 2)
## Backend.
O_UVSW_WRITE = hw_op('uvsw.write', [OM_EXEC_CND, OM_RPT], 0, 2)
O_UVSW_EMIT = hw_op('uvsw.emit', [OM_EXEC_CND])
O_UVSW_ENDTASK = hw_op('uvsw.endtask', [OM_END])
O_UVSW_EMIT_ENDTASK = hw_op('uvsw.emit.endtask', [OM_END])
O_UVSW_WRITE_EMIT_ENDTASK = hw_op('uvsw.write.emit.endtask', [OM_END], 0, 2)
O_FITR = hw_op('fitr', [OM_EXEC_CND, OM_END, OM_ITR_MODE, OM_SAT], 1, 3)
O_FITRP = hw_op('fitrp', [OM_EXEC_CND, OM_END, OM_ITR_MODE, OM_SAT], 1, 4)
O_LD = hw_op('ld', OM_ALU_RPT1 + [OM_MCU_CACHE_MODE_LD], 1, 3)
O_LD_REGBL = hw_op('ld.regbl', OM_ALU_RPT1 + [OM_MCU_CACHE_MODE_LD], 1, 3)
O_ST = hw_direct_op('st', [OM_MCU_CACHE_MODE_ST, OM_IDF], 0, 6)
O_ST_REGBL = hw_direct_op('st.regbl', [OM_MCU_CACHE_MODE_ST, OM_IDF], 0, 6)
# { data, data size, drc, chans, addr, cov_msk}
O_ST_TILED = hw_op('st.tiled', OM_ALU_RPT1 + [OM_MCU_CACHE_MODE_ST], 0, 6)
O_IDF = hw_op('idf', OM_ALU_RPT1, 0, 2)
O_ATOMIC = hw_op('atomic', [OM_OLCHK, OM_EXEC_CND, OM_END, OM_ATOM_OP], 1, 2)
O_SMP = hw_op('smp', OM_ALU_RPT1 + [OM_DIM, OM_PROJ, OM_FCNORM, OM_NNCOORDS,
OM_LOD_MODE, OM_PPLOD, OM_TAO, OM_SOO,
OM_SNO, OM_WRT, OM_SB_MODE, OM_MCU_CACHE_MODE_LD,
OM_ARRAY, OM_INTEGER, OM_SCHEDSWAP, OM_F16], 1, 6)
O_ALPHATST = hw_op('alphatst', OM_ALU_RPT1, 1, 4)
O_ALPHAF = hw_op('alphaf', OM_ALU_RPT1, 1, 4)
O_DEPTHF = hw_op('depthf', OM_ALU_RPT1, 0, 2)
O_SAVMSK = hw_op('savmsk', OM_ALU_RPT1 + [OM_SAVMSK_MODE], 2)
O_EMITPIX = hw_op('emitpix', OM_ALU_RPT1 + [OM_FREEP], 0, 2)
## Bitwise.
O_MOVI32 = hw_op('movi32', OM_ALU, 1, 1)
O_CBS = hw_op('cbs', OM_ALU, 1, 1)
O_FTB = hw_op('ftb', OM_ALU, 1, 1)
O_REV = hw_op('rev', OM_ALU, 1, 1)
O_SHUFFLE = hw_op('shuffle', OM_ALU, 1, 2)
O_LOGICAL = hw_op('logical', OM_ALU + [OM_LOGIOP], 1, 4)
O_SHIFT = hw_op('shift', OM_ALU + [OM_SHIFTOP], 1, 3)
O_COPYSIGN = hw_op('copysign', OM_ALU, 1, 2)
O_IBFE = hw_op('ibfe', OM_ALU, 1, 3)
O_UBFE = hw_op('ubfe', OM_ALU, 1, 3)
O_BFI = hw_op('bfi', OM_ALU, 1, 4)
O_BBYP0BM = hw_direct_op('bbyp0bm', [], 2, 2)
O_BBYP0BM_IMM32 = hw_direct_op('bbyp0bm_imm32', [], 2, 2)
O_BBYP0S1 = hw_direct_op('bbyp0s1', [], 2, 1)
O_MSK_BBYP0S1 = hw_direct_op('msk_bbyp0s1', [], 3, 3)
O_MSK_LSL = hw_direct_op('msk_lsl', [], 3, 3)
## Control.
O_WOP = hw_op('wop')
O_WDF = hw_op('wdf', [], 0, 1)
O_NOP = hw_op('nop', [OM_EXEC_CND, OM_END])
# TODO NEXT: gate usage of OM_F16!
O_DITR = hw_op('ditr', [OM_EXEC_CND, OM_ITR_MODE, OM_SAT, OM_SCHED, OM_F16], 1, 3)
O_DITRP = hw_op('ditrp', [OM_EXEC_CND, OM_ITR_MODE, OM_SAT, OM_SCHED, OM_F16], 1, 4)
O_DITRP_WRITE = hw_op('ditrp.write', [OM_EXEC_CND, OM_ITR_MODE, OM_SAT, OM_SCHED, OM_F16], 1, 4)
O_DITRP_READ = hw_op('ditrp.read', [OM_EXEC_CND, OM_ITR_MODE, OM_SAT, OM_SCHED, OM_F16], 1, 3)
O_CNDST = hw_op('cndst', [OM_EXEC_CND, OM_CND], 2, 2)
O_CNDEF = hw_op('cndef', [OM_EXEC_CND, OM_CND], 2, 2)
O_CNDSM = hw_op('cndsm', [OM_EXEC_CND, OM_CND], 2, 2)
O_CNDLT = hw_op('cndlt', [OM_EXEC_CND, OM_CND], 3, 2)
O_CNDEND = hw_op('cndend', [OM_EXEC_CND], 2, 2)
O_BR = hw_op('br', [OM_EXEC_CND, OM_BRANCH_CND, OM_LINK], has_target_cf_node=True)
O_BR_NEXT = hw_op('br.next', [OM_EXEC_CND])
O_MUTEX = hw_op('mutex', [OM_MUTEX_OP], 0, 1)
# Combination (> 1 instructions per group).
O_SCMP = hw_op('scmp', OM_ALU + [OM_TST_OP_MAIN], 1, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_BCMP = hw_op('bcmp', OM_ALU + [OM_TST_OP_MAIN, OM_TST_TYPE_MAIN], 1, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_BCSEL = hw_op('bcsel', OM_ALU, 1, 3, [], [[], [RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_CSEL = hw_op('csel', OM_ALU + [OM_TST_OP_MAIN, OM_TST_TYPE_MAIN], 1, 3, [], [[], [RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_PSEL = hw_op('psel', OM_ALU, 1, 3)
O_PSEL_TRIG = hw_op('psel_trig', OM_ALU, 1, 3)
O_FSIGN = hw_op('fsign', OM_ALU, 1, 1)
O_ISIGN = hw_op('isign', OM_ALU, 1, 1)
O_FCEIL = hw_op('fceil', OM_ALU, 1, 1)
O_MIN = hw_op('min', OM_ALU + [OM_TST_TYPE_MAIN], 1, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_MAX = hw_op('max', OM_ALU + [OM_TST_TYPE_MAIN], 1, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_IADD32 = hw_op('iadd32', OM_ALU + [OM_S], 1, 3, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_IMUL32 = hw_op('imul32', OM_ALU + [OM_S], 1, 3, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_UADD_CARRY = hw_op('uadd_carry', OM_ALU, 2, 2)
O_UADD_SAT = hw_op('uadd_sat', OM_ALU, 1, 3)
O_TSTZ = hw_op('tstz', OM_ALU + [OM_TST_TYPE_MAIN], 2, 1, [], [[RM_ELEM]])
O_ST32 = hw_op('st32', OM_ALU_RPT1 + [OM_MCU_CACHE_MODE_ST, OM_IDF], 0, 5)
O_ST32_REGBL = hw_op('st32.regbl', OM_ALU_RPT1 + [OM_MCU_CACHE_MODE_ST, OM_IDF], 0, 5)
# [vec3 for store], [data, offset, base_addr_lo, base_addr_hi]
O_SPILL = hw_op('spill', OM_ALU_RPT1, 1, 4)
# [result], [offset, base_addr_lo, base_addr_hi]
O_UNSPILL = hw_op('unspill', OM_ALU_RPT1, 1, 3)
O_IADD32_ATOMIC = hw_op('iadd32.atomic', OM_ALU_ATOMEXT + [OM_S], 2, 3, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_XCHG_ATOMIC = hw_op('xchg.atomic', OM_ALU_ATOMEXT, 2, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_CMPXCHG_ATOMIC = hw_op('cmpxchg.atomic', OM_ALU_ATOMEXT + [OM_TST_TYPE_MAIN], 2, 3, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_MIN_ATOMIC = hw_op('min.atomic', OM_ALU_ATOMEXT + [OM_TST_TYPE_MAIN], 2, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_MAX_ATOMIC = hw_op('max.atomic', OM_ALU_ATOMEXT + [OM_TST_TYPE_MAIN], 2, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_LOGICAL_ATOMIC = hw_op('logical.atomic', OM_ALU_ATOMEXT + [OM_LOGIOP], 2, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_FLUSH_P0 = hw_op('flush.p0', [OM_EXEC_CND, OM_END])
O_MBYP2 = hw_op('mbyp2', OM_ALU, 2, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
# Pseudo-ops (unmapped).
O_FNEG = pseudo_op('fneg', OM_ALU, 1, 1)
O_FABS = pseudo_op('fabs', OM_ALU, 1, 1)
O_FFLR = pseudo_op('fflr', OM_ALU, 1, 1)
O_MOV = pseudo_op('mov', OM_ALU, 1, 1)
O_MOV_OFFSET = pseudo_op('mov.offset', OM_ALU + [OM_OFFSET_SD], 1, 2)
O_VEC = pseudo_op('vec', [OM_EXEC_CND], 1, VARIABLE)
O_COMP = pseudo_op('comp', [], 1, 2)
O_FENCE = pseudo_op('fence')
O_OP_ATOMIC_OFFSET = pseudo_op('op.atomic.offset', OM_ALU_ATOMEXT + [OM_ATOM_OP], 2, 4, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])
O_BREAK = pseudo_op('break', [OM_EXEC_CND])
O_CONTINUE = pseudo_op('continue', [OM_EXEC_CND])
+819
View File
@@ -0,0 +1,819 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_opt.c
*
* \brief PCO optimization passes.
*/
#include "pco.h"
#include "pco_builder.h"
#include "util/bitscan.h"
#include "util/bitset.h"
#include "util/macros.h"
#include "util/ralloc.h"
#include "util/u_dynarray.h"
#include <assert.h>
#include <stdbool.h>
/** Source use. */
struct pco_use {
pco_instr *instr;
pco_ref *psrc;
};
/** Shared optimization context. */
struct pco_opt_ctx {
void *mem_ctx;
struct util_dynarray mods;
};
/**
* \brief Prepares modifiers and their users for propagation.
*
* Instructions with commutative sources may use a modifier in the source which
* can't have said modifier applied to it, e.g. fadd can have {abs,neg,flr} set
* in src0, but src1 only supports abs.
*
* \param[in,out] shader PCO shader.
* \param[in,out] ctx Shared optimization context.
* \return True if any instructions were modified.
*/
static inline bool pco_opt_prep_mods(pco_shader *shader,
struct pco_opt_ctx *ctx)
{
bool progress = false;
util_dynarray_init(&ctx->mods, ctx->mem_ctx);
/* TODO: support for more modifiers/ops. */
/* TODO: support cases where > 1 modifier can be applied (e.g. .abs.neg),
* and where modifiers might need to be applied on more than one source.
*/
pco_foreach_func_in_shader (func, shader) {
pco_foreach_instr_in_func_safe (mod, func) {
if (mod->op != PCO_OP_FNEG && mod->op != PCO_OP_FABS &&
mod->op != PCO_OP_FFLR)
continue;
pco_foreach_instr_in_func_from (instr, mod) {
if (instr->op != PCO_OP_FADD && instr->op != PCO_OP_FMUL)
continue;
pco_ref *match_src = NULL;
pco_ref *other_src = NULL;
pco_foreach_instr_src (psrc, instr) {
if (!pco_ref_is_ssa(*psrc) || psrc->val != mod->dest[0].val)
other_src = psrc;
else
match_src = psrc;
}
/* Instruction doesn't use the mod. */
if (!match_src)
continue;
/* Mod used in *both* sources; swapping would do nothing. */
if (!other_src)
continue;
unsigned match_src_index = match_src - instr->src;
unsigned other_src_index = other_src - instr->src;
bool match_has_mod = false;
bool other_has_mod = false;
switch (mod->op) {
case PCO_OP_FNEG:
match_has_mod = pco_instr_src_has_neg(instr, match_src_index);
other_has_mod = pco_instr_src_has_neg(instr, other_src_index);
break;
case PCO_OP_FABS:
match_has_mod = pco_instr_src_has_abs(instr, match_src_index);
other_has_mod = pco_instr_src_has_abs(instr, other_src_index);
break;
case PCO_OP_FFLR:
match_has_mod = pco_instr_src_has_flr(instr, match_src_index);
other_has_mod = pco_instr_src_has_flr(instr, other_src_index);
break;
default:
UNREACHABLE("");
}
/* Source can already have the mod set. */
if (match_has_mod)
continue;
/* Other source can't have the mod set either. */
if (!other_has_mod)
continue;
/* Swap the sources. */
pco_ref tmp = *match_src;
*match_src = *other_src;
*other_src = tmp;
progress = true;
}
/* Rewrite the mod op to a mov. */
pco_ref src = mod->src[0];
switch (mod->op) {
case PCO_OP_FNEG:
src = pco_ref_neg(src);
break;
case PCO_OP_FABS:
src = pco_ref_abs(src);
break;
case PCO_OP_FFLR:
src = pco_ref_flr(src);
break;
default:
UNREACHABLE("");
}
pco_builder b = pco_builder_create(func, pco_cursor_before_instr(mod));
pco_instr *mov = pco_mov(&b, mod->dest[0], src);
util_dynarray_append(&ctx->mods, mov);
pco_instr_delete(mod);
progress = true;
}
}
return progress;
}
/**
* \brief Lowers modifiers to hardware instructions.
*
* \param[in,out] shader PCO shader.
* \param[in,out] ctx Shared optimization context.
* \return True if any instructions were modified.
*/
static inline bool pco_opt_lower_mods(pco_shader *shader,
struct pco_opt_ctx *ctx)
{
bool progress = false;
util_dynarray_foreach (&ctx->mods, pco_instr *, pmod) {
pco_instr *mod = *pmod;
pco_builder b =
pco_builder_create(mod->parent_func, pco_cursor_before_instr(mod));
if (mod->src[0].flr)
pco_fadd(&b, mod->dest[0], mod->src[0], pco_zero);
else
pco_mbyp(&b, mod->dest[0], mod->src[0]);
pco_instr_delete(mod);
progress = true;
}
return progress;
}
/**
* \brief Checks if an instruction can be back-propagated.
*
* \param[in] to Instruction being back-propagated to.
* \param[in] from Instruction being back-propagated from.
* \return True if from can be back-propagated.
*/
static inline bool can_back_prop_instr(const pco_instr *to,
const pco_instr *from)
{
const struct pco_op_info *info = &pco_op_info[from->op];
/* Ensure any op mods set in from can also be set in to. */
u_foreach_bit64 (mod, info->mods) {
if (pco_instr_has_mod(from, mod) && pco_instr_mod_is_set(from, mod) &&
!pco_instr_has_mod(to, mod))
return false;
}
return true;
}
/**
* \brief Transfers any op mods that have been set.
*
* \param[in] to Instruction receiving the op mods.
* \param[in] from Instruction providing the op mods.
*/
static inline void xfer_set_op_mods(pco_instr *to, const pco_instr *from)
{
const struct pco_op_info *info = &pco_op_info[from->op];
/* Transfer set op mods. */
u_foreach_bit64 (mod, info->mods) {
if (pco_instr_has_mod(from, mod) && pco_instr_mod_is_set(from, mod)) {
assert(pco_instr_has_mod(to, mod));
pco_instr_set_mod(to, mod, pco_instr_get_mod(from, mod));
}
}
}
/**
* \brief Tries to back-propagate an instruction.
*
* \param[in] uses Global list of uses.
* \param[in] instr Instruction to try and back-propagate.
* \return True if back-propagation was successful.
*/
static inline bool try_back_prop_instr(struct pco_use *uses, pco_instr *instr)
{
pco_ref *pdest_to = &instr->dest[0];
if (instr->num_dests != 1 || !pco_ref_is_ssa(*pdest_to))
return false;
struct pco_use *use = &uses[pdest_to->val];
if (!use->instr)
return false;
/* TODO: allow propagating instructions which can have their dest/op
* modifiers set to perform the same operations as use source modifiers.
*
* Make sure to check in can_back_prop_instr when implementing this.
* We're fine for now since mov has no settable dest mods.
*/
if (use->instr->op != PCO_OP_MOV || pco_ref_has_mods_set(*use->psrc))
return false;
if (!can_back_prop_instr(instr, use->instr))
return false;
pco_ref *pdest_from = &use->instr->dest[0];
if (pco_ref_is_idx_reg(*pdest_from))
return false;
if (pco_ref_is_reg(*pdest_from) &&
pco_ref_get_reg_class(*pdest_from) == PCO_REG_CLASS_PIXOUT) {
return false;
bool has_isp_fb = false;
pco_foreach_instr_in_func_from_rev (rev_instr, use->instr) {
if (rev_instr == instr)
break;
if (rev_instr->op == PCO_OP_ALPHAF || rev_instr->op == PCO_OP_DEPTHF) {
has_isp_fb = true;
break;
}
}
if (has_isp_fb)
return false;
/* Don't move pixout regs into instructions that already use them. */
pco_foreach_instr_src (psrc, instr) {
if (pco_ref_is_reg(*psrc) &&
pco_ref_get_reg_class(*psrc) == PCO_REG_CLASS_PIXOUT) {
return false;
}
}
}
assert(pco_ref_get_bits(*pdest_from) == pco_ref_get_bits(*pdest_to));
assert(pco_ref_get_chans(*pdest_from) == pco_ref_get_chans(*pdest_to));
assert(!pco_ref_has_mods_set(*pdest_from) &&
!pco_ref_has_mods_set(*pdest_to));
/* Propagate the destination and the set op mods. */
/* TODO: types? */
*pdest_to = *pdest_from;
xfer_set_op_mods(instr, use->instr);
pco_instr_delete(use->instr);
return true;
}
/**
* \brief Instruction back-propagation pass.
*
* \param[in,out] shader PCO shader.
* \return True if any back-propagations were performed.
*/
static inline bool pco_opt_back_prop(pco_shader *shader)
{
bool progress = false;
struct pco_use *uses;
BITSET_WORD *multi_uses;
pco_foreach_func_in_shader_rev (func, shader) {
uses = rzalloc_array_size(NULL, sizeof(*uses), func->next_ssa);
multi_uses = rzalloc_array_size(uses,
sizeof(*multi_uses),
BITSET_WORDS(func->next_ssa));
pco_foreach_instr_in_func_safe_rev (instr, func) {
pco_foreach_instr_src_ssa (psrc, instr) {
if (BITSET_TEST(multi_uses, psrc->val) || uses[psrc->val].instr) {
BITSET_SET(multi_uses, psrc->val);
uses[psrc->val].instr = NULL;
continue;
}
uses[psrc->val] = (struct pco_use){
.instr = instr,
.psrc = psrc,
};
}
progress |= try_back_prop_instr(uses, instr);
}
ralloc_free(uses);
}
return progress;
}
/**
* \brief Checks if a source can be forward-propagated.
*
* \param[in] to_instr Instruction being forward-propagated to.
* \param[in] to Source being forward-propagated to.
* \param[in] from Source being forward-propagated from.
* \return True if from can be forward-propagated.
*/
static inline bool can_fwd_prop_src(const pco_instr *to_instr,
const pco_ref *to,
const pco_ref *from)
{
/* Check sizes. */
if (pco_ref_get_bits(*from) != pco_ref_get_bits(*to))
return false;
if (pco_ref_get_chans(*from) != pco_ref_get_chans(*to))
return false;
/* See if the modifiers can be propagated. */
unsigned to_src_index = to - to_instr->src;
if (pco_ref_has_mods_set(*from)) {
if (from->oneminus && !pco_instr_src_has_oneminus(to_instr, to_src_index))
return false;
if (from->clamp && !pco_instr_src_has_clamp(to_instr, to_src_index))
return false;
if (from->flr && !pco_instr_src_has_flr(to_instr, to_src_index))
return false;
if (from->abs && !pco_instr_src_has_abs(to_instr, to_src_index))
return false;
if (from->neg && !pco_instr_src_has_neg(to_instr, to_src_index))
return false;
if (from->elem && !pco_instr_src_has_elem(to_instr, to_src_index))
return false;
}
/* TODO: Also need to consider whether the source can be represented in the
* propagated instruction.
* Or, a legalize pass to insert movs; probably better since
* feature/arch-agnostic.
*/
if (pco_ref_is_reg(*from) &&
pco_ref_get_reg_class(*from) == PCO_REG_CLASS_PIXOUT) {
return false;
}
return true;
}
/**
* \brief Tries to forward-propagate an instruction.
*
* \param[in] writes Global list of writes.
* \param[in] instr Instruction to try and forward-propagate.
* \return True if forward-propagation was successful.
*/
static inline bool try_fwd_prop_instr(pco_instr **writes, pco_instr *instr)
{
bool progress = false;
pco_foreach_instr_src_ssa (psrc, instr) {
pco_instr *parent_instr = writes[psrc->val];
if (!parent_instr || parent_instr->op != PCO_OP_MOV)
continue;
if (!can_fwd_prop_src(instr, psrc, &parent_instr->src[0]))
continue;
/* Propagate the source. */
pco_ref repl = parent_instr->src[0];
if (psrc->flr)
repl = pco_ref_flr(repl);
else if (psrc->abs)
repl = pco_ref_abs(repl);
repl.neg ^= psrc->neg;
/* TODO: types? */
*psrc = repl;
if (pco_instr_has_olchk(parent_instr) &&
pco_instr_get_olchk(parent_instr)) {
assert(pco_instr_has_olchk(instr));
pco_instr_set_olchk(instr, true);
}
progress = true;
}
return progress;
}
/**
* \brief Instruction forward-propagation pass.
*
* \param[in,out] shader PCO shader.
* \return True if any forward-propagations were performed.
*/
static inline bool pco_opt_fwd_prop(pco_shader *shader)
{
bool progress = false;
pco_instr **writes;
pco_foreach_func_in_shader (func, shader) {
writes = rzalloc_array_size(NULL, sizeof(*writes), func->next_ssa);
pco_foreach_instr_in_func (instr, func) {
pco_foreach_instr_dest_ssa (pdest, instr) {
writes[pdest->val] = instr;
}
progress |= try_fwd_prop_instr(writes, instr);
}
ralloc_free(writes);
}
return progress;
}
/**
* \brief Tries to propagate a comp instruction referencing hw registers.
*
* \param[in] src Source to match for replacement.
* \param[in] repl Replacement hw register reference.
* \param[in] from Instruction to try and propagate from.
* \return True if propagation was successful.
*/
static inline bool try_prop_hw_comp(pco_ref src, pco_ref repl, pco_instr *from)
{
bool progress = false;
pco_foreach_instr_in_func_from (instr, from) {
pco_foreach_instr_src_ssa (psrc, instr) {
if (psrc->val != src.val)
continue;
/* Propagate the source. */
pco_ref _repl = repl;
if (psrc->flr)
_repl = pco_ref_flr(_repl);
else if (psrc->abs)
_repl = pco_ref_abs(_repl);
_repl.neg ^= psrc->neg;
/* TODO: types? */
*psrc = _repl;
progress = true;
}
}
return progress;
}
/**
* \brief Pass to propagate comp instructions referencing hw registers.
*
* \param[in,out] shader PCO shader.
* \return True if any hw reg propagations were performed.
*/
static inline bool pco_opt_prop_hw_comps(pco_shader *shader)
{
bool progress = false;
pco_foreach_func_in_shader (func, shader) {
pco_foreach_instr_in_func_safe (instr, func) {
if (instr->op != PCO_OP_COMP)
continue;
pco_ref vec_src = instr->src[0];
if (pco_ref_is_ssa(vec_src))
continue;
pco_ref dest = instr->dest[0];
assert(pco_ref_is_ssa(dest));
unsigned offset = pco_ref_get_imm(instr->src[1]);
/* Construct a replacement scalar reference. */
pco_ref repl = vec_src;
repl = pco_ref_chans(repl, 1);
repl = pco_ref_offset(repl, offset);
progress |= try_prop_hw_comp(dest, repl, instr);
pco_instr_delete(instr);
}
}
return progress;
}
/**
* \brief Performs shader optimizations.
*
* \param[in,out] shader PCO shader.
* \return True if the pass made progress.
*/
bool pco_opt(pco_shader *shader)
{
bool progress = false;
struct pco_opt_ctx ctx = { .mem_ctx = ralloc_context(NULL) };
PCO_PASS(progress, shader, pco_opt_prep_mods, &ctx);
PCO_PASS(progress, shader, pco_opt_back_prop);
PCO_PASS(progress, shader, pco_opt_fwd_prop);
/* TODO: Track whether there are any comp instructions referencing hw
* registers resulting from the previous passes, and only run
* pco_opt_prop_hw_comps if this is the case.
*/
PCO_PASS(progress, shader, pco_opt_prop_hw_comps);
PCO_PASS(progress, shader, pco_opt_lower_mods, &ctx);
ralloc_free(ctx.mem_ctx);
return progress;
}
/**
* \brief Checks whether an instruction has side-effects.
*
* \param[in] instr Instruction to check.
* \return True if the instruction has side-effects.
*/
static inline bool instr_has_side_effects(pco_instr *instr)
{
/* Atomic instructions. */
if (pco_instr_has_atom(instr) && pco_instr_get_atom(instr))
return true;
switch (instr->op) {
case PCO_OP_ATOMIC:
case PCO_OP_FDSX:
case PCO_OP_FDSY:
/* TODO: we don't really want to mark this as having side-effects, but
* idfwdf does smp without using the results.
*/
case PCO_OP_SMP:
case PCO_OP_IADD32_ATOMIC:
case PCO_OP_XCHG_ATOMIC:
case PCO_OP_CMPXCHG_ATOMIC:
case PCO_OP_MIN_ATOMIC:
case PCO_OP_MAX_ATOMIC:
case PCO_OP_LOGICAL_ATOMIC:
case PCO_OP_OP_ATOMIC_OFFSET:
return true;
default:
break;
}
/* TODO:
* - gradient
* - conditional
* - sample writes (+ set the destination pointer to point to the write data)
* - others
*/
return false;
}
/**
* \brief Performs DCE.
*
* \param[in,out] shader PCO shader.
* \return True if the pass made progress.
*/
bool pco_dce(pco_shader *shader)
{
bool progress = false;
BITSET_WORD *ssa_used;
BITSET_WORD *vreg_used;
pco_foreach_func_in_shader (func, shader) {
ssa_used = rzalloc_array_size(NULL,
sizeof(*ssa_used),
BITSET_WORDS(func->next_ssa));
vreg_used = rzalloc_array_size(NULL,
sizeof(*vreg_used),
BITSET_WORDS(func->next_vreg));
/* Collect used SSA/vreg sources. */
pco_foreach_instr_in_func (instr, func) {
pco_foreach_instr_src_vreg_ssa (psrc, instr) {
if (pco_ref_is_ssa(*psrc))
BITSET_SET(ssa_used, psrc->val);
else
BITSET_SET(vreg_used, psrc->val);
}
}
pco_foreach_vreg_ssa_if_in_func (pif, func) {
if (pco_ref_is_ssa(pif->cond))
BITSET_SET(ssa_used, pif->cond.val);
else
BITSET_SET(vreg_used, pif->cond.val);
}
/* Remove instructions with unused SSA/vreg destinations (if they also
* have no side-effects).
*/
pco_foreach_instr_in_func_safe (instr, func) {
bool has_dce_dests = false;
bool dests_used = false;
pco_foreach_instr_dest_vreg_ssa (pdest, instr) {
has_dce_dests = true;
if (pco_ref_is_ssa(*pdest))
dests_used |= BITSET_TEST(ssa_used, pdest->val);
else
dests_used |= BITSET_TEST(vreg_used, pdest->val);
}
if (has_dce_dests && !dests_used && !instr_has_side_effects(instr)) {
pco_instr_delete(instr);
progress = true;
}
}
ralloc_free(vreg_used);
ralloc_free(ssa_used);
}
return progress;
}
static inline bool only_uncollated_elems(pco_instr *vec)
{
pco_foreach_instr_src (psrc, vec) {
if (pco_ref_get_chans(*psrc) > 1)
return false;
}
return true;
}
/**
* \brief Shrinks vectors with unused components.
*
* \param[in,out] shader PCO shader.
* \return True if the pass made progress.
*/
bool pco_shrink_vecs(pco_shader *shader)
{
bool progress = false;
pco_foreach_func_in_shader (func, shader) {
pco_foreach_instr_in_func (vec, func) {
if (vec->op != PCO_OP_VEC)
continue;
/* Can't shrink if has collated elems. */
if (!only_uncollated_elems(vec))
continue;
pco_ref *pdest = &vec->dest[0];
unsigned chans_used = 0;
unsigned chans = pco_ref_get_chans(*pdest);
pco_foreach_instr_in_func_from (instr, vec) {
if (instr->op == PCO_OP_COMP) {
pco_ref src = instr->src[0];
if (!pco_ref_is_ssa(src))
continue;
if (src.val != pdest->val)
continue;
unsigned offset = pco_ref_get_imm(instr->src[1]);
chans_used = MAX2(chans_used, offset);
continue;
}
pco_foreach_instr_src_ssa (psrc, instr) {
if (psrc->val == pdest->val) {
chans_used = MAX2(chans_used, pco_ref_get_chans(*psrc) - 1);
}
}
}
++chans_used;
assert(chans_used <= chans);
/* Whole vec used, skip. */
if (chans_used == chans)
continue;
/* Update the vec. */
vec->num_srcs = chans_used;
*pdest = pco_ref_chans(*pdest, chans_used);
progress = true;
}
}
return progress;
}
bool pco_opt_comp_only_vecs(pco_shader *shader)
{
bool progress = false;
pco_foreach_func_in_shader (func, shader) {
pco_foreach_instr_in_func (vec, func) {
if (vec->op != PCO_OP_VEC)
continue;
bool used_by_noncomps = false;
pco_ref dest = vec->dest[0];
struct util_dynarray comps = UTIL_DYNARRAY_INIT;
pco_foreach_instr_in_func_from (instr, vec) {
if (instr->op == PCO_OP_COMP) {
if (instr->src[0].val == dest.val) {
util_dynarray_append(&comps, instr);
}
continue;
}
pco_foreach_instr_src_ssa (psrc, instr) {
if (psrc->val == dest.val) {
used_by_noncomps = true;
break;
}
}
if (used_by_noncomps)
break;
}
if (used_by_noncomps) {
util_dynarray_fini(&comps);
continue;
}
/* Has collated vec, skip. */
/* TODO: support this. */
if (vec->num_srcs != util_dynarray_num_elements(&comps, pco_instr *)) {
util_dynarray_fini(&comps);
continue;
}
util_dynarray_foreach (&comps, pco_instr *, _comp) {
pco_instr *comp = *_comp;
pco_ref dest = comp->dest[0];
assert(pco_ref_is_ssa(dest));
unsigned offset = pco_ref_get_imm(comp->src[1]);
assert(offset < vec->num_srcs);
pco_builder b =
pco_builder_create(func, pco_cursor_before_instr(comp));
pco_mov(&b, comp->dest[0], vec->src[offset]);
pco_instr_delete(comp);
}
util_dynarray_fini(&comps);
progress = true;
}
}
return progress;
}
File diff suppressed because it is too large. Load diff
+500
View File
@@ -0,0 +1,500 @@
# Copyright © 2024 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
from enum import Enum, auto
_ = None
VARIABLE = ~0
prefix = 'pco'
def val_fits_in_bits(val, num_bits):
return val < pow(2, num_bits)
class BaseType(Enum):
bool = auto()
uint = auto()
enum = auto()
class Type(object):
def __init__(self, name, tname, base_type, num_bits, dec_bits, check, encode, nzdefault, print_early, unset, enum):
self.name = name
self.tname = tname
self.base_type = base_type
self.num_bits = num_bits
self.dec_bits = dec_bits
self.check = check
self.encode = encode
self.nzdefault = nzdefault
self.print_early = print_early
self.unset = unset
self.enum = enum
types = {}
def type(name, base_type, num_bits=None, dec_bits=None, check=None, encode=None, nzdefault=None, print_early=False, unset=False, enum=None):
assert name not in types.keys(), f'Duplicate type "{name}".'
if base_type == BaseType.bool:
_name = 'bool'
elif base_type == BaseType.uint:
_name = 'unsigned'
elif base_type == BaseType.enum:
_name = f'enum {prefix}_{name}'
else:
assert False, f'Invalid base type for type {name}.'
t = Type(_name, name, base_type, num_bits, dec_bits, check, encode, nzdefault, print_early, unset, enum)
types[name] = t
return t
# Enum types.
class EnumType(object):
def __init__(self, name, ename, elems, valid, unique_count, is_bitset, parent):
self.name = name
self.ename = ename
self.elems = elems
self.valid = valid
self.unique_count = unique_count
self.is_bitset = is_bitset
self.parent = parent
class EnumElem(object):
def __init__(self, cname, value, string):
self.cname = cname
self.value = value
self.string = string
enums = {}
def enum_type(name, elems, is_bitset=False, num_bits=None, *args, **kwargs):
assert name not in enums.keys(), f'Duplicate enum "{name}".'
_elems = {}
_valid_vals = set()
_valid_valmask = 0
next_value = 0
for e in elems:
if isinstance(e, str):
elem = e
value = (1 << next_value) if is_bitset else next_value
next_value += 1
string = elem
else:
assert isinstance(e, tuple) and len(e) > 1
elem = e[0]
if isinstance(e[1], str) and len(e) == 2:
value = (1 << next_value) if is_bitset else next_value
next_value += 1
string = e[1]
elif isinstance(e[1], int):
value = e[1]
string = e[2] if len(e) == 3 else elem
else:
assert False, f'Invalid defintion for element "{elem}" in elem "{name}".'
assert isinstance(elem, str) and isinstance(value, int) and isinstance(string, str)
assert not num_bits or val_fits_in_bits(value, num_bits), f'Element "{elem}" in elem "{name}" with value "{value}" does not fit into {num_bits} bits.'
# Collect valid values, ensure that elements with repeated values only have one string set.
if is_bitset:
if (_valid_valmask & value) != 0:
string = None
_valid_valmask |= value
else:
if value in _valid_vals:
string = None
_valid_vals.add(value)
assert elem not in _elems.keys(), f'Duplicate element "{elem}" in enum "".'
cname = f'{prefix}_{name}_{elem}'.upper()
_elems[elem] = EnumElem(cname, value, string)
_name = f'{prefix}_{name}'
_valid = _valid_valmask if is_bitset else _valid_vals
_unique_count = bin(_valid_valmask).count('1') if is_bitset else len(_valid_vals)
enum = EnumType(_name, name, _elems, _valid, _unique_count, is_bitset, parent=None)
enums[name] = enum
return type(name, BaseType.enum, num_bits, *args, **kwargs, enum=enum)
def enum_subtype(name, parent, num_bits):
assert name not in enums.keys(), f'Duplicate enum "{name}".'
assert parent.enum is not None
assert not parent.enum.is_bitset
assert parent.num_bits is not None and parent.num_bits > num_bits
_name = f'{prefix}_{name}'
# Validation of subtype - values that will fit in the smaller bit size.
_valid = {val for val in parent.enum.valid if val_fits_in_bits(val, num_bits)}
enum = EnumType(_name, name, None, _valid, None, False, parent)
enums[name] = enum
return type(name, BaseType.enum, num_bits, enum=enum)
# Type specializations.
field_types = {}
field_enum_types = {}
def field_type(name, *args, **kwargs):
assert name not in field_types.keys(), f'Duplicate field type "{name}".'
t = type(name, *args, **kwargs)
field_types[name] = t
return t
def field_enum_type(name, *args, **kwargs):
assert name not in field_types.keys() and name not in field_enum_types.keys(), f'Duplicate field enum type "{name}".'
t = enum_type(name, *args, **kwargs)
field_types[name] = t
field_enum_types[name] = enums[name]
return t
def field_enum_subtype(name, *args, **kwargs):
assert name not in field_types.keys() and name not in field_enum_types.keys(), f'Duplicate field enum (sub)type "{name}".'
t = enum_subtype(name, *args, **kwargs)
field_types[name] = t
field_enum_types[name] = enums[name]
return t
class OpMod(object):
def __init__(self, t, cname, ctype):
self.t = t
self.cname = cname
self.ctype = ctype
op_mods = {}
op_mod_enums = {}
def op_mod(name, *args, **kwargs):
assert name not in op_mods.keys(), f'Duplicate op mod "{name}".'
t = type(name, *args, **kwargs)
cname = f'{prefix}_op_mod_{name}'.upper()
ctype = f'{prefix}_mod_type_{t.base_type.name.upper()}'.upper()
om = op_mods[name] = OpMod(t, cname, ctype)
assert len(op_mods) <= 64, f'Too many op mods ({len(op_mods)})!'
return om
def op_mod_enum(name, *args, **kwargs):
assert name not in op_mods.keys() and name not in op_mod_enums.keys(), f'Duplicate op mod enum "{name}".'
t = enum_type(name, *args, **kwargs)
cname = f'{prefix}_op_mod_{name}'.upper()
ctype = f'{prefix}_mod_type_{t.base_type.name.upper()}'.upper()
om = op_mods[name] = OpMod(t, cname, ctype)
op_mod_enums[name] = enums[name]
assert len(op_mods) <= 64, f'Too many op mods ({len(op_mods)})!'
return om
class RefMod(object):
def __init__(self, t, cname, ctype):
self.t = t
self.cname = cname
self.ctype = ctype
ref_mods = {}
ref_mod_enums = {}
def ref_mod(name, *args, **kwargs):
assert name not in ref_mods.keys(), f'Duplicate ref mod "{name}".'
t = type(name, *args, **kwargs)
cname = f'{prefix}_ref_mod_{name}'.upper()
ctype = f'{prefix}_mod_type_{t.base_type.name.upper()}'.upper()
rm = ref_mods[name] = RefMod(t, cname, ctype)
assert len(ref_mods) <= 64, f'Too many ref mods ({len(ref_mods)})!'
return rm
def ref_mod_enum(name, *args, **kwargs):
assert name not in ref_mods.keys() and name not in ref_mod_enums.keys(), f'Duplicate ref mod enum "{name}".'
t = enum_type(name, *args, **kwargs)
cname = f'{prefix}_ref_mod_{name}'.upper()
ctype = f'{prefix}_mod_type_{t.base_type.name.upper()}'.upper()
rm = ref_mods[name] = RefMod(t, cname, ctype)
ref_mod_enums[name] = enums[name]
assert len(ref_mods) <= 64, f'Too many ref mods ({len(ref_mods)})!'
return rm
# Bit encoding definition helpers.
class BitPiece(object):
def __init__(self, name, byte, hi_bit, lo_bit, num_bits):
self.name = name
self.byte = byte
self.hi_bit = hi_bit
self.lo_bit = lo_bit
self.num_bits = num_bits
def bit_piece(name, byte, bit_range):
assert bit_range.count(':') <= 1, f'Invalid bit range specification in bit piece {name}.'
is_one_bit = not bit_range.count(':')
split_range = [bit_range, bit_range] if is_one_bit else bit_range.split(':', 1)
(hi_bit, lo_bit) = list(map(int, split_range))
assert hi_bit < 8 and hi_bit >= 0 and lo_bit < 8 and lo_bit >= 0 and hi_bit >= lo_bit
_num_bits = hi_bit - lo_bit + 1
return BitPiece(name, byte, hi_bit, lo_bit, _num_bits)
class BitField(object):
def __init__(self, name, cname, field_type, pieces, reserved, validate, encoding, encoded_bits):
self.name = name
self.cname = cname
self.field_type = field_type
self.pieces = pieces
self.reserved = reserved
self.validate = validate
self.encoding = encoding
self.encoded_bits = encoded_bits
class Encoding(object):
def __init__(self, clear, set):
self.clear = clear
self.set = set
def bit_field(bit_set_name, name, bit_set_pieces, field_type, pieces, reserved=None):
_pieces = [bit_set_pieces[p] for p in pieces]
total_bits = sum([p.num_bits for p in _pieces])
assert total_bits == field_type.num_bits, f'Expected {field_type.num_bits}, got {total_bits} in bit field {name}.'
if reserved is not None:
assert val_fits_in_bits(reserved, total_bits), f'Reserved value for bit field {name} is too large.'
cname = f'{bit_set_name}_{name}'.upper()
if field_type.base_type == BaseType.enum:
validate = f'{prefix}_{field_type.enum.ename}_valid({{}})'
else:
validate = f'{{}} < (1ULL << {field_type.num_bits})'
encoding = []
bits_consumed = 0
for i, piece in enumerate(reversed(_pieces)):
enc_clear = f'{{}}[{piece.byte}] &= {hex((((1 << piece.num_bits) - 1) << piece.lo_bit) ^ 0xff)}'
enc_set = f'{{}}[{piece.byte}] |= ('
enc_set += f'({{}} >> {bits_consumed})' if bits_consumed > 0 else '{}'
enc_set += f' & {hex((1 << piece.num_bits) - 1)})'
enc_set += f' << {piece.lo_bit}' if piece.lo_bit > 0 else ''
encoding.append(Encoding(enc_clear, enc_set))
bits_consumed += piece.num_bits
return BitField(name, cname, field_type, _pieces, reserved, validate, encoding, bits_consumed)
class BitSet(object):
def __init__(self, name, bsname, pieces, fields):
self.name = name
self.bsname = bsname
self.pieces = pieces
self.fields = fields
self.bit_structs = {}
self.variants = []
bit_sets = {}
def bit_set(name, pieces, fields):
assert name not in bit_sets.keys(), f'Duplicate bit set "{name}".'
_name = f'{prefix}_{name}'
_pieces = {}
for (piece, spec) in pieces:
assert piece not in _pieces.keys(), f'Duplicate bit piece "{piece}" in bit set "{name}".'
_pieces[piece] = bit_piece(piece, *spec)
_fields = {}
for (field, spec) in fields:
assert field not in _fields.keys(), f'Duplicate bit field "{field}" in bit set "{name}".'
_fields[field] = bit_field(_name, field, _pieces, *spec)
bs = BitSet(_name, name, _pieces, _fields)
bit_sets[name] = bs
return bs
class BitStruct(object):
def __init__(self, name, bsname, struct_fields, encode_fields, num_bytes, data, bit_set):
self.name = name
self.bsname = bsname
self.struct_fields = struct_fields
self.encode_fields = encode_fields
self.num_bytes = num_bytes
self.data = data
self.bit_set = bit_set
class StructField(object):
def __init__(self, type, field, bits):
self.type = type
self.field = field
self.bits = bits
class EncodeField(object):
def __init__(self, name, value):
self.name = name
self.value = value
class Variant(object):
def __init__(self, cname, bytes):
self.cname = cname
self.bytes = bytes
def bit_struct(name, bit_set, field_mappings, data=None):
assert name not in bit_set.bit_structs.keys(), f'Duplicate bit struct "{name}" in bit set "{bit_set.name}".'
struct_fields = {}
encode_fields = []
all_pieces = []
total_bits = 0
for mapping in field_mappings:
if isinstance(mapping, str):
struct_field = mapping
_field = mapping
fixed_value = None
else:
assert isinstance(mapping, tuple)
struct_field, _field, *fixed_value = mapping
assert len(fixed_value) == 0 or len(fixed_value) == 1
fixed_value = None if len(fixed_value) == 0 else fixed_value[0]
assert struct_field not in struct_fields.keys(), f'Duplicate struct field "{struct_field}" in bit struct "{name}".'
assert _field in bit_set.fields.keys(), f'Field "{_field}" in mapping for struct field "{name}.{struct_field}" not defined in bit set "{bit_set.name}".'
field = bit_set.fields[_field]
field_type = field.field_type
is_enum = field_type.base_type == BaseType.enum
if fixed_value is not None:
assert field.reserved is None, f'Fixed value for field mapping "{struct_field}" using field "{_field}" cannot overwrite its reserved value.'
if is_enum and isinstance(fixed_value, str):
enum = field_type.enum
assert fixed_value in enum.elems.keys(), f'Fixed value for field mapping "{struct_field}" using field "{_field}" is not an element of enum {field_type.name}.'
fixed_value = enum.elems[fixed_value].cname.upper()
else:
if isinstance(fixed_value, bool):
fixed_value = int(fixed_value)
assert isinstance(fixed_value, int)
assert val_fits_in_bits(fixed_value, field_type.num_bits), f'Fixed value for field mapping "{struct_field}" using field "{_field}" is too large.'
all_pieces.extend([(piece.lo_bit + (8 * piece.byte), piece.hi_bit + (8 * piece.byte), piece.name) for piece in field.pieces])
total_bits += field_type.num_bits
# Describe how to encode the bit struct.
encode_field = f'{bit_set.name}_{_field}'.upper()
if fixed_value is not None:
encode_value = fixed_value
elif field.reserved is not None:
encode_value = field.reserved
else:
encode_value = f's.{struct_field}'
encode_fields.append(EncodeField(encode_field, encode_value))
# Describe settable fields.
if field.reserved is None and fixed_value is None:
# Use parent enum for struct fields.
if is_enum and field_type.enum.parent is not None:
field_type = field_type.enum.parent
struct_field_bits = field_type.dec_bits if field_type.dec_bits is not None else field_type.num_bits
struct_fields[struct_field] = StructField(field_type, struct_field, struct_field_bits)
# Check for overlapping pieces.
for p0 in all_pieces:
for p1 in all_pieces:
if p0 == p1:
continue
assert p0[1] < p1[0] or p0[0] > p1[1], f'Pieces "{p0[2]}" and "{p1[2]}" overlap in bit struct "{name}".'
# Check for byte-alignment.
assert (total_bits % 8) == 0, f'Bit struct "{name}" has a non-byte-aligned number of bits ({total_bits}).'
_name = f'{bit_set.name}_{name}'
total_bytes = total_bits // 8
bs = BitStruct(_name, name, struct_fields, encode_fields, total_bytes, data, bit_set)
bit_set.bit_structs[name] = bs
bit_set.variants.append(Variant(f'{bit_set.name}_{name}'.upper(), total_bytes))
return bs
# Op definitions.
class Op(object):
def __init__(self, name, cname, bname, op_type, op_mods, cop_mods, op_mod_map, num_dests, num_srcs, dest_mods, cdest_mods, src_mods, csrc_mods, has_target_cf_node, builder_params):
self.name = name
self.cname = cname
self.bname = bname
self.op_type = op_type
self.op_mods = op_mods
self.cop_mods = cop_mods
self.op_mod_map = op_mod_map
self.num_dests = num_dests
self.num_srcs = num_srcs
self.dest_mods = dest_mods
self.cdest_mods = cdest_mods
self.src_mods = src_mods
self.csrc_mods = csrc_mods
self.has_target_cf_node = has_target_cf_node
self.builder_params = builder_params
ops = {}
def op(name, op_type, op_mods, num_dests, num_srcs, dest_mods, src_mods, has_target_cf_node):
assert name not in ops.keys(), f'Duplicate op "{name}".'
_name = name.replace('.', '_')
cname = f'{prefix}_op_{_name}'
bname = f'{prefix}_{_name}'
cop_mods = 0 if not op_mods else ' | '.join([f'(1ULL << {op_mod.cname})' for op_mod in op_mods])
op_mod_map = {op_mod.cname: index + 1 for index, op_mod in enumerate(op_mods)}
cdest_mods = {i: 0 if not destn_mods else ' | '.join([f'(1ULL << {ref_mod.cname})' for ref_mod in destn_mods]) for i, destn_mods in enumerate(dest_mods)}
csrc_mods = {i: 0 if not srcn_mods else ' | '.join([f'(1ULL << {ref_mod.cname})' for ref_mod in srcn_mods]) for i, srcn_mods in enumerate(src_mods)}
builder_params = ['', '', '', '', '', '', '']
builder_params[0] = 'pco_func *func'
builder_params[1] = 'pco_builder *b'
builder_params[2] = 'func'
builder_params[3] = 'b'
if has_target_cf_node:
builder_params[0] += ', pco_cf_node *target_cf_node'
builder_params[1] += ', pco_cf_node *target_cf_node'
builder_params[2] += ', target_cf_node'
builder_params[3] += ', target_cf_node'
if num_dests == VARIABLE:
builder_params[0] += f', unsigned num_dests, pco_ref *dest'
builder_params[1] += f', unsigned num_dests, pco_ref *dest'
builder_params[2] += f', num_dests, dest'
builder_params[3] += f', num_dests, dest'
else:
for d in range(num_dests):
builder_params[0] += f', pco_ref dest{d}'
builder_params[1] += f', pco_ref dest{d}'
builder_params[2] += f', dest{d}'
builder_params[3] += f', dest{d}'
if num_srcs == VARIABLE:
builder_params[0] += f', unsigned num_srcs, pco_ref *src'
builder_params[1] += f', unsigned num_srcs, pco_ref *src'
builder_params[2] += f', num_srcs, src'
builder_params[3] += f', num_srcs, src'
else:
for s in range(num_srcs):
builder_params[0] += f', pco_ref src{s}'
builder_params[1] += f', pco_ref src{s}'
builder_params[2] += f', src{s}'
builder_params[3] += f', src{s}'
if bool(op_mods):
builder_params[0] += f', struct {prefix}_{_name}_mods mods'
builder_params[1] += f', struct {prefix}_{_name}_mods mods'
builder_params[4] = ', ...'
builder_params[5] = f', (struct {bname}_mods){{0, ##__VA_ARGS__}}'
builder_params[6] = ', mods'
op = Op(name, cname, bname, op_type, op_mods, cop_mods, op_mod_map, num_dests, num_srcs, dest_mods, cdest_mods, src_mods, csrc_mods, has_target_cf_node, builder_params)
ops[name] = op
return op
def pseudo_op(name, op_mods=[], num_dests=0, num_srcs=0, dest_mods=[], src_mods=[], has_target_cf_node=False):
return op(name, 'pseudo', op_mods, num_dests, num_srcs, dest_mods, src_mods, has_target_cf_node)
def hw_op(name, op_mods=[], num_dests=0, num_srcs=0, dest_mods=[], src_mods=[], has_target_cf_node=False):
return op(name, 'hw', op_mods, num_dests, num_srcs, dest_mods, src_mods, has_target_cf_node)
def hw_direct_op(name, op_mods=[], num_dests=0, num_srcs=0, dest_mods=[], src_mods=[], has_target_cf_node=False):
return op(name, 'hw_direct', op_mods, num_dests, num_srcs, dest_mods, src_mods, has_target_cf_node)
Loaded 100 of 12511 files, more files were not shown because too many files have changed in this diff. Show more