pvr: Add a Vulkan driver for Imagination Technologies PowerVR Rogue GPUs

Co-authored-by: Rajnesh Kanwal <rajnesh.kanwal@imgtec.com>
Co-authored-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com>
Co-authored-by: Simon Perretta <simon.perretta@imgtec.com>
Co-authored-by: Alexander Wasey <Alexander.Wasey@imgtec.com>
Signed-off-by: Frank Binns <frank.binns@imgtec.com>
Signed-off-by: Rajnesh Kanwal <rajnesh.kanwal@imgtec.com>
Signed-off-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com>
Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Signed-off-by: Alexander Wasey <Alexander.Wasey@imgtec.com>
Acked-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15243>
This commit is contained in:
Frank Binns 2022-02-25 10:28:39 +00:00
parent 5d151ddfba
commit 8991e64641
158 changed files with 54123 additions and 1 deletions

View File

@ -109,6 +109,11 @@ meson.build @dbaker @eric
# Freedreno
/src/gallium/drivers/freedreno/ @robclark
# Imagination
/include/drm-uapi/pvr_drm.h @CreativeCylon @frankbinns @rajnesh-kanwal
/src/imagination/ @CreativeCylon @frankbinns @rajnesh-kanwal
/src/imagination/rogue/ @simon-perretta-img
# Intel
/include/drm-uapi/i915_drm.h @kwg @llandwerlin @jekstrand @idr
/include/pci_ids/i*_pci_ids.h @kwg @llandwerlin @jekstrand @idr

View File

@ -272,6 +272,8 @@ with_swrast_vk = _vulkan_drivers.contains('swrast')
with_virtio_vk = _vulkan_drivers.contains('virtio-experimental')
with_freedreno_kgsl = get_option('freedreno-kgsl')
with_broadcom_vk = _vulkan_drivers.contains('broadcom')
with_imagination_vk = _vulkan_drivers.contains('imagination-experimental')
with_imagination_srv = get_option('imagination-srv')
with_any_vk = _vulkan_drivers.length() != 0
with_any_broadcom = with_gallium_vc4 or with_gallium_v3d or with_broadcom_vk

View File

@ -192,7 +192,7 @@ option(
'vulkan-drivers',
type : 'array',
value : ['auto'],
choices : ['auto', 'amd', 'broadcom', 'freedreno', 'intel', 'panfrost', 'swrast', 'virtio-experimental'],
choices : ['auto', 'amd', 'broadcom', 'freedreno', 'imagination-experimental', 'intel', 'panfrost', 'swrast', 'virtio-experimental'],
description : 'List of vulkan drivers to build. If this is set to auto all drivers applicable to the target OS/architecture will be built'
)
option(
@ -201,6 +201,12 @@ option(
value : false,
description : 'use kgsl backend for freedreno vulkan driver',
)
option(
'imagination-srv',
type : 'boolean',
value : false,
description : 'Enable Services backend for Imagination Technologies vulkan driver',
)
option(
'shader-cache',
type : 'combo',

View File

@ -0,0 +1,247 @@
# 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: false
#AlignConsecutiveBitFields: false # Requires clang-11
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: false
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: false
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: false
# 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: [
'foreach_instr',
'foreach_instr_safe',
'hash_table_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_emit_merge',
'pvr_csb_pack',
'nir_foreach_block',
'nir_foreach_block_safe',
'nir_foreach_function',
'nir_foreach_instr',
'nir_foreach_instr_safe',
'nir_foreach_shader_in_variable',
'nir_foreach_shader_out_variable',
'nir_foreach_use',
'nir_foreach_use_safe',
'nir_foreach_variable_with_modes',
'u_vector_foreach',
'util_dynarray_foreach',
'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'
]
NamespaceMacros: [
]
StatementMacros: [
]
TypenameMacros: [
]
#WhitespaceSensitiveMacros: [] # Requires clang-11

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)
)
)

View File

@ -0,0 +1,2 @@
[*.{c,h,cpp,hpp,cc,hh}]
max_line_length = 80

View File

@ -0,0 +1,33 @@
# 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.
libpowervr_common = static_library(
'powervr_common',
[
'pvr_device_info.c',
],
include_directories : [
inc_include,
inc_src,
],
c_args : [no_override_init_args],
gnu_symbol_visibility : 'hidden',
)

View File

@ -0,0 +1,294 @@
/*
* 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 "pvr_device_info.h"
const struct pvr_device_ident pvr_device_ident_4_V_2_51 = {
.device_id = 0x6250,
.series_name = "Rogue",
.public_name = "GX6250",
};
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_gs_rta_support = true,
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_num_user_clip_planes = true,
.has_robust_buffer_access = true,
.has_slc_cache_line_size_bits = true,
.has_slc_mcu_cache_controls = 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_usc_f16sop_u8 = true,
.has_usc_min_output_registers_per_pix = 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,
.isp_max_tiles_in_flight = 4U,
.isp_samples_per_pixel = 2U,
.max_multisample = 8U,
.max_partitions = 8U,
.max_usc_tasks = 56U,
.num_clusters = 2U,
.num_raster_pipes = 1U,
.num_user_clip_planes = 8U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 32U,
.tile_size_y = 32U,
.usc_min_output_registers_per_pix = 2U,
.uvs_banks = 8U,
.uvs_pba_entries = 320U,
.uvs_vtx_entries = 288U,
.vdm_cam_size = 256U,
};
const struct pvr_device_enhancements pvr_device_enhancements_4_40_2_51 = {
.has_ern35421 = true,
.has_ern38020 = true,
.has_ern38748 = true,
.has_ern42307 = true,
};
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_brn51210 = true,
.has_brn51764 = true,
.has_brn52354 = true,
.has_brn52942 = true,
.has_brn56279 = true,
.has_brn58839 = true,
.has_brn62269 = true,
.has_brn66011 = true,
.has_brn70165 = true,
};
const struct pvr_device_ident pvr_device_ident_33_V_11_3 = {
.device_id = 0x33011003,
.series_name = "A-Series",
.public_name = "AXE-1-16M",
};
const struct pvr_device_features pvr_device_features_33_V_11_3 = {
.has_common_store_size_in_dwords = true,
.has_compute = true,
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_num_user_clip_planes = 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_x = true,
.has_tile_size_y = true,
.has_tile_size_16x16 = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_usc_f16sop_u8 = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_pixel_partition_mask = 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 = 512U * 4U * 4U,
.isp_max_tiles_in_flight = 1U,
.isp_samples_per_pixel = 1U,
.max_multisample = 4U,
.max_partitions = 4U,
.max_usc_tasks = 24U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.num_user_clip_planes = 8U,
.simple_parameter_format_version = 2U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 16U,
.tile_size_y = 16U,
.usc_min_output_registers_per_pix = 1U,
.uvs_banks = 2U,
.uvs_pba_entries = 320U,
.uvs_vtx_entries = 288U,
.vdm_cam_size = 32U,
.has_s8xe = true,
};
const struct pvr_device_enhancements pvr_device_enhancements_33_15_11_3 = {
.has_ern35421 = true,
.has_ern38748 = true,
.has_ern42307 = true,
.has_ern45493 = true,
};
const struct pvr_device_quirks pvr_device_quirks_33_15_11_3 = {
.has_brn70165 = true,
};
const struct pvr_device_ident pvr_device_ident_36_V_104_796 = {
.device_id = 0x36104796,
.series_name = "B-Series",
.public_name = "BXS-4-64",
};
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_gpu_multicore_support = true,
.has_gs_rta_support = true,
.has_isp_max_tiles_in_flight = true,
.has_isp_samples_per_pixel = true,
.has_max_multisample = true,
.has_max_partitions = true,
.has_max_usc_tasks = true,
.has_num_clusters = true,
.has_num_raster_pipes = true,
.has_num_user_clip_planes = true,
.has_paired_tiles = 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_x = true,
.has_tile_size_y = true,
.has_tile_size_16x16 = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_usc_f16sop_u8 = true,
.has_usc_min_output_registers_per_pix = true,
.has_usc_pixel_partition_mask = 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 = 1344U * 4U * 4U,
.isp_max_tiles_in_flight = 6U,
.isp_samples_per_pixel = 4U,
.max_multisample = 4U,
.max_partitions = 16U,
.max_usc_tasks = 156U,
.num_clusters = 1U,
.num_raster_pipes = 1U,
.num_user_clip_planes = 8U,
.simple_parameter_format_version = 2U,
.slc_cache_line_size_bits = 512U,
.tile_size_x = 16U,
.tile_size_y = 16U,
.usc_min_output_registers_per_pix = 2U,
.uvs_banks = 8U,
.uvs_pba_entries = 160U,
.uvs_vtx_entries = 144U,
.vdm_cam_size = 64U,
.xpu_max_slaves = 3U,
.has_s8xe = true,
};
const struct pvr_device_enhancements pvr_device_enhancements_36_53_104_796 = {
.has_ern35421 = true,
.has_ern38748 = true,
.has_ern42307 = true,
.has_ern45493 = true,
};
const struct pvr_device_quirks pvr_device_quirks_36_53_104_796 = {
.has_brn44079 = true,
.has_brn70165 = true,
};
/**
* 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->ident = pvr_device_ident_##_b##_V_##_n##_##_c; \
info->ident.b = _b; \
info->ident.n = _n; \
info->ident.v = _v; \
info->ident.c = _c; \
info->features = pvr_device_features_##_b##_V_##_n##_##_c; \
info->enhancements = pvr_device_enhancements_##_b##_##_v##_##_n##_##_c; \
info->quirks = pvr_device_quirks_##_b##_##_v##_##_n##_##_c; \
return 0
switch (bvnc) {
CASE_PACKED_BVNC_DEVICE_INFO(4, 40, 2, 51);
}
#undef CASE_PACKED_BVNC_DEVICE_INFO
assert(!"Unsupported Device");
return -ENODEV;
}

View File

@ -0,0 +1,381 @@
/*
* 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)
/**
* 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_ERN(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 {
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_gpu_multicore_support : 1;
bool has_gs_rta_support : 1;
bool has_isp_max_tiles_in_flight : 1;
bool has_isp_samples_per_pixel : 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_num_user_clip_planes : 1;
bool has_paired_tiles : 1;
bool has_pds_ddmadt : 1;
bool has_robust_buffer_access : 1;
bool has_roguexe : 1;
bool has_screen_size8K : 1;
bool has_simple_internal_parameter_format : 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_tile_size_x : 1;
bool has_tile_size_y : 1;
bool has_tile_size_16x16 : 1;
bool has_tpu_array_textures : 1;
bool has_tpu_extended_integer_lookup : 1;
bool has_tpu_image_state_v2 : 1;
bool has_usc_f16sop_u8 : 1;
bool has_usc_min_output_registers_per_pix : 1;
bool has_usc_pixel_partition_mask : 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_xpu_max_slaves : 1;
bool has_xt_top_infrastructure : 1;
bool has_zls_subtile : 1;
uint32_t common_store_size_in_dwords;
uint32_t isp_max_tiles_in_flight;
uint32_t isp_samples_per_pixel;
uint32_t max_multisample;
uint32_t max_partitions;
uint32_t max_usc_tasks;
uint32_t num_clusters;
uint32_t num_raster_pipes;
uint32_t num_user_clip_planes;
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 usc_min_output_registers_per_pix;
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_s8xe : 1;
};
struct pvr_device_enhancements {
bool has_ern35421 : 1;
bool has_ern38020 : 1;
bool has_ern38748 : 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_brn51210 : 1;
bool has_brn51764 : 1;
bool has_brn52354 : 1;
bool has_brn52942 : 1;
bool has_brn56279 : 1;
bool has_brn58839 : 1;
bool has_brn62269 : 1;
bool has_brn66011 : 1;
bool has_brn70165 : 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;
};
/**
* 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);
#endif /* PVR_DEVICE_INFO_H */

View File

@ -0,0 +1,934 @@
# encoding=utf-8
# Copyright © 2022 Imagination Technologies Ltd.
# based on anv driver gen_pack_header.py which is:
# Copyright © 2016 Intel Corporation
# based on v3dv driver gen_pack_header.py which is:
# Copyright (C) 2016 Broadcom
# 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.
import argparse
import ast
import xml.parsers.expat
import re
import sys
import copy
import os
import textwrap
license = """/*
* 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.
*/"""
pack_header = """%(license)s
/* Enums, structures and pack functions for %(platform)s.
*
* This file has been generated, do not hand edit.
*/
#ifndef %(guard)s
#define %(guard)s
#include "csbgen/pvr_packet_helpers.h"
"""
def safe_name(name):
if not name[0].isalpha():
name = '_' + name
return name
def num_from_str(num_str):
if num_str.lower().startswith('0x'):
return int(num_str, base=16)
if num_str.startswith('0') and len(num_str) > 1:
raise ValueError('Octal numbers not allowed')
return int(num_str)
class Node:
def __init__(self, parent, name, name_is_safe = False):
self.parent = parent
if name_is_safe:
self.name = name
else:
self.name = safe_name(name)
@property
def full_name(self):
if self.name[0] == '_':
return self.parent.prefix + self.name.upper()
return self.parent.prefix + "_" + self.name.upper()
@property
def prefix(self):
return self.parent.prefix
class Csbgen(Node):
def __init__(self, name, prefix, filename):
super().__init__(None, name.upper())
self.prefix_field = safe_name(prefix.upper())
self.filename = filename
self._defines = []
self._enums = {}
self._structs = {}
@property
def full_name(self):
return self.name + "_" + self.prefix_field
@property
def prefix(self):
return self.full_name
def add(self, element):
if isinstance(element, Enum):
if element.name in self._enums:
raise RuntimeError('Enum redefined. Enum: %s' % element.name)
self._enums[element.name] = element
elif isinstance(element, Struct):
if element.name in self._structs:
raise RuntimeError('Struct redefined. Struct: %s' % element.name)
self._structs[element.name] = element
elif isinstance(element, Define):
define_names = map(lambda d: d.full_name, self._defines)
if element.full_name in define_names:
raise RuntimeError('Define redefined. Define: %s' % element.full_name)
self._defines.append(element)
else:
raise RuntimeError('Element "%s" cannot be nested in csbgen.' %
type(element).__name__)
def _gen_guard(self):
return os.path.basename(self.filename).replace('.xml', '_h').upper()
def emit(self):
print(pack_header % {'license': license,
'platform': self.name,
'guard': self._gen_guard()})
for define in self._defines:
define.emit(self)
print()
for enum in self._enums.values():
enum.emit(self)
for struct in self._structs.values():
struct.emit(self)
print('#endif /* %s */' % self._gen_guard())
def is_known_struct(self, struct_name):
return struct_name in self._structs.keys()
def is_known_enum(self, enum_name):
return enum_name in self._enums.keys()
def get_enum(self, enum_name):
return self._enums[enum_name]
class Enum(Node):
def __init__(self, parent, name):
super().__init__(parent, name)
self._values = {}
self.parent.add(self)
# We override prefix so that the values will contain the enum's name too.
@property
def prefix(self):
return self.full_name
def get_value(self, value_name):
return self._values[value_name]
def add(self, element):
if not isinstance(element, Value):
raise RuntimeError('Element cannot be nested in enum. ' +
'Element Type: %s, Enum: %s' %
(type(element).__name__, self.full_name))
if element.name in self._values:
raise RuntimeError('Value is being redefined. Value: "%s"' % element.name)
self._values[element.name] = element
def emit(self, root):
# This check is invalid if tags other than Value can be nested within an enum.
if not self._values.values():
raise RuntimeError('Enum definition is empty. Enum: "%s"' % self.full_name)
print('enum %s {' % self.full_name)
for value in self._values.values():
value.emit()
print('};\n')
class Value(Node):
def __init__(self, parent, name, value):
super().__init__(parent, name)
self.value = int(value)
self.parent.add(self)
def emit(self):
print(' %-36s = %6d,' % (self.full_name, self.value))
class Struct(Node):
def __init__(self, parent, name, length):
super().__init__(parent, name)
self.length = int(length)
self.size = self.length * 32
if self.length <= 0:
raise ValueError('Struct length must be greater than 0. ' +
'Struct: "%s".' % self.full_name)
self._children = {}
self.parent.add(self)
@property
def fields(self):
# TODO: Should we cache? See TODO in equivalent Condition getter.
fields = []
for child in self._children.values():
if isinstance(child, Condition):
fields += child.fields
else:
fields.append(child)
return fields
@property
def prefix(self):
return self.full_name
def add(self, element):
# We don't support conditions and field having the same name.
if isinstance(element, Field):
if element.name in self._children.keys():
raise ValueError('Field is being redefined. ' +
'Field: "%s", Struct: "%s"' %
(element.name, self.full_name))
self._children[element.name] = element
elif isinstance(element, Condition):
# We only save ifs, and ignore the rest. The rest will be linked to
# the if condition so we just need to call emit() on the if and the
# rest will also be emitted.
if element.type == 'if':
self._children[element.name] = element
else:
if element.name not in self._children.keys():
raise RuntimeError('Unknown condition: "%s"' % element.name)
else:
raise RuntimeError('Element cannot be nested in struct. ' +
'Element Type: %s, Struct: %s' %
(type(element).__name__, self.full_name))
def _emit_header(self, root):
fields = filter(lambda f: hasattr(f, 'default'), self.fields)
default_fields = []
for field in fields:
if field.is_builtin_type:
default_fields.append(" .%-35s = %6d" %
(field.name, field.default))
else:
if not root.is_known_enum(field.type):
# Default values should not apply to structures
raise RuntimeError('Unknown type. Field: "%s" Type: "%s"' %
(field.name, field.type))
enum = root.get_enum(field.type)
try:
value = enum.get_value(field.default)
except KeyError:
raise ValueError('Unknown enum value. ' +
'Value: "%s", Enum: "%s", Field: "%s"' %
(field.default, enum.full_name, field.name))
default_fields.append(" .%-35s = %s" %
(field.name, value.full_name))
print('#define %-40s\\' % (self.full_name + '_header'))
print(", \\\n".join(default_fields))
print('')
def _emit_helper_macros(self, root):
fields_with_defines = filter(lambda f: f.defines, self.fields)
for field in fields_with_defines:
print("/* Helper macros for %s */" % (field.name))
for define in field.defines:
define.emit(root)
print()
def _emit_pack_function(self, root):
print(textwrap.dedent("""\
static inline __attribute__((always_inline)) void
%s_pack(__attribute__((unused)) void * restrict dst,
%s__attribute__((unused)) const struct %s * restrict values)
{""") % (self.full_name, ' ' * len(self.full_name), self.full_name))
group = Group(0, 1, self.size, self.fields)
(dwords, length) = group.collect_dwords_and_length()
if length:
# Cast dst to make header C++ friendly
print(" uint32_t * restrict dw = (uint32_t * restrict) dst;")
group.emit_pack_function(root, dwords, length)
print("}\n")
def emit(self, root):
print('#define %-33s %6d' % (self.full_name + "_length", self.length))
self._emit_header(root)
self._emit_helper_macros(root)
print("struct %s {" % self.full_name)
for child in self._children.values():
child.emit(root)
print("};\n")
self._emit_pack_function(root)
class Field(Node):
def __init__(self, parent, name, start, end, type, default=None, shift=None):
super().__init__(parent, name)
self.start = int(start)
self.end = int(end)
self.type = type
self._defines = {}
self.parent.add(self)
if self.start > self.end:
raise ValueError('Start cannot be after end. ' +
'Start: %d, End: %d, Field: "%s"' %
(self.start, self.end, self.name))
if self.type == 'bool' and self.end != self.start:
raise ValueError('Bool field can only be 1 bit long. ' +
'Field "%s"' % self.name)
if default is not None:
if not self.is_builtin_type:
# Assuming it's an enum type.
self.default = safe_name(default)
else:
self.default = num_from_str(default)
if shift is not None:
if self.type != 'address':
raise RuntimeError('Only address fields can have a shift ' +
'attribute. Field: "%s"' % self.name)
self.shift = int(shift)
Define(self, "ALIGNMENT", 2 ** self.shift)
else:
if self.type == 'address':
raise RuntimeError('Field of address type ' +
'requires a shift attribute. Field "%s"' %
self.name)
@property
def defines(self):
return self._defines.values()
# We override prefix so that the defines will contain the field's name too.
@property
def prefix(self):
return self.full_name
@property
def is_builtin_type(self):
builtins = {'address', 'bool', 'float', 'mbo', 'offset', 'int', 'uint'}
return self.type in builtins
def _get_c_type(self, root):
if self.type == 'address':
return '__pvr_address_type'
elif self.type == 'bool':
return 'bool'
elif self.type == 'float':
return 'float'
elif self.type == 'offset':
return 'uint64_t'
elif self.type == 'int':
return 'int32_t'
elif self.type == 'uint':
if self.end - self.start < 32:
return 'uint32_t'
elif self.end - self.self < 64:
return 'uint64_t'
raise RuntimeError('No known C type found to hold %d bit sized value. ' +
'Field: "%s"' %
(self.end - self.start, self.name))
elif root.is_known_struct(self.type):
return 'struct ' + self.type
elif root.is_known_enum(self.type):
return 'enum ' + root.get_enum(self.type).full_name
raise RuntimeError('Unknown type. Type: "%s", Field: "%s"' %
(self.type, self.name))
def add(self, element):
if self.type == 'mbo':
raise RuntimeError('No element can be nested in an mbo field. ' +
'Element Type: %s, Field: %s' %
(type(element).__name__, self.name))
if isinstance(element, Define):
if element.name in self._defines:
raise RuntimeError('Duplicate define. Define: "%s"' %
element.name)
self._defines[element.name] = element
else:
raise RuntimeError('Element cannot be nested in a field. ' +
'Element Type: %s, Field: %s' %
(type(element).__name__, self.name))
def emit(self, root):
if self.type == 'mbo':
return
print(" %-36s %s;" % (self._get_c_type(root), self.name))
class Define(Node):
def __init__(self, parent, name, value):
super().__init__(parent, name)
self.value = value
self.parent.add(self)
def emit(self, root):
print("#define %-40s %d" % (self.full_name, self.value))
class Condition(Node):
def __init__(self, parent, name, type):
super().__init__(parent, name, name_is_safe = True)
self.type = type
if not Condition._is_valid_type(self.type):
raise RuntimeError('Unknown type: "%s"' % self.name)
self._children = {}
# This is the link to the next branch for the if statement so either
# elif, else, or endif. They themselves will also have a link to the
# next branch up until endif which terminates the chain.
self._child_branch = None
self.parent.add(self)
@property
def fields(self):
# TODO: Should we use some kind of state to indicate the all of the
# child nodes have been added and then cache the fields in here on the
# first call so that we don't have to traverse them again per each call?
# The state could be changed wither when we reach the endif and pop from
# the context, or when we start emitting.
fields = []
for child in self._children.values():
if isinstance(child, Condition):
fields += child.fields
else:
fields.append(child)
if self._child_branch is not None:
fields += self._child_branch.fields
return fields
def _is_valid_type(type):
types = {'if', 'elif', 'else', 'endif'}
return type in types
def _is_compatible_child_branch(self, branch):
types = ['if', 'elif', 'else', 'endif']
idx = types.index(self.type)
return (branch.type in types[idx + 1:] or
self.type == 'elif' and branch.type == 'elif')
def _add_branch(self, branch):
if branch.type == 'elif' and branch.name == self.name:
raise RuntimeError('Elif branch cannot have same check as previous branch. ' +
'Check: "%s"' % (branch.name))
if not self._is_compatible_child_branch(branch):
raise RuntimeError('Invalid branch. Check: "%s", Type: "%s"' %
(branch.name, branch.type))
self._child_branch = branch
# Returns the name of the if condition. This is used for elif branches since
# they have a different name than the if condition thus we have to traverse
# the chain of branches.
# This is used to discriminate nested if conditions from branches since
# branches like 'endif' and 'else' will have the same name as the 'if' (the
# elif is an exception) while nested conditions will have different names.
#
# TODO: Redo this to improve speed? Would caching this be helpful? We could
# just save the name of the if instead of having to walk towards it whenever
# a new condition is being added.
def _top_branch_name(self):
if self.type == 'if':
return self.name
return self.parent._top_branch_name()
def add(self, element):
if isinstance(element, Field):
if element.name in self._children.keys():
raise ValueError('Duplicate field. Field: "%s"' % element.name)
self._children[element.name] = element
elif isinstance(element, Condition):
if element.type == 'elif' or self._top_branch_name() == element.name:
self._add_branch(element)
else:
if element.type != 'if':
raise RuntimeError('Branch of an unopened if condition. ' +
'Check: "%s", Type: "%s".' % (element.name, element.type))
# This is a nested condition and we made sure that the name
# doesn't match _top_branch_name() so we can recognize the else
# and endif.
# We recognized the elif by its type however its name differs
# from the if condition thus when we add an if condition with
# the same name as the elif nested in it, the _top_branch_name()
# check doesn't hold true as the name matched the elif and not
# the if statement which the elif was a branch of, thus the
# nested if condition is not recognized as an invalid branch of
# the outer if statement.
# Sample:
# <condition type="if" check="ROGUEXE"/>
# <condition type="elif" check="COMPUTE"/>
# <condition type="if" check="COMPUTE"/>
# <condition type="endif" check="COMPUTE"/>
# <condition type="endif" check="COMPUTE"/>
# <condition type="endif" check="ROGUEXE"/>
#
# We fix this by checking the if condition name against its
# parent.
if element.name == self.name:
raise RuntimeError('Invalid if condition. Check: "%s"' %
element.name)
self._children[element.name] = element
else:
raise RuntimeError('Element cannot be nested in a condition. ' +
'Element Type: %s, Check: %s' %
(type(element).__name__, self.name))
def emit(self, root):
if self.type == "if":
print("/* if %s is supported use: */" % (self.name))
elif self.type == "elif":
print("/* else if %s is supported use: */" % (self.name))
elif self.type == "else":
print("/* else %s is not-supported use: */" % (self.name))
elif self.type == "endif":
print("/* endif %s */" % (self.name))
return
else:
raise RuntimeError('Unknown condition type. Implementation error.')
for child in self._children.values():
child.emit(root)
self._child_branch.emit(root)
class Group(object):
def __init__(self, start, count, size, fields):
self.start = start
self.count = count
self.size = size
self.fields = fields
class DWord:
def __init__(self):
self.size = 32
self.fields = []
self.addresses = []
def collect_dwords(self, dwords, start, dim):
for field in self.fields:
index = (start + field.start) // 32
if index not in dwords:
dwords[index] = self.DWord()
clone = copy.copy(field)
clone.start = clone.start + start
clone.end = clone.end + start
clone.dim = dim
dwords[index].fields.append(clone)
if field.type == "address":
# assert dwords[index].address == None
dwords[index].addresses.append(clone)
# Coalesce all the dwords covered by this field. The two cases we
# handle are where multiple fields are in a 64 bit word (typically
# and address and a few bits) or where a single struct field
# completely covers multiple dwords.
while index < (start + field.end) // 32:
if index + 1 in dwords and \
not dwords[index] == dwords[index + 1]:
dwords[index].fields.extend(dwords[index + 1].fields)
dwords[index].addresses.extend(dwords[index + 1].addresses)
dwords[index].size = 64
dwords[index + 1] = dwords[index]
index = index + 1
def collect_dwords_and_length(self):
dwords = {}
self.collect_dwords(dwords, 0, "")
# Determine number of dwords in this group. If we have a size, use
# that, since that'll account for MBZ dwords at the end of a group
# (like dword 8 on BDW+ 3DSTATE_HS). Otherwise, use the largest dword
# index we've seen plus one.
if self.size > 0:
length = self.size // 32
elif dwords:
length = max(dwords.keys()) + 1
else:
length = 0
return (dwords, length)
def emit_pack_function(self, root, dwords, length):
for index in range(length):
# Handle MBZ dwords
if index not in dwords:
print("")
print(" dw[%d] = 0;" % index)
continue
# For 64 bit dwords, we aliased the two dword entries in the dword
# dict it occupies. Now that we're emitting the pack function,
# skip the duplicate entries.
dw = dwords[index]
if index > 0 and index - 1 in dwords and dw == dwords[index - 1]:
continue
# Special case: only one field and it's a struct at the beginning
# of the dword. In this case we pack directly into the
# destination. This is the only way we handle embedded structs
# larger than 32 bits.
if len(dw.fields) == 1:
field = dw.fields[0]
name = field.name + field.dim
if root.is_known_struct(field.type) and field.start % 32 == 0:
print("")
print(" %s_pack(data, &dw[%d], &values->%s);" %
(self.parser.gen_prefix(safe_name(field.type)),
index, name))
continue
# Pack any fields of struct type first so we have integer values
# to the dword for those fields.
field_index = 0
for field in dw.fields:
if isinstance(field, Field) and root.is_known_struct(field.type):
name = field.name + field.dim
print("")
print(" uint32_t v%d_%d;" % (index, field_index))
print(" %s_pack(data, &v%d_%d, &values->%s);" %
(self.parser.gen_prefix(safe_name(field.type)),
index, field_index, name))
field_index = field_index + 1
print("")
dword_start = index * 32
address_count = len(dw.addresses);
if dw.size == 32 and not dw.addresses:
v = None
print(" dw[%d] =" % index)
elif len(dw.fields) > address_count:
v = "v%d" % index
print(" const uint%d_t %s =" % (dw.size, v))
else:
v = "0"
field_index = 0
non_address_fields = []
for field in dw.fields:
if field.type != "mbo":
name = field.name + field.dim
if field.type == "mbo":
non_address_fields.append("__pvr_mbo(%d, %d)" %
(field.start - dword_start,
field.end - dword_start))
elif field.type == "address":
pass
elif field.type == "uint":
non_address_fields.append("__pvr_uint(values->%s, %d, %d)" %
(name, field.start - dword_start,
field.end - dword_start))
elif root.is_known_enum(field.type):
non_address_fields.append("__pvr_uint(values->%s, %d, %d)" %
(name, field.start - dword_start,
field.end - dword_start))
elif field.type == "int":
non_address_fields.append("__pvr_sint(values->%s, %d, %d)" %
(name, field.start - dword_start,
field.end - dword_start))
elif field.type == "bool":
non_address_fields.append("__pvr_uint(values->%s, %d, %d)" %
(name, field.start - dword_start,
field.end - dword_start))
elif field.type == "float":
non_address_fields.append("__pvr_float(values->%s)" % name)
elif field.type == "offset":
non_address_fields.append(
"__pvr_offset(values->%s,"" %d, %d)" %
(name, field.start - dword_start,
field.end - dword_start))
elif field.is_struct_type():
non_address_fields.append("__pvr_uint(v%d_%d, %d, %d)" %
(index, field_index,
field.start - dword_start,
field.end - dword_start))
field_index = field_index + 1
else:
non_address_fields.append("/* unhandled field %s,"
" type %s */\n" %
(name, field.type))
if non_address_fields:
print(" |\n".join(" " + f for f in non_address_fields) +
";")
if dw.size == 32:
for i in range(address_count):
print(" dw[%d] = __pvr_address("
"values->%s, %d, %d, %d) | %s;" %
(index, dw.addresses[i].name + field.dim,
dw.addresses[i].shift, dw.addresses[i].start - dword_start,
dw.addresses[i].end - dword_start, v))
continue
v_accumulated_addr = ""
for i in range(address_count):
v_address = "v%d_address" % i
v_accumulated_addr += "v%d_address" % i
print(" const uint64_t %s =\n "
" __pvr_address(values->%s, %d, %d, %d);" %
(v_address, dw.addresses[i].name + field.dim, dw.addresses[i].shift,
dw.addresses[i].start - dword_start,
dw.addresses[i].end - dword_start))
if i < (address_count - 1):
v_accumulated_addr += " |\n "
if dw.addresses:
if len(dw.fields) > address_count:
print(" dw[%d] = %s | %s;" % (index, v_accumulated_addr, v))
print(" dw[%d] = (%s >> 32) | (%s >> 32);" %
(index + 1, v_accumulated_addr, v))
continue
else:
v = v_accumulated_addr
print(" dw[%d] = %s;" % (index, v))
print(" dw[%d] = %s >> 32;" % (index + 1, v))
class Parser(object):
def __init__(self):
self.parser = xml.parsers.expat.ParserCreate()
self.parser.StartElementHandler = self.start_element
self.parser.EndElementHandler = self.end_element
self.context = []
def start_element(self, name, attrs):
if not name == "csbgen":
parent = self.context[-1]
if name == "csbgen":
if self.context:
raise RuntimeError('Can only have 1 csbgen block and it has ' +
'to contain all of the other elements.')
csbgen = Csbgen(attrs["name"], attrs["prefix"], self.filename)
self.context.append(csbgen)
elif name == "struct":
struct = Struct(parent , attrs["name"], attrs["length"])
self.context.append(struct)
elif name == "field":
default = None
if "default" in attrs.keys():
default = attrs["default"]
shift = None
if "shift" in attrs.keys():
shift = attrs["shift"]
field = Field(parent,
name = attrs["name"],
start = int(attrs["start"]),
end = int(attrs["end"]),
type = attrs["type"],
default = default,
shift = shift)
self.context.append(field)
elif name == "enum":
enum = Enum(parent, attrs["name"])
self.context.append(enum)
elif name == "value":
value = Value(parent, attrs["name"], ast.literal_eval(attrs["value"]))
self.context.append(value)
elif name == "define":
define = Define(parent, attrs["name"], ast.literal_eval(attrs["value"]))
self.context.append(define)
elif name == "condition":
condition = Condition(parent, name=attrs["check"], type=attrs["type"])
# Starting with the if statement we push it in the context. For each
# branch following (elif, and else) we assign the top of stack as
# its parent, pop() and push the new condition. So per branch we end
# up having [..., struct, condition]. We don't push an endif since
# it's not supposed to have any children and it's supposed to close
# the whole if statement.
if condition.type != 'if':
# Remove the parent condition from the context. We were peeking
# before, now we pop().
self.context.pop()
if condition.type == 'endif':
if not isinstance(parent, Condition):
raise RuntimeError('Cannot close unopened or already ' +
'closed condition. Condition: "%s"' % condition.name)
else:
self.context.append(condition)
else:
raise RuntimeError('Unknown tag: "%s"' % name)
def end_element(self, name):
if name == 'condition':
element = self.context[-1]
if not isinstance(element, Condition) and not isinstance(element, Struct):
raise RuntimeError("Expected condition or struct tag to be closed.")
return
element = self.context.pop()
if name == "struct":
if not isinstance(element, Struct):
raise RuntimeError("Expected struct tag to be closed.")
elif name == "field":
if not isinstance(element, Field):
raise RuntimeError("Expected field tag to be closed.")
elif name == "enum":
if not isinstance(element, Enum):
raise RuntimeError("Expected enum tag to be closed.")
elif name == "value":
if not isinstance(element, Value):
raise RuntimeError("Expected value tag to be closed.")
elif name == "define":
if not isinstance(element, Define):
raise RuntimeError("Expected define tag to be closed.")
elif name == "csbgen":
if not isinstance(element, Csbgen):
raise RuntimeError("""Expected csbgen tag to be closed.
Some tags may have not been closed""")
element.emit()
else:
raise RuntimeError('Unknown closing element: "%s"' % name)
def parse(self, filename):
file = open(filename, "rb")
self.filename = filename
self.parser.ParseFile(file)
file.close()
if len(sys.argv) < 2:
print("No input xml file specified")
sys.exit(1)
input_file = sys.argv[1]
p = Parser()
p.parse(input_file)

View File

@ -0,0 +1,46 @@
# 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.
pvr_xml_files = [
'rogue_cdm.xml',
'rogue_cr.xml',
'rogue_ipf.xml',
'rogue_lls.xml',
'rogue_pbestate.xml',
'rogue_pds.xml',
'rogue_ppp.xml',
'rogue_texstate.xml',
'rogue_vdm.xml',
]
pvr_xml_pack = []
foreach f : pvr_xml_files
_name = '@0@.h'.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
dep_csbgen = declare_dependency(sources : [pvr_xml_pack])

View File

@ -0,0 +1,176 @@
/*
* 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 <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
union __pvr_value {
float f;
uint32_t dw;
};
static inline __attribute__((always_inline)) uint64_t __pvr_mbo(uint32_t start,
uint32_t end)
{
return (~0ull >> (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 = (1ull << width) - 1;
assert(v <= max);
}
#endif
return v << start;
}
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 = ~0ull >> (64 - width);
return (v & mask) << start;
}
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 = (~0ull >> (64 - (end - start + 1))) << start;
assert((v & ~mask) == 0);
#endif
return v;
}
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 = (~0ull >> (64 - (end - start + 1))) << start;
return ((addr_u64 >> shift) << start) & mask;
}
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)) 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 = ~0ull >> (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 */

View File

@ -0,0 +1,132 @@
<?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">
<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>

View File

@ -0,0 +1,631 @@
<?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="1"/>
<value name="FAST_SCALE" value="2"/>
</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="ZLOADFORMAT_TYPE">
<value name="F32Z" value="0"/>
<value name="24BITINT" value="1"/>
<value name="16BITINT" value="2"/>
<value name="F64Z" value="3"/>
</enum>
<enum name="ZSTOREFORMAT_TYPE">
<value name="F32Z" value="0"/>
<value name="24BITINT" value="1"/>
<value name="16BITINT" value="2"/>
<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="PDS_CTRL" length="2">
<field name="sm_overlap_enable" start="55" end="55" type="bool"/>
<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="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_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_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"/>
</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"/>
</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="ZSTOREFORMAT_TYPE"/>
<field name="zloadformat" start="23" end="24" type="ZLOADFORMAT_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_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"/>
<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>
<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>
</csbgen>

View File

@ -0,0 +1,37 @@
/*
* 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 ROGUE_HWDEFS_H
#define ROGUE_HWDEFS_H
#include "rogue_cdm.h"
#include "rogue_cr.h"
#include "rogue_ipf.h"
#include "rogue_lls.h"
#include "rogue_pbestate.h"
#include "rogue_pds.h"
#include "rogue_ppp.h"
#include "rogue_texstate.h"
#include "rogue_vdm.h"
#endif /* ROGUE_HWDEFS_H */

View File

@ -0,0 +1,40 @@
<?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"/>
<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>
</csbgen>

View File

@ -0,0 +1,49 @@
<?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>

View File

@ -0,0 +1,300 @@
<?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="REG_WORD0_LINESTRIDE">
<value name="ALIGNSHIFT" value="1"/>
<value name="ALIGNSIZE" value="2"/>
<value name="ALIGNSHIFT_PBE_STRIDE_ALIGN_1PIXEL_ENABLED" value="0"/>
<value name="ALIGNSIZE_PBE_STRIDE_ALIGN_1PIXEL_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>

View File

@ -0,0 +1,116 @@
<?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="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="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>

View File

@ -0,0 +1,329 @@
<?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"/>
</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>
<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="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">
<condition type="if" check="TEXTURE_WRAP_VARYING"/>
<field name="f32_linear_wrap" start="24" end="31" type="uint"/>
<condition type="endif" check="TEXTURE_WRAP_VARYING"/>
<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"/>
<condition type="if" check="TEXTURE_WRAP_VARYING"/>
<field name="f32_npc_wrap" start="0" end=" 7" type="uint"/>
<condition type="endif" check="TEXTURE_WRAP_VARYING"/>
</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_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="trp" start="16" end="16" type="bool"/>
<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>

View File

@ -0,0 +1,334 @@
<?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="COMPRESSED_ASTC_4x4" value="0"/>
<value name="COMPRESSED_ASTC_5x4" value="1"/>
<value name="COMPRESSED_ASTC_5x5" value="2"/>
<value name="COMPRESSED_ASTC_6x5" value="3"/>
<value name="COMPRESSED_ASTC_6x6" value="4"/>
<value name="COMPRESSED_ASTC_8x5" value="5"/>
<value name="COMPRESSED_ASTC_8x6" value="6"/>
<value name="COMPRESSED_ASTC_8x8" value="7"/>
<value name="COMPRESSED_ASTC_10x5" value="8"/>
<value name="COMPRESSED_ASTC_10x6" value="9"/>
<value name="COMPRESSED_ASTC_10x8" value="10"/>
<value name="COMPRESSED_ASTC_10x10" value="11"/>
<value name="COMPRESSED_ASTC_12x10" value="12"/>
<value name="COMPRESSED_ASTC_12x12" value="13"/>
<value name="COMPRESSED_PVRT2BPP" value="40"/>
<value name="COMPRESSED_PVRT4BPP" value="41"/>
<value name="COMPRESSED_PVRTII2BPP" value="42"/>
<value name="COMPRESSED_PVRTII4BPP" value="43"/>
<value name="COMPRESSED_UBC1" value="44"/>
<value name="COMPRESSED_UBC2" value="45"/>
<value name="COMPRESSED_UBC3" value="46"/>
<value name="COMPRESSED_UBC4" value="47"/>
<value name="COMPRESSED_SBC4" value="48"/>
<value name="COMPRESSED_UBC5" value="49"/>
<value name="COMPRESSED_SBC5" value="50"/>
<value name="COMPRESSED_UBC6" value="51"/>
<value name="COMPRESSED_SBC6" value="52"/>
<value name="COMPRESSED_UBC7" value="53"/>
<value name="COMPRESSED_ETC2_RGB" value="68"/>
<value name="COMPRESSED_ETC2A_RGBA" value="69"/>
<value name="COMPRESSED_ETC2_PUNCHTHROUGHA" value="70"/>
<value name="COMPRESSED_EAC_R11_UNSIGNED" value="71"/>
<value name="COMPRESSED_EAC_R11_SIGNED" value="72"/>
<value name="COMPRESSED_EAC_RG11_UNSIGNED" value="73"/>
<value name="COMPRESSED_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>
<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"/>
<field name="texformat" start="27" end="33" type="FORMAT"/>
<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"/>
<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="SAMPLER" 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"/>
<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>
</csbgen>

View File

@ -0,0 +1,256 @@
<?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">
<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>

View File

@ -0,0 +1,127 @@
/*
* 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
/* 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
/* 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_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
#define ROGUE_MAX_RENDER_TARGETS 2048U
/* 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_USC_TASK_PROGRAM_SIZE 512U
#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
#endif /* ROGUE_HW_DEFS_H */

View File

@ -0,0 +1,379 @@
/*
* 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_winsys.h"
#define __pvr_address_type pvr_dev_addr_t
#define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr).addr
#include "csbgen/rogue_cdm.h"
#include "csbgen/rogue_lls.h"
#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"
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) {
default:
assert(!"Unsupported number of samples");
FALLTHROUGH;
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 == 2)
*y_out *= 2;
break;
case 8:
*y_out *= 2;
break;
}
}
static inline uint64_t
rogue_get_min_free_list_size(const struct pvr_device_info *dev_info)
{
uint64_t min_num_pages;
if (PVR_HAS_FEATURE(dev_info, roguexe)) {
if (PVR_HAS_QUIRK(dev_info, 66011))
min_num_pages = 40U;
else
min_num_pages = 25U;
} else {
min_num_pages = 50U;
}
return min_num_pages << ROGUE_BIF_PM_PHYSICAL_PAGE_SHIFT;
}
static inline uint32_t
rogue_get_max_num_vdm_pds_tasks(const struct pvr_device_info *dev_info)
{
/* Default value based on the minimum value found in all existing cores. */
uint32_t max_usc_tasks = PVR_GET_FEATURE_VALUE(dev_info, max_usc_tasks, 24U);
/* FIXME: Where does the 9 come from? */
return max_usc_tasks - 9;
}
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;
}
/* To get the number of required Bernado/Phantom(s), divide the number of
* clusters by 4 and round up.
*/
static inline uint32_t
rogue_get_num_phantoms(const struct pvr_device_info *dev_info)
{
return DIV_ROUND_UP(PVR_GET_FEATURE_VALUE(dev_info, num_clusters, 1U), 4U);
}
/* 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;
}
/* Return the total reserved size of partition in dwords. */
static inline uint32_t
rogue_get_total_reserved_partition_size(const struct pvr_device_info *dev_info)
{
uint32_t tile_size_x = PVR_GET_FEATURE_VALUE(dev_info, tile_size_x, 0);
uint32_t tile_size_y = PVR_GET_FEATURE_VALUE(dev_info, tile_size_y, 0);
uint32_t max_partitions = PVR_GET_FEATURE_VALUE(dev_info, max_partitions, 0);
if (tile_size_x == 16 && tile_size_y == 16) {
return tile_size_x * tile_size_y * max_partitions *
PVR_GET_FEATURE_VALUE(dev_info,
usc_min_output_registers_per_pix,
0);
}
return max_partitions * 1024U;
}
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_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)
{
const uint32_t uvs_pba_entries =
PVR_GET_FEATURE_VALUE(dev_info, uvs_pba_entries, 0U);
const uint32_t uvs_banks = PVR_GET_FEATURE_VALUE(dev_info, uvs_banks, 0U);
if (uvs_banks <= 8U && uvs_pba_entries == 160U)
return 64U;
return 128U;
}
static inline uint32_t
rogue_get_reserved_shared_size(const struct pvr_device_info *dev_info)
{
uint32_t common_store_size_in_dwords =
PVR_GET_FEATURE_VALUE(dev_info,
common_store_size_in_dwords,
512U * 4U * 4U);
uint32_t reserved_shared_size =
common_store_size_in_dwords - (256U * 4U) -
rogue_get_total_reserved_partition_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), reserved_shared_size);
}
return reserved_shared_size;
}
static inline uint32_t
rogue_max_compute_shared_registers(const struct pvr_device_info *dev_info)
{
if (PVR_HAS_FEATURE(dev_info, compute))
return 2U * 1024U;
return 0U;
}
static inline uint32_t
rogue_get_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_get_num_phantoms(dev_info);
uint32_t tiles_in_flight =
PVR_GET_FEATURE_VALUE(dev_info, isp_max_tiles_in_flight, 0);
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_ERN(dev_info, 38748))
pending_allocation_shared_regs = 0U;
if (PVR_HAS_ERN(dev_info, 38020)) {
max_coeff_additional_portion +=
rogue_max_compute_shared_registers(dev_info);
}
return rogue_get_reserved_shared_size(dev_info) +
pending_allocation_coeff_regs -
(max_coeff_pixel_portion + max_coeff_additional_portion +
pending_allocation_shared_regs);
}
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 =
PVR_GET_FEATURE_VALUE(dev_info, xpu_max_slaves, 0U) + 1U;
const uint32_t cache_line_size = rogue_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);
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 rogue_get_slc_cache_line_size(dev_info);
return ROGUE_LLS_CDM_CONTEXT_RESUME_BUFFER_ALIGNMENT;
}
static inline uint32_t
rogue_get_cdm_max_local_mem_size_regs(const struct pvr_device_info *dev_info)
{
uint32_t available_coeffs_in_dwords = rogue_get_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 * 2;
}
/* 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 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_ERN(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;
}
#endif /* ROGUE_HW_UTILS_H */

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.
*/
/* 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
/**
* Maximum PB free list size supported by RGX and Services.
*
* Maximum PB free list size must ensure that no PM address space can be fully
* used, because if the full address space was used it would wrap and corrupt
* itself. Since there are two freelists (local is always minimum sized) this
* can be described as following three conditions being met:
*
* Minimum PB + Maximum PB < ALIST PM address space size (16GB)
* Minimum PB + Maximum PB < TE PM address space size (16GB) / NUM_TE_PIPES
* Minimum PB + Maximum PB < VCE PM address space size (16GB) / NUM_VCE_PIPES
*
* Since the max of NUM_TE_PIPES and NUM_VCE_PIPES is 4, we have a hard limit
* of 4GB minus the Minimum PB. For convenience we take the smaller power-of-2
* value of 2GB. This is far more than any normal application would request
* or use.
*/
#define ROGUE_FREE_LIST_MAX_SIZE (2ULL * 1024ULL * 1024ULL * 1024ULL)
/* 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 */

View File

@ -0,0 +1,33 @@
# 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.
inc_imagination = include_directories([
'.',
'common',
'include',
])
if with_imagination_vk
subdir('common')
subdir('csbgen')
subdir('rogue')
subdir('vulkan')
endif

View File

@ -0,0 +1,77 @@
# 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.
libpowervr_rogue_files = files(
'nir/rogue_nir_constreg.c',
'nir/rogue_nir_lower_io.c',
'nir/rogue_nir_pfo.c',
'rogue.c',
'rogue_build_data.c',
'rogue_compiler.c',
'rogue_constreg.c',
'rogue_dump.c',
'rogue_encode.c',
'rogue_encoders.c',
'rogue_instr.c',
'rogue_nir.c',
'rogue_operand.c',
'rogue_regalloc.c',
'rogue_shader.c',
'rogue_util.c',
'rogue_validate.c',
)
libpowervr_rogue = shared_library(
'powervr_rogue',
libpowervr_rogue_files,
include_directories : [
inc_imagination,
inc_include,
inc_compiler,
inc_src,
inc_mapi,
inc_mesa,
inc_gallium,
inc_gallium_aux,
],
c_args : [c_msvc_compat_args, no_override_init_args],
gnu_symbol_visibility : 'hidden',
dependencies : [idep_mesautil, idep_nir, dep_csbgen],
install : true,
)
rogue_compiler = executable(
'rogue_compiler',
'tools/offline_compiler.c',
link_with : [libpowervr_rogue],
dependencies : [idep_mesautil, idep_nir],
include_directories : [
inc_mesa,
inc_include,
inc_src,
inc_mapi,
inc_gallium,
inc_gallium_aux,
inc_compiler,
],
install : false,
)

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 "nir/nir.h"
#include "nir/nir_builder.h"
#include "nir/nir_search_helpers.h"
#include "rogue_constreg.h"
#include "rogue_nir.h"
/* TODO: optimize: if value is in const regs, replace, else, use shared regs and
* notify driver they need to be populated?
*/
/* Replaces multiple ssa uses from load_const with a single use -> a register.
*/
void rogue_nir_constreg(nir_shader *shader)
{
nir_function_impl *impl = nir_shader_get_entrypoint(shader);
nir_builder b;
nir_builder_init(&b, impl);
/* Find load_const instructions. */
nir_foreach_block (block, impl) {
nir_foreach_instr_safe (instr, block) {
if (instr->type != nir_instr_type_load_const)
continue;
nir_load_const_instr *load_const = nir_instr_as_load_const(instr);
/* Skip values that can be pulled from constant registers. */
uint32_t value = nir_const_value_as_uint(load_const->value[0], 32);
size_t const_reg = rogue_constreg_lookup(value);
if (const_reg != ROGUE_NO_CONST_REG)
continue;
b.cursor = nir_after_instr(&load_const->instr);
nir_ssa_def *mov = nir_mov(&b, &load_const->def);
nir_foreach_use_safe (use_src, &load_const->def) {
if (use_src->parent_instr == mov->parent_instr)
continue;
/* Skip when used as an index for intrinsics, as we want to
* access that value directly.
*/
if (use_src->parent_instr->type == nir_instr_type_intrinsic)
continue;
nir_instr_rewrite_src_ssa(use_src->parent_instr, use_src, mov);
}
}
}
}

View File

@ -0,0 +1,171 @@
/*
* 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 <assert.h>
#include <stdint.h>
#include "nir/nir.h"
#include "nir/nir_builder.h"
#include "nir/nir_search_helpers.h"
#include "rogue_nir.h"
#include "rogue_nir_helpers.h"
static void lower_vulkan_resource_index(nir_builder *b,
nir_intrinsic_instr *intr,
void *pipeline_layout)
{
unsigned desc_set = nir_intrinsic_desc_set(intr);
unsigned binding = nir_intrinsic_binding(intr);
nir_ssa_def *def = nir_vec3(b,
nir_imm_int(b, desc_set),
nir_imm_int(b, binding),
nir_imm_int(b, 0));
nir_ssa_def_rewrite_uses(&intr->dest.ssa, def);
nir_instr_remove(&intr->instr);
}
static void lower_load_vulkan_descriptor(nir_builder *b,
nir_intrinsic_instr *intr)
{
/* Loading the descriptor happens as part of the load/store instruction so
* this is a no-op.
*/
nir_ssa_def_rewrite_uses(&intr->dest.ssa, intr->src[0].ssa);
nir_instr_remove(&intr->instr);
}
static void lower_load_ubo_to_scalar(nir_builder *b, nir_intrinsic_instr *intr)
{
/* Scalarize the load_ubo. */
b->cursor = nir_before_instr(&intr->instr);
assert(intr->dest.is_ssa);
assert(intr->num_components > 1);
nir_ssa_def *loads[NIR_MAX_VEC_COMPONENTS];
for (uint8_t i = 0; i < intr->num_components; i++) {
size_t scaled_range = nir_intrinsic_range(intr) / intr->num_components;
nir_intrinsic_instr *chan_intr =
nir_intrinsic_instr_create(b->shader, intr->intrinsic);
nir_ssa_dest_init(&chan_intr->instr,
&chan_intr->dest,
1,
intr->dest.ssa.bit_size,
NULL);
chan_intr->num_components = 1;
nir_intrinsic_set_access(chan_intr, nir_intrinsic_access(intr));
nir_intrinsic_set_align_mul(chan_intr, nir_intrinsic_align_mul(intr));
nir_intrinsic_set_align_offset(chan_intr,
nir_intrinsic_align_offset(intr));
nir_intrinsic_set_range_base(chan_intr,
nir_intrinsic_range_base(intr) +
(i * intr->num_components));
nir_intrinsic_set_range(chan_intr, scaled_range);
/* Base (desc_set, binding). */
nir_src_copy(&chan_intr->src[0], &intr->src[0]);
/* Offset (unused). */
chan_intr->src[1] = nir_src_for_ssa(nir_imm_int(b, 0));
nir_builder_instr_insert(b, &chan_intr->instr);
loads[i] = &chan_intr->dest.ssa;
}
nir_ssa_def_rewrite_uses(&intr->dest.ssa,
nir_vec(b, loads, intr->num_components));
nir_instr_remove(&intr->instr);
}
static bool
lower_intrinsic(nir_builder *b, nir_intrinsic_instr *instr, void *layout)
{
switch (instr->intrinsic) {
case nir_intrinsic_load_vulkan_descriptor:
lower_load_vulkan_descriptor(b, instr);
return true;
case nir_intrinsic_vulkan_resource_index:
lower_vulkan_resource_index(b, instr, layout);
return true;
case nir_intrinsic_load_ubo:
lower_load_ubo_to_scalar(b, instr);
return true;
default:
break;
}
return false;
}
static bool lower_impl(nir_function_impl *impl, void *layout)
{
bool progress = false;
nir_builder b;
nir_builder_init(&b, impl);
nir_foreach_block (block, impl) {
nir_foreach_instr_safe (instr, block) {
b.cursor = nir_before_instr(instr);
switch (instr->type) {
case nir_instr_type_intrinsic:
progress |=
lower_intrinsic(&b, nir_instr_as_intrinsic(instr), layout);
break;
default:
break;
}
}
}
if (progress)
nir_metadata_preserve(impl, nir_metadata_none);
else
nir_metadata_preserve(impl, nir_metadata_all);
return progress;
}
bool rogue_nir_lower_io(nir_shader *shader, void *layout)
{
bool progress = false;
nir_foreach_function (function, shader) {
if (function->impl)
progress |= lower_impl(function->impl, layout);
}
if (progress)
nir_opt_dce(shader);
return progress;
}

View File

@ -0,0 +1,86 @@
/*
* 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 "nir/nir.h"
#include "nir/nir_builder.h"
#include "nir/nir_search_helpers.h"
#include "rogue_nir.h"
static void insert_pfo(nir_builder *b,
nir_intrinsic_instr *store_output,
nir_src *output_src)
{
/* TODO: Support complex PFO with blending. */
/* TODO: Verify type is vec4. */
/* Pack the output color components into U8888 format. */
nir_ssa_def *new_output_src_ssa = nir_pack_unorm_4x8(b, output_src->ssa);
nir_src new_output_src = nir_src_for_ssa(new_output_src_ssa);
/* Update the store_output intrinsic. */
nir_instr_rewrite_src(&store_output->instr, output_src, new_output_src);
nir_intrinsic_set_write_mask(store_output, 1);
store_output->num_components = 1;
nir_intrinsic_set_src_type(store_output, nir_type_uint32);
}
void rogue_nir_pfo(nir_shader *shader)
{
nir_function_impl *impl = nir_shader_get_entrypoint(shader);
nir_builder b;
/* Only apply to fragment shaders. */
if (shader->info.stage != MESA_SHADER_FRAGMENT)
return;
nir_builder_init(&b, impl);
nir_foreach_block (block, impl) {
nir_foreach_instr_safe (instr, block) {
if (instr->type == nir_instr_type_intrinsic) {
/* Find the store_output intrinsic and pack the output value. */
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic != nir_intrinsic_store_output)
continue;
b.cursor = nir_before_instr(&intr->instr);
insert_pfo(&b, intr, &intr->src[0]);
} else if (instr->type == nir_instr_type_deref) {
/* Find variable derefs and update their type. */
nir_deref_instr *deref = nir_instr_as_deref(instr);
if (!nir_deref_mode_is(deref, nir_var_shader_out))
continue;
if (deref->deref_type != nir_deref_type_var)
continue;
nir_variable *out = nir_deref_instr_get_variable(deref);
deref->type = glsl_uintN_t_type(32);
out->type = glsl_uintN_t_type(32);
}
}
}
}

View File

@ -0,0 +1,789 @@
/*
* 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 <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "compiler/shader_enums.h"
#include "compiler/spirv/nir_spirv.h"
#include "nir/nir.h"
#include "rogue.h"
#include "rogue_build_data.h"
#include "rogue_compiler.h"
#include "rogue_constreg.h"
#include "rogue_encode.h"
#include "rogue_nir.h"
#include "rogue_nir_helpers.h"
#include "rogue_operand.h"
#include "rogue_regalloc.h"
#include "rogue_shader.h"
#include "rogue_validate.h"
#include "util/macros.h"
#include "util/memstream.h"
#include "util/ralloc.h"
/**
* \file rogue.c
*
* \brief Contains the top-level Rogue compiler interface for Vulkan driver and
* the offline compiler.
*/
/**
* \brief Converts a SPIR-V shader to NIR.
*
* \param[in] ctx Shared multi-stage build context.
* \param[in] stage Shader stage.
* \param[in] spirv_size SPIR-V data length in DWORDs.
* \param[in] spirv_data SPIR-V data.
* \param[in] num_spec Number of SPIR-V specializations.
* \param[in] spec SPIR-V specializations.
* \return A nir_shader* if successful, or NULL if unsuccessful.
*/
nir_shader *rogue_spirv_to_nir(struct rogue_build_ctx *ctx,
gl_shader_stage stage,
const char *entry,
size_t spirv_size,
const uint32_t *spirv_data,
unsigned num_spec,
struct nir_spirv_specialization *spec)
{
nir_shader *nir;
nir = spirv_to_nir(spirv_data,
spirv_size,
spec,
num_spec,
stage,
entry,
rogue_get_spirv_options(ctx->compiler),
rogue_get_compiler_options(ctx->compiler));
if (!nir)
return NULL;
ralloc_steal(ctx, nir);
/* Apply passes. */
if (!rogue_nir_passes(ctx, nir, stage)) {
ralloc_free(nir);
return NULL;
}
/* Collect I/O data to pass back to the driver. */
if (!rogue_collect_io_data(ctx, nir)) {
ralloc_free(nir);
return NULL;
}
return nir;
}
/**
* \brief Converts a Rogue shader to binary.
*
* \param[in] ctx Shared multi-stage build context.
* \param[in] shader Rogue shader.
* \return A rogue_shader_binary* if successful, or NULL if unsuccessful.
*/
struct rogue_shader_binary *rogue_to_binary(struct rogue_build_ctx *ctx,
const struct rogue_shader *shader)
{
struct rogue_shader_binary *binary;
struct u_memstream mem;
size_t buf_size;
char *buf;
if (!rogue_validate_shader(shader))
return NULL;
if (!u_memstream_open(&mem, &buf, &buf_size))
return NULL;
if (!rogue_encode_shader(shader, u_memstream_get(&mem))) {
u_memstream_close(&mem);
free(buf);
return NULL;
}
u_memstream_close(&mem);
binary = rzalloc_size(ctx, sizeof(*binary) + buf_size);
if (!binary) {
free(buf);
return NULL;
}
binary->size = buf_size;
memcpy(binary->data, buf, buf_size);
free(buf);
return binary;
}
static bool
setup_alu_dest(struct rogue_instr *instr, size_t dest_index, nir_alu_instr *alu)
{
assert(dest_index == 0);
/* Dest validation. */
assert(nir_dest_num_components(alu->dest.dest) == 1 ||
nir_dest_num_components(alu->dest.dest) == 4);
assert(nir_dest_bit_size(alu->dest.dest) == 32);
size_t nir_dest_reg = nir_alu_dest_regindex(alu);
if (nir_dest_num_components(alu->dest.dest) == 1) {
CHECK(rogue_instr_set_operand_vreg(instr, dest_index, nir_dest_reg));
} else {
size_t comp = nir_alu_dest_comp(alu);
CHECK(rogue_instr_set_operand_vreg_vec(instr,
dest_index,
comp,
nir_dest_reg));
}
return true;
}
static bool trans_constreg_operand(struct rogue_instr *instr,
size_t operand_index,
uint32_t const_value)
{
size_t const_reg = rogue_constreg_lookup(const_value);
/* Only values that can be sourced from const regs should be left from the
* rogue_nir_constreg pass.
*/
assert(const_reg != ROGUE_NO_CONST_REG);
CHECK(rogue_instr_set_operand_reg(instr,
operand_index,
ROGUE_OPERAND_TYPE_REG_CONST,
const_reg));
return true;
}
static bool trans_nir_alu_fmax(struct rogue_shader *shader, nir_alu_instr *alu)
{
/* Src validation. */
assert(nir_src_num_components(alu->src[0].src) == 1);
assert(nir_src_bit_size(alu->src[0].src) == 32);
assert(nir_src_num_components(alu->src[1].src) == 1);
assert(nir_src_bit_size(alu->src[1].src) == 32);
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MAX);
CHECK(setup_alu_dest(instr, 0, alu));
for (size_t u = 0; u < nir_op_infos[nir_op_fmax].num_inputs; ++u) {
/* Handle values that can be pulled from const regs. */
if (nir_alu_src_is_const(alu, u)) {
CHECK(trans_constreg_operand(instr, u + 1, nir_alu_src_const(alu, u)));
continue;
}
size_t nir_src_reg = nir_alu_src_regindex(alu, u);
CHECK(rogue_instr_set_operand_vreg(instr, u + 1, nir_src_reg));
}
return true;
}
static bool trans_nir_alu_fmin(struct rogue_shader *shader, nir_alu_instr *alu)
{
/* Src validation. */
assert(nir_src_num_components(alu->src[0].src) == 1);
assert(nir_src_bit_size(alu->src[0].src) == 32);
assert(nir_src_num_components(alu->src[1].src) == 1);
assert(nir_src_bit_size(alu->src[1].src) == 32);
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MIN);
CHECK(setup_alu_dest(instr, 0, alu));
for (size_t u = 0; u < nir_op_infos[nir_op_fmin].num_inputs; ++u) {
/* Handle values that can be pulled from const regs. */
if (nir_alu_src_is_const(alu, u)) {
CHECK(trans_constreg_operand(instr, u + 1, nir_alu_src_const(alu, u)));
continue;
}
size_t nir_src_reg = nir_alu_src_regindex(alu, u);
CHECK(rogue_instr_set_operand_vreg(instr, u + 1, nir_src_reg));
}
return true;
}
static bool trans_nir_alu_mov_imm(struct rogue_shader *shader,
nir_alu_instr *alu)
{
/* Src validation. */
assert(nir_src_num_components(alu->src[0].src) == 1);
assert(nir_src_bit_size(alu->src[0].src) == 32);
uint32_t value = nir_alu_src_const(alu, 0);
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MOV_IMM);
CHECK(setup_alu_dest(instr, 0, alu));
CHECK(rogue_instr_set_operand_imm(instr, 1, value));
return true;
}
static bool trans_nir_alu_mov(struct rogue_shader *shader, nir_alu_instr *alu)
{
/* Constant value that isn't in constregs. */
if (nir_alu_src_is_const(alu, 0) &&
nir_dest_num_components(alu->dest.dest) == 1)
return trans_nir_alu_mov_imm(shader, alu);
/* Src validation. */
assert(nir_src_num_components(alu->src[0].src) == 1);
assert(nir_src_bit_size(alu->src[0].src) == 32);
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MOV);
CHECK(setup_alu_dest(instr, 0, alu));
/* Handle values that can be pulled from const regs. */
if (nir_alu_src_is_const(alu, 0)) {
return trans_constreg_operand(instr, 1, nir_alu_src_const(alu, 0));
}
size_t nir_src_reg = nir_alu_src_regindex(alu, 0);
CHECK(rogue_instr_set_operand_vreg(instr, 1, nir_src_reg));
return true;
}
static bool trans_nir_alu_pack_unorm_4x8(struct rogue_shader *shader,
nir_alu_instr *alu)
{
/* Src/dest validation. */
assert(nir_dest_num_components(alu->dest.dest) == 1);
assert(nir_dest_bit_size(alu->dest.dest) == 32);
assert(nir_src_num_components(alu->src[0].src) == 4);
assert(nir_src_bit_size(alu->src[0].src) == 32);
size_t nir_src_reg = nir_alu_src_regindex(alu, 0);
size_t nir_dest_reg = nir_alu_dest_regindex(alu);
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_PACK_U8888);
CHECK(rogue_instr_set_operand_vreg(instr, 0, nir_dest_reg));
/* Ensure all 4 components are being sourced in order. */
for (size_t u = 0; u < nir_src_num_components(alu->src[0].src); ++u)
assert(alu->src->swizzle[u] == u);
CHECK(rogue_instr_set_operand_vreg_vec(instr,
1,
ROGUE_COMPONENT_ALL,
nir_src_reg));
return true;
}
static bool trans_nir_alu_fmul(struct rogue_shader *shader, nir_alu_instr *alu)
{
/* Src validation. */
assert(nir_src_num_components(alu->src[0].src) == 1);
assert(nir_src_bit_size(alu->src[0].src) == 32);
assert(nir_src_num_components(alu->src[1].src) == 1);
assert(nir_src_bit_size(alu->src[1].src) == 32);
size_t nir_in_reg_a = nir_alu_src_regindex(alu, 0);
size_t nir_in_reg_b = nir_alu_src_regindex(alu, 1);
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MUL);
CHECK(setup_alu_dest(instr, 0, alu));
CHECK(rogue_instr_set_operand_vreg(instr, 1, nir_in_reg_a));
CHECK(rogue_instr_set_operand_vreg(instr, 2, nir_in_reg_b));
return true;
}
static bool trans_nir_alu_ffma(struct rogue_shader *shader, nir_alu_instr *alu)
{
/* Src validation. */
assert(nir_src_num_components(alu->src[0].src) == 1);
assert(nir_src_bit_size(alu->src[0].src) == 32);
assert(nir_src_num_components(alu->src[1].src) == 1);
assert(nir_src_bit_size(alu->src[1].src) == 32);
assert(nir_src_num_components(alu->src[2].src) == 1);
assert(nir_src_bit_size(alu->src[2].src) == 32);
size_t nir_in_reg_a = nir_alu_src_regindex(alu, 0);
size_t nir_in_reg_b = nir_alu_src_regindex(alu, 1);
size_t nir_in_reg_c = nir_alu_src_regindex(alu, 2);
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_FMA);
CHECK(setup_alu_dest(instr, 0, alu));
CHECK(rogue_instr_set_operand_vreg(instr, 1, nir_in_reg_a));
CHECK(rogue_instr_set_operand_vreg(instr, 2, nir_in_reg_b));
CHECK(rogue_instr_set_operand_vreg(instr, 3, nir_in_reg_c));
return true;
}
static bool trans_nir_alu(struct rogue_shader *shader, nir_alu_instr *alu)
{
switch (alu->op) {
case nir_op_fmax:
return trans_nir_alu_fmax(shader, alu);
case nir_op_fmin:
return trans_nir_alu_fmin(shader, alu);
case nir_op_pack_unorm_4x8:
return trans_nir_alu_pack_unorm_4x8(shader, alu);
case nir_op_mov:
return trans_nir_alu_mov(shader, alu);
case nir_op_fmul:
return trans_nir_alu_fmul(shader, alu);
case nir_op_ffma:
return trans_nir_alu_ffma(shader, alu);
default:
break;
}
unreachable("Unimplemented NIR ALU instruction.");
}
static bool trans_nir_intrinsic_load_input_fs(struct rogue_shader *shader,
nir_intrinsic_instr *intr)
{
struct rogue_fs_build_data *fs_data = &shader->ctx->stage_data.fs;
/* Src/dest validation. */
assert(nir_dest_num_components(intr->dest) == 1);
assert(nir_dest_bit_size(intr->dest) == 32);
assert(nir_src_num_components(intr->src[0]) == 1);
assert(nir_src_bit_size(intr->src[0]) == 32);
assert(nir_intr_src_is_const(intr, 0));
/* Intrinsic index validation. */
assert(nir_intrinsic_dest_type(intr) == nir_type_float32);
struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr);
size_t component = nir_intrinsic_component(intr);
size_t coeff_index = rogue_coeff_index_fs(&fs_data->iterator_args,
io_semantics.location,
component);
size_t wcoeff_index = rogue_coeff_index_fs(&fs_data->iterator_args, ~0, 0);
size_t drc_num = rogue_acquire_drc(shader);
uint64_t source_count = nir_dest_num_components(intr->dest);
size_t nir_dest_reg = nir_intr_dest_regindex(intr);
/* pixiter.w instruction. */
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_PIX_ITER_W);
CHECK(rogue_instr_set_operand_vreg(instr, 0, nir_dest_reg));
CHECK(rogue_instr_set_operand_drc(instr, 1, drc_num));
CHECK(rogue_instr_set_operand_reg(instr,
2,
ROGUE_OPERAND_TYPE_REG_COEFF,
coeff_index));
CHECK(rogue_instr_set_operand_reg(instr,
3,
ROGUE_OPERAND_TYPE_REG_COEFF,
wcoeff_index));
CHECK(rogue_instr_set_operand_imm(instr, 4, source_count));
/* wdf instruction must follow the pixiter.w. */
instr = rogue_shader_insert(shader, ROGUE_OP_WDF);
CHECK(rogue_instr_set_operand_drc(instr, 0, drc_num));
rogue_release_drc(shader, drc_num);
return true;
}
static bool trans_nir_intrinsic_load_input_vs(struct rogue_shader *shader,
nir_intrinsic_instr *intr)
{
/* Src/dest validation. */
assert(nir_dest_num_components(intr->dest) == 1);
assert(nir_dest_bit_size(intr->dest) == 32);
assert(nir_src_num_components(intr->src[0]) == 1);
assert(nir_src_bit_size(intr->src[0]) == 32);
assert(nir_intr_src_is_const(intr, 0));
/* Intrinsic index validation. */
assert(nir_intrinsic_dest_type(intr) == nir_type_float32);
size_t component = nir_intrinsic_component(intr);
struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr);
size_t vi_reg_index = ((io_semantics.location - VERT_ATTRIB_GENERIC0) * 3) +
component; /* TODO: get these properly with the
* intrinsic index (ssa argument)
*/
size_t nir_dest_reg = nir_intr_dest_regindex(intr);
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MOV);
CHECK(rogue_instr_set_operand_vreg(instr, 0, nir_dest_reg));
CHECK(rogue_instr_set_operand_reg(instr,
1,
ROGUE_OPERAND_TYPE_REG_VERTEX_IN,
vi_reg_index));
return true;
}
static bool trans_nir_intrinsic_load_input(struct rogue_shader *shader,
nir_intrinsic_instr *intr)
{
switch (shader->stage) {
case MESA_SHADER_FRAGMENT:
return trans_nir_intrinsic_load_input_fs(shader, intr);
case MESA_SHADER_VERTEX:
return trans_nir_intrinsic_load_input_vs(shader, intr);
default:
break;
}
unreachable("Unimplemented NIR load_input variant.");
}
static bool trans_nir_intrinsic_store_output_fs(struct rogue_shader *shader,
nir_intrinsic_instr *intr)
{
/* Src/dest validation. */
assert(nir_src_num_components(intr->src[0]) == 1);
assert(nir_src_bit_size(intr->src[0]) == 32);
assert(!nir_intr_src_is_const(intr, 0));
assert(nir_src_num_components(intr->src[1]) == 1);
assert(nir_src_bit_size(intr->src[1]) == 32);
assert(nir_intr_src_is_const(intr, 1));
/* Intrinsic index validation. */
assert(nir_intrinsic_src_type(intr) == nir_type_uint32);
/* Fetch the output offset. */
/* TODO: Is this really the right value to use for pixel out reg. num? */
size_t offset = nir_intr_src_const(intr, 1);
/* Fetch the components. */
size_t src_reg = nir_intr_src_regindex(intr, 0);
/* mov.olchk instruction. */
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MOV);
CHECK(rogue_instr_set_operand_reg(instr,
0,
ROGUE_OPERAND_TYPE_REG_PIXEL_OUT,
offset));
CHECK(rogue_instr_set_operand_vreg(instr, 1, src_reg));
CHECK(rogue_instr_set_flag(instr, ROGUE_INSTR_FLAG_OLCHK));
return true;
}
static bool trans_nir_intrinsic_store_output_vs(struct rogue_shader *shader,
nir_intrinsic_instr *intr)
{
struct rogue_vs_build_data *vs_data = &shader->ctx->stage_data.vs;
/* Src/dest validation. */
assert(nir_src_num_components(intr->src[0]) == 1);
assert(nir_src_bit_size(intr->src[0]) == 32);
assert(!nir_intr_src_is_const(intr, 0));
assert(nir_src_num_components(intr->src[1]) == 1);
assert(nir_src_bit_size(intr->src[1]) == 32);
assert(nir_intr_src_is_const(intr, 1));
/* Intrinsic index validation. */
assert(nir_intrinsic_src_type(intr) == nir_type_float32);
assert(util_bitcount(nir_intrinsic_write_mask(intr)) == 1);
struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr);
size_t component = nir_intrinsic_component(intr);
size_t vo_index = rogue_output_index_vs(&vs_data->outputs,
io_semantics.location,
component);
size_t src_reg = nir_intr_src_regindex(intr, 0);
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_VTXOUT);
CHECK(rogue_instr_set_operand_imm(instr, 0, vo_index));
CHECK(rogue_instr_set_operand_vreg(instr, 1, src_reg));
return true;
}
static bool trans_nir_intrinsic_store_output(struct rogue_shader *shader,
nir_intrinsic_instr *intr)
{
switch (shader->stage) {
case MESA_SHADER_FRAGMENT:
return trans_nir_intrinsic_store_output_fs(shader, intr);
case MESA_SHADER_VERTEX:
return trans_nir_intrinsic_store_output_vs(shader, intr);
default:
break;
}
unreachable("Unimplemented NIR store_output variant.");
}
static bool trans_nir_intrinsic_load_ubo(struct rogue_shader *shader,
nir_intrinsic_instr *intr)
{
struct rogue_ubo_data *ubo_data =
&shader->ctx->common_data[shader->stage].ubo_data;
/* Src/dest validation. */
assert(nir_dest_num_components(intr->dest) == 1);
assert(nir_dest_bit_size(intr->dest) == 32);
assert(nir_src_num_components(intr->src[0]) == 2);
assert(nir_src_bit_size(intr->src[0]) == 32);
assert(nir_intr_src_is_const(intr, 0));
assert(nir_src_num_components(intr->src[1]) == 1);
assert(nir_src_bit_size(intr->src[1]) == 32);
assert(nir_intr_src_is_const(intr, 1));
/* Intrinsic index validation. */
assert((nir_intrinsic_range_base(intr) % ROGUE_REG_SIZE_BYTES) == 0);
assert(nir_intrinsic_range(intr) == ROGUE_REG_SIZE_BYTES);
size_t nir_dest_reg = nir_intr_dest_regindex(intr);
size_t desc_set = nir_intr_src_comp_const(intr, 0, 0);
size_t binding = nir_intr_src_comp_const(intr, 0, 1);
size_t offset = nir_intrinsic_range_base(intr);
size_t sh_num = rogue_ubo_reg(ubo_data, desc_set, binding, offset);
struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MOV);
CHECK(rogue_instr_set_operand_vreg(instr, 0, nir_dest_reg));
CHECK(rogue_instr_set_operand_reg(instr,
1,
ROGUE_OPERAND_TYPE_REG_SHARED,
sh_num));
return true;
}
static bool trans_nir_intrinsic(struct rogue_shader *shader,
nir_intrinsic_instr *intr)
{
switch (intr->intrinsic) {
case nir_intrinsic_load_input:
return trans_nir_intrinsic_load_input(shader, intr);
case nir_intrinsic_store_output:
return trans_nir_intrinsic_store_output(shader, intr);
case nir_intrinsic_load_ubo:
return trans_nir_intrinsic_load_ubo(shader, intr);
default:
break;
}
unreachable("Unimplemented NIR intrinsic instruction.");
}
static bool trans_nir_load_const(struct rogue_shader *shader,
nir_load_const_instr *load_const)
{
/* Src/dest validation. */
assert(load_const->def.bit_size == 32);
/* Ensure that two-component load_consts are used only by load_ubos. */
if (load_const->def.num_components == 2) {
nir_foreach_use (use_src, &load_const->def) {
nir_instr *instr = use_src->parent_instr;
assert(instr->type == nir_instr_type_intrinsic);
ASSERTED nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
assert(intr->intrinsic == nir_intrinsic_load_ubo);
}
} else {
assert(load_const->def.num_components == 1);
}
/* TODO: This is currently done in MOV_IMM, but instead now would be the
* time to lookup the constant value, see if it lives in const regs, or if
* it needs to generate a MOV_IMM (or be constant calc-ed).
*/
return true;
}
static bool trans_nir_jump_return(struct rogue_shader *shader,
nir_jump_instr *jump)
{
enum rogue_opcode return_op;
switch (shader->stage) {
case MESA_SHADER_FRAGMENT:
return_op = ROGUE_OP_END_FRAG;
break;
case MESA_SHADER_VERTEX:
return_op = ROGUE_OP_END_VERT;
break;
default:
unreachable("Unimplemented NIR return instruction type.");
}
rogue_shader_insert(shader, return_op);
return true;
}
static bool trans_nir_jump(struct rogue_shader *shader, nir_jump_instr *jump)
{
switch (jump->type) {
case nir_jump_return:
return trans_nir_jump_return(shader, jump);
default:
break;
}
unreachable("Unimplemented NIR jump instruction type.");
}
/**
* \brief Converts a NIR shader to Rogue.
*
* \param[in] ctx Shared multi-stage build context.
* \param[in] nir NIR shader.
* \return A rogue_shader* if successful, or NULL if unsuccessful.
*/
struct rogue_shader *rogue_nir_to_rogue(struct rogue_build_ctx *ctx,
const nir_shader *nir)
{
gl_shader_stage stage = nir->info.stage;
struct rogue_shader *shader = rogue_shader_create(ctx, stage);
if (!shader)
return NULL;
/* Make sure we only have a single function. */
assert(exec_list_length(&nir->functions) == 1);
/* Translate shader entrypoint. */
nir_function_impl *entry = nir_shader_get_entrypoint((nir_shader *)nir);
nir_foreach_block (block, entry) {
nir_foreach_instr (instr, block) {
switch (instr->type) {
case nir_instr_type_alu:
/* TODO: Cleanup on failure. */
CHECKF(trans_nir_alu(shader, nir_instr_as_alu(instr)),
"Failed to translate NIR ALU instruction.");
break;
case nir_instr_type_intrinsic:
CHECKF(trans_nir_intrinsic(shader, nir_instr_as_intrinsic(instr)),
"Failed to translate NIR intrinsic instruction.");
break;
case nir_instr_type_load_const:
CHECKF(trans_nir_load_const(shader, nir_instr_as_load_const(instr)),
"Failed to translate NIR load_const instruction.");
break;
case nir_instr_type_jump:
CHECKF(trans_nir_jump(shader, nir_instr_as_jump(instr)),
"Failed to translate NIR jump instruction.");
break;
default:
unreachable("Unimplemented NIR instruction type.");
}
}
}
/* Perform register allocation. */
/* TODO: handle failure. */
if (!rogue_ra_alloc(&shader->instr_list,
shader->ra,
&ctx->common_data[stage].temps,
&ctx->common_data[stage].internals))
return NULL;
return shader;
}
/**
* \brief Creates and sets up a shared multi-stage build context.
*
* \param[in] compiler The compiler context.
* \return A pointer to the new build context, or NULL on failure.
*/
struct rogue_build_ctx *
rogue_create_build_context(struct rogue_compiler *compiler)
{
struct rogue_build_ctx *ctx;
ctx = rzalloc_size(compiler, sizeof(*ctx));
if (!ctx)
return NULL;
ctx->compiler = compiler;
/* nir/rogue/binary shaders need to be default-zeroed;
* this is taken care of by rzalloc_size.
*/
/* Setup non-zero defaults. */
ctx->stage_data.fs.msaa_mode = ROGUE_MSAA_MODE_PIXEL;
return ctx;
}

View File

@ -0,0 +1,75 @@
/*
* 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 ROGUE_H
#define ROGUE_H
#include <stddef.h>
#include <stdint.h>
#include "compiler/shader_enums.h"
#include "nir/nir.h"
/* All registers are 32-bit in size. */
#define ROGUE_REG_SIZE_BYTES 4
#define ROGUE_REG_UNUSED UINT32_MAX
struct nir_spirv_specialization;
struct rogue_build_ctx;
struct rogue_shader;
enum rogue_msaa_mode {
ROGUE_MSAA_MODE_UNDEF = 0, /* explicitly treat 0 as undefined */
/* One task for all samples. */
ROGUE_MSAA_MODE_PIXEL,
/* For on-edge pixels only: separate tasks for each sample. */
ROGUE_MSAA_MODE_SELECTIVE,
/* For all pixels: separate tasks for each sample. */
ROGUE_MSAA_MODE_FULL,
};
/**
* \brief Shader binary.
*/
struct rogue_shader_binary {
size_t size;
uint8_t data[];
};
PUBLIC
nir_shader *rogue_spirv_to_nir(struct rogue_build_ctx *ctx,
gl_shader_stage stage,
const char *entry,
size_t spirv_size,
const uint32_t *spirv_data,
unsigned num_spec,
struct nir_spirv_specialization *spec);
PUBLIC
struct rogue_shader_binary *rogue_to_binary(struct rogue_build_ctx *ctx,
const struct rogue_shader *shader);
PUBLIC
struct rogue_shader *rogue_nir_to_rogue(struct rogue_build_ctx *ctx,
const nir_shader *nir);
#endif /* ROGUE_H */

View File

@ -0,0 +1,602 @@
/*
* 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 <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "compiler/shader_enums.h"
#include "nir/nir.h"
#include "rogue_build_data.h"
#include "rogue_nir_helpers.h"
#include "rogue_operand.h"
#include "util/macros.h"
#define __pvr_address_type uint64_t
#define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr)
#include "csbgen/rogue_pds.h"
#undef __pvr_get_address
#undef __pvr_address_type
/**
* \brief Allocates the coefficient registers that will contain the iterator
* data for the fragment shader input varyings.
*
* \param[in] args The iterator argument data.
* \return The total number of coefficient registers required by the iterators.
*/
static size_t alloc_iterator_regs(struct rogue_iterator_args *args)
{
size_t coeffs = 0;
for (size_t u = 0; u < args->num_fpu_iterators; ++u) {
/* Ensure there aren't any gaps. */
assert(args->base[u] == ~0);
args->base[u] = coeffs;
coeffs += ROGUE_COEFF_ALIGN * args->components[u];
}
return coeffs;
}
/**
* \brief Reserves an iterator for a fragment shader input varying,
* and calculates its setup data.
*
* \param[in] args The iterator argument data.
* \param[in] i The iterator index.
* \param[in] type The interpolation type of the varying.
* \param[in] f16 Whether the data type is F16 or F32.
* \param[in] components The number of components in the varying.
*/
static void reserve_iterator(struct rogue_iterator_args *args,
size_t i,
enum glsl_interp_mode type,
bool f16,
size_t components)
{
struct ROGUE_PDSINST_DOUT_FIELDS_DOUTI_SRC data = { 0 };
assert(components >= 1 && components <= 4);
/* The first iterator (W) *must* be INTERP_MODE_NOPERSPECTIVE. */
assert(i > 0 || type == INTERP_MODE_NOPERSPECTIVE);
assert(i < ARRAY_SIZE(args->fpu_iterators));
switch (type) {
/* Default interpolation is smooth. */
case INTERP_MODE_NONE:
data.shademodel = ROGUE_PDSINST_DOUTI_SHADEMODEL_GOURUAD;
data.perspective = true;
break;
case INTERP_MODE_NOPERSPECTIVE:
data.shademodel = ROGUE_PDSINST_DOUTI_SHADEMODEL_GOURUAD;
data.perspective = false;
break;
default:
unreachable("Unimplemented interpolation type.");
}
/* Number of components in this varying
* (corresponds to ROGUE_PDSINST_DOUTI_SIZE_1..4D).
*/
data.size = (components - 1);
/* TODO: Investigate F16 support. */
assert(!f16);
data.f16 = f16;
/* Offsets within the vertex. */
data.f32_offset = 2 * i;
data.f16_offset = data.f32_offset;
ROGUE_PDSINST_DOUT_FIELDS_DOUTI_SRC_pack(&args->fpu_iterators[i], &data);
args->destination[i] = i;
args->base[i] = ~0;
args->components[i] = components;
++args->num_fpu_iterators;
}
/**
* \brief Collects the fragment shader I/O data to feed-back to the driver.
*
* \sa #collect_io_data()
*
* \param[in] common_data Common build data.
* \param[in] fs_data Fragment-specific build data.
* \param[in] nir NIR fragment shader.
* \return true if successful, otherwise false.
*/
static bool collect_io_data_fs(struct rogue_common_build_data *common_data,
struct rogue_fs_build_data *fs_data,
nir_shader *nir)
{
size_t num_inputs = nir_count_variables_with_modes(nir, nir_var_shader_in);
assert(num_inputs < (ARRAY_SIZE(fs_data->iterator_args.fpu_iterators) - 1));
/* Process inputs (if present). */
if (num_inputs) {
/* If the fragment shader has inputs, the first iterator
* must be used for the W component.
*/
reserve_iterator(&fs_data->iterator_args,
0,
INTERP_MODE_NOPERSPECTIVE,
false,
1);
nir_foreach_shader_in_variable (var, nir) {
size_t i = (var->data.location - VARYING_SLOT_VAR0) + 1;
size_t components = glsl_get_components(var->type);
enum glsl_interp_mode interp = var->data.interpolation;
bool f16 = glsl_type_is_16bit(var->type);
/* Check that arguments are either F16 or F32. */
assert(glsl_get_base_type(var->type) == GLSL_TYPE_FLOAT);
assert(f16 || glsl_type_is_32bit(var->type));
/* Check input location. */
assert(var->data.location >= VARYING_SLOT_VAR0 &&
var->data.location <= VARYING_SLOT_VAR31);
reserve_iterator(&fs_data->iterator_args, i, interp, f16, components);
}
common_data->coeffs = alloc_iterator_regs(&fs_data->iterator_args);
assert(common_data->coeffs);
assert(common_data->coeffs < ROGUE_MAX_REG_COEFF);
}
/* TODO: Process outputs. */
return true;
}
/**
* \brief Allocates the vertex shader input registers.
*
* \param[in] inputs The vertex shader input data.
* \return The total number of vertex input registers required.
*/
static size_t alloc_vs_inputs(struct rogue_vertex_inputs *inputs)
{
size_t vs_inputs = 0;
for (size_t u = 0; u < inputs->num_input_vars; ++u) {
/* Ensure there aren't any gaps. */
assert(inputs->base[u] == ~0);
inputs->base[u] = vs_inputs;
vs_inputs += inputs->components[u];
}
return vs_inputs;
}
/**
* \brief Allocates the vertex shader outputs.
*
* \param[in] outputs The vertex shader output data.
* \return The total number of vertex outputs required.
*/
static size_t alloc_vs_outputs(struct rogue_vertex_outputs *outputs)
{
size_t vs_outputs = 0;
for (size_t u = 0; u < outputs->num_output_vars; ++u) {
/* Ensure there aren't any gaps. */
assert(outputs->base[u] == ~0);
outputs->base[u] = vs_outputs;
vs_outputs += outputs->components[u];
}
return vs_outputs;
}
/**
* \brief Counts the varyings used by the vertex shader.
*
* \param[in] outputs The vertex shader output data.
* \return The number of varyings used.
*/
static size_t count_vs_varyings(struct rogue_vertex_outputs *outputs)
{
size_t varyings = 0;
/* Skip the position. */
for (size_t u = 1; u < outputs->num_output_vars; ++u)
varyings += outputs->components[u];
return varyings;
}
/**
* \brief Reserves space for a vertex shader input.
*
* \param[in] inputs The vertex input data.
* \param[in] i The vertex input index.
* \param[in] components The number of components in the input.
*/
static void reserve_vs_input(struct rogue_vertex_inputs *inputs,
size_t i,
size_t components)
{
assert(components >= 1 && components <= 4);
assert(i < ARRAY_SIZE(inputs->base));
inputs->base[i] = ~0;
inputs->components[i] = components;
++inputs->num_input_vars;
}
/**
* \brief Reserves space for a vertex shader output.
*
* \param[in] outputs The vertex output data.
* \param[in] i The vertex output index.
* \param[in] components The number of components in the output.
*/
static void reserve_vs_output(struct rogue_vertex_outputs *outputs,
size_t i,
size_t components)
{
assert(components >= 1 && components <= 4);
assert(i < ARRAY_SIZE(outputs->base));
outputs->base[i] = ~0;
outputs->components[i] = components;
++outputs->num_output_vars;
}
/**
* \brief Collects the vertex shader I/O data to feed-back to the driver.
*
* \sa #collect_io_data()
*
* \param[in] common_data Common build data.
* \param[in] vs_data Vertex-specific build data.
* \param[in] nir NIR vertex shader.
* \return true if successful, otherwise false.
*/
static bool collect_io_data_vs(struct rogue_common_build_data *common_data,
struct rogue_vs_build_data *vs_data,
nir_shader *nir)
{
ASSERTED bool out_pos_present = false;
ASSERTED size_t num_outputs =
nir_count_variables_with_modes(nir, nir_var_shader_out);
/* Process inputs. */
nir_foreach_shader_in_variable (var, nir) {
size_t components = glsl_get_components(var->type);
size_t i = var->data.location - VERT_ATTRIB_GENERIC0;
/* Check that inputs are F32. */
/* TODO: Support other types. */
assert(glsl_get_base_type(var->type) == GLSL_TYPE_FLOAT);
assert(glsl_type_is_32bit(var->type));
/* Check input location. */
assert(var->data.location >= VERT_ATTRIB_GENERIC0 &&
var->data.location <= VERT_ATTRIB_GENERIC15);
reserve_vs_input(&vs_data->inputs, i, components);
}
vs_data->num_vertex_input_regs = alloc_vs_inputs(&vs_data->inputs);
assert(vs_data->num_vertex_input_regs);
assert(vs_data->num_vertex_input_regs < ROGUE_MAX_REG_VERTEX_IN);
/* Process outputs. */
/* We should always have at least a position variable. */
assert(num_outputs > 0 && "Invalid number of vertex shader outputs.");
nir_foreach_shader_out_variable (var, nir) {
size_t components = glsl_get_components(var->type);
/* Check that outputs are F32. */
/* TODO: Support other types. */
assert(glsl_get_base_type(var->type) == GLSL_TYPE_FLOAT);
assert(glsl_type_is_32bit(var->type));
if (var->data.location == VARYING_SLOT_POS) {
assert(components == 4);
out_pos_present = true;
reserve_vs_output(&vs_data->outputs, 0, components);
} else if ((var->data.location >= VARYING_SLOT_VAR0) &&
(var->data.location <= VARYING_SLOT_VAR31)) {
size_t i = (var->data.location - VARYING_SLOT_VAR0) + 1;
reserve_vs_output(&vs_data->outputs, i, components);
} else {
unreachable("Unsupported vertex output type.");
}
}
/* Always need the output position to be present. */
assert(out_pos_present);
vs_data->num_vertex_outputs = alloc_vs_outputs(&vs_data->outputs);
assert(vs_data->num_vertex_outputs);
assert(vs_data->num_vertex_outputs < ROGUE_MAX_VERTEX_OUTPUTS);
vs_data->num_varyings = count_vs_varyings(&vs_data->outputs);
return true;
}
/**
* \brief Allocates the shared registers that will contain the UBOs.
*
* \param[in] ubo_data The UBO data.
* \return The total number of coefficient registers required by the iterators.
*/
static size_t alloc_ubos(struct rogue_ubo_data *ubo_data)
{
size_t shareds = 0;
for (size_t u = 0; u < ubo_data->num_ubo_entries; ++u) {
/* Ensure there aren't any gaps. */
assert(ubo_data->dest[u] == ~0);
ubo_data->dest[u] = shareds;
shareds += ubo_data->size[u];
}
return shareds;
}
/**
* \brief Reserves a UBO and calculates its data.
*
* \param[in] ubo_data The UBO data.
* \param[in] desc_set The UBO descriptor set.
* \param[in] binding The UBO binding.
* \param[in] size The size required by the UBO (in dwords).
*/
static void reserve_ubo(struct rogue_ubo_data *ubo_data,
size_t desc_set,
size_t binding,
size_t size)
{
size_t i = ubo_data->num_ubo_entries;
assert(i < ARRAY_SIZE(ubo_data->desc_set));
ubo_data->desc_set[i] = desc_set;
ubo_data->binding[i] = binding;
ubo_data->dest[i] = ~0;
ubo_data->size[i] = size;
++ubo_data->num_ubo_entries;
}
/**
* \brief Collects UBO data to feed-back to the driver.
*
* \param[in] common_data Common build data.
* \param[in] nir NIR shader.
* \return true if successful, otherwise false.
*/
static bool collect_ubo_data(struct rogue_common_build_data *common_data,
nir_shader *nir)
{
/* Iterate over each UBO. */
nir_foreach_variable_with_modes (var, nir, nir_var_mem_ubo) {
size_t desc_set = var->data.driver_location;
size_t binding = var->data.binding;
size_t ubo_size_regs = 0;
nir_function_impl *entry = nir_shader_get_entrypoint(nir);
/* Iterate over each load_ubo that uses this UBO. */
nir_foreach_block (block, entry) {
nir_foreach_instr (instr, block) {
if (instr->type != nir_instr_type_intrinsic)
continue;
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic != nir_intrinsic_load_ubo)
continue;
assert(nir_src_num_components(intr->src[0]) == 2);
assert(nir_intr_src_is_const(intr, 0));
size_t load_desc_set = nir_intr_src_comp_const(intr, 0, 0);
size_t load_binding = nir_intr_src_comp_const(intr, 0, 1);
if (load_desc_set != desc_set || load_binding != binding)
continue;
ASSERTED size_t size_bytes = nir_intrinsic_range(intr);
assert(size_bytes == ROGUE_REG_SIZE_BYTES);
size_t offset_bytes = nir_intrinsic_range_base(intr);
assert(!(offset_bytes % ROGUE_REG_SIZE_BYTES));
size_t offset_regs = offset_bytes / ROGUE_REG_SIZE_BYTES;
/* TODO: Put offsets in a BITSET_DECLARE and check for gaps. */
/* Find the largest load offset. */
ubo_size_regs = MAX2(ubo_size_regs, offset_regs);
}
}
/* UBO size = largest offset + 1. */
++ubo_size_regs;
reserve_ubo(&common_data->ubo_data, desc_set, binding, ubo_size_regs);
}
common_data->shareds = alloc_ubos(&common_data->ubo_data);
assert(common_data->shareds < ROGUE_MAX_REG_SHARED);
return true;
}
/**
* \brief Collects I/O data to feed-back to the driver.
*
* Collects the inputs/outputs/memory required, and feeds that back to the
* driver. Done at this stage rather than at the start of rogue_to_binary, so
* that all the I/O of all the shader stages is known before backend
* compilation, which would let us do things like cull unused inputs.
*
* \param[in] ctx Shared multi-stage build context.
* \param[in] nir NIR shader.
* \return true if successful, otherwise false.
*/
bool rogue_collect_io_data(struct rogue_build_ctx *ctx, nir_shader *nir)
{
gl_shader_stage stage = nir->info.stage;
struct rogue_common_build_data *common_data = &ctx->common_data[stage];
/* Collect stage-agnostic data. */
if (!collect_ubo_data(common_data, nir))
return false;
/* Collect stage-specific data. */
switch (stage) {
case MESA_SHADER_FRAGMENT:
return collect_io_data_fs(common_data, &ctx->stage_data.fs, nir);
case MESA_SHADER_VERTEX:
return collect_io_data_vs(common_data, &ctx->stage_data.vs, nir);
default:
break;
}
return false;
}
/**
* \brief Returns the allocated coefficient register index for a component of an
* input varying location.
*
* \param[in] args The allocated iterator argument data.
* \param[in] location The input varying location, or ~0 for the W coefficient.
* \param[in] component The requested component.
* \return The coefficient register index.
*/
size_t rogue_coeff_index_fs(struct rogue_iterator_args *args,
gl_varying_slot location,
size_t component)
{
size_t i;
/* Special case: W coefficient. */
if (location == ~0) {
/* The W component shouldn't be the only one. */
assert(args->num_fpu_iterators > 1);
assert(args->destination[0] == 0);
return 0;
}
i = (location - VARYING_SLOT_VAR0) + 1;
assert(location >= VARYING_SLOT_VAR0 && location <= VARYING_SLOT_VAR31);
assert(i < args->num_fpu_iterators);
assert(component < args->components[i]);
assert(args->base[i] != ~0);
return args->base[i] + (ROGUE_COEFF_ALIGN * component);
}
/**
* \brief Returns the allocated vertex output index for a component of an input
* varying location.
*
* \param[in] outputs The vertex output data.
* \param[in] location The output varying location.
* \param[in] component The requested component.
* \return The vertex output index.
*/
size_t rogue_output_index_vs(struct rogue_vertex_outputs *outputs,
gl_varying_slot location,
size_t component)
{
size_t i;
if (location == VARYING_SLOT_POS) {
/* Always at location 0. */
assert(outputs->base[0] == 0);
i = 0;
} else if ((location >= VARYING_SLOT_VAR0) &&
(location <= VARYING_SLOT_VAR31)) {
i = (location - VARYING_SLOT_VAR0) + 1;
} else {
unreachable("Unsupported vertex output type.");
}
assert(i < outputs->num_output_vars);
assert(component < outputs->components[i]);
assert(outputs->base[i] != ~0);
return outputs->base[i] + component;
}
/**
* \brief Returns the allocated shared register index for a given UBO offset.
*
* \param[in] ubo_data The UBO data.
* \param[in] desc_set The UBO descriptor set.
* \param[in] binding The UBO binding.
* \param[in] offset_bytes The UBO offset in bytes.
* \return The UBO offset shared register index.
*/
size_t rogue_ubo_reg(struct rogue_ubo_data *ubo_data,
size_t desc_set,
size_t binding,
size_t offset_bytes)
{
size_t ubo_index = ~0;
size_t offset_regs;
/* Find UBO located at (desc_set, binding). */
for (size_t u = 0; u < ubo_data->num_ubo_entries; ++u) {
if (ubo_data->dest[u] == ~0)
continue;
if (ubo_data->desc_set[u] != desc_set || ubo_data->binding[u] != binding)
continue;
ubo_index = u;
break;
}
assert(ubo_index != ~0);
assert(!(offset_bytes % ROGUE_REG_SIZE_BYTES));
offset_regs = offset_bytes / ROGUE_REG_SIZE_BYTES;
return ubo_data->dest[ubo_index] + offset_regs;
}

View File

@ -0,0 +1,163 @@
/*
* 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 ROGUE_BUILD_DATA_H
#define ROGUE_BUILD_DATA_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "compiler/shader_enums.h"
#include "nir/nir.h"
#include "rogue.h"
/* Max number of I/O varying variables.
* Fragment shader: MAX_VARYING + 1 (W coefficient).
* Vertex shader: MAX_VARYING + 1 (position slot).
*/
#define ROGUE_MAX_IO_VARYING_VARS (MAX_VARYING + 1)
/* VERT_ATTRIB_GENERIC0-15 */
#define ROGUE_MAX_IO_ATTRIB_VARS 16
/* Max buffers entries that can be used. */
/* TODO: Currently UBOs are the only supported buffers. */
#define ROGUE_MAX_BUFFERS 24
struct rogue_compiler;
struct rogue_shader;
struct rogue_shader_binary;
/**
* \brief UBO data.
*/
struct rogue_ubo_data {
size_t num_ubo_entries;
size_t desc_set[ROGUE_MAX_BUFFERS];
size_t binding[ROGUE_MAX_BUFFERS];
size_t dest[ROGUE_MAX_BUFFERS];
size_t size[ROGUE_MAX_BUFFERS];
};
/**
* \brief Per-stage common build data.
*/
struct rogue_common_build_data {
size_t temps;
size_t internals;
size_t coeffs;
size_t shareds;
struct rogue_ubo_data ubo_data;
};
/**
* \brief Arguments for the FPU iterator(s)
* (produces varyings for the fragment shader).
*/
struct rogue_iterator_args {
uint32_t num_fpu_iterators;
uint32_t fpu_iterators[ROGUE_MAX_IO_VARYING_VARS];
uint32_t destination[ROGUE_MAX_IO_VARYING_VARS];
size_t base[ROGUE_MAX_IO_VARYING_VARS];
size_t components[ROGUE_MAX_IO_VARYING_VARS];
};
/**
* \brief Vertex input register allocations.
*/
struct rogue_vertex_inputs {
size_t num_input_vars;
size_t base[ROGUE_MAX_IO_ATTRIB_VARS];
size_t components[ROGUE_MAX_IO_ATTRIB_VARS];
};
/**
* \brief Vertex output allocations.
*/
struct rogue_vertex_outputs {
size_t num_output_vars;
size_t base[ROGUE_MAX_IO_VARYING_VARS];
size_t components[ROGUE_MAX_IO_VARYING_VARS];
};
/**
* \brief Stage-specific build data.
*/
struct rogue_build_data {
struct rogue_fs_build_data {
struct rogue_iterator_args iterator_args;
enum rogue_msaa_mode msaa_mode;
bool phas; /* Indicates the presence of PHAS instruction. */
} fs;
struct rogue_vs_build_data {
struct rogue_vertex_inputs inputs;
size_t num_vertex_input_regs; /* Final number of inputs. */
struct rogue_vertex_outputs outputs;
size_t num_vertex_outputs; /* Final number of outputs. */
size_t num_varyings; /* Final number of varyings. */
} vs;
};
/**
* \brief Shared multi-stage build context.
*/
struct rogue_build_ctx {
struct rogue_compiler *compiler;
/* Shaders in various stages of compilations. */
nir_shader *nir[MESA_SHADER_FRAGMENT + 1];
struct rogue_shader *rogue[MESA_SHADER_FRAGMENT + 1];
struct rogue_shader_binary *binary[MESA_SHADER_FRAGMENT + 1];
struct rogue_common_build_data common_data[MESA_SHADER_FRAGMENT + 1];
struct rogue_build_data stage_data;
};
PUBLIC
struct rogue_build_ctx *
rogue_create_build_context(struct rogue_compiler *compiler);
PUBLIC
bool rogue_collect_io_data(struct rogue_build_ctx *ctx, nir_shader *nir);
PUBLIC
size_t rogue_coeff_index_fs(struct rogue_iterator_args *args,
gl_varying_slot location,
size_t component);
PUBLIC
size_t rogue_output_index_vs(struct rogue_vertex_outputs *outputs,
gl_varying_slot location,
size_t component);
PUBLIC
size_t rogue_ubo_reg(struct rogue_ubo_data *ubo_data,
size_t desc_set,
size_t binding,
size_t offset_bytes);
#endif /* ROGUE_BUILD_DATA_H */

View File

@ -0,0 +1,72 @@
/*
* 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 <stddef.h>
#include "compiler/glsl_types.h"
#include "rogue_compiler.h"
#include "util/ralloc.h"
/**
* \file rogue_compiler.c
*
* \brief Contains the Rogue compiler interface.
*/
/**
* \brief Creates and sets up a Rogue compiler context.
*
* \param[in] dev_info Device info pointer.
* \return A pointer to the new compiler context, or NULL on failure.
*/
struct rogue_compiler *
rogue_compiler_create(const struct pvr_device_info *dev_info)
{
struct rogue_compiler *compiler;
compiler = rzalloc_size(NULL, sizeof(*compiler));
if (!compiler)
return NULL;
compiler->dev_info = dev_info;
/* TODO: Additional compiler setup (allocators? error message output
* location?).
*/
glsl_type_singleton_init_or_ref();
return compiler;
}
/**
* \brief Destroys and frees a compiler context.
*
* \param[in] compiler The compiler context.
*/
void rogue_compiler_destroy(struct rogue_compiler *compiler)
{
glsl_type_singleton_decref();
ralloc_free(compiler);
}

View File

@ -0,0 +1,45 @@
/*
* 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 ROGUE_COMPILER_H
#define ROGUE_COMPILER_H
#include "util/macros.h"
struct pvr_device_info;
/**
* \brief Compiler context.
*/
struct rogue_compiler {
const struct pvr_device_info *dev_info;
};
PUBLIC
struct rogue_compiler *
rogue_compiler_create(const struct pvr_device_info *dev_info);
PUBLIC
void rogue_compiler_destroy(struct rogue_compiler *compiler);
#endif /* ROGUE_COMPILER_H */

View File

@ -0,0 +1,199 @@
/*
* 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 <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "rogue_constreg.h"
#include "util/macros.h"
/**
* \file rogue_constreg.c
*
* \brief Contains functions to find and allocate constant register values.
*/
/**
* \brief Mapping of constant register values and their indices.
*/
struct rogue_constreg {
uint32_t value;
size_t index;
};
#define CONSTREG(VALUE, INDEX) \
{ \
.value = (VALUE), .index = (INDEX), \
}
/**
* \brief Constant register values (sorted for bsearch).
*/
static const struct rogue_constreg const_regs[] = {
CONSTREG(0x00000000U, 0U), /* 0 (INT32) / 0.0 (Float) */
CONSTREG(0x00000001U, 1U), /* 1 (INT32) */
CONSTREG(0x00000002U, 2U), /* 2 (INT32) */
CONSTREG(0x00000003U, 3U), /* 3 (INT32) */
CONSTREG(0x00000004U, 4U), /* 4 (INT32) */
CONSTREG(0x00000005U, 5U), /* 5 (INT32) */
CONSTREG(0x00000006U, 6U), /* 6 (INT32) */
CONSTREG(0x00000007U, 7U), /* 7 (INT32) */
CONSTREG(0x00000008U, 8U), /* 8 (INT32) */
CONSTREG(0x00000009U, 9U), /* 9 (INT32) */
CONSTREG(0x0000000aU, 10U), /* 10 (INT32) */
CONSTREG(0x0000000bU, 11U), /* 11 (INT32) */
CONSTREG(0x0000000cU, 12U), /* 12 (INT32) */
CONSTREG(0x0000000dU, 13U), /* 13 (INT32) */
CONSTREG(0x0000000eU, 14U), /* 14 (INT32) */
CONSTREG(0x0000000fU, 15U), /* 15 (INT32) */
CONSTREG(0x00000010U, 16U), /* 16 (INT32) */
CONSTREG(0x00000011U, 17U), /* 17 (INT32) */
CONSTREG(0x00000012U, 18U), /* 18 (INT32) */
CONSTREG(0x00000013U, 19U), /* 19 (INT32) */
CONSTREG(0x00000014U, 20U), /* 20 (INT32) */
CONSTREG(0x00000015U, 21U), /* 21 (INT32) */
CONSTREG(0x00000016U, 22U), /* 22 (INT32) */
CONSTREG(0x00000017U, 23U), /* 23 (INT32) */
CONSTREG(0x00000018U, 24U), /* 24 (INT32) */
CONSTREG(0x00000019U, 25U), /* 25 (INT32) */
CONSTREG(0x0000001aU, 26U), /* 26 (INT32) */
CONSTREG(0x0000001bU, 27U), /* 27 (INT32) */
CONSTREG(0x0000001cU, 28U), /* 28 (INT32) */
CONSTREG(0x0000001dU, 29U), /* 29 (INT32) */
CONSTREG(0x0000001eU, 30U), /* 30 (INT32) */
CONSTREG(0x0000001fU, 31U), /* 31 (INT32) */
CONSTREG(0x0000007fU, 147U), /* 127 (INT32) */
CONSTREG(0x37800000U, 134U), /* 1.0f/65536f */
CONSTREG(0x38000000U, 135U), /* 1.0f/32768f */
CONSTREG(0x38800000U, 88U), /* float(2^-14) */
CONSTREG(0x39000000U, 87U), /* float(2^-13) */
CONSTREG(0x39800000U, 86U), /* float(2^-12) */
CONSTREG(0x3a000000U, 85U), /* float(2^-11) */
CONSTREG(0x3a800000U, 84U), /* float(2^-10) */
CONSTREG(0x3b000000U, 83U), /* float(2^-9) */
CONSTREG(0x3b4d2e1cU, 136U), /* 0.0031308f */
CONSTREG(0x3b800000U, 82U), /* float(2^-8) */
CONSTREG(0x3c000000U, 81U), /* float(2^-7) */
CONSTREG(0x3c800000U, 80U), /* float(2^-6) */
CONSTREG(0x3d000000U, 79U), /* float(2^-5) */
CONSTREG(0x3d25aee6U, 156U), /* 0.04045f */
CONSTREG(0x3d6147aeU, 140U), /* 0.055f */
CONSTREG(0x3d800000U, 78U), /* float(2^-4) */
CONSTREG(0x3d9e8391U, 157U), /* 1.0f/12.92f */
CONSTREG(0x3e000000U, 77U), /* float(2^-3) */
CONSTREG(0x3e2aaaabU, 153U), /* 1/6 */
CONSTREG(0x3e800000U, 76U), /* float(2^-2) */
CONSTREG(0x3e9a209bU, 145U), /* Log_10(2) */
CONSTREG(0x3ea2f983U, 128U), /* Float 1/PI */
CONSTREG(0x3eaaaaabU, 152U), /* 1/3 */
CONSTREG(0x3ebc5ab2U, 90U), /* 1/e */
CONSTREG(0x3ed55555U, 138U), /* 1.0f/2.4f */
CONSTREG(0x3f000000U, 75U), /* float(2^-1) */
CONSTREG(0x3f22f983U, 129U), /* Float 2/PI */
CONSTREG(0x3f317218U, 146U), /* Log_e(2) */
CONSTREG(0x3f3504f3U, 92U), /* Float 1/SQRT(2) */
CONSTREG(0x3f490fdbU, 93U), /* Float PI/4 */
CONSTREG(0x3f72a76fU, 158U), /* 1.0f/1.055f */
CONSTREG(0x3f800000U, 64U), /* 1.0f */
CONSTREG(0x3f860a92U, 151U), /* Pi/3 */
CONSTREG(0x3f870a3dU, 139U), /* 1.055f */
CONSTREG(0x3fa2f983U, 130U), /* Float 4/PI */
CONSTREG(0x3fb504f3U, 91U), /* Float SQRT(2) */
CONSTREG(0x3fb8aa3bU, 155U), /* Log_2(e) */
CONSTREG(0x3fc90fdbU, 94U), /* Float PI/2 */
CONSTREG(0x40000000U, 65U), /* float(2^1) */
CONSTREG(0x4019999aU, 159U), /* 2.4f */
CONSTREG(0x402df854U, 89U), /* e */
CONSTREG(0x40490fdbU, 95U), /* Float PI */
CONSTREG(0x40549a78U, 154U), /* Log_2(10) */
CONSTREG(0x40800000U, 66U), /* float(2^2) */
CONSTREG(0x40c90fdbU, 131U), /* Float 2*PI */
CONSTREG(0x41000000U, 67U), /* float(2^3) */
CONSTREG(0x41490fdbU, 132U), /* Float 4*PI */
CONSTREG(0x414eb852U, 137U), /* 12.92f */
CONSTREG(0x41800000U, 68U), /* float(2^4) */
CONSTREG(0x41c90fdbU, 133U), /* Float 8*PI */
CONSTREG(0x42000000U, 69U), /* float(2^5) */
CONSTREG(0x42800000U, 70U), /* float(2^6) */
CONSTREG(0x43000000U, 71U), /* float(2^7) */
CONSTREG(0x43800000U, 72U), /* float(2^8) */
CONSTREG(0x44000000U, 73U), /* float(2^9) */
CONSTREG(0x44800000U, 74U), /* float(2^10) */
CONSTREG(0x4b000000U, 149U), /* 2^23 */
CONSTREG(0x4b800000U, 150U), /* 2^24 */
CONSTREG(0x7f7fffffU, 148U), /* FLT_MAX */
CONSTREG(0x7f800000U, 142U), /* Infinity */
CONSTREG(0x7fff7fffU, 144U), /* ARGB1555 mask */
CONSTREG(0x80000000U, 141U), /* -0.0f */
CONSTREG(0xffffffffU, 143U), /* -1 */
};
#undef CONSTREG
/**
* \brief Comparison function for bsearch() to support struct rogue_constreg.
*
* \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 rogue_constreg *l = lhs;
const struct rogue_constreg *r = rhs;
if (l->value < r->value)
return -1;
else if (l->value > r->value)
return 1;
return 0;
}
/**
* \brief Determines whether a given integer value exists in a constant
* register.
*
* \param[in] value The value required.
* \return The index of the constant register containing the value, or
* ROGUE_NO_CONST_REG if the value is not found.
*/
size_t rogue_constreg_lookup(uint32_t value)
{
struct rogue_constreg constreg_target = {
.value = value,
};
const struct rogue_constreg *constreg;
constreg = bsearch(&constreg_target,
const_regs,
ARRAY_SIZE(const_regs),
sizeof(struct rogue_constreg),
constreg_cmp);
if (!constreg)
return ROGUE_NO_CONST_REG;
return constreg->index;
}

View File

@ -0,0 +1,51 @@
/*
* 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 ROGUE_CONSTREGS_H
#define ROGUE_CONSTREGS_H
#include <stddef.h>
#include <stdint.h>
#include "util/macros.h"
#include "util/u_math.h"
#define ROGUE_NO_CONST_REG SIZE_MAX
PUBLIC
size_t rogue_constreg_lookup(uint32_t value);
/**
* \brief Determines whether a given floating point value exists in a constant
* register.
*
* \param[in] value The value required.
* \return The index of the constant register containing the value, or
* ROGUE_NO_CONST_REG if the value is not found.
*/
static inline size_t rogue_constreg_lookup_float(float value)
{
return rogue_constreg_lookup(fui(value));
}
#endif /* ROGUE_CONSTREGS_H */

View File

@ -0,0 +1,170 @@
/*
* 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 <stdint.h>
#include "rogue_dump.h"
#include "rogue_shader.h"
#include "rogue_util.h"
#include "util/bitscan.h"
/**
* \file rogue_dump.c
*
* \brief Contains functions to dump Rogue data structures into a textual
* format.
*/
static const char *const rogue_operand_string[ROGUE_OPERAND_TYPE_COUNT] = {
[ROGUE_OPERAND_TYPE_REG_TEMP] = "r",
[ROGUE_OPERAND_TYPE_REG_COEFF] = "cf",
[ROGUE_OPERAND_TYPE_REG_CONST] = "c",
[ROGUE_OPERAND_TYPE_REG_SHARED] = "sh",
[ROGUE_OPERAND_TYPE_REG_PIXEL_OUT] = "po",
[ROGUE_OPERAND_TYPE_REG_VERTEX_IN] = "vi",
[ROGUE_OPERAND_TYPE_REG_INTERNAL] = "i",
[ROGUE_OPERAND_TYPE_IMMEDIATE] = "#",
[ROGUE_OPERAND_TYPE_DRC] = "drc",
[ROGUE_OPERAND_TYPE_VREG] = "V",
};
static const char *const rogue_opcode_string[ROGUE_OP_COUNT] = {
[ROGUE_OP_NOP] = "nop",
[ROGUE_OP_END_FRAG] = "end.frag",
[ROGUE_OP_END_VERT] = "end.vert",
[ROGUE_OP_WDF] = "wdf",
[ROGUE_OP_PIX_ITER_W] = "pixiter.w",
[ROGUE_OP_MAX] = "max",
[ROGUE_OP_MIN] = "min",
[ROGUE_OP_PACK_U8888] = "pack.u8888",
[ROGUE_OP_MOV] = "mov",
[ROGUE_OP_MOV_IMM] = "mov.imm",
[ROGUE_OP_FMA] = "fma",
[ROGUE_OP_MUL] = "mul",
[ROGUE_OP_VTXOUT] = "vtxout",
};
static const char *const rogue_instr_flag_string[ROGUE_INSTR_FLAG_COUNT] = {
[ROGUE_INSTR_FLAG_SAT] = "sat",
[ROGUE_INSTR_FLAG_LP] = "lp",
[ROGUE_INSTR_FLAG_OLCHK] = "olchk",
};
static const char rogue_vector_string[4] = {
'x',
'y',
'z',
'w',
};
/**
* \brief Dumps an operand as text to a file pointer.
*
* \param[in] operand The operand.
* \param[in] fp The file pointer.
* \return true if successful, otherwise false.
*/
bool rogue_dump_operand(const struct rogue_operand *operand, FILE *fp)
{
ASSERT_OPERAND_RANGE(operand->type);
fprintf(fp, "%s", rogue_operand_string[operand->type]);
if (operand->type == ROGUE_OPERAND_TYPE_IMMEDIATE)
fprintf(fp, "%" PRIu64, operand->immediate.value);
else if (operand->type == ROGUE_OPERAND_TYPE_DRC)
fprintf(fp, "%zu", operand->drc.number);
else if (rogue_check_bitset(rogue_onehot(operand->type), ROGUE_MASK_ANY_REG))
fprintf(fp, "%zu", operand->reg.number);
else if (operand->type == ROGUE_OPERAND_TYPE_VREG) {
fprintf(fp, "%zu", operand->vreg.number);
if (operand->vreg.is_vector)
fprintf(fp, ".%c", rogue_vector_string[operand->vreg.component]);
}
return true;
}
/**
* \brief Dumps an instruction as text to a file pointer.
*
* \param[in] instr The instruction.
* \param[in] fp The file pointer.
* \return true if successful, otherwise false.
*/
bool rogue_dump_instr(const struct rogue_instr *instr, FILE *fp)
{
uint64_t flags = 0U;
ASSERT_OPCODE_RANGE(instr->opcode);
flags = instr->flags;
fprintf(fp, "%s", rogue_opcode_string[instr->opcode]);
/* Iterate over each flag bit and print its string form. */
while (flags) {
uint64_t flag = u_bit_scan64(&flags);
ASSERT_INSTR_FLAG_RANGE(flag);
fprintf(fp, ".%s", rogue_instr_flag_string[flag]);
}
if (instr->num_operands)
fprintf(fp, " ");
/* Dump each operand. */
for (size_t u = 0U; u < instr->num_operands; ++u) {
CHECKF(rogue_dump_operand(&instr->operands[u], fp),
"Failed to dump operand.");
if (u < (instr->num_operands - 1))
fprintf(fp, ", ");
}
fprintf(fp, ";");
return true;
}
/**
* \brief Dumps a shader as text to a file pointer.
*
* \param[in] shader The shader.
* \param[in] fp The file pointer.
* \return true if successful, otherwise false.
*/
bool rogue_dump_shader(const struct rogue_shader *shader, FILE *fp)
{
/* Dump the shader stage. */
fprintf(fp, "# %s shader\n", _mesa_shader_stage_to_string(shader->stage));
/* Dump each instruction. */
foreach_instr (instr, &shader->instr_list) {
CHECKF(rogue_dump_instr(instr, fp), "Failed to dump instruction.");
fprintf(fp, "\n");
}
fprintf(fp, "\n");
return true;
}

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 ROGUE_DUMP_H
#define ROGUE_DUMP_H
#include <stdbool.h>
#include <stdio.h>
#include "rogue_instr.h"
#include "rogue_operand.h"
#include "rogue_shader.h"
#include "util/macros.h"
PUBLIC
bool rogue_dump_operand(const struct rogue_operand *operand, FILE *fp);
PUBLIC
bool rogue_dump_instr(const struct rogue_instr *instr, FILE *fp);
PUBLIC
bool rogue_dump_shader(const struct rogue_shader *shader, FILE *fp);
#endif /* ROGUE_DUMP_H */

View File

@ -0,0 +1,851 @@
/*
* 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 <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hwdef/rogue_hw_defs.h"
#include "rogue_encode.h"
#include "rogue_encoders.h"
#include "rogue_operand.h"
#include "rogue_shader.h"
#include "rogue_util.h"
#include "util/bitscan.h"
#include "util/macros.h"
static size_t rogue_encode_reg_bank(const struct rogue_operand *operand)
{
switch (operand->type) {
case ROGUE_OPERAND_TYPE_REG_INTERNAL:
case ROGUE_OPERAND_TYPE_REG_PIXEL_OUT:
case ROGUE_OPERAND_TYPE_REG_CONST:
return 0;
case ROGUE_OPERAND_TYPE_REG_TEMP:
return 1;
case ROGUE_OPERAND_TYPE_REG_VERTEX_IN:
return 2;
case ROGUE_OPERAND_TYPE_REG_COEFF:
return 3;
case ROGUE_OPERAND_TYPE_REG_SHARED:
return 4;
default:
break;
}
unreachable("Unimplemented register bank.");
}
/**
* \brief Field mapping type.
*/
enum rogue_map_type {
ROGUE_MAP_TYPE_INSTR_FLAG = 0,
ROGUE_MAP_TYPE_OPERAND_FLAG,
ROGUE_MAP_TYPE_OPERAND,
ROGUE_MAP_TYPE_COUNT,
};
/**
* \brief Field mapping rule description.
*/
struct rogue_field_mapping {
/* Type of mapping being performed. */
enum rogue_map_type type;
/* Index of the source operand/flag being mapped. */
size_t index;
/* List of ranges to perform mapping. */
struct rogue_rangelist rangelist;
/* Function used to encode the input into the value to be mapped. */
field_encoder_t encoder_fn;
};
/**
* \brief Instruction encoding rule description.
*/
struct rogue_instr_encoding {
/* Number of bytes making up the base mask. */
size_t num_bytes;
/* Base mask bytes. */
uint8_t *bytes;
/* Number of field mappings for this instruction. */
size_t num_mappings;
/* Field mappings. */
struct rogue_field_mapping *mappings;
};
static const
struct rogue_instr_encoding instr_encodings[ROGUE_OP_COUNT] = {
[ROGUE_OP_NOP] = {
.num_bytes = 8,
.bytes = (uint8_t []) { 0x04, 0x80, 0x6e, 0x00, 0xf2, 0xff, 0xff, 0xff },
},
[ROGUE_OP_END_FRAG] = {
.num_bytes = 8,
.bytes = (uint8_t []) { 0x04, 0x80, 0xee, 0x00, 0xf2, 0xff, 0xff, 0xff },
},
[ROGUE_OP_END_VERT] = {
.num_bytes = 8,
.bytes = (uint8_t []) { 0x44, 0xa0, 0x80, 0x05, 0x00, 0x00, 0x00, 0xff },
},
[ROGUE_OP_WDF] = {
.num_bytes = 8,
.bytes = (uint8_t []) { 0x04, 0x80, 0x6a, 0xff, 0xf2, 0xff, 0xff, 0xff },
.num_mappings = 1,
.mappings = (struct rogue_field_mapping []) {
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 0,
.rangelist = {
.num_ranges = 1,
.ranges = (struct rogue_bitrange []) {
{ .start = 47, .num = 1, },
},
},
.encoder_fn = &rogue_encoder_drc,
},
},
},
[ROGUE_OP_PIX_ITER_W] = {
.num_bytes = 16,
.bytes = (uint8_t []) { 0x48, 0x20, 0xb0, 0x01, 0x80, 0x40, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0xf1, 0xff },
.num_mappings = 6,
.mappings = (struct rogue_field_mapping []) {
/* Instruction flag mappings. */
{
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
.index = ROGUE_INSTR_FLAG_SAT,
.rangelist = {
.num_ranges = 1,
.ranges = (struct rogue_bitrange []) {
{ .start = 100, .num = 1, },
},
},
.encoder_fn = NULL,
},
/* Operand mappings. */
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 0,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 43, .num = 2, }, /* SB3(2..1) */
{ .start = 54, .num = 1, }, /* SB3(0) */
{ .start = 34, .num = 3, }, /* S3(10..8) */
{ .start = 41, .num = 2, }, /* S3(7..6) */
{ .start = 53, .num = 6, }, /* S3(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 1,
.rangelist = {
.num_ranges = 1,
.ranges = (struct rogue_bitrange []) {
{ .start = 59, .num = 1, },
},
},
.encoder_fn = &rogue_encoder_drc,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 2,
.rangelist = {
.num_ranges = 6,
.ranges = (struct rogue_bitrange []) {
{ .start = 59, .num = 1, }, /* SB0(2) */
{ .start = 76, .num = 1, }, /* SB0(1) */
{ .start = 94, .num = 1, }, /* SB0(0) */
{ .start = 57, .num = 1, }, /* S0(7) */
{ .start = 74, .num = 1, }, /* S0(6) */
{ .start = 93, .num = 6, }, /* S0(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_8,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 3,
.rangelist = {
.num_ranges = 4,
.ranges = (struct rogue_bitrange []) {
{ .start = 63, .num = 1, }, /* SB2(2) */
{ .start = 71, .num = 2, }, /* SB2(1..0) */
{ .start = 62, .num = 2, }, /* S2(7..6) */
{ .start = 69, .num = 6, }, /* S2(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_8,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 4,
.rangelist = {
.num_ranges = 1,
.ranges = (struct rogue_bitrange []) {
{ .start = 99, .num = 4, },
},
},
.encoder_fn = &rogue_encoder_ls_1_16,
},
},
},
[ROGUE_OP_MAX] = {
.num_bytes = 16,
.bytes = (uint8_t []) { 0x68, 0x42, 0xd0, 0x3c, 0xfa, 0x10, 0x87, 0x80, 0xc0, 0x80, 0x10, 0x00, 0x32, 0x80, 0x00, 0xff },
.num_mappings = 3,
.mappings = (struct rogue_field_mapping []) {
/* Operand mappings. */
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 0,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 11, .num = 2, }, /* DBn(2..1) */
{ .start = 22, .num = 1, }, /* DBn(0) */
{ .start = 14, .num = 3, }, /* Dn(10..8) */
{ .start = 9, .num = 2, }, /* Dn(7..6) */
{ .start = 21, .num = 6, }, /* Dn(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 1,
.rangelist = {
.num_ranges = 7,
.ranges = (struct rogue_bitrange []) {
{ .start = 43, .num = 1, }, /* SB0(2) */
{ .start = 52, .num = 1, }, /* SB0(1) */
{ .start = 70, .num = 1, }, /* SB0(0) */
{ .start = 47, .num = 3, }, /* S0(10..8) */
{ .start = 41, .num = 1, }, /* S0(7) */
{ .start = 50, .num = 1, }, /* S0(6) */
{ .start = 69, .num = 6, }, /* S0(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 2,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 51, .num = 1, }, /* SB1(1) */
{ .start = 61, .num = 1, }, /* SB1(0) */
{ .start = 40, .num = 1, }, /* S1(7) */
{ .start = 49, .num = 2, }, /* S1(6..5) */
{ .start = 60, .num = 5, }, /* S1(4..0) */
},
},
.encoder_fn = &rogue_encoder_reg_2_8,
},
},
},
[ROGUE_OP_MIN] = {
.num_bytes = 16,
.bytes = (uint8_t []) { 0x68, 0x42, 0xd0, 0x3c, 0xf0, 0x11, 0x87, 0x80, 0xc0, 0x80, 0x10, 0x00, 0x32, 0x80, 0x00, 0xff },
.num_mappings = 3,
.mappings = (struct rogue_field_mapping []) {
/* Operand mappings. */
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 0,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 11, .num = 2, }, /* DBn(2..1) */
{ .start = 22, .num = 1, }, /* DBn(0) */
{ .start = 14, .num = 3, }, /* Dn(10..8) */
{ .start = 9, .num = 2, }, /* Dn(7..6) */
{ .start = 21, .num = 6, }, /* Dn(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 1,
.rangelist = {
.num_ranges = 7,
.ranges = (struct rogue_bitrange []) {
{ .start = 43, .num = 1, }, /* SB0(2) */
{ .start = 52, .num = 1, }, /* SB0(1) */
{ .start = 70, .num = 1, }, /* SB0(0) */
{ .start = 47, .num = 3, }, /* S0(10..8) */
{ .start = 41, .num = 1, }, /* S0(7) */
{ .start = 50, .num = 1, }, /* S0(6) */
{ .start = 69, .num = 6, }, /* S0(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 2,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 51, .num = 1, }, /* SB1(1) */
{ .start = 61, .num = 1, }, /* SB1(0) */
{ .start = 40, .num = 1, }, /* S1(7) */
{ .start = 49, .num = 2, }, /* S1(6..5) */
{ .start = 60, .num = 5, }, /* S1(4..0) */
},
},
.encoder_fn = &rogue_encoder_reg_2_8,
},
},
},
[ROGUE_OP_PACK_U8888] = {
.num_bytes = 16,
.bytes = (uint8_t []) { 0x58, 0x92, 0x06, 0x9c, 0x20, 0x80, 0x00, 0x00, 0x00, 0x2c, 0x80, 0x00, 0xf2, 0xff, 0xff, 0xff },
.num_mappings = 2,
.mappings = (struct rogue_field_mapping []) {
/* Operand mappings. */
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 0,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 35, .num = 2, }, /* DBn(2..1) */
{ .start = 46, .num = 1, }, /* DBn(0) */
{ .start = 38, .num = 3, }, /* Dn(10..8) */
{ .start = 33, .num = 2, }, /* Dn(7..6) */
{ .start = 45, .num = 6, }, /* Dn(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 1,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 75, .num = 2, }, /* SB0(2..1) */
{ .start = 86, .num = 1, }, /* SB0(0) */
{ .start = 66, .num = 3, }, /* S0(10..8) */
{ .start = 73, .num = 2, }, /* S0(7..6) */
{ .start = 85, .num = 6, }, /* S0(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
},
},
[ROGUE_OP_MOV] = {
.num_bytes = 16,
.bytes = (uint8_t []) { 0x48, 0x42, 0xd0, 0x3f, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xf2, 0xff, 0xff, 0xff },
.num_mappings = 3,
.mappings = (struct rogue_field_mapping []) {
/* Instruction flag mappings. */
{
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
.index = ROGUE_INSTR_FLAG_OLCHK,
.rangelist = {
.num_ranges = 1,
.ranges = (struct rogue_bitrange []) {
{ .start = 115, .num = 1, },
},
},
.encoder_fn = NULL,
},
/* Operand mappings. */
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 0,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 35, .num = 2, }, /* DBn(2..1) */
{ .start = 46, .num = 1, }, /* DBn(0) */
{ .start = 38, .num = 3, }, /* Dn(10..8) */
{ .start = 33, .num = 2, }, /* Dn(7..6) */
{ .start = 45, .num = 6, }, /* Dn(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 1,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 75, .num = 2, }, /* SB0(2..1) */
{ .start = 86, .num = 1, }, /* SB0(0) */
{ .start = 66, .num = 3, }, /* S0(10..8) */
{ .start = 73, .num = 2, }, /* S0(7..6) */
{ .start = 85, .num = 6, }, /* S0(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
},
},
[ROGUE_OP_MOV_IMM] = {
.num_bytes = 16,
.bytes = (uint8_t []) { 0x88, 0x92, 0x40, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xf2, 0xff, 0xff, 0xff },
.num_mappings = 2,
.mappings = (struct rogue_field_mapping []) {
/* Operand mappings. */
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 0,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 35, .num = 2, }, /* DBn(2..1) */
{ .start = 46, .num = 1, }, /* DBn(0) */
{ .start = 38, .num = 3, }, /* Dn(10..8) */
{ .start = 33, .num = 2, }, /* Dn(7..6) */
{ .start = 45, .num = 6, }, /* Dn(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 1,
.rangelist = {
.num_ranges = 4,
.ranges = (struct rogue_bitrange []) {
{ .start = 71, .num = 8, }, /* imm(31:24) */
{ .start = 79, .num = 8, }, /* imm(23:16) */
{ .start = 87, .num = 8, }, /* imm(15:8) */
{ .start = 95, .num = 8, }, /* imm(7:0) */
},
},
.encoder_fn = &rogue_encoder_imm,
},
},
},
[ROGUE_OP_FMA] = {
.num_bytes = 16,
.bytes = (uint8_t []) { 0x28, 0x02, 0xd0, 0x00, 0x80, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xff, 0xf1, 0xff },
.num_mappings = 6,
.mappings = (struct rogue_field_mapping []) {
/* Instruction flag mappings. */
{
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
.index = ROGUE_INSTR_FLAG_SAT,
.rangelist = {
.num_ranges = 1,
.ranges = (struct rogue_bitrange []) {
{ .start = 104, .num = 1, },
},
},
.encoder_fn = NULL,
},
{
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
.index = ROGUE_INSTR_FLAG_LP,
.rangelist = {
.num_ranges = 1,
.ranges = (struct rogue_bitrange []) {
{ .start = 100, .num = 1, },
},
},
.encoder_fn = NULL,
},
/* Operand mappings. */
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 0,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 27, .num = 2, }, /* DBn(2..1) */
{ .start = 38, .num = 1, }, /* DBn(0) */
{ .start = 30, .num = 3, }, /* Dn(10..8) */
{ .start = 25, .num = 2, }, /* Dn(7..6) */
{ .start = 37, .num = 6, }, /* Dn(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 1,
.rangelist = {
.num_ranges = 6,
.ranges = (struct rogue_bitrange []) {
{ .start = 59, .num = 1, }, /* SB0(2) */
{ .start = 76, .num = 1, }, /* SB0(1) */
{ .start = 94, .num = 1, }, /* SB0(0) */
{ .start = 57, .num = 1, }, /* S0(7) */
{ .start = 74, .num = 1, }, /* S0(6) */
{ .start = 93, .num = 6, }, /* S0(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_8,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 2,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 75, .num = 1, }, /* SB1(1) */
{ .start = 85, .num = 1, }, /* SB1(0) */
{ .start = 56, .num = 1, }, /* S1(7) */
{ .start = 73, .num = 2, }, /* S1(6..5) */
{ .start = 84, .num = 5, }, /* S1(4..0) */
},
},
.encoder_fn = &rogue_encoder_reg_2_8,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 3,
.rangelist = {
.num_ranges = 4,
.ranges = (struct rogue_bitrange []) {
{ .start = 63, .num = 1, }, /* SB2(2) */
{ .start = 71, .num = 2, }, /* SB2(1..0) */
{ .start = 62, .num = 2, }, /* S2(7..6) */
{ .start = 69, .num = 6, }, /* S2(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_8,
},
},
},
[ROGUE_OP_MUL] = {
.num_bytes = 16,
.bytes = (uint8_t []) { 0x28, 0x02, 0x40, 0x80, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0xff, 0xf2, 0xff, 0xff, 0xff },
.num_mappings = 5,
.mappings = (struct rogue_field_mapping []) {
/* Instruction flag mappings. */
{
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
.index = ROGUE_INSTR_FLAG_SAT,
.rangelist = {
.num_ranges = 1,
.ranges = (struct rogue_bitrange []) {
{ .start = 108, .num = 1, },
},
},
.encoder_fn = NULL,
},
{
.type = ROGUE_MAP_TYPE_INSTR_FLAG,
.index = ROGUE_INSTR_FLAG_LP,
.rangelist = {
.num_ranges = 1,
.ranges = (struct rogue_bitrange []) {
{ .start = 109, .num = 1, },
},
},
.encoder_fn = NULL,
},
/* Operand mappings. */
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 0,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 43, .num = 2, }, /* DBn(2..1) */
{ .start = 54, .num = 1, }, /* DBn(0) */
{ .start = 46, .num = 3, }, /* Dn(10..8) */
{ .start = 41, .num = 2, }, /* Dn(7..6) */
{ .start = 53, .num = 6, }, /* Dn(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 1,
.rangelist = {
.num_ranges = 7,
.ranges = (struct rogue_bitrange []) {
{ .start = 75, .num = 1, }, /* SB0(2) */
{ .start = 84, .num = 1, }, /* SB0(1) */
{ .start = 102, .num = 1, }, /* SB0(0) */
{ .start = 79, .num = 3, }, /* S0(10..8) */
{ .start = 73, .num = 1, }, /* S0(7) */
{ .start = 82, .num = 1, }, /* S0(6) */
{ .start = 101, .num = 6, }, /* S0(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 2,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 83, .num = 1, }, /* SB1(1) */
{ .start = 93, .num = 1, }, /* SB1(0) */
{ .start = 72, .num = 1, }, /* S1(7) */
{ .start = 81, .num = 2, }, /* S1(6..5) */
{ .start = 92, .num = 5, }, /* S1(4..0) */
},
},
.encoder_fn = &rogue_encoder_reg_2_8,
},
},
},
[ROGUE_OP_VTXOUT] = {
.num_bytes = 16,
.bytes = (uint8_t []) { 0x48, 0x20, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x30, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff },
.num_mappings = 2,
.mappings = (struct rogue_field_mapping []) {
/* Operand mappings. */
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 0,
.rangelist = {
.num_ranges = 1,
.ranges = (struct rogue_bitrange []) {
{ .start = 103, .num = 8, }, /* Immediate address. */
},
},
.encoder_fn = &rogue_encoder_imm,
},
{
.type = ROGUE_MAP_TYPE_OPERAND,
.index = 1,
.rangelist = {
.num_ranges = 5,
.ranges = (struct rogue_bitrange []) {
{ .start = 83, .num = 2, }, /* SB0(2..1) */
{ .start = 94, .num = 1, }, /* SB0(0) */
{ .start = 74, .num = 3, }, /* S0(10..8) */
{ .start = 81, .num = 2, }, /* S0(7..6) */
{ .start = 93, .num = 6, }, /* S0(5..0) */
},
},
.encoder_fn = &rogue_encoder_reg_3_11,
},
},
},
};
/**
* \brief Applies a boolean flag encoding onto an instruction mask.
*
* \param[in] set Whether to set/unset the flag.
* \param[in] mapping The field mapping to apply.
* \param[in] instr_size The size of the instruction mask in bytes.
* \param[in] instr_bytes The instruction mask.
* \return true if encoding was successful.
*/
static bool rogue_encode_flag(bool set,
const struct rogue_field_mapping *mapping,
size_t instr_size,
uint8_t instr_bytes[instr_size])
{
return rogue_distribute_value((uint64_t)set,
&mapping->rangelist,
instr_size,
instr_bytes);
}
/**
* \brief Applies an operand encoding onto an instruction mask.
*
* \param[in] operand The operand to apply.
* \param[in] mapping The field mapping to apply.
* \param[in] instr_size The size of the instruction mask in bytes.
* \param[in] instr_bytes The instruction mask.
* \return true if encoding was successful.
*/
static bool rogue_encode_operand(const struct rogue_operand *operand,
const struct rogue_field_mapping *mapping,
size_t instr_size,
uint8_t instr_bytes[instr_size])
{
uint64_t value = 0U;
switch (operand->type) {
case ROGUE_OPERAND_TYPE_REG_PIXEL_OUT:
CHECKF(
mapping->encoder_fn(&value,
2,
rogue_encode_reg_bank(operand),
operand->reg.number + ROGUE_PIXEL_OUT_REG_OFFSET),
"Failed to encode pixel output register operand.");
break;
case ROGUE_OPERAND_TYPE_REG_INTERNAL:
CHECKF(
mapping->encoder_fn(&value,
2,
rogue_encode_reg_bank(operand),
operand->reg.number + ROGUE_INTERNAL_REG_OFFSET),
"Failed to encode internal register operand.");
break;
case ROGUE_OPERAND_TYPE_REG_TEMP:
case ROGUE_OPERAND_TYPE_REG_COEFF:
case ROGUE_OPERAND_TYPE_REG_CONST:
case ROGUE_OPERAND_TYPE_REG_SHARED:
case ROGUE_OPERAND_TYPE_REG_VERTEX_IN:
CHECKF(mapping->encoder_fn(&value,
2,
rogue_encode_reg_bank(operand),
operand->reg.number),
"Failed to encode register operand.");
break;
case ROGUE_OPERAND_TYPE_IMMEDIATE:
CHECKF(mapping->encoder_fn(&value, 1, operand->immediate.value),
"Failed to encode immediate operand.");
break;
case ROGUE_OPERAND_TYPE_DRC:
CHECKF(mapping->encoder_fn(&value, 1, (uint64_t)operand->drc.number),
"Failed to encode DRC operand.");
break;
default:
return false;
}
CHECKF(rogue_distribute_value(value,
&mapping->rangelist,
instr_size,
instr_bytes),
"Failed to distribute value.");
return true;
}
/**
* \brief Applies operand and flag encodings to the base instruction bytes, then
* writes the result to file pointer "fp".
*
* \param[in] instr The instruction to be encoded.
* \param[in] fp The file pointer.
* \return true if encoding was successful.
*/
bool rogue_encode_instr(const struct rogue_instr *instr, FILE *fp)
{
const struct rogue_instr_encoding *instr_encoding;
size_t instr_size;
uint8_t instr_bytes[ROGUE_MAX_INSTR_BYTES];
ASSERT_OPCODE_RANGE(instr->opcode);
instr_encoding = &instr_encodings[instr->opcode];
/* Set up base instruction bytes. */
instr_size = instr_encoding->num_bytes;
assert(instr_size <= ARRAY_SIZE(instr_bytes));
memcpy(instr_bytes, instr_encoding->bytes, instr_size);
/* Encode the operands and flags. */
for (size_t u = 0U; u < instr_encoding->num_mappings; ++u) {
const struct rogue_field_mapping *mapping = &instr_encoding->mappings[u];
switch (mapping->type) {
case ROGUE_MAP_TYPE_INSTR_FLAG: {
uint64_t flag = rogue_onehot(mapping->index);
CHECKF(rogue_encode_flag(!!(instr->flags & flag),
mapping,
instr_size,
instr_bytes),
"Failed to encode instruction flag.");
break;
}
case ROGUE_MAP_TYPE_OPERAND_FLAG:
return false;
case ROGUE_MAP_TYPE_OPERAND: {
size_t operand_index = mapping->index;
CHECKF(rogue_encode_operand(&instr->operands[operand_index],
mapping,
instr_size,
instr_bytes),
"Failed to encode instruction operand.");
break;
}
default:
return false;
}
}
CHECKF(fwrite(instr_bytes, 1, instr_size, fp) == instr_size,
"Failed to write encoded instruction bytes.");
fflush(fp);
return true;
}
/**
* \brief Encodes each instruction in "shader", writing the output to "fp".
*
* \param[in] shader The shader to be encoded.
* \param[in] fp The file pointer.
* \return true if encoding was successful.
*/
bool rogue_encode_shader(const struct rogue_shader *shader, FILE *fp)
{
long bytes_written;
/* Encode each instruction. */
foreach_instr (instr, &shader->instr_list)
CHECKF(rogue_encode_instr(instr, fp), "Failed to encode instruction.");
/* Pad end of shader if required. */
bytes_written = ftell(fp);
if (bytes_written <= 0)
return false;
/* FIXME: Figure out the define for alignment of 16. */
for (size_t u = 0; u < (bytes_written % 16); ++u)
fputc(0xff, fp);
return true;
}

View File

@ -0,0 +1,41 @@
/*
* 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 ROGUE_ENCODE_H
#define ROGUE_ENCODE_H
#include <stdbool.h>
#include <stdio.h>
#include "util/macros.h"
struct rogue_instr;
struct rogue_shader;
PUBLIC
bool rogue_encode_instr(const struct rogue_instr *instr, FILE *fp);
PUBLIC
bool rogue_encode_shader(const struct rogue_shader *shader, FILE *fp);
#endif /* ROGUE_ENCODE_H */

View File

@ -0,0 +1,164 @@
/*
* 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 <assert.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "rogue_encoders.h"
#include "rogue_util.h"
#include "util/bitscan.h"
/**
* \brief Passes the input value through unchanged.
*
* \param[in] value Pointer to the destination value.
* \param[in] inputs Number of inputs provided.
* \param[in] ... Input value(s).
* \return true if encoding was successful.
*/
bool rogue_encoder_pass(uint64_t *value, size_t inputs, ...)
{
va_list args;
assert(inputs == 1);
va_start(args, inputs);
*value = va_arg(args, uint64_t);
va_end(args);
return true;
}
/**
* \brief Encoder for DRC values.
*
* \sa #rogue_encoder_pass()
*
* \param[in] value Pointer to the destination value.
* \param[in] inputs Number of inputs provided.
* \param[in] ... Input value(s).
* \return true if encoding was successful.
*/
bool rogue_encoder_drc(uint64_t *value, size_t inputs, ...)
__attribute__((alias("rogue_encoder_pass")));
/**
* \brief Encoder for immediate values.
*
* \sa #rogue_encoder_pass()
*
* \param[in] value Pointer to the destination value.
* \param[in] inputs Number of inputs provided.
* \param[in] ... Input value(s).
* \return true if encoding was successful.
*/
bool rogue_encoder_imm(uint64_t *value, size_t inputs, ...)
__attribute__((alias("rogue_encoder_pass")));
/**
* \brief Encodes input ranges {1..15 -> 1-15} and {16 -> 0}.
*
* The input should be in the range 1-16; the function represents 1-15 normally
* and represents 16 by 0.
*
* \param[in] value Pointer to the destination value.
* \param[in] inputs Number of inputs provided.
* \param[in] ... Input value(s).
* \return true if encoding was successful.
*/
bool rogue_encoder_ls_1_16(uint64_t *value, size_t inputs, ...)
{
va_list args;
uint64_t input;
assert(inputs == 1);
va_start(args, inputs);
input = va_arg(args, uint64_t);
va_end(args);
/* Validate the input range. */
if (!input || input > 16) {
*value = UINT64_MAX;
return false;
}
*value = input % 16;
return true;
}
/**
* \brief Encodes registers according to the number of bits needed to specify
* the bank number and register number.
*
* \param[in] value Pointer to the destination value.
* \param[in] bank_bits The number of bits used to represent the register bank.
* \param[in] bank the register bank
* \param[in] num_bits The number of bits used to represent the register number.
* \param[in] num The register number.
* \return true if encoding was successful.
*/
static bool rogue_encoder_reg(uint64_t *value,
size_t bank_bits,
size_t bank,
size_t num_bits,
size_t num)
{
/* Verify "num" fits in "num_bits" and "bank" fits in "bank_bits". */
assert(util_last_bit64(num) <= num_bits);
assert(util_last_bit64(bank) <= bank_bits);
*value = num;
*value |= (bank << num_bits);
return true;
}
/**
* \brief Macro to define the rogue_encoder_reg variants.
*/
#define ROGUE_ENCODER_REG_VARIANT(bank_bits, num_bits) \
bool rogue_encoder_reg_##bank_bits##_##num_bits(uint64_t *value, \
size_t inputs, \
...) \
{ \
va_list args; \
size_t bank; \
size_t num; \
assert(inputs == 2); \
va_start(args, inputs); \
bank = va_arg(args, size_t); \
num = va_arg(args, size_t); \
va_end(args); \
return rogue_encoder_reg(value, bank_bits, bank, num_bits, num); \
}
ROGUE_ENCODER_REG_VARIANT(2, 8)
ROGUE_ENCODER_REG_VARIANT(3, 8)
ROGUE_ENCODER_REG_VARIANT(3, 11)
#undef ROGUE_ENCODER_REG_VARIANT

View File

@ -0,0 +1,53 @@
/*
* 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 ROGUE_ENCODERS_H
#define ROGUE_ENCODERS_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "util/macros.h"
/* Returns false if input was invalid. */
typedef bool (*field_encoder_t)(uint64_t *value, size_t inputs, ...);
bool rogue_encoder_pass(uint64_t *value, size_t inputs, ...);
bool rogue_encoder_drc(uint64_t *value, size_t inputs, ...);
bool rogue_encoder_imm(uint64_t *value, size_t inputs, ...);
bool rogue_encoder_ls_1_16(uint64_t *value, size_t inputs, ...);
/**
* \brief Macro to declare the rogue_encoder_reg variants.
*/
#define ROGUE_ENCODER_REG_VARIANT(bank_bits, num_bits) \
bool rogue_encoder_reg_##bank_bits##_##num_bits(uint64_t *value, \
size_t inputs, \
...);
ROGUE_ENCODER_REG_VARIANT(2, 8)
ROGUE_ENCODER_REG_VARIANT(3, 8)
ROGUE_ENCODER_REG_VARIANT(3, 11)
#undef ROGUE_ENCODER_REG_VARIANT
#endif /* ROGUE_ENCODERS_H */

View File

@ -0,0 +1,227 @@
/*
* 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 <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "rogue_instr.h"
#include "rogue_operand.h"
#include "rogue_util.h"
#include "util/ralloc.h"
/**
* \file rogue_instr.c
*
* \brief Contains functions to manipulate Rogue instructions.
*/
/* clang-format off */
static const size_t instr_operand_count[ROGUE_OP_COUNT] = {
[ROGUE_OP_NOP] = 0,
[ROGUE_OP_END_FRAG] = 0,
[ROGUE_OP_END_VERT] = 0,
[ROGUE_OP_WDF] = 1,
[ROGUE_OP_PIX_ITER_W] = 5,
[ROGUE_OP_MAX] = 3,
[ROGUE_OP_MIN] = 3,
[ROGUE_OP_PACK_U8888] = 2,
[ROGUE_OP_MOV] = 2,
[ROGUE_OP_MOV_IMM] = 2,
[ROGUE_OP_FMA] = 4,
[ROGUE_OP_MUL] = 3,
[ROGUE_OP_VTXOUT] = 2,
};
/* clang-format on */
/**
* \brief Returns the number of operands an instruction takes.
*
* \param[in] opcode The instruction opcode.
* \return The number of operands.
*/
static inline size_t rogue_instr_num_operands(enum rogue_opcode opcode)
{
ASSERT_OPCODE_RANGE(opcode);
return instr_operand_count[opcode];
}
/**
* \brief Allocates and sets up a Rogue instruction.
*
* \param[in] mem_ctx The memory context for the instruction.
* \param[in] opcode The instruction opcode.
* \return A rogue_instr* if successful, or NULL if unsuccessful.
*/
struct rogue_instr *rogue_instr_create(void *mem_ctx, enum rogue_opcode opcode)
{
struct rogue_instr *instr;
ASSERT_OPCODE_RANGE(opcode);
instr = rzalloc_size(mem_ctx, sizeof(*instr));
if (!instr)
return NULL;
instr->opcode = opcode;
instr->num_operands = rogue_instr_num_operands(opcode);
/* Allocate space for operand array. */
if (instr->num_operands) {
instr->operands = rzalloc_array_size(instr,
sizeof(*instr->operands),
instr->num_operands);
if (!instr->operands) {
ralloc_free(instr);
return NULL;
}
}
return instr;
}
/**
* \brief Sets a Rogue instruction flag.
*
* \param[in] instr The instruction.
* \param[in] flag The flag to set.
* \return true if valid, otherwise false.
*/
bool rogue_instr_set_flag(struct rogue_instr *instr, enum rogue_instr_flag flag)
{
instr->flags = ROH(flag);
return true;
}
/**
* \brief Sets a Rogue instruction operand to an immediate value.
*
* \param[in] instr The instruction.
* \param[in] index The operand index.
* \param[in] value The value to set.
* \return true if valid, otherwise false.
*/
bool rogue_instr_set_operand_imm(struct rogue_instr *instr,
size_t index,
uint64_t value)
{
ASSERT_INSTR_OPERAND_INDEX(instr, index);
instr->operands[index].type = ROGUE_OPERAND_TYPE_IMMEDIATE;
instr->operands[index].immediate.value = value;
return true;
}
/**
* \brief Sets a Rogue instruction operand to a DRC number.
*
* \param[in] instr The instruction.
* \param[in] index The operand index.
* \param[in] number The DRC number to set.
* \return true if valid, otherwise false.
*/
bool rogue_instr_set_operand_drc(struct rogue_instr *instr,
size_t index,
size_t number)
{
ASSERT_INSTR_OPERAND_INDEX(instr, index);
instr->operands[index].type = ROGUE_OPERAND_TYPE_DRC;
instr->operands[index].drc.number = number;
return true;
}
/**
* \brief Sets a Rogue instruction operand to a register.
*
* \param[in] instr The instruction.
* \param[in] index The operand index.
* \param[in] type The register type to set.
* \param[in] number The register number to set.
* \return true if valid, otherwise false.
*/
bool rogue_instr_set_operand_reg(struct rogue_instr *instr,
size_t index,
enum rogue_operand_type type,
size_t number)
{
ASSERT_INSTR_OPERAND_INDEX(instr, index);
ASSERT_OPERAND_REG(type);
instr->operands[index].type = type;
instr->operands[index].reg.number = number;
return true;
}
/**
* \brief Sets a Rogue instruction operand to a virtual register.
*
* \param[in] instr The instruction.
* \param[in] index The operand index.
* \param[in] number The register number to set.
* \return true if valid, otherwise false.
*/
bool rogue_instr_set_operand_vreg(struct rogue_instr *instr,
size_t index,
size_t number)
{
ASSERT_INSTR_OPERAND_INDEX(instr, index);
instr->operands[index].type = ROGUE_OPERAND_TYPE_VREG;
instr->operands[index].vreg.number = number;
instr->operands[index].vreg.is_vector = false;
return true;
}
/**
* \brief Sets a Rogue instruction operand to a virtual register
* that is a vector type.
*
* \param[in] instr The instruction.
* \param[in] index The operand index.
* \param[in] component The vector component.
* \param[in] number The register number to set.
* \return true if valid, otherwise false.
*/
bool rogue_instr_set_operand_vreg_vec(struct rogue_instr *instr,
size_t index,
size_t component,
size_t number)
{
ASSERT_INSTR_OPERAND_INDEX(instr, index);
instr->operands[index].type = ROGUE_OPERAND_TYPE_VREG;
instr->operands[index].vreg.number = number;
instr->operands[index].vreg.is_vector = true;
instr->operands[index].vreg.component = component;
return true;
}

View File

@ -0,0 +1,113 @@
/*
* 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 ROGUE_INSTR_H
#define ROGUE_INSTR_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "rogue_operand.h"
#include "util/list.h"
/**
* \brief Instruction opcodes.
*/
enum rogue_opcode {
ROGUE_OP_NOP = 0, /** No-operation. */
ROGUE_OP_END_FRAG, /** Fragment shader end. */
ROGUE_OP_END_VERT, /** Vertex shader end. */
ROGUE_OP_WDF, /** Write data fence. */
ROGUE_OP_PIX_ITER_W, /** Pixel iteration with coefficients. */
ROGUE_OP_MAX, /** Returns the largest out of two floats. */
ROGUE_OP_MIN, /** Returns the smallest out of two floats. */
ROGUE_OP_PACK_U8888, /** Scales the four input floats:
* [0.0f, 0.1f] -> [0, 255] and packs them
* into a 32-bit unsigned integer.
*/
ROGUE_OP_MOV, /** Register move instruction. */
ROGUE_OP_MOV_IMM, /** Move immediate instruction. */
ROGUE_OP_FMA, /** Fused-multiply-add (float). */
ROGUE_OP_MUL, /** Multiply (float). */
ROGUE_OP_VTXOUT, /** Writes the input register
* to the given vertex output index.
*/
ROGUE_OP_COUNT,
};
/**
* \brief Instruction flags.
*/
enum rogue_instr_flag {
ROGUE_INSTR_FLAG_SAT = 0, /** Saturate values to 0.0 ... 1.0. */
ROGUE_INSTR_FLAG_LP, /** Low-precision modifier. */
ROGUE_INSTR_FLAG_OLCHK, /** Overlap check (pixel write). */
ROGUE_INSTR_FLAG_COUNT,
};
/**
* \brief Instruction description.
*/
struct rogue_instr {
enum rogue_opcode opcode;
size_t num_operands;
struct rogue_operand *operands;
uint64_t flags; /** A mask of #rogue_instr_flag values. */
struct list_head node; /** Linked list node. */
};
struct rogue_instr *rogue_instr_create(void *mem_ctx, enum rogue_opcode opcode);
bool rogue_instr_set_flag(struct rogue_instr *instr,
enum rogue_instr_flag flag);
bool rogue_instr_set_operand_imm(struct rogue_instr *instr,
size_t index,
uint64_t value);
bool rogue_instr_set_operand_drc(struct rogue_instr *instr,
size_t index,
size_t number);
bool rogue_instr_set_operand_reg(struct rogue_instr *instr,
size_t index,
enum rogue_operand_type type,
size_t number);
bool rogue_instr_set_operand_vreg(struct rogue_instr *instr,
size_t index,
size_t number);
bool rogue_instr_set_operand_vreg_vec(struct rogue_instr *instr,
size_t index,
size_t component,
size_t number);
#endif /* ROGUE_INSTR_H */

View File

@ -0,0 +1,191 @@
/*
* 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 "compiler/spirv/nir_spirv.h"
#include "nir/nir.h"
#include "nir/nir_schedule.h"
#include "rogue_nir.h"
#include "rogue_operand.h"
/**
* \file rogue_nir.c
*
* \brief Contains NIR-specific functions.
*/
/**
* \brief SPIR-V to NIR compilation options.
*/
static const struct spirv_to_nir_options spirv_options = {
.environment = NIR_SPIRV_VULKAN,
/* Buffer address: (descriptor_set, binding), offset. */
.ubo_addr_format = nir_address_format_vec2_index_32bit_offset,
};
static const nir_shader_compiler_options nir_options = {
.lower_fsat = true,
.fuse_ffma32 = true,
};
const struct spirv_to_nir_options *
rogue_get_spirv_options(const struct rogue_compiler *compiler)
{
return &spirv_options;
}
const nir_shader_compiler_options *
rogue_get_compiler_options(const struct rogue_compiler *compiler)
{
return &nir_options;
}
static int rogue_glsl_type_size(const struct glsl_type *type, bool bindless)
{
return glsl_count_attribute_slots(type, false);
}
/**
* \brief Applies optimizations and passes required to lower the NIR shader into
* a form suitable for lowering to Rogue IR.
*
* \param[in] ctx Shared multi-stage build context.
* \param[in] shader Rogue shader.
* \param[in] stage Shader stage.
* \return true if successful, otherwise false.
*/
bool rogue_nir_passes(struct rogue_build_ctx *ctx,
nir_shader *nir,
gl_shader_stage stage)
{
bool progress;
nir_validate_shader(nir, "after spirv_to_nir");
/* Splitting. */
NIR_PASS_V(nir, nir_split_var_copies);
NIR_PASS_V(nir, nir_split_per_member_structs);
/* Ensure fs outputs are in the [0.0f...1.0f] range. */
NIR_PASS_V(nir, nir_lower_clamp_color_outputs);
/* Replace references to I/O variables with intrinsics. */
NIR_PASS_V(nir,
nir_lower_io,
nir_var_shader_in | nir_var_shader_out,
rogue_glsl_type_size,
(nir_lower_io_options)0);
/* Load inputs to scalars (single registers later). */
NIR_PASS_V(nir, nir_lower_io_to_scalar, nir_var_shader_in);
/* Optimize GL access qualifiers. */
const nir_opt_access_options opt_access_options = {
.is_vulkan = true,
.infer_non_readable = true,
};
NIR_PASS_V(nir, nir_opt_access, &opt_access_options);
/* Apply PFO code to the fragment shader output. */
if (nir->info.stage == MESA_SHADER_FRAGMENT)
NIR_PASS_V(nir, rogue_nir_pfo);
/* Load outputs to scalars (single registers later). */
NIR_PASS_V(nir, nir_lower_io_to_scalar, nir_var_shader_out);
/* Lower ALU operations to scalars. */
NIR_PASS_V(nir, nir_lower_alu_to_scalar, NULL, NULL);
/* Algebraic opts. */
do {
progress = false;
NIR_PASS(progress, nir, nir_copy_prop);
NIR_PASS(progress, nir, nir_opt_cse);
NIR_PASS(progress, nir, nir_opt_algebraic);
NIR_PASS(progress, nir, nir_opt_constant_folding);
NIR_PASS(progress, nir, nir_opt_dce);
NIR_PASS_V(nir, nir_opt_gcm, false);
} while (progress);
/* Additional I/O lowering. */
NIR_PASS_V(nir,
nir_lower_explicit_io,
nir_var_mem_ubo,
spirv_options.ubo_addr_format);
NIR_PASS_V(nir, rogue_nir_lower_io, NULL);
/* Late algebraic opts. */
do {
progress = false;
NIR_PASS(progress, nir, nir_opt_algebraic_late);
NIR_PASS_V(nir, nir_opt_constant_folding);
NIR_PASS_V(nir, nir_copy_prop);
NIR_PASS_V(nir, nir_opt_dce);
NIR_PASS_V(nir, nir_opt_cse);
} while (progress);
/* Replace SSA constant references with a register that loads the value. */
NIR_PASS_V(nir, rogue_nir_constreg);
/* Remove unused constant registers. */
NIR_PASS_V(nir, nir_opt_dce);
/* Move loads to just before they're needed. */
NIR_PASS_V(nir, nir_opt_move, nir_move_load_ubo | nir_move_load_input);
/* Convert vecNs to movs so we can sequentially allocate them later. */
NIR_PASS_V(nir, nir_lower_vec_to_movs, NULL, NULL);
/* Out of SSA pass. */
NIR_PASS_V(nir, nir_convert_from_ssa, false);
/* TODO: Re-enable scheduling after register pressure tweaks. */
#if 0
/* Instruction scheduling. */
struct nir_schedule_options schedule_options = {
.threshold = ROGUE_MAX_REG_TEMP / 2,
};
NIR_PASS_V(nir, nir_schedule, &schedule_options);
#endif
/* Assign I/O locations. */
nir_assign_io_var_locations(nir,
nir_var_shader_in,
&nir->num_inputs,
nir->info.stage);
nir_assign_io_var_locations(nir,
nir_var_shader_out,
&nir->num_outputs,
nir->info.stage);
/* Gather info into nir shader struct. */
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
/* Clean-up after passes. */
nir_sweep(nir);
nir_validate_shader(nir, "after passes");
return true;
}

View File

@ -0,0 +1,52 @@
/*
* 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 ROGUE_NIR_H
#define ROGUE_NIR_H
#include "compiler/shader_enums.h"
#include "nir/nir.h"
#include "util/macros.h"
struct rogue_build_ctx;
struct rogue_compiler;
struct spirv_to_nir_options;
PUBLIC
const struct spirv_to_nir_options *
rogue_get_spirv_options(const struct rogue_compiler *compiler);
PUBLIC
const nir_shader_compiler_options *
rogue_get_compiler_options(const struct rogue_compiler *compiler);
bool rogue_nir_passes(struct rogue_build_ctx *ctx,
nir_shader *nir,
gl_shader_stage stage);
/* Custom passes. */
void rogue_nir_pfo(nir_shader *shader);
void rogue_nir_constreg(nir_shader *shader);
bool rogue_nir_lower_io(nir_shader *shader, void *layout);
#endif /* ROGUE_NIR_H */

View File

@ -0,0 +1,149 @@
/*
* 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 ROGUE_NIR_HELPERS_H
#define ROGUE_NIR_HELPERS_H
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include "nir/nir.h"
#include "util/bitscan.h"
/**
* \file rogue_nir.c
*
* \brief Contains various NIR helper functions.
*/
static inline unsigned nir_alu_dest_regindex(const nir_alu_instr *alu)
{
assert(!alu->dest.dest.is_ssa);
return alu->dest.dest.reg.reg->index;
}
static inline unsigned nir_alu_dest_comp(const nir_alu_instr *alu)
{
assert(!alu->dest.dest.is_ssa);
assert(util_is_power_of_two_nonzero(alu->dest.write_mask));
return ffs(alu->dest.write_mask) - 1;
}
static inline unsigned nir_alu_src_regindex(const nir_alu_instr *alu,
size_t src)
{
assert(src < nir_op_infos[alu->op].num_inputs);
assert(!alu->src[src].src.is_ssa);
return alu->src[src].src.reg.reg->index;
}
static inline uint32_t nir_alu_src_const(const nir_alu_instr *alu, size_t src)
{
assert(src < nir_op_infos[alu->op].num_inputs);
assert(alu->src[src].src.is_ssa);
nir_const_value *const_value = nir_src_as_const_value(alu->src[src].src);
return nir_const_value_as_uint(*const_value, 32);
}
static inline bool nir_alu_src_is_const(const nir_alu_instr *alu, size_t src)
{
assert(src < nir_op_infos[alu->op].num_inputs);
if (!alu->src[src].src.is_ssa)
return false;
assert(alu->src[src].src.ssa->parent_instr);
return (alu->src[src].src.ssa->parent_instr->type ==
nir_instr_type_load_const);
}
static inline unsigned nir_intr_dest_regindex(const nir_intrinsic_instr *intr)
{
assert(!intr->dest.is_ssa);
return intr->dest.reg.reg->index;
}
static inline unsigned nir_intr_src_regindex(const nir_intrinsic_instr *intr,
size_t src)
{
assert(src < nir_intrinsic_infos[intr->intrinsic].num_srcs);
assert(!intr->src[src].is_ssa);
return intr->src[src].reg.reg->index;
}
static inline uint32_t nir_intr_src_const(const nir_intrinsic_instr *intr,
size_t src)
{
assert(src < nir_intrinsic_infos[intr->intrinsic].num_srcs);
assert(intr->src[src].is_ssa);
nir_const_value *const_value = nir_src_as_const_value(intr->src[src]);
return nir_const_value_as_uint(*const_value, 32);
}
static inline uint32_t nir_intr_src_comp_const(const nir_intrinsic_instr *intr,
size_t src,
size_t comp)
{
assert(src < nir_intrinsic_infos[intr->intrinsic].num_srcs);
assert(intr->src[src].is_ssa);
assert(comp < nir_src_num_components(intr->src[src]));
return nir_src_comp_as_uint(intr->src[src], comp);
}
static inline bool nir_intr_src_is_const(const nir_intrinsic_instr *intr,
size_t src)
{
assert(src < nir_intrinsic_infos[intr->intrinsic].num_srcs);
if (!intr->src[src].is_ssa)
return false;
assert(intr->src[src].ssa->parent_instr);
return (intr->src[src].ssa->parent_instr->type == nir_instr_type_load_const);
}
static inline size_t nir_count_variables_with_modes(const nir_shader *nir,
nir_variable_mode mode)
{
size_t count = 0;
nir_foreach_variable_with_modes (var, nir, mode)
++count;
return count;
}
#endif /* ROGUE_NIR_HELPERS_H */

View File

@ -0,0 +1,30 @@
/*
* 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 "rogue_operand.h"
/**
* \file rogue_operand.c
*
* \brief Contains functions to manipulate Rogue instruction operands.
*/

View File

@ -0,0 +1,158 @@
/*
* 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 ROGUE_OPERAND_H
#define ROGUE_OPERAND_H
#include <stddef.h>
#include <stdint.h>
#include "rogue_util.h"
#include "util/macros.h"
/* Register-related defines. */
/* Total max number of registers per class
* (instances > ROGUE_MAX_REG_INDEX addressable via indexing only).
*/
#define ROGUE_MAX_REG_TEMP 248
#define ROGUE_MAX_REG_COEFF 4096
#define ROGUE_MAX_REG_CONST 240
#define ROGUE_MAX_REG_SHARED 4096
#define ROGUE_MAX_REG_PIXEL_OUT 8
#define ROGUE_MAX_REG_VERTEX_IN 248
#define ROGUE_MAX_REG_INTERNAL 8
/* Maximum register index via offset encoding. */
#define ROGUE_MAX_REG_INDEX 256
/* Pixel-out register offset. */
#define ROGUE_PIXEL_OUT_REG_OFFSET 32
/* Internal register offset. */
#define ROGUE_INTERNAL_REG_OFFSET 36
/* Coefficient registers are typically used in groups of 4. */
#define ROGUE_COEFF_ALIGN 4
/* Defines for other operand types. */
/* Available dependent read counters. */
#define ROGUE_NUM_DRCS 2
/* Maximum number of vertex outputs. */
#define ROGUE_MAX_VERTEX_OUTPUTS 256
/* All components of an emulated vec4 register group. */
#define ROGUE_COMPONENT_ALL (~0)
/**
* \brief Operand types.
*/
enum rogue_operand_type {
/* Register operands. */
ROGUE_OPERAND_TYPE_REG_TEMP = 0, /** Temporary register. */
ROGUE_OPERAND_TYPE_REG_COEFF, /** Coefficient register. */
ROGUE_OPERAND_TYPE_REG_CONST, /** Constant register. */
ROGUE_OPERAND_TYPE_REG_SHARED, /** Shared register. */
ROGUE_OPERAND_TYPE_REG_PIXEL_OUT, /** Pixel output register. */
ROGUE_OPERAND_TYPE_REG_VERTEX_IN, /** Vertex input register. */
ROGUE_OPERAND_TYPE_REG_INTERNAL, /** Internal register. */
ROGUE_OPERAND_TYPE_REG_MAX = ROGUE_OPERAND_TYPE_REG_INTERNAL,
ROGUE_OPERAND_TYPE_IMMEDIATE, /** Immediate value. */
ROGUE_OPERAND_TYPE_DRC, /** Dependent read counter. */
ROGUE_OPERAND_TYPE_VREG, /** Virtual register (pre-regalloc). */
ROGUE_OPERAND_TYPE_COUNT,
};
/* clang-format off */
#define ROGUE_NUM_REG_TYPES (ROGUE_OPERAND_TYPE_REG_MAX + 1)
/**
* \brief A bitmask for any register operand type.
*/
#define ROGUE_MASK_ANY_REG \
ROH(ROGUE_OPERAND_TYPE_REG_TEMP) | \
ROH(ROGUE_OPERAND_TYPE_REG_COEFF) | \
ROH(ROGUE_OPERAND_TYPE_REG_CONST) | \
ROH(ROGUE_OPERAND_TYPE_REG_PIXEL_OUT) | \
ROH(ROGUE_OPERAND_TYPE_REG_VERTEX_IN) | \
ROH(ROGUE_OPERAND_TYPE_REG_SHARED) | \
ROH(ROGUE_OPERAND_TYPE_REG_INTERNAL)
/* clang-format on */
/**
* \brief Operand description.
*/
struct rogue_operand {
enum rogue_operand_type type;
union {
struct {
uint64_t value;
} immediate;
struct {
size_t number;
} drc;
struct {
size_t number;
} reg;
struct {
size_t number;
bool is_vector;
size_t component;
} vreg;
};
};
/**
* \brief Register access flags.
*/
enum rogue_register_access {
ROGUE_REG_ACCESS_READ = BITFIELD_BIT(0U), /** Read-only. */
ROGUE_REG_ACCESS_WRITE = BITFIELD_BIT(1U), /* Write-only. */
ROGUE_REG_ACCESS_RW = ROGUE_REG_ACCESS_READ |
ROGUE_REG_ACCESS_WRITE, /** Read/write. */
};
/**
* \brief Register modifier flags.
*/
enum rogue_register_modifier {
ROGUE_REG_MOD_NONE = 0U,
ROGUE_REG_MOD_IDX = BITFIELD_BIT(0U), /** Index modifier. */
ROGUE_REG_MOD_DIM = BITFIELD_BIT(1U), /** Dimension modifier. */
ROGUE_REG_MOD_ALL = ROGUE_REG_MOD_IDX | ROGUE_REG_MOD_DIM,
};
#endif /* ROGUE_OPERAND_H */

View File

@ -0,0 +1,313 @@
/*
* 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 <stddef.h>
#include <stdint.h>
#include "rogue_operand.h"
#include "rogue_regalloc.h"
#include "rogue_shader.h"
#include "rogue_util.h"
#include "util/hash_table.h"
#include "util/list.h"
#include "util/ralloc.h"
#include "util/register_allocate.h"
#include "util/u_dynarray.h"
/**
* \file rogue_regalloc.c
*
* \brief Contains register allocation helper functions.
*/
/**
* \brief Sets up the register data with the classes to be used for allocation.
*
* \param[in] data The register data array.
*/
static void
rogue_reg_data_init(struct rogue_reg_data data[static ROGUE_REG_CLASS_COUNT])
{
data[ROGUE_REG_CLASS_TEMP].type = ROGUE_OPERAND_TYPE_REG_TEMP;
data[ROGUE_REG_CLASS_TEMP].count = ROGUE_MAX_REG_TEMP;
data[ROGUE_REG_CLASS_TEMP].stride = 1;
data[ROGUE_REG_CLASS_VEC4].type = ROGUE_OPERAND_TYPE_REG_INTERNAL;
data[ROGUE_REG_CLASS_VEC4].count = ROGUE_MAX_REG_INTERNAL;
data[ROGUE_REG_CLASS_VEC4].stride = 4;
}
/**
* \brief Initializes the Rogue register allocation context.
*
* \param[in] mem_ctx The memory context for the ra context.
* \return A rogue_ra * if successful, or NULL if unsuccessful.
*/
struct rogue_ra *rogue_ra_init(void *mem_ctx)
{
struct rogue_ra *ra;
size_t total_regs = 0;
ra = rzalloc_size(mem_ctx, sizeof(*ra));
if (!ra)
return NULL;
/* Initialize the register class data. */
rogue_reg_data_init(ra->reg_data);
/* Count up the registers classes and set up their offsets.
*
* The physical register numbers are sequential, even if the
* registers are from different banks, so keeping track of
* the offset means we can get the true physical register
* number back after allocation.
*/
for (size_t u = 0; u < ARRAY_SIZE(ra->reg_data); ++u) {
ra->reg_data[u].offset = total_regs;
total_regs += ra->reg_data[u].count;
}
/* Create a register set for allocation. */
ra->regs = ra_alloc_reg_set(ra, total_regs, true);
if (!ra->regs) {
ralloc_free(ra);
return NULL;
}
/* Create the register class for the temps. */
ra->reg_data[ROGUE_REG_CLASS_TEMP].class =
ra_alloc_contig_reg_class(ra->regs, 1);
/* Create the register class for vec4 registers
* (using the internal register bank).
*/
ra->reg_data[ROGUE_REG_CLASS_VEC4].class =
ra_alloc_contig_reg_class(ra->regs, 4);
/* Populate the register classes. */
for (size_t u = 0; u < ARRAY_SIZE(ra->reg_data); ++u) {
struct rogue_reg_data *reg_data = &ra->reg_data[u];
size_t offset = reg_data->offset;
size_t end = reg_data->offset + reg_data->count;
size_t stride = reg_data->stride;
for (size_t r = offset; r < end; r += stride)
ra_class_add_reg(reg_data->class, r);
}
/* Finalize the set (no early conflicts passed along for now). */
ra_set_finalize(ra->regs, NULL);
return ra;
}
/**
* \brief The range for which a (virtual) register is live, and its references.
*/
struct live_range {
size_t start;
size_t end;
enum rogue_reg_class class;
struct util_dynarray operand_refs;
};
/**
* \brief Performs register allocation.
*
* \param[in] instr_list A linked list of instructions with virtual registers to
* be allocated.
* \param[in] ra The register allocation context.
*/
bool rogue_ra_alloc(struct list_head *instr_list,
struct rogue_ra *ra,
size_t *temps_used,
size_t *internals_used)
{
/* Used for ra_alloc_interference_graph() as it doesn't
* like having gaps (e.g. with v0, v2 count = 3 rather
* than 2).
*/
size_t max_vreg = 0;
struct hash_table *reg_ht =
_mesa_hash_table_create(ra, _mesa_hash_uint, _mesa_key_uint_equal);
if (!reg_ht)
return false;
/* Calculate live ranges for virtual registers. */
size_t ip = 0U; /* "Instruction pointer". */
foreach_instr (instr, instr_list) {
for (size_t u = 0U; u < instr->num_operands; ++u) {
struct hash_entry *entry;
struct live_range *range;
if (instr->operands[u].type != ROGUE_OPERAND_TYPE_VREG)
continue;
entry =
_mesa_hash_table_search(reg_ht, &instr->operands[u].vreg.number);
if (!entry) {
/* First use of this virtual register: initialize live range. */
/* TODO: Error handling. */
range = rzalloc_size(reg_ht, sizeof(*range));
range->start = ip;
range->end = ip;
range->class = instr->operands[u].vreg.is_vector
? ROGUE_REG_CLASS_VEC4
: ROGUE_REG_CLASS_TEMP;
entry = _mesa_hash_table_insert(reg_ht,
&instr->operands[u].vreg.number,
range);
max_vreg = MAX2(max_vreg, instr->operands[u].vreg.number);
util_dynarray_init(&range->operand_refs, range);
} else {
/* Subsequent uses: update live range end. */
range = entry->data;
range->end = MAX2(range->end, ip);
assert(range->class == (instr->operands[u].vreg.is_vector
? ROGUE_REG_CLASS_VEC4
: ROGUE_REG_CLASS_TEMP));
}
/* Save a reference to the operand. */
util_dynarray_append(&range->operand_refs,
struct rogue_operand *,
&instr->operands[u]);
}
++ip;
}
/* Initialize the interference graph. */
struct ra_graph *g = ra_alloc_interference_graph(ra->regs, max_vreg + 1);
/* Set each virtual register to the appropriate class. */
hash_table_foreach (reg_ht, entry) {
const uint32_t *vreg = entry->key;
struct live_range *range = entry->data;
struct ra_class *class = ra->reg_data[range->class].class;
ra_set_node_class(g, *vreg, class);
/* TODO: ra_set_node_spill_cost(g, *vreg, cost); */
}
/* Build interference graph from overlapping live ranges. */
hash_table_foreach (reg_ht, entry_first) {
const uint32_t *vreg_first = entry_first->key;
struct live_range *range_first = entry_first->data;
hash_table_foreach (reg_ht, entry_second) {
const uint32_t *vreg_second = entry_second->key;
struct live_range *range_second = entry_second->data;
if (*vreg_first == *vreg_second)
continue;
/* If the live ranges overlap, those register nodes interfere. */
if (!(range_first->start >= range_second->end ||
range_second->start >= range_first->end)) {
ra_add_node_interference(g, *vreg_first, *vreg_second);
}
}
}
/* Add node interferences such that the same register can't be used for
* both an instruction's source and destination.
*/
foreach_instr (instr, instr_list) {
for (size_t u = 0U; u < instr->num_operands; ++u) {
if (instr->operands[u].type != ROGUE_OPERAND_TYPE_VREG)
continue;
/* Operand 0 (if it exists and is virtual) is always
* the destination register.
*/
if (u > 0 && instr->operands[0].type == ROGUE_OPERAND_TYPE_VREG)
ra_add_node_interference(g,
instr->operands[0].vreg.number,
instr->operands[u].vreg.number);
}
}
/* Perform register allocation. */
/* TODO: Spilling support. */
assert(ra_allocate(g));
/* Replace virtual registers with allocated physical registers.
* N.B. This is a destructive process as it overwrites the hash table key!
*/
hash_table_foreach (reg_ht, entry) {
uint32_t vreg = *(uint32_t *)entry->key;
unsigned phy_reg = ra_get_node_reg(g, vreg);
struct live_range *range = entry->data;
struct rogue_reg_data *reg_data = &ra->reg_data[range->class];
enum rogue_operand_type type = reg_data->type;
size_t reg_offset = reg_data->offset;
size_t *num_used = &reg_data->num_used;
util_dynarray_foreach (&range->operand_refs,
struct rogue_operand *,
operand_ptr) {
size_t num = phy_reg - reg_offset;
struct rogue_operand *operand = *operand_ptr;
assert(operand->type == ROGUE_OPERAND_TYPE_VREG);
assert(operand->vreg.number == vreg);
/* Index the component of emulated vec4 registers. */
if (operand->vreg.is_vector &&
operand->vreg.component != ROGUE_COMPONENT_ALL)
num += operand->vreg.component;
operand->type = type;
operand->reg.number = num;
*num_used = MAX2(*num_used, operand->reg.number);
}
util_dynarray_fini(&range->operand_refs);
_mesa_hash_table_remove(reg_ht, entry);
}
/* Registers used = max reg number + 1. */
for (size_t u = 0; u < ARRAY_SIZE(ra->reg_data); ++u)
if (ra->reg_data[u].num_used)
++ra->reg_data[u].num_used;
/* Pass back the registers used. */
if (temps_used)
*temps_used = ra->reg_data[ROGUE_REG_CLASS_TEMP].num_used;
if (internals_used)
*internals_used = ra->reg_data[ROGUE_REG_CLASS_VEC4].num_used;
ralloc_free(g);
_mesa_hash_table_destroy(reg_ht, NULL);
return true;
}

View File

@ -0,0 +1,70 @@
/*
* 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 ROGUE_REGALLOC_H
#define ROGUE_REGALLOC_H
#include <stdbool.h>
#include <stddef.h>
#include "util/list.h"
/**
* \brief Register classes used for allocation.
*/
enum rogue_reg_class {
ROGUE_REG_CLASS_TEMP,
ROGUE_REG_CLASS_VEC4,
ROGUE_REG_CLASS_COUNT,
};
/**
* \brief Register data for each class.
*/
struct rogue_reg_data {
enum rogue_operand_type type;
size_t count;
size_t stride;
size_t offset;
struct ra_class *class;
size_t num_used;
};
/**
* \brief Register allocation context.
*/
struct rogue_ra {
struct ra_regs *regs;
struct rogue_reg_data reg_data[ROGUE_REG_CLASS_COUNT];
};
struct rogue_ra *rogue_ra_init(void *mem_ctx);
bool rogue_ra_alloc(struct list_head *instr_list,
struct rogue_ra *ra,
size_t *temps_used,
size_t *internals_used);
#endif /* ROGUE_REGALLOC_H */

View File

@ -0,0 +1,133 @@
/*
* 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 <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "rogue_shader.h"
#include "rogue_instr.h"
#include "rogue_regalloc.h"
#include "rogue_util.h"
#include "util/ralloc.h"
/**
* \file rogue_shader.c
*
* \brief Contains functions to manipulate Rogue shaders.
*/
/**
* \brief Counts how many times an instruction is used in a shader.
*
* \param[in] shader The shader containing instructions to count.
* \param[in] opcode The opcode of the instruction to be counted.
* \return The number of times "opcode" is present, or 0 on error.
*/
size_t rogue_shader_instr_count_type(const struct rogue_shader *shader,
enum rogue_opcode opcode)
{
size_t count = 0U;
ASSERT_OPCODE_RANGE(opcode);
foreach_instr (instr, &shader->instr_list)
if (instr->opcode == opcode)
++count;
return count;
}
/**
* \brief Allocates and sets up a Rogue shader.
*
* \param[in] stage The shader stage.
* \return A rogue_shader* if successful, or NULL if unsuccessful.
*/
struct rogue_shader *rogue_shader_create(struct rogue_build_ctx *ctx,
gl_shader_stage stage)
{
struct rogue_shader *shader;
if (!ctx)
return NULL;
shader = rzalloc_size(ctx, sizeof(*shader));
if (!shader)
return NULL;
shader->stage = stage;
list_inithead(&shader->instr_list);
shader->ctx = ctx;
shader->ra = rogue_ra_init(shader);
if (!shader->ra) {
ralloc_free(shader);
return NULL;
}
return shader;
}
/**
* \brief Creates an instruction and appends it to a Rogue shader.
*
* \param[in] shader The shader.
* \param[in] opcode The instruction opcode.
* \return A rogue_instr* if successful, or NULL if unsuccessful.
*/
struct rogue_instr *rogue_shader_insert(struct rogue_shader *shader,
enum rogue_opcode opcode)
{
struct rogue_instr *instr = rogue_instr_create(shader, opcode);
if (!instr)
return NULL;
list_addtail(&instr->node, &shader->instr_list);
return instr;
}
size_t rogue_acquire_drc(struct rogue_shader *shader)
{
size_t drc;
/* If both DRCs are in use, we have a problem. */
if (shader->drc_used[0] && shader->drc_used[1])
return SIZE_MAX;
drc = !shader->drc_used[0] ? 0 : 1;
shader->drc_used[drc] = true;
return drc;
}
void rogue_release_drc(struct rogue_shader *shader, size_t drc)
{
assert(drc < ROGUE_NUM_DRCS);
assert(shader->drc_used[drc]);
shader->drc_used[drc] = false;
}

View File

@ -0,0 +1,81 @@
/*
* 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 ROGUE_SHADER_H
#define ROGUE_SHADER_H
#include <stdbool.h>
#include <stddef.h>
#include "compiler/shader_enums.h"
#include "rogue_instr.h"
#include "rogue_operand.h"
#include "rogue_util.h"
#include "util/list.h"
#include "util/macros.h"
struct rogue_build_ctx;
struct rogue_ra;
/**
* \brief Shader description.
*/
struct rogue_shader {
gl_shader_stage stage; /** Shader stage. */
struct list_head instr_list; /** Instructions linked list. */
struct rogue_build_ctx *ctx;
struct rogue_ra *ra;
bool drc_used[ROGUE_NUM_DRCS];
};
/* Shader instruction list iterators and helpers. */
#define foreach_instr(__instr, __list) \
list_for_each_entry (struct rogue_instr, __instr, __list, node)
#define foreach_instr_rev(__instr, __list) \
list_for_each_entry_rev (struct rogue_instr, __instr, __list, node)
#define foreach_instr_safe(__instr, __list) \
list_for_each_entry_safe (struct rogue_instr, __instr, __list, node)
#define instr_first_entry(__list) \
list_first_entry(__list, struct rogue_instr, node)
#define instr_last_entry(__list) \
list_last_entry(__list, struct rogue_instr, node)
size_t rogue_shader_instr_count_type(const struct rogue_shader *shader,
enum rogue_opcode opcode);
PUBLIC
struct rogue_shader *rogue_shader_create(struct rogue_build_ctx *ctx,
gl_shader_stage stage);
PUBLIC
struct rogue_instr *rogue_shader_insert(struct rogue_shader *shader,
enum rogue_opcode opcode);
size_t rogue_acquire_drc(struct rogue_shader *shader);
void rogue_release_drc(struct rogue_shader *shader, size_t drc);
#endif /* ROGUE_SHADER_H */

View File

@ -0,0 +1,98 @@
/*
* 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 <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "rogue_util.h"
#include "util/macros.h"
/**
* \file rogue_util.c
*
* \brief Contains compiler utility and helper functions.
*/
/**
* \brief Splits and distributes value "source" across "dest_bytes" according to
* the ranges specified (from MSB to LSB).
*
* \param[in] source The source value to be distributed.
* \param[in] rangelist The rangelist describing how to distribute "source".
* \param[in] dest_size The size of the destination in bytes.
* \param[in] dest_bytes The destination byte array.
* \return false if invalid inputs were provided, else true.
*/
bool rogue_distribute_value(uint64_t source,
const struct rogue_rangelist *rangelist,
size_t dest_size,
uint8_t dest_bytes[dest_size])
{
size_t total_bits_left = 0U;
/* Check that "value" is actually representable in "total_bits" bits. */
total_bits_left = rogue_rangelist_bits(rangelist);
assert(util_last_bit64(source) <= total_bits_left &&
"Value cannot be represented.");
/* Iterate over each range. */
for (size_t u = 0U; u < rangelist->num_ranges; ++u) {
struct rogue_bitrange *range = &rangelist->ranges[u];
size_t dest_bit = range->start;
size_t bits_left = range->num;
size_t bytes_covered = rogue_bytes_spilled(range) + 1;
size_t base_byte = rogue_byte_index(range, dest_size);
/* Iterate over each byte covered by the current range. */
for (size_t b = 0U; b < bytes_covered; ++b) {
size_t max_bits = rogue_max_bits(dest_bit);
size_t bits_to_place = MIN2(bits_left, max_bits);
size_t dest_byte_bit = dest_bit % 8;
size_t source_bit = total_bits_left - 1;
/* Mask and shuffle the source value so that it'll fit into the
* correct place in the destination byte:
*/
/* Extract bits. */
uint64_t value_masked =
(source & BITMASK64_N(source_bit, bits_to_place));
/* Shift all the way right. */
value_masked >>= (1 + source_bit - bits_to_place);
/* Shift left to the correct position. */
value_masked <<= (1 + dest_byte_bit - bits_to_place);
/* Place value into byte. */
dest_bytes[base_byte + b] |= (value_masked & 0xff);
dest_bit -= max_bits;
bits_left -= bits_to_place;
total_bits_left -= bits_to_place;
}
}
return true;
}

View File

@ -0,0 +1,320 @@
/*
* 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 ROGUE_UTIL_H
#define ROGUE_UTIL_H
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "util/bitscan.h"
#include "util/log.h"
#include "util/macros.h"
/* Input validation helpers. */
/**
* \brief Returns false if "expr" is not asserted.
*
* \param[in] expr The expression to check.
*/
#define CHECK(expr) \
do { \
if (!(expr)) \
return false; \
} while (0)
/**
* \brief Returns false if "expr" is not asserted,
* and logs the provided error message.
*
* \param[in] expr The expression to check.
* \param[in] fmt The error message to print.
* \param[in] ... The printf-style varable arguments.
*/
#define CHECKF(expr, fmt, ...) \
do { \
if (!(expr)) { \
mesa_log(MESA_LOG_ERROR, "ROGUE", fmt, ##__VA_ARGS__); \
return false; \
} \
} while (0)
/**
* \brief Asserts if "opcode" is invalid.
*
* \param[in] opcode The opcode to check.
*/
#define ASSERT_OPCODE_RANGE(opcode) assert((opcode) < ROGUE_OP_COUNT)
/**
* \brief Asserts if "operand" is invalid.
*
* \param[in] operand The operand to check.
*/
#define ASSERT_OPERAND_RANGE(operand) \
assert((operand) < ROGUE_OPERAND_TYPE_COUNT)
/**
* \brief Asserts if "operand" is not a register.
*
* \param[in] operand The operand to check.
*/
#define ASSERT_OPERAND_REG(operand) \
assert((operand) <= ROGUE_OPERAND_TYPE_REG_MAX)
/**
* \brief Asserts if "flag" is invalid.
*
* \param[in] flag The flag to check.
*/
#define ASSERT_INSTR_FLAG_RANGE(flag) assert((flag) < ROGUE_INSTR_FLAG_COUNT)
/**
* \brief Asserts if operand index "index" is out of range.
*
* \param[in] instr The target instruction.
* \param[in] index The operand index to check.
*/
#define ASSERT_INSTR_OPERAND_INDEX(instr, index) \
assert((index) < (instr)->num_operands)
/**
* \brief Asserts if "stage" is invalid.
*
* \param[in] stage The stage to check.
*/
#define ASSERT_SHADER_STAGE_RANGE(stage) assert((stage) < MESA_SHADER_STAGES)
/**
* \brief Creates a "n"-bit mask starting from bit "b".
*
* \param[in] b The starting bit.
* \param[in] n The number of bits in the mask.
*/
#define BITMASK64_N(b, n) (((~0ULL) << (64 - (n))) >> (63 - (b)))
/**
* \brief Compile-time rogue_onehot.
*
* \sa #rogue_onehot()
*/
#define ROH(OFFSET) BITFIELD64_BIT(OFFSET)
/* TODO: Consider integrating the following into src/util/{macros,bitscan}.h */
/**
* \brief Converts a one-hot encoding to an offset encoding.
*
* E.g. 0b10000 -> 4
*
* \param[in] onehot The one-hot encoding.
* \return The offset encoding.
*/
static inline uint64_t rogue_offset(uint64_t onehot)
{
assert(util_bitcount64(onehot) == 1);
return ffsll(onehot) - 1;
}
/**
* \brief Converts an offset encoding to a one-hot encoding.
*
* E.g. 0 -> 0b1
*
* \param[in] offset The offset encoding.
* \return The one-hot encoding.
*/
static inline uint64_t rogue_onehot(uint64_t offset)
{
assert(offset < 64ULL);
return (1ULL << offset);
}
/**
* \brief Checks whether an input bitfield contains only a valid bitset.
*
* E.g. rogue_check_bitset(0b00001100, 0b00001111) -> true
* rogue_check_bitset(0b00001100, 0b00000111) -> false
*
* \param[in] input The input bitfield.
* \param[in] valid_bits The valid bitset.
* \return true if "input" contains only "valid_bits", false otherwise.
*/
static inline bool rogue_check_bitset(uint64_t input, uint64_t valid_bits)
{
input &= ~valid_bits;
return !input;
}
/**
* \brief Describes a downward range of bits within an arbitrarily-sized
* sequence.
*
* E.g. for start = 7 and num = 3:
*
* 76543210
* abcdefgh
*
* the bit range would be: abc.
*/
struct rogue_bitrange {
size_t start;
size_t num;
};
/**
* \brief Describes a collection of bit-ranges within an arbitrarily-sized
* sequence that are meaningful together.
*
* E.g. an 8-bit value that is encoded within a larger value:
* 8-bit value: abcdefgh
* Parent value: 010ab0cdef0010gh
*
*/
struct rogue_rangelist {
size_t num_ranges;
struct rogue_bitrange *ranges;
};
/**
* \brief Counts the total number of bits described in a rangelist.
*
* \param[in] rangelist The input rangelist.
* \return The total number of bits.
*/
static inline size_t
rogue_rangelist_bits(const struct rogue_rangelist *rangelist)
{
size_t total_bits = 0U;
for (size_t u = 0U; u < rangelist->num_ranges; ++u)
total_bits += rangelist->ranges[u].num;
return total_bits;
}
/**
* \brief Returns the byte offset of the bitrange moving left from the LSB.
*
* \param[in] bitrange The input bit-range.
* \return The byte offset.
*/
static inline size_t rogue_byte_num(const struct rogue_bitrange *bitrange)
{
/* Make sure there are enough bits. */
assert(bitrange->num <= (bitrange->start + 1));
return bitrange->start / 8;
}
/**
* \brief Returns the array-indexable byte offset of a bit-range if the sequence
* it represents were to be stored in an byte-array containing "num_bytes"
* bytes.
*
* E.g. uint8_t array[2] is a sequence of 16 bits:
* bit(0) is located in array[1].
* bit(15) is located in array[0].
*
* For uint8_t array[4]:
* bit(0) is located in array[3].
* bit(15) is located in array[2].
*
* \param[in] bitrange The input bit-range.
* \param[in] num_bytes The number of bytes that are used to contain the
* bit-range. \return The byte offset.
*/
static inline size_t rogue_byte_index(const struct rogue_bitrange *bitrange,
size_t num_bytes)
{
/* Make sure there are enough bits. */
assert(bitrange->num <= (bitrange->start + 1));
return num_bytes - rogue_byte_num(bitrange) - 1;
}
/**
* \brief Returns the bit offset of a bit-range if the sequence it represents is
* being accessed in a byte-wise manner.
*
* E.g. bit 17 has a bit offset of 1.
*
* \param[in] bitrange The input bit-range.
* \return The bit offset.
*/
static inline size_t rogue_bit_offset(const struct rogue_bitrange *bitrange)
{
/* Make sure there are enough bits. */
assert(bitrange->num <= (bitrange->start + 1));
return bitrange->start % 8;
}
/**
* \brief Returns the number of additional bytes that the bit-range spills into
* (excluding its "starting" byte).
*
* \param[in] bitrange The input bit-range.
* \return The number of bytes spilled.
*/
static inline size_t rogue_bytes_spilled(const struct rogue_bitrange *bitrange)
{
/* Make sure there are enough bits. */
assert(bitrange->num <= (bitrange->start + 1));
return ((bitrange->num - 1) / 8) +
((bitrange->num % 8) > (rogue_bit_offset(bitrange) + 1));
}
/**
* \brief For a given bit offset, returns the maximum number of bits (including
* itself) that are accessible before spilling into the following byte.
*
* E.g. When trying to insert an 8-bit value offset of 13, a maximum of 6 bits
* can be placed; the last 2 bits will need to go into the next byte.
*
* 8-bit value: abcdefgh
*
* array[0] array[1]
* 15 8 7 0
* iiiiiiii jjjjjjjj
* ^
* abcdef gh
*
* \param[in] The bit offset.
* \return The maximum number of accessible bits.
*/
static inline size_t rogue_max_bits(size_t offset)
{
return (offset % 8) + 1;
}
bool rogue_distribute_value(uint64_t source,
const struct rogue_rangelist *rangelist,
size_t dest_size,
uint8_t dest_bytes[dest_size]);
#endif /* ROGUE_UTIL_H */

View File

@ -0,0 +1,288 @@
/*
* 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.
*/
/**
* \file rogue_validate.c
*
* \brief Contains rules and functions for validating Rogue data structures.
*/
#include <stdbool.h>
#include "rogue_operand.h"
#include "rogue_shader.h"
#include "rogue_util.h"
#include "rogue_validate.h"
#include "util/list.h"
#include "util/macros.h"
/**
* \brief Register operand rules.
*/
#define REG_RULE(OPERAND, ACCESS, MAX, MODIFIERS) \
[ROGUE_OPERAND_TYPE_REG_##OPERAND] = { \
.access = ROGUE_REG_ACCESS_##ACCESS, \
.max = MAX, \
.modifiers = ROGUE_REG_MOD_##MODIFIERS, \
}
/* TODO: Support register indexing > ROGUE_MAX_REG_TEMP. */
static const struct rogue_register_rule reg_rules[ROGUE_NUM_REG_TYPES] = {
REG_RULE(TEMP, RW, MIN2(ROGUE_MAX_REG_INDEX, ROGUE_MAX_REG_TEMP), ALL),
REG_RULE(COEFF, RW, MIN2(ROGUE_MAX_REG_INDEX, ROGUE_MAX_REG_COEFF), ALL),
REG_RULE(CONST, RW, MIN2(ROGUE_MAX_REG_INDEX, ROGUE_MAX_REG_CONST), NONE),
REG_RULE(SHARED, RW, MIN2(ROGUE_MAX_REG_INDEX, ROGUE_MAX_REG_SHARED), ALL),
REG_RULE(PIXEL_OUT,
RW,
MIN2(ROGUE_MAX_REG_INDEX, ROGUE_MAX_REG_PIXEL_OUT),
NONE),
REG_RULE(VERTEX_IN,
RW,
MIN2(ROGUE_MAX_REG_INDEX, ROGUE_MAX_REG_VERTEX_IN),
ALL),
REG_RULE(INTERNAL,
RW,
MIN2(ROGUE_MAX_REG_INDEX, ROGUE_MAX_REG_INTERNAL),
NONE),
};
#undef REG_RULE
/**
* \brief Instruction rules.
*/
/* TODO: Common up register classes to prevent long lines. */
static const struct rogue_instr_rule instr_rules[ROGUE_OP_COUNT] = {
[ROGUE_OP_NOP] = { .flags = 0, .num_operands = 0, .operand_rules = NULL, },
[ROGUE_OP_END_FRAG] = { .flags = 0, .num_operands = 0, .operand_rules = NULL, },
[ROGUE_OP_END_VERT] = { .flags = 0, .num_operands = 0, .operand_rules = NULL, },
[ROGUE_OP_WDF] = { .flags = 0,
.num_operands = 1, .operand_rules = (struct rogue_instr_operand_rule[]){
[0] = { .mask = ROH(ROGUE_OPERAND_TYPE_DRC), .min = -1, .max = -1, .align = -1, },
},
},
[ROGUE_OP_PIX_ITER_W] = { .flags = ROH(ROGUE_INSTR_FLAG_SAT),
.num_operands = 5, .operand_rules = (struct rogue_instr_operand_rule[]){
[0] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
[1] = { .mask = ROH(ROGUE_OPERAND_TYPE_DRC), .min = -1, .max = -1, .align = -1, },
[2] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_COEFF), .min = -1, .max = -1, .align = ROGUE_COEFF_ALIGN, },
[3] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_COEFF), .min = -1, .max = -1, .align = ROGUE_COEFF_ALIGN, },
[4] = { .mask = ROH(ROGUE_OPERAND_TYPE_IMMEDIATE), .min = 1, .max = 16, .align = -1, },
},
},
[ROGUE_OP_MAX] = { .flags = 0,
.num_operands = 3, .operand_rules = (struct rogue_instr_operand_rule[]){
[0] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
[1] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
[2] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_CONST) | ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
},
},
[ROGUE_OP_MIN] = { .flags = 0,
.num_operands = 3, .operand_rules = (struct rogue_instr_operand_rule[]){
[0] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP) | ROH(ROGUE_OPERAND_TYPE_REG_INTERNAL), .min = -1, .max = -1, .align = -1, },
[1] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
[2] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_CONST) | ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
},
},
/* TODO: Add representation for 4 sequential registers. */
[ROGUE_OP_PACK_U8888] = { .flags = 0,
.num_operands = 2, .operand_rules = (struct rogue_instr_operand_rule[]){
[0] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
[1] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_INTERNAL), .min = -1, .max = -1, .align = -1, },
},
},
[ROGUE_OP_MOV] = { .flags = ROH(ROGUE_INSTR_FLAG_OLCHK),
.num_operands = 2, .operand_rules = (struct rogue_instr_operand_rule[]){
[0] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP) | ROH(ROGUE_OPERAND_TYPE_REG_INTERNAL) | ROH(ROGUE_OPERAND_TYPE_REG_PIXEL_OUT), .min = -1, .max = -1, .align = -1, },
[1] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_CONST) | ROH(ROGUE_OPERAND_TYPE_REG_TEMP) | ROH(ROGUE_OPERAND_TYPE_REG_SHARED) | ROH(ROGUE_OPERAND_TYPE_REG_VERTEX_IN), .min = -1, .max = -1, .align = -1, },
},
},
[ROGUE_OP_MOV_IMM] = { .flags = 0,
.num_operands = 2, .operand_rules = (struct rogue_instr_operand_rule[]){
[0] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
[1] = { .mask = ROH(ROGUE_OPERAND_TYPE_IMMEDIATE), .min = 0, .max = UINT32_MAX, .align = -1, },
},
},
[ROGUE_OP_FMA] = { .flags = ROH(ROGUE_INSTR_FLAG_SAT) | ROH(ROGUE_INSTR_FLAG_LP),
.num_operands = 4, .operand_rules = (struct rogue_instr_operand_rule[]){
[0] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
[1] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
[2] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
[3] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
},
},
[ROGUE_OP_MUL] = { .flags = ROH(ROGUE_INSTR_FLAG_SAT) | ROH(ROGUE_INSTR_FLAG_LP),
.num_operands = 3, .operand_rules = (struct rogue_instr_operand_rule[]){
[0] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
[1] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
[2] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
},
},
[ROGUE_OP_VTXOUT] = { .flags = 0,
.num_operands = 2, .operand_rules = (struct rogue_instr_operand_rule[]){
[0] = { .mask = ROH(ROGUE_OPERAND_TYPE_IMMEDIATE), .min = 0, .max = ROGUE_MAX_VERTEX_OUTPUTS, .align = -1, },
[1] = { .mask = ROH(ROGUE_OPERAND_TYPE_REG_TEMP), .min = -1, .max = -1, .align = -1, },
},
},
};
/**
* \brief Validates an operand.
*
* \param[in] operand The operand.
* \return true if valid, otherwise false.
*/
bool rogue_validate_operand(const struct rogue_operand *operand)
{
ASSERT_OPERAND_RANGE(operand->type);
switch (operand->type) {
case ROGUE_OPERAND_TYPE_IMMEDIATE:
return true;
case ROGUE_OPERAND_TYPE_DRC:
CHECKF(operand->drc.number < ROGUE_NUM_DRCS,
"Invalid DRC number '%zu'.",
operand->drc.number);
return true;
case ROGUE_OPERAND_TYPE_REG_TEMP:
case ROGUE_OPERAND_TYPE_REG_COEFF:
case ROGUE_OPERAND_TYPE_REG_CONST:
case ROGUE_OPERAND_TYPE_REG_SHARED:
case ROGUE_OPERAND_TYPE_REG_PIXEL_OUT:
case ROGUE_OPERAND_TYPE_REG_VERTEX_IN:
case ROGUE_OPERAND_TYPE_REG_INTERNAL:
CHECKF(operand->reg.number < reg_rules[operand->type].max,
"Register number '%zu' out of range.",
operand->reg.number);
return true;
default:
break;
}
return false;
}
/**
* \brief Validates an instruction.
*
* \param[in] instr The instruction.
* \return true if valid, otherwise false.
*/
bool rogue_validate_instr(const struct rogue_instr *instr)
{
const struct rogue_instr_rule *rule;
ASSERT_OPCODE_RANGE(instr->opcode);
rule = &instr_rules[instr->opcode];
/* Validate flags. */
CHECKF(rogue_check_bitset(instr->flags, rule->flags),
"Invalid instruction flags specified.");
/* Validate number of operands. */
CHECKF(instr->num_operands == rule->num_operands,
"Invalid number of operands specified.");
CHECK(!rule->num_operands || instr->operands);
for (size_t u = 0U; u < instr->num_operands; ++u) {
/* Validate operand types. */
CHECKF(rogue_check_bitset(rogue_onehot(instr->operands[u].type),
rule->operand_rules[u].mask),
"Invalid type for operand %zu.",
u);
/* Validate immediate ranges. */
if (rogue_check_bitset(rogue_onehot(instr->operands[u].type),
ROH(ROGUE_OPERAND_TYPE_IMMEDIATE)) &&
rule->operand_rules[u].min != -1 &&
rule->operand_rules[u].max != -1) {
CHECKF(
instr->operands[u].immediate.value >= rule->operand_rules[u].min &&
instr->operands[u].immediate.value <= rule->operand_rules[u].max,
"Immediate value out of range for operand %zu.",
u);
}
/* Validate register alignment. */
if (rogue_check_bitset(rogue_onehot(instr->operands[u].type),
ROGUE_MASK_ANY_REG) &&
rule->operand_rules[u].align != -1) {
CHECKF(!(instr->operands[u].reg.number % rule->operand_rules[u].align),
"Invalid register alignment in operand %zu.",
u);
}
/* Validate each operand. */
CHECKF(rogue_validate_operand(&instr->operands[u]),
"Failed to validate operand.");
}
return true;
}
/**
* \brief Validates a shader.
*
* \param[in] shader The shader.
* \return true if valid, otherwise false.
*/
bool rogue_validate_shader(const struct rogue_shader *shader)
{
CHECK(!list_is_empty(&shader->instr_list));
ASSERT_SHADER_STAGE_RANGE(shader->stage);
/* Shader stage-specific validation. */
switch (shader->stage) {
case MESA_SHADER_VERTEX:
/* Make sure there is (only) one end vertex shader instruction. */
CHECKF(rogue_shader_instr_count_type(shader, ROGUE_OP_END_VERT) == 1,
"Shader must contain a single end.vert instruction.");
/* Make sure the end vertex shader instruction is the last one. */
CHECKF(instr_last_entry(&shader->instr_list)->opcode == ROGUE_OP_END_VERT,
"end.vert not last instruction.");
break;
case MESA_SHADER_FRAGMENT:
/* Make sure there is (only) one end fragment shader instruction. */
CHECKF(rogue_shader_instr_count_type(shader, ROGUE_OP_END_FRAG) == 1,
"Shader must contain a single end.frag instruction.");
/* Make sure the end fragment shader instruction is the last one. */
CHECKF(instr_last_entry(&shader->instr_list)->opcode == ROGUE_OP_END_FRAG,
"end.frag not last instruction.");
break;
default:
return false;
}
/* Validate each instruction. */
foreach_instr (instr, &shader->instr_list)
CHECKF(rogue_validate_instr(instr), "Failed to validate instruction.");
return true;
}

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.
*/
#ifndef ROGUE_VALIDATE_H
#define ROGUE_VALIDATE_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include "rogue_instr.h"
#include "rogue_operand.h"
#include "rogue_shader.h"
#include "util/macros.h"
/**
* \brief Register rule description.
*/
struct rogue_register_rule {
enum rogue_register_access access;
size_t max;
enum rogue_register_modifier modifiers;
};
/**
* \brief Instruction operand rule description.
*/
struct rogue_instr_operand_rule {
uint64_t mask;
ssize_t min;
ssize_t max;
ssize_t align;
};
/**
* \brief Instruction rule description.
*/
struct rogue_instr_rule {
uint64_t flags; /** A mask of #rogue_instr_flag values. */
size_t num_operands;
struct rogue_instr_operand_rule *operand_rules;
};
PUBLIC
bool rogue_validate_operand(const struct rogue_operand *operand);
PUBLIC
bool rogue_validate_instr(const struct rogue_instr *instr);
PUBLIC
bool rogue_validate_shader(const struct rogue_shader *shader);
#endif /* ROGUE_VALIDATE_H */

View File

@ -0,0 +1,314 @@
/*
* 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 "compiler/shader_enums.h"
#include "nir/nir.h"
#include "rogue.h"
#include "rogue_build_data.h"
#include "rogue_compiler.h"
#include "rogue_dump.h"
#include "util/os_file.h"
#include "util/ralloc.h"
#include <getopt.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Number of hex columns to dump before starting a new line. */
#define ARRAY_DUMP_COLS 16
/**
* \file compiler.c
*
* \brief Rogue offline compiler.
*/
static const struct option cmdline_opts[] = {
/* Arguments. */
{ "stage", required_argument, NULL, 's' },
{ "file", required_argument, NULL, 'f' },
{ "entry", required_argument, NULL, 'e' },
/* Options. */
{ "help", no_argument, NULL, 'h' },
{ "out", required_argument, NULL, 'o' },
{ "dump-c-array", no_argument, NULL, 'c' },
{ "dump-rogue", no_argument, NULL, 'r' },
{ "dump-nir", no_argument, NULL, 'n' },
{ NULL, 0, NULL, 0 },
};
struct compiler_opts {
gl_shader_stage stage;
char *file;
char *entry;
char *out_file;
bool dump_c_array;
bool dump_rogue;
bool dump_nir;
};
static void usage(const char *argv0)
{
/* clang-format off */
printf("Rogue offline compiler.\n");
printf("Usage: %s -s <stage> -f <file> [-e <entry>] [-o <file>] [-c] [-r] [-n] [-h]\n", argv0);
printf("\n");
printf("Required arguments:\n");
printf("\t-s, --stage <stage> Shader stage (supported options: frag, vert).\n");
printf("\t-f, --file <file> Shader SPIR-V filename.\n");
printf("\n");
printf("Options:\n");
printf("\t-h, --help Prints this help message.\n");
printf("\t-e, --entry <entry> Overrides the shader entry-point name (default: 'main').\n");
printf("\t-o, --out <file> Overrides the output filename (default: 'out.bin').\n");
printf("\n");
printf("\t-c, --dump-c-array Print the shader binary as a C byte array.\n");
printf("\t-r, --dump-rogue Prints the shader Rogue assembly.\n");
printf("\t-n, --dump-nir Prints the shader NIR.\n");
printf("\n");
/* clang-format on */
}
static bool parse_cmdline(int argc, char *argv[], struct compiler_opts *opts)
{
int opt;
int longindex;
while (
(opt =
getopt_long(argc, argv, "crnhs:f:e:o:", cmdline_opts, &longindex)) !=
-1) {
switch (opt) {
case 'c':
opts->dump_c_array = true;
break;
case 'e':
if (opts->entry)
continue;
opts->entry = optarg;
break;
case 'f':
if (opts->file)
continue;
opts->file = optarg;
break;
case 'n':
opts->dump_nir = true;
break;
case 'o':
if (opts->out_file)
continue;
opts->out_file = optarg;
break;
case 'r':
opts->dump_rogue = true;
break;
case 's':
if (opts->stage != MESA_SHADER_NONE)
continue;
if (!strcmp(optarg, "frag"))
opts->stage = MESA_SHADER_FRAGMENT;
else if (!strcmp(optarg, "vert"))
opts->stage = MESA_SHADER_VERTEX;
else {
fprintf(stderr, "Invalid stage \"%s\".\n", optarg);
usage(argv[0]);
return false;
}
break;
case 'h':
default:
usage(argv[0]);
return false;
}
}
if (opts->stage == MESA_SHADER_NONE || !opts->file) {
fprintf(stderr,
"%s: --stage and --file are required arguments.\n",
argv[0]);
usage(argv[0]);
return false;
}
if (!opts->out_file)
opts->out_file = "out.bin";
if (!opts->entry)
opts->entry = "main";
return true;
}
int main(int argc, char *argv[])
{
/* Command-line options. */
/* N.B. MESA_SHADER_NONE != 0 */
struct compiler_opts opts = { .stage = MESA_SHADER_NONE, 0 };
/* Input file data. */
char *input_data;
size_t input_size;
/* Compiler context. */
struct rogue_compiler *compiler;
/* Multi-stage build context. */
struct rogue_build_ctx *ctx;
/* Output file. */
FILE *fp;
size_t bytes_written;
/* Parse command-line options. */
if (!parse_cmdline(argc, argv, &opts))
return 1;
/* Load SPIR-V input file. */
input_data = os_read_file(opts.file, &input_size);
if (!input_data) {
fprintf(stderr, "Failed to read file \"%s\".\n", opts.file);
return 1;
}
/* Create compiler context. */
compiler = rogue_compiler_create(NULL);
if (!compiler) {
fprintf(stderr, "Failed to set up compiler context.\n");
goto err_free_input;
}
ctx = rogue_create_build_context(compiler);
if (!ctx) {
fprintf(stderr, "Failed to set up build context.\n");
goto err_destroy_compiler;
}
/* SPIR-V -> NIR. */
ctx->nir[opts.stage] = rogue_spirv_to_nir(ctx,
opts.stage,
opts.entry,
input_size / sizeof(uint32_t),
(uint32_t *)input_data,
0,
NULL);
if (!ctx->nir[opts.stage]) {
fprintf(stderr, "Failed to translate SPIR-V input to NIR.\n");
goto err_free_build_context;
}
/* Dump NIR shader. */
if (opts.dump_nir)
nir_print_shader(ctx->nir[opts.stage], stdout);
/* NIR -> Rogue. */
ctx->rogue[opts.stage] = rogue_nir_to_rogue(ctx, ctx->nir[opts.stage]);
if (!ctx->rogue[opts.stage]) {
fprintf(stderr, "Failed to translate NIR input to Rogue.\n");
goto err_free_build_context;
}
/* Dump Rogue shader. */
if (opts.dump_rogue)
rogue_dump_shader(ctx->rogue[opts.stage], stdout);
/* Rogue -> Binary. */
ctx->binary[opts.stage] = rogue_to_binary(ctx, ctx->rogue[opts.stage]);
if (!ctx->binary[opts.stage]) {
fprintf(stderr, "Failed to translate Rogue to binary.\n");
goto err_free_build_context;
}
/* Dump binary as a C array. */
if (opts.dump_c_array) {
printf("uint8_t shader_bytes[%zu] = {", ctx->binary[opts.stage]->size);
for (size_t u = 0U; u < ctx->binary[opts.stage]->size; ++u) {
if (!(u % ARRAY_DUMP_COLS))
printf("\n\t");
printf("0x%02x, ", ctx->binary[opts.stage]->data[u]);
}
printf("\n};\n");
}
/* Write shader binary to disk. */
fp = fopen(opts.out_file, "wb");
if (!fp) {
fprintf(stderr, "Failed to open output file \"%s\".\n", opts.out_file);
goto err_free_build_context;
}
bytes_written = fwrite(ctx->binary[opts.stage]->data,
1,
ctx->binary[opts.stage]->size,
fp);
if (bytes_written != ctx->binary[opts.stage]->size) {
fprintf(
stderr,
"Failed to write to output file \"%s\" (%zu bytes of %zu written).\n",
opts.out_file,
bytes_written,
ctx->binary[opts.stage]->size);
goto err_close_outfile;
}
/* Clean up. */
fclose(fp);
ralloc_free(ctx);
rogue_compiler_destroy(compiler);
free(input_data);
return 0;
err_close_outfile:
fclose(fp);
err_free_build_context:
ralloc_free(ctx);
err_destroy_compiler:
rogue_compiler_destroy(compiler);
err_free_input:
free(input_data);
return 1;
}

View File

@ -0,0 +1,171 @@
# 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.
subdir('pds')
pvr_entrypoints = custom_target(
'pvr_entrypoints',
input : [vk_entrypoints_gen, vk_api_xml],
output : ['pvr_entrypoints.h', 'pvr_entrypoints.c'],
command : [
prog_python, '@INPUT0@', '--xml', '@INPUT1@', '--proto', '--weak',
'--out-h', '@OUTPUT0@', '--out-c', '@OUTPUT1@', '--prefix', 'pvr',
],
depend_files : vk_entrypoints_gen_depend_files,
)
pvr_files = files(
'winsys/powervr/pvr_drm.c',
'winsys/pvr_winsys.c',
'winsys/pvr_winsys_helper.c',
'pvr_blit.c',
'pvr_bo.c',
'pvr_cmd_buffer.c',
'pvr_csb.c',
'pvr_descriptor_set.c',
'pvr_device.c',
'pvr_formats.c',
'pvr_hw_pass.c',
'pvr_image.c',
'pvr_job_common.c',
'pvr_job_compute.c',
'pvr_job_context.c',
'pvr_job_render.c',
'pvr_pass.c',
'pvr_pipeline.c',
'pvr_pipeline_cache.c',
'pvr_query.c',
'pvr_queue.c',
'pvr_shader.c',
'pvr_tex_state.c',
'pvr_wsi.c',
)
pvr_includes = [
include_directories('usc/programs'),
include_directories('winsys'),
libpowervr_pds_includes,
]
pvr_deps = [
dep_csbgen,
dep_libdrm,
dep_valgrind,
idep_vulkan_runtime,
idep_vulkan_util,
idep_vulkan_wsi,
]
pvr_flags = [
no_override_init_args,
]
if with_imagination_srv
pvr_files += files(
'winsys/pvrsrvkm/pvr_srv.c',
'winsys/pvrsrvkm/pvr_srv_bo.c',
'winsys/pvrsrvkm/pvr_srv_bridge.c',
'winsys/pvrsrvkm/pvr_srv_job_compute.c',
'winsys/pvrsrvkm/pvr_srv_job_render.c',
'winsys/pvrsrvkm/pvr_srv_syncobj.c',
)
pvr_flags += '-DPVR_SUPPORT_SERVICES_DRIVER'
endif
libvulkan_powervr_mesa = shared_library(
'vulkan_powervr_mesa',
[pvr_files, pvr_entrypoints],
include_directories : [
pvr_includes,
inc_gallium_aux,
inc_imagination,
inc_include,
inc_src,
inc_mesa,
inc_gallium,
inc_compiler,
],
link_with : [
libpowervr_common,
libpowervr_pds,
libpowervr_rogue,
libvulkan_wsi,
],
dependencies : [
pvr_deps,
idep_nir,
],
c_args : pvr_flags,
link_args : [
ld_args_build_id,
ld_args_bsymbolic,
ld_args_gc_sections
],
gnu_symbol_visibility : 'hidden',
install : true,
)
if with_symbols_check
test(
'pvr symbols check',
symbols_check,
args : [
'--lib', libvulkan_powervr_mesa,
'--symbols-file', vulkan_icd_symbols,
symbols_check_args,
],
suite : ['imagination'],
)
endif
powervr_mesa_icd = custom_target(
'powervr_mesa_icd',
input : [vk_icd_gen, vk_api_xml],
output : 'powervr_mesa_icd.@0@.json'.format(host_machine.cpu()),
command : [
prog_python, '@INPUT0@',
'--api-version', '1.0', '--xml', '@INPUT1@',
'--lib-path', join_paths(get_option('prefix'), get_option('libdir'),
'libvulkan_powervr_mesa.so'),
'--out', '@OUTPUT@',
],
build_by_default : true,
install_dir : with_vulkan_icd_dir,
install : true,
)
if meson.version().version_compare('>= 0.58')
_dev_icdname = 'powervr_mesa_devenv_icd.@0@.json'.format(host_machine.cpu())
custom_target(
'powervr_mesa_devenv_icd',
input : [vk_icd_gen, vk_api_xml],
output : _dev_icdname,
command : [
prog_python, '@INPUT0@',
'--api-version', '1.0', '--xml', '@INPUT1@',
'--lib-path', meson.current_build_dir() / 'libvulkan_powervr_mesa.so',
'--out', '@OUTPUT@',
],
build_by_default : true,
)
devenv.append('VK_ICD_FILENAMES', meson.current_build_dir() / _dev_icdname)
endif

View File

@ -0,0 +1,50 @@
# 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.
libpowervr_pds_files = files(
'pvr_pds.c',
'pvr_pds_disasm.c',
'pvr_pds_printer.c',
'pvr_xgl_pds.c',
)
libpowervr_pds_includes = include_directories(
'..',
'.',
'pvr_pds_programs',
)
libpowervr_pds = static_library(
'pvr_pds',
[libpowervr_pds_files],
include_directories : [
libpowervr_pds_includes,
inc_include,
inc_src,
inc_imagination,
],
c_args : [
no_override_init_args,
],
gnu_symbol_visibility : 'hidden',
pic : true,
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,666 @@
/*
* 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 <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "pvr_rogue_pds_defs.h"
#include "pvr_rogue_pds_disasm.h"
#include "pvr_rogue_pds_encode.h"
#include "util/log.h"
#define X(lop, str) #str,
static const char *const LOP[] = { PVR_PDS_LOP };
#undef X
static void pvr_pds_disassemble_operand(struct pvr_operand *op,
char *instr_str,
size_t instr_len)
{
#define X(enum, str, size) { #str, #size },
static const char *const regs[][2] = { PVR_PDS_OPERAND_TYPES };
#undef X
if (op->type == LITERAL_NUM) {
snprintf(instr_str,
instr_len,
"%s (%llu)",
regs[op->type][0],
(unsigned long long)op->literal);
} else if (op->type == UNRESOLVED) {
snprintf(instr_str, instr_len, "UNRESOLVED");
} else {
snprintf(instr_str,
instr_len,
"%s[%u].%s",
regs[op->type][0],
op->absolute_address,
regs[op->type][1]);
}
}
static void pvr_pds_disassemble_instruction_add64(struct pvr_add *add,
char *instr_str,
size_t instr_len)
{
char dst[32];
char src0[32];
char src1[32];
pvr_pds_disassemble_operand(add->src0, src0, sizeof(src0));
pvr_pds_disassemble_operand(add->src1, src1, sizeof(src1));
pvr_pds_disassemble_operand(add->dst, dst, sizeof(dst));
snprintf(instr_str,
instr_len,
"%-16s%s%s = %s %s %s %s",
"ADD64",
add->cc ? "? " : "",
dst,
src0,
add->sna ? "-" : "+",
src1,
add->alum ? "[signed]" : "");
}
static void pvr_pds_disassemble_instruction_add32(struct pvr_add *add,
char *instr_str,
size_t instr_len)
{
char dst[32];
char src0[32];
char src1[32];
pvr_pds_disassemble_operand(add->src0, src0, sizeof(src0));
pvr_pds_disassemble_operand(add->src1, src1, sizeof(src1));
pvr_pds_disassemble_operand(add->dst, dst, sizeof(dst));
snprintf(instr_str,
instr_len,
"%-16s%s%s = %s %s %s %s",
"ADD32",
add->cc ? "? " : "",
dst,
src0,
add->sna ? "-" : "+",
src1,
add->alum ? "[signed]" : "");
}
static void
pvr_pds_disassemble_instruction_sftlp32(struct pvr_sftlp *instruction,
char *instr_str,
size_t instr_len)
{
char dst[32];
char src0[32];
char src1[32];
char src2[32];
pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0));
pvr_pds_disassemble_operand(instruction->src1, src1, sizeof(src1));
pvr_pds_disassemble_operand(instruction->dst, dst, sizeof(dst));
if (instruction->IM)
snprintf(src2, sizeof(src2), "%u", (uint32_t)instruction->src2->literal);
else
pvr_pds_disassemble_operand(instruction->src2, src2, sizeof(src2));
if (instruction->lop == LOP_NONE) {
snprintf(instr_str,
instr_len,
"%-16s%s%s = %s %s %s",
"SFTLP32",
instruction->cc ? "? " : "",
dst,
src0,
instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
src2);
} else if (instruction->lop == LOP_NOT) {
snprintf(instr_str,
instr_len,
"%-16s%s%s = (~%s) %s %s",
"SFTLP32",
instruction->cc ? "? " : "",
dst,
src0,
instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
src2);
} else {
snprintf(instr_str,
instr_len,
"%-16s%s%s = (%s %s %s) %s %s",
"SFTLP32",
instruction->cc ? "? " : "",
dst,
src0,
LOP[instruction->lop],
src1,
instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
src2);
}
}
static void pvr_pds_disassemble_instruction_stm(struct pvr_stm *instruction,
char *instr_str,
size_t instr_len)
{
char src0[32];
char src1[32];
char src2[32];
char src3[32];
char stm_pred[64];
pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0));
pvr_pds_disassemble_operand(instruction->src1, src1, sizeof(src1));
pvr_pds_disassemble_operand(instruction->src2, src2, sizeof(src2));
pvr_pds_disassemble_operand(instruction->src3, src3, sizeof(src3));
if (instruction->ccs_global)
snprintf(stm_pred, sizeof(stm_pred), "overflow_any");
else if (instruction->ccs_so)
snprintf(stm_pred, sizeof(stm_pred), "overflow_current");
else
stm_pred[0] = 0;
snprintf(instr_str,
instr_len,
"%-16s%s%s%s stm%u = %s, %s, %s, %s",
"STM",
instruction->cc ? "? " : "",
stm_pred,
instruction->tst ? " (TST only)" : "",
instruction->stream_out,
src0,
src1,
src2,
src3);
}
static void pds_disassemble_instruction_stmc(struct pvr_stmc *instruction,
char *instr_str,
size_t instr_len)
{
char src0[32];
pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0));
snprintf(instr_str,
instr_len,
"%-16s%s %s",
"STMC",
instruction->cc ? "? " : "",
src0);
}
static void
pvr_pds_disassemble_instruction_sftlp64(struct pvr_sftlp *instruction,
char *instr_str,
size_t instr_len)
{
char dst[32];
char src0[32];
char src1[32];
char src2[32];
pvr_pds_disassemble_operand(instruction->src0, src0, sizeof(src0));
pvr_pds_disassemble_operand(instruction->src1, src1, sizeof(src1));
pvr_pds_disassemble_operand(instruction->dst, dst, sizeof(dst));
if (instruction->IM)
snprintf(src2, sizeof(src2), "%u", (uint32_t)instruction->src2->literal);
else
pvr_pds_disassemble_operand(instruction->src2, src2, sizeof(src2));
if (instruction->lop == LOP_NONE) {
snprintf(instr_str,
instr_len,
"%-16s%s%s = %s %s %s",
"SFTLP64",
instruction->cc ? "? " : "",
dst,
src0,
instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
src2);
} else if (instruction->lop == LOP_NOT) {
snprintf(instr_str,
instr_len,
"%-16s%s%s = (~%s) %s %s",
"SFTLP64",
instruction->cc ? "? " : "",
dst,
src0,
instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
src2);
} else {
snprintf(instr_str,
instr_len,
"%-16s%s%s = (%s %s %s) %s %s",
"SFTLP64",
instruction->cc ? "? " : "",
dst,
src0,
LOP[instruction->lop],
src1,
instruction->IM ? instruction->src2->negate ? ">>" : "<<" : "<<",
src2);
}
}
static void pvr_pds_disassemble_instruction_cmp(struct pvr_cmp *cmp,
char *instr_str,
size_t instr_len)
{
char src0[32];
char src1[32];
static const char *const COP[] = { "=", ">", "<", "!=" };
pvr_pds_disassemble_operand(cmp->src0, src0, sizeof(src0));
if (cmp->IM) {
snprintf(src1,
sizeof(src1),
"%#04llx",
(unsigned long long)cmp->src1->literal);
} else {
pvr_pds_disassemble_operand(cmp->src1, src1, sizeof(src1));
}
snprintf(instr_str,
instr_len,
"%-16s%sP0 = (%s %s %s)",
"CMP",
cmp->cc ? "? " : "",
src0,
COP[cmp->cop],
src1);
}
static void pvr_pds_disassemble_instruction_ldst(struct pvr_ldst *ins,
char *instr_str,
size_t instr_len)
{
char src0[PVR_PDS_MAX_INST_STR_LEN];
pvr_pds_disassemble_operand(ins->src0, src0, sizeof(src0));
if (ins->st) {
snprintf(instr_str,
instr_len,
"%-16s%s%s: mem(%s) <= src(%s)",
"ST",
ins->cc ? "? " : "",
src0,
"?",
"?");
} else {
snprintf(instr_str,
instr_len,
"%-16s%s%s: dst(%s) <= mem(%s)",
"ld",
ins->cc ? "? " : "",
src0,
"?",
"?");
}
}
static void pvr_pds_disassemble_simple(struct pvr_simple *simple,
const char *type,
char *instr_str,
size_t instr_len)
{
snprintf(instr_str, instr_len, "%-16s%s", type, simple->cc ? "? " : "");
}
static void pvr_pds_disassemble_instruction_limm(struct pvr_limm *limm,
char *instr_str,
size_t instr_len)
{
int32_t imm = (uint32_t)limm->src0->literal;
char dst[PVR_PDS_MAX_INST_STR_LEN];
pvr_pds_disassemble_operand(limm->dst, dst, sizeof(dst));
if (limm->GR) {
char *pchGReg;
switch (imm) {
case 0:
pchGReg = "cluster";
break;
case 1:
pchGReg = "instance";
break;
default:
pchGReg = "unknown";
}
snprintf(instr_str,
instr_len,
"%-16s%s%s = G%d (%s)",
"LIMM",
limm->cc ? "? " : "",
dst,
imm,
pchGReg);
} else {
snprintf(instr_str,
instr_len,
"%-16s%s%s = %#04x",
"LIMM",
limm->cc ? "? " : "",
dst,
imm);
}
}
static void pvr_pds_disassemble_instruction_ddmad(struct pvr_ddmad *ddmad,
char *instr_str,
size_t instr_len)
{
char src0[PVR_PDS_MAX_INST_STR_LEN];
char src1[PVR_PDS_MAX_INST_STR_LEN];
char src2[PVR_PDS_MAX_INST_STR_LEN];
char src3[PVR_PDS_MAX_INST_STR_LEN];
pvr_pds_disassemble_operand(ddmad->src0, src0, sizeof(src0));
pvr_pds_disassemble_operand(ddmad->src1, src1, sizeof(src1));
pvr_pds_disassemble_operand(ddmad->src2, src2, sizeof(src2));
pvr_pds_disassemble_operand(ddmad->src3, src3, sizeof(src3));
snprintf(instr_str,
instr_len,
"%-16s%sdoutd = (%s * %s) + %s, %s%s",
"DDMAD",
ddmad->cc ? "? " : "",
src0,
src1,
src2,
src3,
ddmad->END ? "; HALT" : "");
}
static void pvr_pds_disassemble_predicate(uint32_t predicate,
char *buffer,
size_t buffer_length)
{
switch (predicate) {
case PVR_ROGUE_PDSINST_PREDICATE_P0:
snprintf(buffer, buffer_length, "%s", "p0");
break;
case PVR_ROGUE_PDSINST_PREDICATE_IF0:
snprintf(buffer, buffer_length, "%s", "if0");
break;
case PVR_ROGUE_PDSINST_PREDICATE_IF1:
snprintf(buffer, buffer_length, "%s", "if1");
break;
case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_0:
snprintf(buffer, buffer_length, "%s", "so_overflow_0");
break;
case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_1:
snprintf(buffer, buffer_length, "%s", "so_overflow_1");
break;
case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_2:
snprintf(buffer, buffer_length, "%s", "so_overflow_2");
break;
case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_3:
snprintf(buffer, buffer_length, "%s", "so_overflow_3");
break;
case PVR_ROGUE_PDSINST_PREDICATE_SO_OVERFLOW_PREDICATE_GLOBAL:
snprintf(buffer, buffer_length, "%s", "so_overflow_any");
break;
case PVR_ROGUE_PDSINST_PREDICATE_KEEP:
snprintf(buffer, buffer_length, "%s", "keep");
break;
case PVR_ROGUE_PDSINST_PREDICATE_OOB:
snprintf(buffer, buffer_length, "%s", "oob");
break;
default:
snprintf(buffer, buffer_length, "%s", "<ERROR>");
break;
}
}
static void pvr_pds_disassemble_instruction_bra(struct pvr_bra *bra,
char *instr_str,
size_t instr_len)
{
char setc_pred[32];
char srcc_pred[32];
pvr_pds_disassemble_predicate(bra->srcc->predicate,
srcc_pred,
sizeof(srcc_pred));
pvr_pds_disassemble_predicate(bra->setc->predicate,
setc_pred,
sizeof(setc_pred));
if (bra->setc->predicate != PVR_ROGUE_PDSINST_PREDICATE_KEEP) {
snprintf(instr_str,
instr_len,
"%-16sif %s%s %d ( setc = %s )",
"BRA",
bra->srcc->negate ? "! " : "",
srcc_pred,
bra->address,
setc_pred);
} else {
snprintf(instr_str,
instr_len,
"%-16sif %s%s %d",
"BRA",
bra->srcc->negate ? "! " : "",
srcc_pred,
bra->address);
}
}
static void pvr_pds_disassemble_instruction_mad(struct pvr_mad *mad,
char *instr_str,
size_t instr_len)
{
char src0[PVR_PDS_MAX_INST_STR_LEN];
char src1[PVR_PDS_MAX_INST_STR_LEN];
char src2[PVR_PDS_MAX_INST_STR_LEN];
char dst[PVR_PDS_MAX_INST_STR_LEN];
pvr_pds_disassemble_operand(mad->src0, src0, sizeof(src0));
pvr_pds_disassemble_operand(mad->src1, src1, sizeof(src1));
pvr_pds_disassemble_operand(mad->src2, src2, sizeof(src2));
pvr_pds_disassemble_operand(mad->dst, dst, sizeof(dst));
snprintf(instr_str,
instr_len,
"%-16s%s%s = (%s * %s) %s %s%s",
"MAD",
mad->cc ? "? " : "",
dst,
src0,
src1,
mad->sna ? "-" : "+",
src2,
mad->alum ? " [signed]" : "");
}
static void pvr_pds_disassemble_instruction_dout(struct pvr_dout *dout,
char *instr_str,
size_t instr_len)
{
char src0[PVR_PDS_MAX_INST_STR_LEN];
char src1[PVR_PDS_MAX_INST_STR_LEN];
#define X(dout_dst, str) #str,
static const char *const dst[] = { PVR_PDS_DOUT_DSTS };
#undef X
pvr_pds_disassemble_operand(dout->src0, src0, sizeof(src0));
pvr_pds_disassemble_operand(dout->src1, src1, sizeof(src1));
{
snprintf(instr_str,
instr_len,
"%-16s%s%s = %s, %s%s",
"DOUT",
dout->cc ? "? " : "",
dst[dout->dst],
src0,
src1,
dout->END ? "; HALT" : "");
}
}
void pvr_pds_disassemble_instruction(char *instr_str,
size_t instr_len,
struct pvr_instruction *instruction)
{
if (!instruction) {
snprintf(instr_str,
instr_len,
"Instruction was not disassembled properly\n");
return;
}
switch (instruction->type) {
case INS_LIMM:
pvr_pds_disassemble_instruction_limm((struct pvr_limm *)instruction,
instr_str,
instr_len);
break;
case INS_ADD64:
pvr_pds_disassemble_instruction_add64((struct pvr_add *)instruction,
instr_str,
instr_len);
break;
case INS_ADD32:
pvr_pds_disassemble_instruction_add32((struct pvr_add *)instruction,
instr_str,
instr_len);
break;
case INS_CMP:
pvr_pds_disassemble_instruction_cmp((struct pvr_cmp *)instruction,
instr_str,
instr_len);
break;
case INS_MAD:
pvr_pds_disassemble_instruction_mad((struct pvr_mad *)instruction,
instr_str,
instr_len);
break;
case INS_BRA:
pvr_pds_disassemble_instruction_bra((struct pvr_bra *)instruction,
instr_str,
instr_len);
break;
case INS_DDMAD:
pvr_pds_disassemble_instruction_ddmad((struct pvr_ddmad *)instruction,
instr_str,
instr_len);
break;
case INS_DOUT:
pvr_pds_disassemble_instruction_dout((struct pvr_dout *)instruction,
instr_str,
instr_len);
break;
case INS_LD:
case INS_ST:
pvr_pds_disassemble_instruction_ldst((struct pvr_ldst *)instruction,
instr_str,
instr_len);
break;
case INS_WDF:
pvr_pds_disassemble_simple((struct pvr_simple *)instruction,
"WDF",
instr_str,
instr_len);
break;
case INS_LOCK:
pvr_pds_disassemble_simple((struct pvr_simple *)instruction,
"LOCK",
instr_str,
instr_len);
break;
case INS_RELEASE:
pvr_pds_disassemble_simple((struct pvr_simple *)instruction,
"RELEASE",
instr_str,
instr_len);
break;
case INS_HALT:
pvr_pds_disassemble_simple((struct pvr_simple *)instruction,
"HALT",
instr_str,
instr_len);
break;
case INS_NOP:
pvr_pds_disassemble_simple((struct pvr_simple *)instruction,
"NOP",
instr_str,
instr_len);
break;
case INS_SFTLP32:
pvr_pds_disassemble_instruction_sftlp32((struct pvr_sftlp *)instruction,
instr_str,
instr_len);
break;
case INS_SFTLP64:
pvr_pds_disassemble_instruction_sftlp64((struct pvr_sftlp *)instruction,
instr_str,
instr_len);
break;
case INS_STM:
pvr_pds_disassemble_instruction_stm((struct pvr_stm *)instruction,
instr_str,
instr_len);
break;
case INS_STMC:
pds_disassemble_instruction_stmc((struct pvr_stmc *)instruction,
instr_str,
instr_len);
break;
default:
snprintf(instr_str, instr_len, "Printing not implemented\n");
break;
}
}
#if defined(DUMP_PDS)
void pvr_pds_print_instruction(uint32_t instr)
{
char instruction_str[1024];
struct pvr_instruction *decoded =
pvr_pds_disassemble_instruction2(0, 0, instr);
if (!decoded) {
mesa_logd("%X\n", instr);
} else {
pvr_pds_disassemble_instruction(instruction_str,
sizeof(instruction_str),
decoded);
mesa_logd("\t0x%08x, /* %s */\n", instr, instruction_str);
}
}
#endif

View File

@ -0,0 +1,105 @@
/*
* 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_DRAW_INDIRECTARRAYS0_H
#define PVR_DRAW_INDIRECTARRAYS0_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays0_code[15] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1940000, /* LIMM temp[5].32 = 0000 */
0x500c0804, /* SFTLP32 temp[4].32 = temp[1].32 << 0 */
0xb1880000, /* CMP P0 = (temp[4].64 = 0000) */
0xd9800000, /* LIMM ? temp[0].32 = 0000 */
0xd9840000, /* LIMM ? temp[1].32 = 0000 */
0x04081023, /* MAD temp[6].64 = (temp[1].32 * const[2].32) +
const[4].64 */
0x50343001, /* SFTLP32 temp[1].32 = temp[6].32 << 0 */
0x912040c1, /* ADD32 temp[1].32 = temp[1].32 - const[3].32 */
0xd0800003, /* ST const[6].64: mem(?) <= src(?) */
0xd0000004, /* LD const[8].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf40a4003, /* DOUT doutv = temp[0].64, const[10].32; HALT */
};
static const struct pvr_psc_program_output pvr_draw_indirect_arrays0_program = {
pvr_draw_indirect_arrays0_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
16, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
11, /* size of data segment, in dwords */
15, /* size of code segment, in dwords */
10, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays0_di_data(buffer, addr, device) \
do { \
uint64_t data = ((addr) | (0x40000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays0_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x30000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays0_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x1940000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays0_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays0_immediates(buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,105 @@
/*
* 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_DRAW_INDIRECTARRAYS1_H
#define PVR_DRAW_INDIRECTARRAYS1_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays1_code[15] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1940000, /* LIMM temp[5].32 = 0000 */
0x50141004, /* SFTLP32 temp[4].32 = temp[2].32 << 0 */
0xb1880000, /* CMP P0 = (temp[4].64 = 0000) */
0xd9840000, /* LIMM ? temp[1].32 = 0000 */
0xd9880000, /* LIMM ? temp[2].32 = 0000 */
0x04101023, /* MAD temp[6].64 = (temp[2].32 * const[2].32) +
const[4].64 */
0x50343002, /* SFTLP32 temp[2].32 = temp[6].32 << 0 */
0x912080c2, /* ADD32 temp[2].32 = temp[2].32 - const[3].32 */
0xd0800003, /* ST const[6].64: mem(?) <= src(?) */
0xd0000004, /* LD const[8].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf40a4003, /* DOUT doutv = temp[0].64, const[10].32; HALT */
};
static const struct pvr_psc_program_output pvr_draw_indirect_arrays1_program = {
pvr_draw_indirect_arrays1_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
16, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
11, /* size of data segment, in dwords */
15, /* size of code segment, in dwords */
10, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays1_di_data(buffer, addr, device) \
do { \
uint64_t data = ((addr) | (0x40000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays1_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x430000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays1_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x1940000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays1_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays1_immediates(buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,105 @@
/*
* 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_DRAW_INDIRECTARRAYS2_H
#define PVR_DRAW_INDIRECTARRAYS2_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays2_code[15] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x501c1800, /* SFTLP32 temp[0].32 = temp[3].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd9880000, /* LIMM ? temp[2].32 = 0000 */
0xd98c0000, /* LIMM ? temp[3].32 = 0000 */
0x04181023, /* MAD temp[6].64 = (temp[3].32 * const[2].32) +
const[4].64 */
0x50343003, /* SFTLP32 temp[3].32 = temp[6].32 << 0 */
0x9120c0c3, /* ADD32 temp[3].32 = temp[3].32 - const[3].32 */
0xd0800003, /* ST const[6].64: mem(?) <= src(?) */
0xd0000004, /* LD const[8].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf40a4003, /* DOUT doutv = temp[0].64, const[10].32; HALT */
};
static const struct pvr_psc_program_output pvr_draw_indirect_arrays2_program = {
pvr_draw_indirect_arrays2_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
16, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
11, /* size of data segment, in dwords */
15, /* size of code segment, in dwords */
10, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays2_di_data(buffer, addr, device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays2_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x830000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays2_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x1940000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays2_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays2_immediates(buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,105 @@
/*
* 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_DRAW_INDIRECTARRAYS3_H
#define PVR_DRAW_INDIRECTARRAYS3_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays3_code[15] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x50242000, /* SFTLP32 temp[0].32 = temp[4].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd98c0000, /* LIMM ? temp[3].32 = 0000 */
0xd9900000, /* LIMM ? temp[4].32 = 0000 */
0x04201023, /* MAD temp[6].64 = (temp[4].32 * const[2].32) +
const[4].64 */
0x50343004, /* SFTLP32 temp[4].32 = temp[6].32 << 0 */
0x912100c4, /* ADD32 temp[4].32 = temp[4].32 - const[3].32 */
0xd0800003, /* ST const[6].64: mem(?) <= src(?) */
0xd0000004, /* LD const[8].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf40a4003, /* DOUT doutv = temp[0].64, const[10].32; HALT */
};
static const struct pvr_psc_program_output pvr_draw_indirect_arrays3_program = {
pvr_draw_indirect_arrays3_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
16, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
11, /* size of data segment, in dwords */
15, /* size of code segment, in dwords */
10, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays3_di_data(buffer, addr, device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays3_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0xc30000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays3_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x1940000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays3_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays3_immediates(buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,111 @@
/*
* 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_DRAW_INDIRECTARRAYS_BASE_INSTANCE0_H
#define PVR_DRAW_INDIRECTARRAYS_BASE_INSTANCE0_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays_base_instance0_code[18] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1940000, /* LIMM temp[5].32 = 0000 */
0x500c0804, /* SFTLP32 temp[4].32 = temp[1].32 << 0 */
0xb1880000, /* CMP P0 = (temp[4].64 = 0000) */
0xd9800000, /* LIMM ? temp[0].32 = 0000 */
0xd9840000, /* LIMM ? temp[1].32 = 0000 */
0x04081023, /* MAD temp[6].64 = (temp[1].32 * const[2].32) +
const[4].64 */
0x50343001, /* SFTLP32 temp[1].32 = temp[6].32 << 0 */
0x912040c1, /* ADD32 temp[1].32 = temp[1].32 - const[3].32 */
0x9001a0a0, /* ADD32 ptemp[0].32 = const[6].32 + temp[2].32 */
0xd0800004, /* ST const[8].64: mem(?) <= src(?) */
0x9001a0e1, /* ADD32 ptemp[1].32 = const[6].32 + temp[3].32 */
0x9130f0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 - ptemp[3].32 */
0xd0000005, /* LD const[10].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4064003, /* DOUT doutv = temp[0].64, const[6].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_arrays_base_instance0_program = {
pvr_draw_indirect_arrays_base_instance0_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
20, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
12, /* size of data segment, in dwords */
18, /* size of code segment, in dwords */
10, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays_base_instance0_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x40000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance0_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x30000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance0_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x1940000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance0_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance0_immediates(buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,111 @@
/*
* 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_DRAW_INDIRECTARRAYS_BASE_INSTANCE1_H
#define PVR_DRAW_INDIRECTARRAYS_BASE_INSTANCE1_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays_base_instance1_code[18] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd19c0000, /* LIMM temp[7].32 = 0000 */
0x50141006, /* SFTLP32 temp[6].32 = temp[2].32 << 0 */
0xb18c0000, /* CMP P0 = (temp[6].64 = 0000) */
0xd9840000, /* LIMM ? temp[1].32 = 0000 */
0xd9880000, /* LIMM ? temp[2].32 = 0000 */
0x04101024, /* MAD temp[8].64 = (temp[2].32 * const[2].32) +
const[4].64 */
0x50444002, /* SFTLP32 temp[2].32 = temp[8].32 << 0 */
0x912080c2, /* ADD32 temp[2].32 = temp[2].32 - const[3].32 */
0x9001a0e0, /* ADD32 ptemp[0].32 = const[6].32 + temp[3].32 */
0xd0800004, /* ST const[8].64: mem(?) <= src(?) */
0x9001a121, /* ADD32 ptemp[1].32 = const[6].32 + temp[4].32 */
0x9130f0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 - ptemp[3].32 */
0xd0000005, /* LD const[10].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4064003, /* DOUT doutv = temp[0].64, const[6].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_arrays_base_instance1_program = {
pvr_draw_indirect_arrays_base_instance1_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
20, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
12, /* size of data segment, in dwords */
18, /* size of code segment, in dwords */
12, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays_base_instance1_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance1_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x430000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance1_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x2140000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance1_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance1_immediates(buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,111 @@
/*
* 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_DRAW_INDIRECTARRAYS_BASE_INSTANCE2_H
#define PVR_DRAW_INDIRECTARRAYS_BASE_INSTANCE2_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays_base_instance2_code[18] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x501c1800, /* SFTLP32 temp[0].32 = temp[3].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd9880000, /* LIMM ? temp[2].32 = 0000 */
0xd98c0000, /* LIMM ? temp[3].32 = 0000 */
0x04181023, /* MAD temp[6].64 = (temp[3].32 * const[2].32) +
const[4].64 */
0x50343003, /* SFTLP32 temp[3].32 = temp[6].32 << 0 */
0x9120c0c3, /* ADD32 temp[3].32 = temp[3].32 - const[3].32 */
0x9001a120, /* ADD32 ptemp[0].32 = const[6].32 + temp[4].32 */
0xd0800004, /* ST const[8].64: mem(?) <= src(?) */
0x9001a161, /* ADD32 ptemp[1].32 = const[6].32 + temp[5].32 */
0x9130f0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 - ptemp[3].32 */
0xd0000005, /* LD const[10].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4064003, /* DOUT doutv = temp[0].64, const[6].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_arrays_base_instance2_program = {
pvr_draw_indirect_arrays_base_instance2_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
20, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
12, /* size of data segment, in dwords */
18, /* size of code segment, in dwords */
10, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays_base_instance2_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance2_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x830000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance2_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x1940000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance2_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance2_immediates(buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,111 @@
/*
* 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_DRAW_INDIRECTARRAYS_BASE_INSTANCE3_H
#define PVR_DRAW_INDIRECTARRAYS_BASE_INSTANCE3_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays_base_instance3_code[18] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x50242000, /* SFTLP32 temp[0].32 = temp[4].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd98c0000, /* LIMM ? temp[3].32 = 0000 */
0xd9900000, /* LIMM ? temp[4].32 = 0000 */
0x04201024, /* MAD temp[8].64 = (temp[4].32 * const[2].32) +
const[4].64 */
0x50444004, /* SFTLP32 temp[4].32 = temp[8].32 << 0 */
0x912100c4, /* ADD32 temp[4].32 = temp[4].32 - const[3].32 */
0x9001a160, /* ADD32 ptemp[0].32 = const[6].32 + temp[5].32 */
0xd0800004, /* ST const[8].64: mem(?) <= src(?) */
0x9001a1a1, /* ADD32 ptemp[1].32 = const[6].32 + temp[6].32 */
0x9130f0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 - ptemp[3].32 */
0xd0000005, /* LD const[10].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4064003, /* DOUT doutv = temp[0].64, const[6].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_arrays_base_instance3_program = {
pvr_draw_indirect_arrays_base_instance3_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
20, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
12, /* size of data segment, in dwords */
18, /* size of code segment, in dwords */
12, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays_base_instance3_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x80000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance3_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0xc30000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance3_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x2140000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance3_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance3_immediates(buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,115 @@
/*
* 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_DRAW_INDIRECTARRAYS_BASE_INSTANCE_DRAWID0_H
#define PVR_DRAW_INDIRECTARRAYS_BASE_INSTANCE_DRAWID0_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays_base_instance_drawid0_code[18] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1940000, /* LIMM temp[5].32 = 0000 */
0x500c0804, /* SFTLP32 temp[4].32 = temp[1].32 << 0 */
0xb1880000, /* CMP P0 = (temp[4].64 = 0000) */
0xd9800000, /* LIMM ? temp[0].32 = 0000 */
0xd9840000, /* LIMM ? temp[1].32 = 0000 */
0x04081023, /* MAD temp[6].64 = (temp[1].32 * const[2].32) +
const[4].64 */
0x50343001, /* SFTLP32 temp[1].32 = temp[6].32 << 0 */
0x912040c1, /* ADD32 temp[1].32 = temp[1].32 - const[3].32 */
0x9001a0a0, /* ADD32 ptemp[0].32 = const[6].32 + temp[2].32 */
0xd0800004, /* ST const[8].64: mem(?) <= src(?) */
0x9001a0e1, /* ADD32 ptemp[1].32 = const[6].32 + temp[3].32 */
0x9030c0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 + const[3].32 */
0xd0000005, /* LD const[10].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4064003, /* DOUT doutv = temp[0].64, const[6].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_arrays_base_instance_drawid0_program = {
pvr_draw_indirect_arrays_base_instance_drawid0_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
20, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
12, /* size of data segment, in dwords */
18, /* size of code segment, in dwords */
10, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays_base_instance_drawid0_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x40000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid0_write_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x30000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid0_flush_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x1940000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid0_num_views(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid0_immediates( \
buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,115 @@
/*
* 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_DRAW_INDIRECTARRAYS_BASE_INSTANCE_DRAWID1_H
#define PVR_DRAW_INDIRECTARRAYS_BASE_INSTANCE_DRAWID1_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays_base_instance_drawid1_code[18] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd19c0000, /* LIMM temp[7].32 = 0000 */
0x50141006, /* SFTLP32 temp[6].32 = temp[2].32 << 0 */
0xb18c0000, /* CMP P0 = (temp[6].64 = 0000) */
0xd9840000, /* LIMM ? temp[1].32 = 0000 */
0xd9880000, /* LIMM ? temp[2].32 = 0000 */
0x04101024, /* MAD temp[8].64 = (temp[2].32 * const[2].32) +
const[4].64 */
0x50444002, /* SFTLP32 temp[2].32 = temp[8].32 << 0 */
0x912080c2, /* ADD32 temp[2].32 = temp[2].32 - const[3].32 */
0x9001a0e0, /* ADD32 ptemp[0].32 = const[6].32 + temp[3].32 */
0xd0800004, /* ST const[8].64: mem(?) <= src(?) */
0x9001a121, /* ADD32 ptemp[1].32 = const[6].32 + temp[4].32 */
0x9030c0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 + const[3].32 */
0xd0000005, /* LD const[10].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4064003, /* DOUT doutv = temp[0].64, const[6].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_arrays_base_instance_drawid1_program = {
pvr_draw_indirect_arrays_base_instance_drawid1_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
20, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
12, /* size of data segment, in dwords */
18, /* size of code segment, in dwords */
12, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays_base_instance_drawid1_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid1_write_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x430000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid1_flush_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x2140000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid1_num_views(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid1_immediates( \
buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,115 @@
/*
* 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_DRAW_INDIRECTARRAYS_BASE_INSTANCE_DRAWID2_H
#define PVR_DRAW_INDIRECTARRAYS_BASE_INSTANCE_DRAWID2_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays_base_instance_drawid2_code[18] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x501c1800, /* SFTLP32 temp[0].32 = temp[3].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd9880000, /* LIMM ? temp[2].32 = 0000 */
0xd98c0000, /* LIMM ? temp[3].32 = 0000 */
0x04181023, /* MAD temp[6].64 = (temp[3].32 * const[2].32) +
const[4].64 */
0x50343003, /* SFTLP32 temp[3].32 = temp[6].32 << 0 */
0x9120c0c3, /* ADD32 temp[3].32 = temp[3].32 - const[3].32 */
0x9001a120, /* ADD32 ptemp[0].32 = const[6].32 + temp[4].32 */
0xd0800004, /* ST const[8].64: mem(?) <= src(?) */
0x9001a161, /* ADD32 ptemp[1].32 = const[6].32 + temp[5].32 */
0x9030c0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 + const[3].32 */
0xd0000005, /* LD const[10].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4064003, /* DOUT doutv = temp[0].64, const[6].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_arrays_base_instance_drawid2_program = {
pvr_draw_indirect_arrays_base_instance_drawid2_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
20, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
12, /* size of data segment, in dwords */
18, /* size of code segment, in dwords */
10, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays_base_instance_drawid2_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid2_write_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x830000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid2_flush_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x1940000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid2_num_views(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid2_immediates( \
buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,115 @@
/*
* 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_DRAW_INDIRECTARRAYS_BASE_INSTANCE_DRAWID3_H
#define PVR_DRAW_INDIRECTARRAYS_BASE_INSTANCE_DRAWID3_H
/* Initially generated from ARB_draw_indirect_arrays.pds */
static const uint32_t pvr_draw_indirect_arrays_base_instance_drawid3_code[18] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x50242000, /* SFTLP32 temp[0].32 = temp[4].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd98c0000, /* LIMM ? temp[3].32 = 0000 */
0xd9900000, /* LIMM ? temp[4].32 = 0000 */
0x04201024, /* MAD temp[8].64 = (temp[4].32 * const[2].32) +
const[4].64 */
0x50444004, /* SFTLP32 temp[4].32 = temp[8].32 << 0 */
0x912100c4, /* ADD32 temp[4].32 = temp[4].32 - const[3].32 */
0x9001a160, /* ADD32 ptemp[0].32 = const[6].32 + temp[5].32 */
0xd0800004, /* ST const[8].64: mem(?) <= src(?) */
0x9001a1a1, /* ADD32 ptemp[1].32 = const[6].32 + temp[6].32 */
0x9030c0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 + const[3].32 */
0xd0000005, /* LD const[10].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4064003, /* DOUT doutv = temp[0].64, const[6].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_arrays_base_instance_drawid3_program = {
pvr_draw_indirect_arrays_base_instance_drawid3_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
4, /* number of constant mappings */
12, /* size of data segment, in dwords, aligned to 4 */
20, /* size of code segment, in dwords, aligned to 4 */
12, /* size of temp segment, in dwords, aligned to 4 */
12, /* size of data segment, in dwords */
18, /* size of code segment, in dwords */
12, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_arrays_base_instance_drawid3_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x80000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid3_write_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0xc30000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid3_flush_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x2140000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid3_num_views(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_arrays_base_instance_drawid3_immediates( \
buffer) \
do { \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ARRAYS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,131 @@
/*
* 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_DRAW_INDIRECTELEMENTS0_H
#define PVR_DRAW_INDIRECTELEMENTS0_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t pvr_draw_indirect_elements0_code[21] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a0e0, /* ADD32 ptemp[0].32 = const[2].32 + temp[3].32 */
0x04101822, /* MAD temp[4].64 = (temp[2].32 * const[3].32) +
const[4].64 */
0x53283006, /* SFTLP32 temp[6].32 = (temp[5].32 | const[6].32) << 0
*/
0x50242007, /* SFTLP32 temp[7].32 = temp[4].32 << 0 */
0x04083842, /* MAD temp[4].64 = (temp[1].32 * const[7].32) +
const[8].64 */
0x50242001, /* SFTLP32 temp[1].32 = temp[4].32 << 0 */
0x50040008, /* SFTLP32 temp[8].32 = temp[0].32 << 0 */
0x91204289, /* ADD32 temp[9].32 = temp[1].32 - const[10].32 */
0x501c180a, /* SFTLP32 temp[10].32 = temp[3].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1940000, /* LIMM temp[5].32 = 0000 */
0x500c0804, /* SFTLP32 temp[4].32 = temp[1].32 << 0 */
0xb1880000, /* CMP P0 = (temp[4].64 = 0000) */
0xd9a00000, /* LIMM ? temp[8].32 = 0000 */
0xd9a40000, /* LIMM ? temp[9].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output pvr_draw_indirect_elements0_program = {
pvr_draw_indirect_elements0_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
21, /* size of code segment, in dwords */
18, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements0_di_data(buffer, addr, device) \
do { \
uint64_t data = ((addr) | (0x40000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements0_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x1850000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements0_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x3160000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements0_idx_stride(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements0_idx_base(buffer, value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements0_idx_header(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements0_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 7, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements0_immediates(buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,131 @@
/*
* 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_DRAW_INDIRECTELEMENTS1_H
#define PVR_DRAW_INDIRECTELEMENTS1_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t pvr_draw_indirect_elements1_code[21] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a120, /* ADD32 ptemp[0].32 = const[2].32 + temp[4].32 */
0x04181823, /* MAD temp[6].64 = (temp[3].32 * const[3].32) +
const[4].64 */
0x53383008, /* SFTLP32 temp[8].32 = (temp[7].32 | const[6].32) << 0
*/
0x50343009, /* SFTLP32 temp[9].32 = temp[6].32 << 0 */
0x04103843, /* MAD temp[6].64 = (temp[2].32 * const[7].32) +
const[8].64 */
0x50343002, /* SFTLP32 temp[2].32 = temp[6].32 << 0 */
0x500c080a, /* SFTLP32 temp[10].32 = temp[1].32 << 0 */
0x9120828b, /* ADD32 temp[11].32 = temp[2].32 - const[10].32 */
0x5024200c, /* SFTLP32 temp[12].32 = temp[4].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd19c0000, /* LIMM temp[7].32 = 0000 */
0x50141006, /* SFTLP32 temp[6].32 = temp[2].32 << 0 */
0xb18c0000, /* CMP P0 = (temp[6].64 = 0000) */
0xd9a80000, /* LIMM ? temp[10].32 = 0000 */
0xd9ac0000, /* LIMM ? temp[11].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output pvr_draw_indirect_elements1_program = {
pvr_draw_indirect_elements1_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
21, /* size of code segment, in dwords */
20, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements1_di_data(buffer, addr, device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements1_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x2050000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements1_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x3960000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements1_idx_stride(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements1_idx_base(buffer, value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements1_idx_header(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements1_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 7, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements1_immediates(buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,131 @@
/*
* 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_DRAW_INDIRECTELEMENTS2_H
#define PVR_DRAW_INDIRECTELEMENTS2_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t pvr_draw_indirect_elements2_code[21] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a160, /* ADD32 ptemp[0].32 = const[2].32 + temp[5].32 */
0x04201820, /* MAD temp[0].64 = (temp[4].32 * const[3].32) +
const[4].64 */
0x53083006, /* SFTLP32 temp[6].32 = (temp[1].32 | const[6].32) << 0
*/
0x50040007, /* SFTLP32 temp[7].32 = temp[0].32 << 0 */
0x04183840, /* MAD temp[0].64 = (temp[3].32 * const[7].32) +
const[8].64 */
0x50040003, /* SFTLP32 temp[3].32 = temp[0].32 << 0 */
0x50141008, /* SFTLP32 temp[8].32 = temp[2].32 << 0 */
0x9120c289, /* ADD32 temp[9].32 = temp[3].32 - const[10].32 */
0x502c280a, /* SFTLP32 temp[10].32 = temp[5].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x501c1800, /* SFTLP32 temp[0].32 = temp[3].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd9a00000, /* LIMM ? temp[8].32 = 0000 */
0xd9a40000, /* LIMM ? temp[9].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output pvr_draw_indirect_elements2_program = {
pvr_draw_indirect_elements2_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
21, /* size of code segment, in dwords */
18, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements2_di_data(buffer, addr, device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements2_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x1850000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements2_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x3160000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements2_idx_stride(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements2_idx_base(buffer, value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements2_idx_header(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements2_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 7, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements2_immediates(buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,131 @@
/*
* 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_DRAW_INDIRECTELEMENTS3_H
#define PVR_DRAW_INDIRECTELEMENTS3_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t pvr_draw_indirect_elements3_code[21] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a1a0, /* ADD32 ptemp[0].32 = const[2].32 + temp[6].32 */
0x04281820, /* MAD temp[0].64 = (temp[5].32 * const[3].32) +
const[4].64 */
0x53083007, /* SFTLP32 temp[7].32 = (temp[1].32 | const[6].32) << 0
*/
0x50040008, /* SFTLP32 temp[8].32 = temp[0].32 << 0 */
0x04203840, /* MAD temp[0].64 = (temp[4].32 * const[7].32) +
const[8].64 */
0x50040004, /* SFTLP32 temp[4].32 = temp[0].32 << 0 */
0x501c1809, /* SFTLP32 temp[9].32 = temp[3].32 << 0 */
0x9121028a, /* ADD32 temp[10].32 = temp[4].32 - const[10].32 */
0x5034300b, /* SFTLP32 temp[11].32 = temp[6].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x50242000, /* SFTLP32 temp[0].32 = temp[4].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd9a40000, /* LIMM ? temp[9].32 = 0000 */
0xd9a80000, /* LIMM ? temp[10].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output pvr_draw_indirect_elements3_program = {
pvr_draw_indirect_elements3_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
21, /* size of code segment, in dwords */
18, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements3_di_data(buffer, addr, device) \
do { \
uint64_t data = ((addr) | (0x80000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements3_write_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x1c50000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements3_flush_vdm(buffer, addr) \
do { \
uint64_t data = ((addr) | (0x3160000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements3_idx_stride(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements3_idx_base(buffer, value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements3_idx_header(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements3_num_views(buffer, value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 7, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements3_immediates(buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,142 @@
/*
* 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_DRAW_INDIRECTELEMENTS_BASE_INSTANCE0_H
#define PVR_DRAW_INDIRECTELEMENTS_BASE_INSTANCE0_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t pvr_draw_indirect_elements_base_instance0_code[23] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a0e0, /* ADD32 ptemp[0].32 = const[2].32 + temp[3].32 */
0x9000a121, /* ADD32 ptemp[1].32 = const[2].32 + temp[4].32 */
0x9130f0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 - ptemp[3].32 */
0x04101823, /* MAD temp[6].64 = (temp[2].32 * const[3].32) +
const[4].64 */
0x53383008, /* SFTLP32 temp[8].32 = (temp[7].32 | const[6].32) << 0
*/
0x50343009, /* SFTLP32 temp[9].32 = temp[6].32 << 0 */
0x04083843, /* MAD temp[6].64 = (temp[1].32 * const[7].32) +
const[8].64 */
0x50343001, /* SFTLP32 temp[1].32 = temp[6].32 << 0 */
0x5004000a, /* SFTLP32 temp[10].32 = temp[0].32 << 0 */
0x9120428b, /* ADD32 temp[11].32 = temp[1].32 - const[10].32 */
0x501c180c, /* SFTLP32 temp[12].32 = temp[3].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd19c0000, /* LIMM temp[7].32 = 0000 */
0x500c0806, /* SFTLP32 temp[6].32 = temp[1].32 << 0 */
0xb18c0000, /* CMP P0 = (temp[6].64 = 0000) */
0xd9a80000, /* LIMM ? temp[10].32 = 0000 */
0xd9ac0000, /* LIMM ? temp[11].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_elements_base_instance0_program = {
pvr_draw_indirect_elements_base_instance0_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
23, /* size of code segment, in dwords */
20, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements_base_instance0_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance0_write_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x2050000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance0_flush_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x3960000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance0_idx_stride(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance0_idx_base(buffer, \
value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance0_idx_header(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance0_num_views(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 7, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance0_immediates(buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,142 @@
/*
* 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_DRAW_INDIRECTELEMENTS_BASE_INSTANCE1_H
#define PVR_DRAW_INDIRECTELEMENTS_BASE_INSTANCE1_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t pvr_draw_indirect_elements_base_instance1_code[23] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a120, /* ADD32 ptemp[0].32 = const[2].32 + temp[4].32 */
0x9000a161, /* ADD32 ptemp[1].32 = const[2].32 + temp[5].32 */
0x9130f0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 - ptemp[3].32 */
0x04181823, /* MAD temp[6].64 = (temp[3].32 * const[3].32) +
const[4].64 */
0x53383008, /* SFTLP32 temp[8].32 = (temp[7].32 | const[6].32) << 0
*/
0x50343009, /* SFTLP32 temp[9].32 = temp[6].32 << 0 */
0x04103843, /* MAD temp[6].64 = (temp[2].32 * const[7].32) +
const[8].64 */
0x50343002, /* SFTLP32 temp[2].32 = temp[6].32 << 0 */
0x500c080a, /* SFTLP32 temp[10].32 = temp[1].32 << 0 */
0x9120828b, /* ADD32 temp[11].32 = temp[2].32 - const[10].32 */
0x5024200c, /* SFTLP32 temp[12].32 = temp[4].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd19c0000, /* LIMM temp[7].32 = 0000 */
0x50141006, /* SFTLP32 temp[6].32 = temp[2].32 << 0 */
0xb18c0000, /* CMP P0 = (temp[6].64 = 0000) */
0xd9a80000, /* LIMM ? temp[10].32 = 0000 */
0xd9ac0000, /* LIMM ? temp[11].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_elements_base_instance1_program = {
pvr_draw_indirect_elements_base_instance1_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
23, /* size of code segment, in dwords */
20, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements_base_instance1_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance1_write_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x2050000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance1_flush_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x3960000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance1_idx_stride(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance1_idx_base(buffer, \
value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance1_idx_header(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance1_num_views(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 7, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance1_immediates(buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,142 @@
/*
* 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_DRAW_INDIRECTELEMENTS_BASE_INSTANCE2_H
#define PVR_DRAW_INDIRECTELEMENTS_BASE_INSTANCE2_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t pvr_draw_indirect_elements_base_instance2_code[23] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a160, /* ADD32 ptemp[0].32 = const[2].32 + temp[5].32 */
0x9000a1a1, /* ADD32 ptemp[1].32 = const[2].32 + temp[6].32 */
0x9130f0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 - ptemp[3].32 */
0x04201820, /* MAD temp[0].64 = (temp[4].32 * const[3].32) +
const[4].64 */
0x53083007, /* SFTLP32 temp[7].32 = (temp[1].32 | const[6].32) << 0
*/
0x50040008, /* SFTLP32 temp[8].32 = temp[0].32 << 0 */
0x04183840, /* MAD temp[0].64 = (temp[3].32 * const[7].32) +
const[8].64 */
0x50040003, /* SFTLP32 temp[3].32 = temp[0].32 << 0 */
0x50141009, /* SFTLP32 temp[9].32 = temp[2].32 << 0 */
0x9120c28a, /* ADD32 temp[10].32 = temp[3].32 - const[10].32 */
0x502c280b, /* SFTLP32 temp[11].32 = temp[5].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x501c1800, /* SFTLP32 temp[0].32 = temp[3].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd9a40000, /* LIMM ? temp[9].32 = 0000 */
0xd9a80000, /* LIMM ? temp[10].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_elements_base_instance2_program = {
pvr_draw_indirect_elements_base_instance2_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
23, /* size of code segment, in dwords */
18, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements_base_instance2_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x80000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance2_write_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x1c50000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance2_flush_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x3160000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance2_idx_stride(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance2_idx_base(buffer, \
value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance2_idx_header(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance2_num_views(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 7, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance2_immediates(buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,142 @@
/*
* 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_DRAW_INDIRECTELEMENTS_BASE_INSTANCE3_H
#define PVR_DRAW_INDIRECTELEMENTS_BASE_INSTANCE3_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t pvr_draw_indirect_elements_base_instance3_code[23] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a1a0, /* ADD32 ptemp[0].32 = const[2].32 + temp[6].32 */
0x9000a1e1, /* ADD32 ptemp[1].32 = const[2].32 + temp[7].32 */
0x9130f0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 - ptemp[3].32 */
0x04281820, /* MAD temp[0].64 = (temp[5].32 * const[3].32) +
const[4].64 */
0x53083008, /* SFTLP32 temp[8].32 = (temp[1].32 | const[6].32) << 0
*/
0x50040009, /* SFTLP32 temp[9].32 = temp[0].32 << 0 */
0x04203840, /* MAD temp[0].64 = (temp[4].32 * const[7].32) +
const[8].64 */
0x50040004, /* SFTLP32 temp[4].32 = temp[0].32 << 0 */
0x501c180a, /* SFTLP32 temp[10].32 = temp[3].32 << 0 */
0x9121028b, /* ADD32 temp[11].32 = temp[4].32 - const[10].32 */
0x5034300c, /* SFTLP32 temp[12].32 = temp[6].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x50242000, /* SFTLP32 temp[0].32 = temp[4].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd9a80000, /* LIMM ? temp[10].32 = 0000 */
0xd9ac0000, /* LIMM ? temp[11].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_elements_base_instance3_program = {
pvr_draw_indirect_elements_base_instance3_code, /* code segment */
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
23, /* size of code segment, in dwords */
20, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements_base_instance3_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x80000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance3_write_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x2050000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance3_flush_vdm(buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x3960000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance3_idx_stride(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance3_idx_base(buffer, \
value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance3_idx_header(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance3_num_views(buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 7, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance3_immediates(buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,152 @@
/*
* 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_DRAW_INDIRECTELEMENTS_BASE_INSTANCE_DRAWID0_H
#define PVR_DRAW_INDIRECTELEMENTS_BASE_INSTANCE_DRAWID0_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t
pvr_draw_indirect_elements_base_instance_drawid0_code[23] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a0e0, /* ADD32 ptemp[0].32 = const[2].32 + temp[3].32 */
0x9000a121, /* ADD32 ptemp[1].32 = const[2].32 + temp[4].32 */
0x9030c0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 + const[3].32 */
0x04102033, /* MAD temp[6].64 = (temp[2].32 * const[4].32) +
const[6].64 */
0x53382808, /* SFTLP32 temp[8].32 = (temp[7].32 | const[5].32) <<
* 0
*/
0x50343009, /* SFTLP32 temp[9].32 = temp[6].32 << 0 */
0x04084053, /* MAD temp[6].64 = (temp[1].32 * const[8].32) +
const[10].64 */
0x50343001, /* SFTLP32 temp[1].32 = temp[6].32 << 0 */
0x5004000a, /* SFTLP32 temp[10].32 = temp[0].32 << 0 */
0x912040cb, /* ADD32 temp[11].32 = temp[1].32 - const[3].32 */
0x501c180c, /* SFTLP32 temp[12].32 = temp[3].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd19c0000, /* LIMM temp[7].32 = 0000 */
0x500c0806, /* SFTLP32 temp[6].32 = temp[1].32 << 0 */
0xb18c0000, /* CMP P0 = (temp[6].64 = 0000) */
0xd9a80000, /* LIMM ? temp[10].32 = 0000 */
0xd9ac0000, /* LIMM ? temp[11].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_elements_base_instance_drawid0_program = {
pvr_draw_indirect_elements_base_instance_drawid0_code, /* code segment
*/
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
23, /* size of code segment, in dwords */
20, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements_base_instance_drawid0_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid0_write_vdm( \
buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x2050000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid0_flush_vdm( \
buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x3960000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid0_idx_stride( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid0_idx_base( \
buffer, \
value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid0_idx_header( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 5, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid0_num_views( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid0_immediates( \
buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,152 @@
/*
* 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_DRAW_INDIRECTELEMENTS_BASE_INSTANCE_DRAWID1_H
#define PVR_DRAW_INDIRECTELEMENTS_BASE_INSTANCE_DRAWID1_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t
pvr_draw_indirect_elements_base_instance_drawid1_code[23] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a120, /* ADD32 ptemp[0].32 = const[2].32 + temp[4].32 */
0x9000a161, /* ADD32 ptemp[1].32 = const[2].32 + temp[5].32 */
0x9030c0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 + const[3].32 */
0x04182033, /* MAD temp[6].64 = (temp[3].32 * const[4].32) +
const[6].64 */
0x53382808, /* SFTLP32 temp[8].32 = (temp[7].32 | const[5].32) <<
* 0
*/
0x50343009, /* SFTLP32 temp[9].32 = temp[6].32 << 0 */
0x04104053, /* MAD temp[6].64 = (temp[2].32 * const[8].32) +
const[10].64 */
0x50343002, /* SFTLP32 temp[2].32 = temp[6].32 << 0 */
0x500c080a, /* SFTLP32 temp[10].32 = temp[1].32 << 0 */
0x912080cb, /* ADD32 temp[11].32 = temp[2].32 - const[3].32 */
0x5024200c, /* SFTLP32 temp[12].32 = temp[4].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd19c0000, /* LIMM temp[7].32 = 0000 */
0x50141006, /* SFTLP32 temp[6].32 = temp[2].32 << 0 */
0xb18c0000, /* CMP P0 = (temp[6].64 = 0000) */
0xd9a80000, /* LIMM ? temp[10].32 = 0000 */
0xd9ac0000, /* LIMM ? temp[11].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_elements_base_instance_drawid1_program = {
pvr_draw_indirect_elements_base_instance_drawid1_code, /* code segment
*/
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
23, /* size of code segment, in dwords */
20, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements_base_instance_drawid1_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x60000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid1_write_vdm( \
buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x2050000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid1_flush_vdm( \
buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x3960000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid1_idx_stride( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid1_idx_base( \
buffer, \
value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid1_idx_header( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 5, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid1_num_views( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid1_immediates( \
buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,152 @@
/*
* 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_DRAW_INDIRECTELEMENTS_BASE_INSTANCE_DRAWID2_H
#define PVR_DRAW_INDIRECTELEMENTS_BASE_INSTANCE_DRAWID2_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t
pvr_draw_indirect_elements_base_instance_drawid2_code[23] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a160, /* ADD32 ptemp[0].32 = const[2].32 + temp[5].32 */
0x9000a1a1, /* ADD32 ptemp[1].32 = const[2].32 + temp[6].32 */
0x9030c0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 + const[3].32 */
0x04202030, /* MAD temp[0].64 = (temp[4].32 * const[4].32) +
const[6].64 */
0x53082807, /* SFTLP32 temp[7].32 = (temp[1].32 | const[5].32) <<
* 0
*/
0x50040008, /* SFTLP32 temp[8].32 = temp[0].32 << 0 */
0x04184050, /* MAD temp[0].64 = (temp[3].32 * const[8].32) +
const[10].64 */
0x50040003, /* SFTLP32 temp[3].32 = temp[0].32 << 0 */
0x50141009, /* SFTLP32 temp[9].32 = temp[2].32 << 0 */
0x9120c0ca, /* ADD32 temp[10].32 = temp[3].32 - const[3].32 */
0x502c280b, /* SFTLP32 temp[11].32 = temp[5].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x501c1800, /* SFTLP32 temp[0].32 = temp[3].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd9a40000, /* LIMM ? temp[9].32 = 0000 */
0xd9a80000, /* LIMM ? temp[10].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_elements_base_instance_drawid2_program = {
pvr_draw_indirect_elements_base_instance_drawid2_code, /* code segment
*/
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
23, /* size of code segment, in dwords */
18, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements_base_instance_drawid2_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x80000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid2_write_vdm( \
buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x1c50000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid2_flush_vdm( \
buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x3160000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid2_idx_stride( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid2_idx_base( \
buffer, \
value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid2_idx_header( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 5, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid2_num_views( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid2_immediates( \
buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

View File

@ -0,0 +1,152 @@
/*
* 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_DRAW_INDIRECTELEMENTS_BASE_INSTANCE_DRAWID3_H
#define PVR_DRAW_INDIRECTELEMENTS_BASE_INSTANCE_DRAWID3_H
/* Initially generated from ARB_draw_indirect_elements.pds */
static const uint32_t
pvr_draw_indirect_elements_base_instance_drawid3_code[23] = {
0xd0000000, /* LD const[0].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0x9000a1a0, /* ADD32 ptemp[0].32 = const[2].32 + temp[6].32 */
0x9000a1e1, /* ADD32 ptemp[1].32 = const[2].32 + temp[7].32 */
0x9030c0e3, /* ADD32 ptemp[3].32 = ptemp[3].32 + const[3].32 */
0x04282030, /* MAD temp[0].64 = (temp[5].32 * const[4].32) +
const[6].64 */
0x53082808, /* SFTLP32 temp[8].32 = (temp[1].32 | const[5].32) <<
* 0
*/
0x50040009, /* SFTLP32 temp[9].32 = temp[0].32 << 0 */
0x04204050, /* MAD temp[0].64 = (temp[4].32 * const[8].32) +
const[10].64 */
0x50040004, /* SFTLP32 temp[4].32 = temp[0].32 << 0 */
0x501c180a, /* SFTLP32 temp[10].32 = temp[3].32 << 0 */
0x912100cb, /* ADD32 temp[11].32 = temp[4].32 - const[3].32 */
0x5034300c, /* SFTLP32 temp[12].32 = temp[6].32 << 0 */
0xc8000001, /* BRA if keep 1 ( setc = p0 ) */
0xd1840000, /* LIMM temp[1].32 = 0000 */
0x50242000, /* SFTLP32 temp[0].32 = temp[4].32 << 0 */
0xb1800000, /* CMP P0 = (temp[0].64 = 0000) */
0xd9a80000, /* LIMM ? temp[10].32 = 0000 */
0xd9ac0000, /* LIMM ? temp[11].32 = 0000 */
0xd0800006, /* ST const[12].64: mem(?) <= src(?) */
0xd0000007, /* LD const[14].64: dst(?) <= mem(?) */
0xd1000000, /* WDF */
0xf4024003, /* DOUT doutv = temp[0].64, const[2].32; HALT */
};
static const struct pvr_psc_program_output
pvr_draw_indirect_elements_base_instance_drawid3_program = {
pvr_draw_indirect_elements_base_instance_drawid3_code, /* code segment
*/
0, /* constant mappings, zeroed since we use the macros below */
7, /* number of constant mappings */
16, /* size of data segment, in dwords, aligned to 4 */
24, /* size of code segment, in dwords, aligned to 4 */
20, /* size of temp segment, in dwords, aligned to 4 */
16, /* size of data segment, in dwords */
23, /* size of code segment, in dwords */
20, /* size of temp segment, in dwords */
NULL /* function pointer to write data segment */
};
#define pvr_write_draw_indirect_elements_base_instance_drawid3_di_data(buffer, \
addr, \
device) \
do { \
uint64_t data = ((addr) | (0x80000000000ULL) | \
ENABLE_SLC_MCU_CACHE_CONTROLS(device)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 0, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid3_write_vdm( \
buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x2050000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 12, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid3_flush_vdm( \
buffer, \
addr) \
do { \
uint64_t data = ((addr) | (0x3960000000000ULL)); \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 14, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid3_idx_stride( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 4, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid3_idx_base( \
buffer, \
value) \
do { \
uint64_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 6, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid3_idx_header( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 5, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid3_num_views( \
buffer, \
value) \
do { \
uint32_t data = value; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 8, &data, sizeof(data)); \
} while (0)
#define pvr_write_draw_indirect_elements_base_instance_drawid3_immediates( \
buffer) \
do { \
{ \
uint32_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 2, &data, sizeof(data)); \
} \
{ \
uint32_t data = 0x1; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 3, &data, sizeof(data)); \
} \
{ \
uint64_t data = 0x0; \
PVR_PDS_PRINT_DATA("DRAW_INDIRECT_ELEMENTS", data, 0); \
memcpy(buffer + 10, &data, sizeof(data)); \
} \
} while (0)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,287 @@
/*
* 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_ROGUE_PDS_DISASM_H
#define PVR_ROGUE_PDS_DISASM_H
#include <stdbool.h>
#include <stdint.h>
#include "util/log.h"
/* Type of operand for an instruction. */
#define PVR_PDS_OPERAND_TYPES \
X(TEMP32, temp, 32) \
X(PTEMP32, ptemp, 32) \
X(CONST32, const, 32) \
X(TEMP64, temp, 64) \
X(PTEMP64, ptemp, 64) \
X(CONST64, const, 64) \
X(UNRESOLVED, UNRESOLVED, 0) \
X(LITERAL_NUM, literal, 0)
#define X(enum, str, size) enum,
enum pvr_operand_type { PVR_PDS_OPERAND_TYPES };
#undef X
#if defined(DUMP_PDS)
# define PVR_PDS_PRINT_INST(X) pvr_pds_print_instruction(X)
# define PVR_PDS_PRINT_DATA(X, Y, Z) \
mesa_logd("\t%s : DATA = 0x%lX ADDRESS = 0x%X\n", X, (uint64_t)(Y), Z)
#else
# define PVR_PDS_PRINT_INST(X)
# define PVR_PDS_PRINT_DATA(X, Y, Z)
#endif
#define PVR_INSTRUCTION_STMP
#define PVR_INSTRUCTION_IDIV
#define PVR_INSTRUCTION_AA
#define PVR_INSTRUCTION_POL
#define PVR_INSTRUCTION_IDF
#define PVR_INSTRUCTIONS \
X(STM) \
PVR_INSTRUCTION_STMP \
PVR_INSTRUCTION_IDIV \
PVR_INSTRUCTION_AA \
PVR_INSTRUCTION_IDF \
PVR_INSTRUCTION_POL \
X(STMC) \
X(LD) \
X(ST) \
X(ADD32) \
X(ADD64) \
X(MAD) \
X(DDMAD) \
X(DOUT) \
X(CMP) \
X(BRA) \
X(LIMM) \
X(SFTLP32) \
X(SFTLP64) \
X(WDF) \
X(LOCK) \
X(RELEASE) \
X(HALT) \
X(NOP)
#define X(a) INS_##a,
enum pvr_instruction_type { PVR_INSTRUCTIONS };
#undef X
struct pvr_predicate {
uint32_t predicate;
bool negate;
};
struct pvr_instruction;
/* Operands are either sources or dst of an instruction. */
struct pvr_operand {
enum pvr_operand_type type;
struct pvr_instruction *instruction;
uint64_t literal; /* Literal value if type == LITERAL_NUM */
int address; /* Address in word-sizes. */
unsigned absolute_address; /* Address in segment, */
unsigned index; /* Index within instruction, 0 = dst, 1 = src0 .. */
bool negate; /* True if the literal is negative. */
};
#define PVR_PDS_LOP \
X(LOP_NONE, none) \
X(LOP_NOT, ~) \
X(LOP_AND, &) \
X(LOP_OR, |) \
X(LOP_XOR, xor) \
X(LOP_XNOR, xnor) \
X(LOP_NAND, nand) \
X(LOP_NOR, nor)
#define X(lop, str) lop,
enum pvr_pds_lop { PVR_PDS_LOP };
#undef X
#define PVR_PDS_DOUT_DSTS \
X(DOUT_D, doutd) \
X(DOUT_W, doutw) \
X(DOUT_U, doutu) \
X(DOUT_V, doutv) \
X(DOUT_I, douti) \
X(DOUT_C, doutc) \
X(DOUT_R, doutr) \
X(DOUT_INVALID0, invalid)
#define X(dout_dst, str) dout_dst,
enum pvr_dout_type { PVR_PDS_DOUT_DSTS };
#undef X
#define PVR_PDS_MAX_INST_STR_LEN 256
enum pvr_cop { COP_EQ, COP_GT, COP_LT, COP_NE };
struct pvr_instruction {
enum pvr_instruction_type type;
struct pvr_instruction *next;
};
struct pvr_add {
struct pvr_instruction instruction;
struct pvr_operand *dst;
struct pvr_operand *src1;
struct pvr_operand *src0;
bool cc;
bool sna;
bool alum;
};
struct pvr_simple {
struct pvr_instruction instruction;
bool cc;
};
struct pvr_ldst {
struct pvr_instruction instruction;
bool cc;
struct pvr_operand *src0;
bool st;
};
struct pvr_mad {
struct pvr_instruction instruction;
struct pvr_operand *dst;
struct pvr_operand *src0;
struct pvr_operand *src1;
struct pvr_operand *src2;
bool cc;
bool sna;
bool alum;
};
struct pvr_stm {
struct pvr_instruction instruction;
struct pvr_operand *src0;
struct pvr_operand *src1;
struct pvr_operand *src2;
struct pvr_operand *src3;
unsigned stream_out;
bool tst;
bool cc;
bool ccs_global;
bool ccs_so;
};
struct pvr_stmc {
struct pvr_instruction instruction;
struct pvr_operand *src0;
bool cc;
};
struct pvr_bra {
struct pvr_instruction instruction;
struct pvr_predicate *srcc;
struct pvr_predicate *setc; /* negate ignored */
char *target;
signed address; /* signed relative address */
};
struct pvr_dout {
struct pvr_instruction instruction;
struct pvr_operand *src0;
struct pvr_operand *src1;
enum pvr_dout_type dst;
bool cc;
bool END;
};
struct pvr_ddmad {
struct pvr_instruction instruction;
struct pvr_operand *src0;
struct pvr_operand *src1;
struct pvr_operand *src2;
struct pvr_operand *src3;
bool cc;
bool END;
};
struct pvr_sftlp {
struct pvr_instruction instruction;
enum pvr_pds_lop lop;
struct pvr_operand *dst;
struct pvr_operand *src0;
struct pvr_operand *src1;
struct pvr_operand *src2;
bool cc;
bool IM;
};
struct pvr_limm {
struct pvr_instruction instruction;
bool cc;
bool GR;
struct pvr_operand *dst;
struct pvr_operand *src0;
};
struct pvr_cmp {
struct pvr_instruction instruction;
enum pvr_cop cop;
bool IM;
bool cc;
struct pvr_operand *src0;
struct pvr_operand *src1;
};
#define PVR_PDS_ERR_PARAM_RANGE 0 /* Error when register is out of range. */
#define PVR_PDS_ERR_SP_UNKNOWN \
1 /* Error when opcode for sp instruction is unknown. */
struct pvr_dissassembler_error {
uint32_t type; /* One of PDS_ERR_* */
enum pvr_instruction_type instruction; /* The type of instruction where
the error occurred. */
char *text; /* A string representation of the error. */
uint32_t parameter; /* The parameter of the instruction, 0 = dst,
1 = src0.. */
uint32_t raw; /* The raw value that caused the error. */
void *context; /* The passed in context. */
};
/* Callback when an error happens. */
typedef void (*PVR_ERR_CALLBACK)(struct pvr_dissassembler_error);
void pvr_pds_free_instruction(struct pvr_instruction *inst);
struct pvr_instruction *
pvr_pds_disassemble_instruction2(void *context,
PVR_ERR_CALLBACK error_call_back,
uint32_t instruction);
void pvr_pds_disassemble_instruction(char *buffer,
size_t instr_len,
struct pvr_instruction *instruction);
#if defined(DUMP_PDS)
void pvr_pds_print_instruction(uint32_t instr);
#endif
#endif /* PVR_ROGUE_PDS_DISASM_H */

View File

@ -0,0 +1,538 @@
/*
* 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_ROGUE_PDS_ENCODE_H
#define PVR_ROGUE_PDS_ENCODE_H
#include <stdint.h>
#include "pvr_rogue_pds_defs.h"
#include "pvr_rogue_pds_disasm.h"
#include "util/macros.h"
static ALWAYS_INLINE uint32_t
pvr_pds_inst_decode_field_range_regs64tp(uint32_t value)
{
if (value <= PVR_ROGUE_PDSINST_REGS64TP_TEMP64_UPPER)
return PVR_ROGUE_PDSINST_REGS64TP_TEMP64;
if ((value >= PVR_ROGUE_PDSINST_REGS64TP_PTEMP64_LOWER) &&
(value <= PVR_ROGUE_PDSINST_REGS64TP_PTEMP64_UPPER)) {
return PVR_ROGUE_PDSINST_REGS64TP_PTEMP64;
}
return 2;
}
static ALWAYS_INLINE uint32_t
pvr_pds_inst_decode_field_range_regs32(uint32_t value)
{
if (value <= PVR_ROGUE_PDSINST_REGS32_CONST32_UPPER)
return PVR_ROGUE_PDSINST_REGS32_CONST32;
if ((value >= PVR_ROGUE_PDSINST_REGS32_TEMP32_LOWER) &&
(value <= PVR_ROGUE_PDSINST_REGS32_TEMP32_UPPER)) {
return PVR_ROGUE_PDSINST_REGS32_TEMP32;
}
if ((value >= PVR_ROGUE_PDSINST_REGS32_PTEMP32_LOWER) &&
(value <= PVR_ROGUE_PDSINST_REGS32_PTEMP32_UPPER)) {
return PVR_ROGUE_PDSINST_REGS32_PTEMP32;
}
return 3;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_stflp64(uint32_t cc,
uint32_t lop,
uint32_t im,
uint32_t src0,
uint32_t src1,
uint32_t src2,
uint32_t dst)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_SFTLP64
<< PVR_ROGUE_PDSINST_SFTLP64_OPCODE_SHIFT;
encoded |= ((dst & PVR_ROGUE_PDSINST_REGS64TP_MASK)
<< PVR_ROGUE_PDSINST_SFTLP64_DST_SHIFT);
encoded |= ((src2 & PVR_ROGUE_PDSINST_REGS32_MASK)
<< PVR_ROGUE_PDSINST_SFTLP64_SRC2_SHIFT);
encoded |= ((src1 & PVR_ROGUE_PDSINST_REGS64TP_MASK)
<< PVR_ROGUE_PDSINST_SFTLP64_SRC1_SHIFT);
encoded |= ((src0 & PVR_ROGUE_PDSINST_REGS64TP_MASK)
<< PVR_ROGUE_PDSINST_SFTLP64_SRC0_SHIFT);
encoded |= ((im & 1U) << PVR_ROGUE_PDSINST_SFTLP64_IM_SHIFT);
encoded |= ((lop & PVR_ROGUE_PDSINST_LOP_MASK)
<< PVR_ROGUE_PDSINST_SFTLP64_LOP_SHIFT);
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_SFTLP64_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t
pvr_pds_inst_decode_field_range_regs32t(uint32_t value)
{
if (value <= PVR_ROGUE_PDSINST_REGS32T_TEMP32_UPPER)
return PVR_ROGUE_PDSINST_REGS32T_TEMP32;
return 1;
}
static ALWAYS_INLINE uint32_t
pvr_pds_inst_decode_field_range_regs32tp(uint32_t value)
{
if (value <= PVR_ROGUE_PDSINST_REGS32TP_TEMP32_UPPER)
return PVR_ROGUE_PDSINST_REGS32TP_TEMP32;
if ((value >= PVR_ROGUE_PDSINST_REGS32TP_PTEMP32_LOWER) &&
(value <= PVR_ROGUE_PDSINST_REGS32TP_PTEMP32_UPPER)) {
return PVR_ROGUE_PDSINST_REGS32TP_PTEMP32;
}
return 2;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_stflp32(uint32_t im,
uint32_t cc,
uint32_t lop,
uint32_t src0,
uint32_t src1,
uint32_t src2,
uint32_t dst)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEB_SFTLP32
<< PVR_ROGUE_PDSINST_SFTLP32_OPCODE_SHIFT;
encoded |= ((dst & PVR_ROGUE_PDSINST_REGS32T_MASK)
<< PVR_ROGUE_PDSINST_SFTLP32_DST_SHIFT);
encoded |= ((src2 & PVR_ROGUE_PDSINST_REGS32TP_MASK)
<< PVR_ROGUE_PDSINST_SFTLP32_SRC2_SHIFT);
encoded |= ((src1 & PVR_ROGUE_PDSINST_REGS32_MASK)
<< PVR_ROGUE_PDSINST_SFTLP32_SRC1_SHIFT);
encoded |= ((src0 & PVR_ROGUE_PDSINST_REGS32T_MASK)
<< PVR_ROGUE_PDSINST_SFTLP32_SRC0_SHIFT);
encoded |= ((lop & PVR_ROGUE_PDSINST_LOP_MASK)
<< PVR_ROGUE_PDSINST_SFTLP32_LOP_SHIFT);
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_SFTLP32_CC_SHIFT);
encoded |= ((im & 1U) << PVR_ROGUE_PDSINST_SFTLP32_IM_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_stm(uint32_t CCS_CCS_GLOBAL,
uint32_t CCS_CCS_SO,
uint32_t CCS_CCS_CC,
uint32_t SO_TST,
uint32_t SO,
uint32_t SO_SRC0,
uint32_t SO_SRC1,
uint32_t SO_SRC2,
uint32_t SO_SRC3)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEB_STM
<< PVR_ROGUE_PDSINST_STM_OPCODE_SHIFT;
encoded |= ((SO_SRC3 & PVR_ROGUE_PDSINST_REGS64TP_MASK)
<< PVR_ROGUE_PDSINST_STM_SO_SRC3_SHIFT);
encoded |= ((SO_SRC2 & PVR_ROGUE_PDSINST_REGS32_MASK)
<< PVR_ROGUE_PDSINST_STM_SO_SRC2_SHIFT);
encoded |= ((SO_SRC1 & PVR_ROGUE_PDSINST_REGS64TP_MASK)
<< PVR_ROGUE_PDSINST_STM_SO_SRC1_SHIFT);
encoded |= ((SO_SRC0 & PVR_ROGUE_PDSINST_REGS64TP_MASK)
<< PVR_ROGUE_PDSINST_STM_SO_SRC0_SHIFT);
encoded |=
((SO & PVR_ROGUE_PDSINST_SO_MASK) << PVR_ROGUE_PDSINST_STM_SO_SHIFT);
encoded |= ((SO_TST & 1U) << PVR_ROGUE_PDSINST_STM_SO_TST_SHIFT);
encoded |= ((CCS_CCS_CC & 1U) << PVR_ROGUE_PDSINST_STM_CCS_CCS_CC_SHIFT);
encoded |= ((CCS_CCS_SO & 1U) << PVR_ROGUE_PDSINST_STM_CCS_CCS_SO_SHIFT);
encoded |=
((CCS_CCS_GLOBAL & 1U) << PVR_ROGUE_PDSINST_STM_CCS_CCS_GLOBAL_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t
pvr_pds_inst_decode_field_range_regs64(uint32_t value)
{
if (value <= PVR_ROGUE_PDSINST_REGS64_CONST64_UPPER)
return PVR_ROGUE_PDSINST_REGS64_CONST64;
if ((value >= PVR_ROGUE_PDSINST_REGS64_TEMP64_LOWER) &&
(value <= PVR_ROGUE_PDSINST_REGS64_TEMP64_UPPER)) {
return PVR_ROGUE_PDSINST_REGS64_TEMP64;
}
if ((value >= PVR_ROGUE_PDSINST_REGS64_PTEMP64_LOWER) &&
(value <= PVR_ROGUE_PDSINST_REGS64_PTEMP64_UPPER)) {
return PVR_ROGUE_PDSINST_REGS64_PTEMP64;
}
return 3;
}
static ALWAYS_INLINE uint32_t pvr_rogue_inst_encode_mad(uint32_t sna,
uint32_t alum,
uint32_t cc,
uint32_t src0,
uint32_t src1,
uint32_t src2,
uint32_t dst)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEA_MAD
<< PVR_ROGUE_PDSINST_MAD_OPCODE_SHIFT;
encoded |= ((dst & PVR_ROGUE_PDSINST_REGS64T_MASK)
<< PVR_ROGUE_PDSINST_MAD_DST_SHIFT);
encoded |= ((src2 & PVR_ROGUE_PDSINST_REGS64_MASK)
<< PVR_ROGUE_PDSINST_MAD_SRC2_SHIFT);
encoded |= ((src1 & PVR_ROGUE_PDSINST_REGS32_MASK)
<< PVR_ROGUE_PDSINST_MAD_SRC1_SHIFT);
encoded |= ((src0 & PVR_ROGUE_PDSINST_REGS32_MASK)
<< PVR_ROGUE_PDSINST_MAD_SRC0_SHIFT);
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_MAD_CC_SHIFT);
encoded |= ((alum & 1U) << PVR_ROGUE_PDSINST_MAD_ALUM_SHIFT);
encoded |= ((sna & 1U) << PVR_ROGUE_PDSINST_MAD_SNA_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_add64(uint32_t cc,
uint32_t alum,
uint32_t sna,
uint32_t src0,
uint32_t src1,
uint32_t dst)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_ADD64
<< PVR_ROGUE_PDSINST_ADD64_OPCODE_SHIFT;
encoded |= ((dst & PVR_ROGUE_PDSINST_REGS64TP_MASK)
<< PVR_ROGUE_PDSINST_ADD64_DST_SHIFT);
encoded |= ((src1 & PVR_ROGUE_PDSINST_REGS64_MASK)
<< PVR_ROGUE_PDSINST_ADD64_SRC1_SHIFT);
encoded |= ((src0 & PVR_ROGUE_PDSINST_REGS64_MASK)
<< PVR_ROGUE_PDSINST_ADD64_SRC0_SHIFT);
encoded |= ((sna & 1U) << PVR_ROGUE_PDSINST_ADD64_SNA_SHIFT);
encoded |= ((alum & 1U) << PVR_ROGUE_PDSINST_ADD64_ALUM_SHIFT);
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_ADD64_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_add32(uint32_t cc,
uint32_t alum,
uint32_t sna,
uint32_t src0,
uint32_t src1,
uint32_t dst)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_ADD32
<< PVR_ROGUE_PDSINST_ADD32_OPCODE_SHIFT;
encoded |= ((dst & PVR_ROGUE_PDSINST_REGS32TP_MASK)
<< PVR_ROGUE_PDSINST_ADD32_DST_SHIFT);
encoded |= ((src1 & PVR_ROGUE_PDSINST_REGS32_MASK)
<< PVR_ROGUE_PDSINST_ADD32_SRC1_SHIFT);
encoded |= ((src0 & PVR_ROGUE_PDSINST_REGS32_MASK)
<< PVR_ROGUE_PDSINST_ADD32_SRC0_SHIFT);
encoded |= ((sna & 1U) << PVR_ROGUE_PDSINST_ADD32_SNA_SHIFT);
encoded |= ((alum & 1U) << PVR_ROGUE_PDSINST_ADD32_ALUM_SHIFT);
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_ADD32_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_cmp(uint32_t cc,
uint32_t cop,
uint32_t src0,
uint32_t src1)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_CMP
<< PVR_ROGUE_PDSINST_CMP_OPCODE_SHIFT;
encoded |= ((src1 & PVR_ROGUE_PDSINST_REGS64_MASK)
<< PVR_ROGUE_PDSINST_CMP_SRC1_SHIFT);
encoded |= ((src0 & PVR_ROGUE_PDSINST_REGS64TP_MASK)
<< PVR_ROGUE_PDSINST_CMP_SRC0_SHIFT);
encoded |= UINT32_C(0x0) << PVR_ROGUE_PDSINST_CMP_IM_SHIFT;
encoded |= UINT32_C(0x1) << PVR_ROGUE_PDSINST_CMP_SETCP_SHIFT;
encoded |=
((cop & PVR_ROGUE_PDSINST_COP_MASK) << PVR_ROGUE_PDSINST_CMP_COP_SHIFT);
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_CMP_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_cmpi(uint32_t cc,
uint32_t cop,
uint32_t src0,
uint32_t im16)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_CMP
<< PVR_ROGUE_PDSINST_CMPI_OPCODE_SHIFT;
encoded |= ((im16 & PVR_ROGUE_PDSINST_IMM16_MASK)
<< PVR_ROGUE_PDSINST_CMPI_IM16_SHIFT);
encoded |= ((src0 & PVR_ROGUE_PDSINST_REGS64TP_MASK)
<< PVR_ROGUE_PDSINST_CMPI_SRC0_SHIFT);
encoded |= UINT32_C(0x1) << PVR_ROGUE_PDSINST_CMPI_IM_SHIFT;
encoded |= UINT32_C(0x1) << PVR_ROGUE_PDSINST_CMPI_SETCP_SHIFT;
encoded |=
((cop & PVR_ROGUE_PDSINST_COP_MASK) << PVR_ROGUE_PDSINST_CMPI_COP_SHIFT);
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_CMPI_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_bra(uint32_t srcc,
uint32_t neg,
uint32_t setc,
uint32_t addr)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_BRA
<< PVR_ROGUE_PDSINST_BRA_OPCODE_SHIFT;
encoded |= ((addr & PVR_ROGUE_PDSINST_BRAADDR_MASK)
<< PVR_ROGUE_PDSINST_BRA_ADDR_SHIFT);
encoded |= ((setc & PVR_ROGUE_PDSINST_PREDICATE_MASK)
<< PVR_ROGUE_PDSINST_BRA_SETC_SHIFT);
encoded |= ((neg & 1U) << PVR_ROGUE_PDSINST_BRA_NEG_SHIFT);
encoded |= ((srcc & PVR_ROGUE_PDSINST_PREDICATE_MASK)
<< PVR_ROGUE_PDSINST_BRA_SRCC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_ld(uint32_t cc, uint32_t src0)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_SP << PVR_ROGUE_PDSINST_LD_OPCODE_SHIFT;
encoded |= ((src0 & PVR_ROGUE_PDSINST_REGS64_MASK)
<< PVR_ROGUE_PDSINST_LD_SRC0_SHIFT);
encoded |= PVR_ROGUE_PDSINST_OPCODESP_LD << PVR_ROGUE_PDSINST_LD_OP_SHIFT;
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_LD_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_st(uint32_t cc, uint32_t src0)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_SP << PVR_ROGUE_PDSINST_ST_OPCODE_SHIFT;
encoded |= ((src0 & PVR_ROGUE_PDSINST_REGS64_MASK)
<< PVR_ROGUE_PDSINST_ST_SRC0_SHIFT);
encoded |= PVR_ROGUE_PDSINST_OPCODESP_ST << PVR_ROGUE_PDSINST_ST_OP_SHIFT;
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_ST_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_wdf(uint32_t cc)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_SP
<< PVR_ROGUE_PDSINST_WDF_OPCODE_SHIFT;
encoded |= PVR_ROGUE_PDSINST_OPCODESP_WDF << PVR_ROGUE_PDSINST_WDF_OP_SHIFT;
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_WDF_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_limm(uint32_t cc,
uint32_t src1,
uint32_t src0,
uint32_t gr)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_SP
<< PVR_ROGUE_PDSINST_LIMM_OPCODE_SHIFT;
encoded |= ((gr & 1U) << PVR_ROGUE_PDSINST_LIMM_GR_SHIFT);
encoded |= ((src0 & PVR_ROGUE_PDSINST_IMM16_MASK)
<< PVR_ROGUE_PDSINST_LIMM_SRC0_SHIFT);
encoded |= ((src1 & PVR_ROGUE_PDSINST_REGS32T_MASK)
<< PVR_ROGUE_PDSINST_LIMM_SRC1_SHIFT);
encoded |= PVR_ROGUE_PDSINST_OPCODESP_LIMM
<< PVR_ROGUE_PDSINST_LIMM_OP_SHIFT;
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_LIMM_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_lock(uint32_t cc)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_SP
<< PVR_ROGUE_PDSINST_LOCK_OPCODE_SHIFT;
encoded |= PVR_ROGUE_PDSINST_OPCODESP_LOCK
<< PVR_ROGUE_PDSINST_LOCK_OP_SHIFT;
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_LOCK_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_release(uint32_t cc)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_SP
<< PVR_ROGUE_PDSINST_RELEASE_OPCODE_SHIFT;
encoded |= PVR_ROGUE_PDSINST_OPCODESP_RELEASE
<< PVR_ROGUE_PDSINST_RELEASE_OP_SHIFT;
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_RELEASE_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_halt(uint32_t cc)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_SP
<< PVR_ROGUE_PDSINST_HALT_OPCODE_SHIFT;
encoded |= PVR_ROGUE_PDSINST_OPCODESP_HALT
<< PVR_ROGUE_PDSINST_HALT_OP_SHIFT;
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_HALT_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_stmc(uint32_t cc,
uint32_t so_mask)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_SP
<< PVR_ROGUE_PDSINST_STMC_OPCODE_SHIFT;
encoded |= ((so_mask & PVR_ROGUE_PDSINST_SOMASK_MASK)
<< PVR_ROGUE_PDSINST_STMC_SOMASK_SHIFT);
encoded |= PVR_ROGUE_PDSINST_OPCODESP_STMC
<< PVR_ROGUE_PDSINST_STMC_OP_SHIFT;
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_STMC_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t
pvr_rogue_pds_inst_decode_field_range_regs64c(uint32_t value)
{
if (value <= PVR_ROGUE_PDSINST_REGS64C_CONST64_UPPER)
return PVR_ROGUE_PDSINST_REGS64C_CONST64;
return 1;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_ddmad(uint32_t cc,
uint32_t end,
uint32_t src0,
uint32_t src1,
uint32_t src2,
uint32_t src3)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_DDMAD
<< PVR_ROGUE_PDSINST_DDMAD_OPCODE_SHIFT;
encoded |= ((src3 & PVR_ROGUE_PDSINST_REGS64C_MASK)
<< PVR_ROGUE_PDSINST_DDMAD_SRC3_SHIFT);
encoded |= ((src2 & PVR_ROGUE_PDSINST_REGS64_MASK)
<< PVR_ROGUE_PDSINST_DDMAD_SRC2_SHIFT);
encoded |= ((src1 & PVR_ROGUE_PDSINST_REGS32T_MASK)
<< PVR_ROGUE_PDSINST_DDMAD_SRC1_SHIFT);
encoded |= ((src0 & PVR_ROGUE_PDSINST_REGS32_MASK)
<< PVR_ROGUE_PDSINST_DDMAD_SRC0_SHIFT);
encoded |= ((end & 1U) << PVR_ROGUE_PDSINST_DDMAD_END_SHIFT);
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_DDMAD_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
static ALWAYS_INLINE uint32_t pvr_pds_inst_encode_dout(uint32_t cc,
uint32_t end,
uint32_t src1,
uint32_t src0,
uint32_t dst)
{
uint32_t encoded = 0;
encoded |= PVR_ROGUE_PDSINST_OPCODEC_DOUT
<< PVR_ROGUE_PDSINST_DOUT_OPCODE_SHIFT;
encoded |= ((dst & PVR_ROGUE_PDSINST_DSTDOUT_MASK)
<< PVR_ROGUE_PDSINST_DOUT_DST_SHIFT);
encoded |= ((src0 & PVR_ROGUE_PDSINST_REGS64_MASK)
<< PVR_ROGUE_PDSINST_DOUT_SRC0_SHIFT);
encoded |= ((src1 & PVR_ROGUE_PDSINST_REGS32_MASK)
<< PVR_ROGUE_PDSINST_DOUT_SRC1_SHIFT);
encoded |= ((end & 1U) << PVR_ROGUE_PDSINST_DOUT_END_SHIFT);
encoded |= ((cc & 1U) << PVR_ROGUE_PDSINST_DOUT_CC_SHIFT);
PVR_PDS_PRINT_INST(encoded);
return encoded;
}
#endif /* PVR_ROGUE_PDS_ENCODE_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,147 @@
/*
* 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 <assert.h>
#include <stdint.h>
#include <vulkan/vulkan.h>
#include "pvr_csb.h"
#include "pvr_private.h"
#include "util/list.h"
#include "vk_alloc.h"
#include "vk_command_buffer.h"
#include "vk_command_pool.h"
#include "vk_log.h"
/* TODO: Investigate where this limit comes from. */
#define PVR_MAX_TRANSFER_SIZE_IN_TEXELS 2048U
void pvr_CmdBlitImage2KHR(VkCommandBuffer commandBuffer,
const VkBlitImageInfo2KHR *pBlitImageInfo)
{
assert(!"Unimplemented");
}
void pvr_CmdCopyImageToBuffer2KHR(
VkCommandBuffer commandBuffer,
const VkCopyImageToBufferInfo2KHR *pCopyImageToBufferInfo)
{
assert(!"Unimplemented");
}
void pvr_CmdCopyImage2KHR(VkCommandBuffer commandBuffer,
const VkCopyImageInfo2KHR *pCopyImageInfo)
{
assert(!"Unimplemented");
}
void pvr_CmdUpdateBuffer(VkCommandBuffer commandBuffer,
VkBuffer dstBuffer,
VkDeviceSize dstOffset,
VkDeviceSize dataSize,
const void *pData)
{
assert(!"Unimplemented");
}
void pvr_CmdFillBuffer(VkCommandBuffer commandBuffer,
VkBuffer dstBuffer,
VkDeviceSize dstOffset,
VkDeviceSize fillSize,
uint32_t data)
{
assert(!"Unimplemented");
}
void pvr_CmdCopyBufferToImage2KHR(
VkCommandBuffer commandBuffer,
const VkCopyBufferToImageInfo2KHR *pCopyBufferToImageInfo)
{
assert(!"Unimplemented");
}
void pvr_CmdClearColorImage(VkCommandBuffer commandBuffer,
VkImage _image,
VkImageLayout imageLayout,
const VkClearColorValue *pColor,
uint32_t rangeCount,
const VkImageSubresourceRange *pRanges)
{
assert(!"Unimplemented");
}
void pvr_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,
VkImage image_h,
VkImageLayout imageLayout,
const VkClearDepthStencilValue *pDepthStencil,
uint32_t rangeCount,
const VkImageSubresourceRange *pRanges)
{
assert(!"Unimplemented");
}
void pvr_CmdCopyBuffer2KHR(VkCommandBuffer commandBuffer,
const VkCopyBufferInfo2KHR *pCopyBufferInfo)
{
PVR_FROM_HANDLE(pvr_cmd_buffer, cmd_buffer, commandBuffer);
PVR_FROM_HANDLE(pvr_buffer, src, pCopyBufferInfo->srcBuffer);
PVR_FROM_HANDLE(pvr_buffer, dst, pCopyBufferInfo->dstBuffer);
const size_t regions_size =
pCopyBufferInfo->regionCount * sizeof(*pCopyBufferInfo->pRegions);
struct pvr_transfer_cmd *transfer_cmd;
PVR_CHECK_COMMAND_BUFFER_BUILDING_STATE(cmd_buffer);
transfer_cmd = vk_alloc(&cmd_buffer->vk.pool->alloc,
sizeof(*transfer_cmd) + regions_size,
8U,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!transfer_cmd) {
cmd_buffer->state.status =
vk_error(cmd_buffer, VK_ERROR_OUT_OF_HOST_MEMORY);
return;
}
transfer_cmd->src = src;
transfer_cmd->dst = dst;
transfer_cmd->region_count = pCopyBufferInfo->regionCount;
memcpy(transfer_cmd->regions, pCopyBufferInfo->pRegions, regions_size);
pvr_cmd_buffer_add_transfer_cmd(cmd_buffer, transfer_cmd);
}
void pvr_CmdClearAttachments(VkCommandBuffer commandBuffer,
uint32_t attachmentCount,
const VkClearAttachment *pAttachments,
uint32_t rectCount,
const VkClearRect *pRects)
{
assert(!"Unimplemented");
}
void pvr_CmdResolveImage2KHR(VkCommandBuffer commandBuffer,
const VkResolveImageInfo2KHR *pResolveImageInfo)
{
assert(!"Unimplemented");
}

View File

@ -0,0 +1,199 @@
/*
* 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 <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <vulkan/vulkan.h>
#include "pvr_bo.h"
#include "pvr_private.h"
#include "pvr_winsys.h"
#include "vk_alloc.h"
#include "vk_log.h"
static uint32_t pvr_bo_alloc_to_winsys_flags(uint64_t flags)
{
uint32_t ws_flags = 0;
if (flags & PVR_BO_ALLOC_FLAG_CPU_ACCESS)
ws_flags |= PVR_WINSYS_BO_FLAG_CPU_ACCESS;
if (flags & PVR_BO_ALLOC_FLAG_GPU_UNCACHED)
ws_flags |= PVR_WINSYS_BO_FLAG_GPU_UNCACHED;
if (flags & PVR_BO_ALLOC_FLAG_PM_FW_PROTECT)
ws_flags |= PVR_WINSYS_BO_FLAG_PM_FW_PROTECT;
if (flags & PVR_BO_ALLOC_FLAG_ZERO_ON_ALLOC)
ws_flags |= PVR_WINSYS_BO_FLAG_ZERO_ON_ALLOC;
return ws_flags;
}
/**
* \brief Helper interface to allocate a GPU buffer and map it to both host and
* device virtual memory. Host mapping is conditional and is controlled by
* flags.
*
* \param[in] device Logical device pointer.
* \param[in] heap Heap to allocate device virtual address from.
* \param[in] size Size of buffer to allocate.
* \param[in] alignment Required alignment of the allocation. Must be a power
* of two.
* \param[in] flags Controls allocation, CPU and GPU mapping behavior
* using PVR_BO_ALLOC_FLAG_*.
* \param[out] pvr_bo_out On success output buffer is returned in this pointer.
* \return VK_SUCCESS on success, or error code otherwise.
*
* \sa #pvr_bo_free()
*/
VkResult pvr_bo_alloc(struct pvr_device *device,
struct pvr_winsys_heap *heap,
uint64_t size,
uint64_t alignment,
uint64_t flags,
struct pvr_bo **const pvr_bo_out)
{
const uint32_t ws_flags = pvr_bo_alloc_to_winsys_flags(flags);
struct pvr_bo *pvr_bo;
pvr_dev_addr_t addr;
VkResult result;
pvr_bo = vk_alloc(&device->vk.alloc,
sizeof(*pvr_bo),
8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!pvr_bo)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
result = device->ws->ops->buffer_create(device->ws,
size,
alignment,
PVR_WINSYS_BO_TYPE_GPU,
ws_flags,
&pvr_bo->bo);
if (result != VK_SUCCESS)
goto err_vk_free;
if (flags & PVR_BO_ALLOC_FLAG_CPU_MAPPED) {
void *map = device->ws->ops->buffer_map(pvr_bo->bo);
if (!map) {
result = VK_ERROR_MEMORY_MAP_FAILED;
goto err_buffer_destroy;
}
}
pvr_bo->vma = device->ws->ops->heap_alloc(heap, size, alignment);
if (!pvr_bo->vma) {
result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
goto err_buffer_unmap;
}
addr = device->ws->ops->vma_map(pvr_bo->vma, pvr_bo->bo, 0, size);
if (!addr.addr) {
result = VK_ERROR_MEMORY_MAP_FAILED;
goto err_heap_free;
}
*pvr_bo_out = pvr_bo;
return VK_SUCCESS;
err_heap_free:
device->ws->ops->heap_free(pvr_bo->vma);
err_buffer_unmap:
if (flags & PVR_BO_ALLOC_FLAG_CPU_MAPPED)
device->ws->ops->buffer_unmap(pvr_bo->bo);
err_buffer_destroy:
device->ws->ops->buffer_destroy(pvr_bo->bo);
err_vk_free:
vk_free(&device->vk.alloc, pvr_bo);
return result;
}
/**
* \brief Interface to map the buffer into host virtual address space.
*
* Buffer should have been created with the #PVR_BO_ALLOC_FLAG_CPU_ACCESS
* flag. It should also not already be mapped or it should have been unmapped
* using #pvr_bo_cpu_unmap() before mapping again.
*
* \param[in] device Logical device pointer.
* \param[in] pvr_bo Buffer to map.
* \return Valid host virtual address on success, or NULL otherwise.
*
* \sa #pvr_bo_alloc(), #PVR_BO_ALLOC_FLAG_CPU_MAPPED
*/
void *pvr_bo_cpu_map(struct pvr_device *device, struct pvr_bo *pvr_bo)
{
assert(!pvr_bo->bo->map);
return device->ws->ops->buffer_map(pvr_bo->bo);
}
/**
* \brief Interface to unmap the buffer from host virtual address space.
*
* Buffer should have a valid mapping, created either using #pvr_bo_cpu_map() or
* by passing #PVR_BO_ALLOC_FLAG_CPU_MAPPED flag to #pvr_bo_alloc() at
* allocation time.
*
* Buffer can be remapped using #pvr_bo_cpu_map().
*
* \param[in] device Logical device pointer.
* \param[in] pvr_bo Buffer to unmap.
*/
void pvr_bo_cpu_unmap(struct pvr_device *device, struct pvr_bo *pvr_bo)
{
assert(pvr_bo->bo->map);
device->ws->ops->buffer_unmap(pvr_bo->bo);
}
/**
* \brief Interface to free the buffer object.
*
* \param[in] device Logical device pointer.
* \param[in] pvr_bo Buffer to free.
*
* \sa #pvr_bo_alloc()
*/
void pvr_bo_free(struct pvr_device *device, struct pvr_bo *pvr_bo)
{
if (!pvr_bo)
return;
device->ws->ops->vma_unmap(pvr_bo->vma);
device->ws->ops->heap_free(pvr_bo->vma);
if (pvr_bo->bo->map)
device->ws->ops->buffer_unmap(pvr_bo->bo);
device->ws->ops->buffer_destroy(pvr_bo->bo);
vk_free(&device->vk.alloc, pvr_bo);
}

View File

@ -0,0 +1,91 @@
/*
* 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_BO_H
#define PVR_BO_H
#include <stddef.h>
#include <stdint.h>
#include <vulkan/vulkan.h>
#include "util/list.h"
#include "util/macros.h"
struct pvr_device;
struct pvr_winsys_bo;
struct pvr_winsys_vma;
struct pvr_winsys_heap;
struct pvr_bo {
/* Since multiple components (csb, caching logic, etc) can make use of
* linking buffers in a list, we add 'link' in pvr_bo to avoid an extra
* level of structure inheritance. It's the responsibility of the buffer
* user to manage the list and remove the buffer from the list before
* freeing it.
*/
struct list_head link;
struct pvr_winsys_bo *bo;
struct pvr_winsys_vma *vma;
};
/**
* \brief Flag passed to #pvr_bo_alloc() to indicate that the buffer should be
* CPU accessible. This is required in order to map a buffer with
* #pvr_bo_cpu_map().
*/
#define PVR_BO_ALLOC_FLAG_CPU_ACCESS BITFIELD_BIT(0U)
/**
* \brief Flag passed to #pvr_bo_alloc() to indicate that the buffer should
* be mapped to the CPU. Implies #PVR_BO_ALLOC_FLAG_CPU_ACCESS.
*/
#define PVR_BO_ALLOC_FLAG_CPU_MAPPED \
(BITFIELD_BIT(1U) | PVR_BO_ALLOC_FLAG_CPU_ACCESS)
/**
* \brief Flag passed to #pvr_bo_alloc() to indicate that the buffer should be
* mapped to the GPU as uncached.
*/
#define PVR_BO_ALLOC_FLAG_GPU_UNCACHED BITFIELD_BIT(2U)
/**
* \brief Flag passed to #pvr_bo_alloc() to indicate that the buffer GPU mapping
* should be restricted to only allow access to the Parameter Manager unit and
* firmware processor.
*/
#define PVR_BO_ALLOC_FLAG_PM_FW_PROTECT BITFIELD_BIT(3U)
/**
* \brief Flag passed to #pvr_bo_alloc() to indicate that the buffer should be
* zeroed at allocation time.
*/
#define PVR_BO_ALLOC_FLAG_ZERO_ON_ALLOC BITFIELD_BIT(4U)
VkResult pvr_bo_alloc(struct pvr_device *device,
struct pvr_winsys_heap *heap,
uint64_t size,
uint64_t alignment,
uint64_t flags,
struct pvr_bo **const bo_out);
void *pvr_bo_cpu_map(struct pvr_device *device, struct pvr_bo *bo);
void pvr_bo_cpu_unmap(struct pvr_device *device, struct pvr_bo *bo);
void pvr_bo_free(struct pvr_device *device, struct pvr_bo *bo);
#endif /* PVR_BO_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,281 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* based in part on anv driver which is:
* Copyright © 2015 Intel Corporation
*
* based in part on v3dv_cl.c which is:
* Copyright © 2019 Raspberry Pi
*
* 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 <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <vulkan/vulkan.h>
#include "hwdef/rogue_hw_utils.h"
#include "pvr_bo.h"
#include "pvr_csb.h"
#include "pvr_device_info.h"
#include "pvr_private.h"
#include "vk_log.h"
/**
* \file pvr_csb.c
*
* \brief Contains functions to manage Control Stream Builder (csb) object.
*
* A csb object can be used to create a primary/main control stream, referred
* as control stream hereafter, or a secondary control stream, also referred as
* a sub control stream. The main difference between these is that, the control
* stream is the one directly submitted to the GPU and is terminated using
* STREAM_TERMINATE. Whereas, the secondary control stream can be thought of as
* an independent set of commands that can be referenced by a primary control
* stream to avoid duplication and is instead terminated using STREAM_RETURN,
* which means the control stream parser should return to the main stream it
* came from.
*
* Note: Sub control stream is only supported for PVR_CMD_STREAM_TYPE_GRAPHICS
* type control streams.
*/
/**
* \brief Size of the individual csb buffer object.
*/
#define PVR_CMD_BUFFER_CSB_BO_SIZE 4096
/**
* \brief Initializes the csb object.
*
* \param[in] device Logical device pointer.
* \param[in] csb Control Stream Builder object to initialize.
*
* \sa #pvr_csb_finish()
*/
void pvr_csb_init(struct pvr_device *device,
enum pvr_cmd_stream_type stream_type,
struct pvr_csb *csb)
{
csb->start = NULL;
csb->next = NULL;
csb->pvr_bo = NULL;
csb->end = NULL;
csb->device = device;
csb->stream_type = stream_type;
csb->status = VK_SUCCESS;
list_inithead(&csb->pvr_bo_list);
}
/**
* \brief Frees the resources associated with the csb object.
*
* \param[in] csb Control Stream Builder object to free.
*
* \sa #pvr_csb_init()
*/
void pvr_csb_finish(struct pvr_csb *csb)
{
list_for_each_entry_safe (struct pvr_bo, pvr_bo, &csb->pvr_bo_list, link) {
list_del(&pvr_bo->link);
pvr_bo_free(csb->device, pvr_bo);
}
/* Leave the csb in a reset state to catch use after destroy instances */
pvr_csb_init(NULL, PVR_CMD_STREAM_TYPE_INVALID, csb);
}
/**
* \brief Helper function to extend csb memory.
*
* Allocates a new buffer object and links it with the previous buffer object
* using STREAM_LINK dwords and updates csb object to use the new buffer.
*
* To make sure that we have enough space to emit STREAM_LINK dwords in the
* current buffer, a few bytes are reserved at the end, every time a buffer is
* created. Every time we allocate a new buffer we fix the current buffer in use
* to emit the stream link dwords. This makes sure that when
* #pvr_csb_alloc_dwords() is called from #pvr_csb_emit() to add STREAM_LINK0
* and STREAM_LINK1, it succeeds without trying to allocate new pages.
*
* \param[in] csb Control Stream Builder object to extend.
* \return true on success and false otherwise.
*/
static bool pvr_csb_buffer_extend(struct pvr_csb *csb)
{
const uint8_t stream_link_space = (pvr_cmd_length(VDMCTRL_STREAM_LINK0) +
pvr_cmd_length(VDMCTRL_STREAM_LINK1)) *
4;
const uint32_t cache_line_size =
rogue_get_slc_cache_line_size(&csb->device->pdevice->dev_info);
struct pvr_bo *pvr_bo;
VkResult result;
/* Make sure extra space allocated for stream links is sufficient for both
* stream types.
*/
STATIC_ASSERT((pvr_cmd_length(VDMCTRL_STREAM_LINK0) +
pvr_cmd_length(VDMCTRL_STREAM_LINK1)) ==
(pvr_cmd_length(CDMCTRL_STREAM_LINK0) +
pvr_cmd_length(CDMCTRL_STREAM_LINK1)));
result = pvr_bo_alloc(csb->device,
csb->device->heaps.general_heap,
PVR_CMD_BUFFER_CSB_BO_SIZE,
cache_line_size,
PVR_BO_ALLOC_FLAG_CPU_MAPPED,
&pvr_bo);
if (result != VK_SUCCESS) {
vk_error(csb->device, result);
csb->status = result;
return false;
}
/* Chain to the old BO if this is not the first BO in csb */
if (csb->pvr_bo) {
csb->end += stream_link_space;
assert(csb->next + stream_link_space <= csb->end);
switch (csb->stream_type) {
case PVR_CMD_STREAM_TYPE_GRAPHICS:
pvr_csb_emit (csb, VDMCTRL_STREAM_LINK0, link) {
link.link_addrmsb = pvr_bo->vma->dev_addr;
}
pvr_csb_emit (csb, VDMCTRL_STREAM_LINK1, link) {
link.link_addrlsb = pvr_bo->vma->dev_addr;
}
break;
case PVR_CMD_STREAM_TYPE_COMPUTE:
pvr_csb_emit (csb, CDMCTRL_STREAM_LINK0, link) {
link.link_addrmsb = pvr_bo->vma->dev_addr;
}
pvr_csb_emit (csb, CDMCTRL_STREAM_LINK1, link) {
link.link_addrlsb = pvr_bo->vma->dev_addr;
}
break;
default:
unreachable("Unknown stream type");
break;
}
}
csb->pvr_bo = pvr_bo;
csb->start = pvr_bo->bo->map;
/* Reserve stream link size at the end to make sure we don't run out of
* space when a stream link is required.
*/
csb->end = csb->start + pvr_bo->bo->size - stream_link_space;
csb->next = csb->start;
list_addtail(&pvr_bo->link, &csb->pvr_bo_list);
return true;
}
/**
* \brief Provides a chunk of memory from the current csb buffer. In cases where
* the buffer is not able to fulfill the required amount of memory,
* #pvr_csb_buffer_extend() is called to allocate a new buffer. Maximum size
* allocable in bytes is #PVR_CMD_BUFFER_CSB_BO_SIZE - size of STREAM_LINK0
* and STREAM_LINK1 dwords.
*
* \param[in] csb Control Stream Builder object to allocate from.
* \param[in] num_dwords Number of dwords to allocate.
* \return Valid host virtual address or NULL otherwise.
*/
void *pvr_csb_alloc_dwords(struct pvr_csb *csb, uint32_t num_dwords)
{
const uint32_t required_space = num_dwords * 4;
if (csb->status != VK_SUCCESS)
return NULL;
if (csb->next + required_space > csb->end) {
bool ret = pvr_csb_buffer_extend(csb);
if (!ret)
return NULL;
}
void *p = csb->next;
csb->next += required_space;
assert(csb->next <= csb->end);
return p;
}
/**
* \brief Adds VDMCTRL_STREAM_RETURN dword into the control stream pointed by
* csb object. Given a VDMCTRL_STREAM_RETURN marks the end of the sub control
* stream, we return the status of the control stream as well.
*
* \param[in] csb Control Stream Builder object to add VDMCTRL_STREAM_RETURN to.
* \return VK_SUCCESS on success, or error code otherwise.
*/
VkResult pvr_csb_emit_return(struct pvr_csb *csb)
{
/* STREAM_RETURN is only supported by graphics control stream. */
assert(csb->stream_type == PVR_CMD_STREAM_TYPE_GRAPHICS);
/* clang-format off */
pvr_csb_emit(csb, VDMCTRL_STREAM_RETURN, ret);
/* clang-format on */
return csb->status;
}
/**
* \brief Adds STREAM_TERMINATE dword into the control stream pointed by csb
* object. Given a STREAM_TERMINATE marks the end of the control stream, we
* return the status of the control stream as well.
*
* \param[in] csb Control Stream Builder object to terminate.
* \return VK_SUCCESS on success, or error code otherwise.
*/
VkResult pvr_csb_emit_terminate(struct pvr_csb *csb)
{
switch (csb->stream_type) {
case PVR_CMD_STREAM_TYPE_GRAPHICS:
/* clang-format off */
pvr_csb_emit(csb, VDMCTRL_STREAM_TERMINATE, terminate);
/* clang-format on */
break;
case PVR_CMD_STREAM_TYPE_COMPUTE:
/* clang-format off */
pvr_csb_emit(csb, CDMCTRL_STREAM_TERMINATE, terminate);
/* clang-format on */
break;
default:
unreachable("Unknown stream type");
break;
}
return csb->status;
}

View File

@ -0,0 +1,205 @@
/*
* Copyright © 2022 Imagination Technologies Ltd.
*
* based in part on anv driver which is:
* Copyright © 2015 Intel Corporation
*
* based in part on v3dv_cl.h which is:
* Copyright © 2019 Raspberry Pi
*
* 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_CSB_H
#define PVR_CSB_H
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <vulkan/vulkan.h>
#include "pvr_bo.h"
#include "pvr_winsys.h"
#include "util/list.h"
#define __pvr_address_type pvr_dev_addr_t
#define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr).addr
#include "csbgen/rogue_hwdefs.h"
struct pvr_device;
enum pvr_cmd_stream_type {
PVR_CMD_STREAM_TYPE_INVALID = 0, /* explicitly treat 0 as invalid */
PVR_CMD_STREAM_TYPE_GRAPHICS,
PVR_CMD_STREAM_TYPE_COMPUTE,
};
struct pvr_csb {
struct pvr_device *device;
/* Pointer to current csb buffer object */
struct pvr_bo *pvr_bo;
/* pointers to current bo memory */
void *start;
void *end;
void *next;
/* List of csb buffer objects */
struct list_head pvr_bo_list;
enum pvr_cmd_stream_type stream_type;
/* Current error status of the command buffer. Used to track inconsistent
* or incomplete command buffer states that are the consequence of run-time
* errors such as out of memory scenarios. We want to track this in the
* csb because the command buffer object is not visible to some parts
* of the driver.
*/
VkResult status;
};
/**
* \brief Gets the status of the csb.
*
* \param[in] csb Control Stream Builder object.
* \return VK_SUCCESS if the csb hasn't encountered any error or error code
* otherwise.
*/
static inline VkResult pvr_csb_get_status(struct pvr_csb *csb)
{
return csb->status;
}
/**
* \brief Checks if the control stream is empty or not.
*
* \param[in] csb Control Stream Builder object.
* \return true if csb is empty false otherwise.
*/
static inline bool pvr_csb_is_empty(struct pvr_csb *csb)
{
return list_is_empty(&csb->pvr_bo_list);
}
static inline pvr_dev_addr_t pvr_csb_get_start_address(struct pvr_csb *csb)
{
if (!pvr_csb_is_empty(csb)) {
struct pvr_bo *pvr_bo =
list_first_entry(&csb->pvr_bo_list, struct pvr_bo, link);
return pvr_bo->vma->dev_addr;
}
return PVR_DEV_ADDR_INVALID;
}
void pvr_csb_init(struct pvr_device *device,
enum pvr_cmd_stream_type stream_type,
struct pvr_csb *csb);
void pvr_csb_finish(struct pvr_csb *csb);
void *pvr_csb_alloc_dwords(struct pvr_csb *csb, uint32_t num_dwords);
VkResult pvr_csb_emit_return(struct pvr_csb *csb);
VkResult pvr_csb_emit_terminate(struct pvr_csb *csb);
#define PVRX(x) ROGUE_##x
#define pvr_cmd_struct(x) PVRX(x)
#define pvr_cmd_length(x) PVRX(x##_length)
#define pvr_cmd_header(x) PVRX(x##_header)
#define pvr_cmd_pack(x) PVRX(x##_pack)
/**
* \brief Packs a command/state into one or more dwords and stores them in the
* memory pointed to by _dst.
*
* \param[out] _dst Pointer to store the packed command/state.
* \param[in] cmd Command/state type.
* \param[in,out] name Name to give to the command/state structure variable,
* which contains the information to be packed and emitted.
* This can be used by the caller to modify the command or
* state information before it's packed.
*/
#define pvr_csb_pack(_dst, cmd, name) \
for (struct pvr_cmd_struct(cmd) name = { pvr_cmd_header(cmd) }, \
*_loop_terminate = &name; \
__builtin_expect(_loop_terminate != NULL, 1); \
({ \
pvr_cmd_pack(cmd)((_dst), &name); \
_loop_terminate = NULL; \
}))
/**
* \brief Merges dwords0 and dwords1 arrays and stores the result into the
* control stream pointed by the csb object.
*
* \param[in] csb Control Stream Builder object.
* \param[in] dwords0 Dwords0 array.
* \param[in] dwords1 Dwords1 array.
*/
#define pvr_csb_emit_merge(csb, dwords0, dwords1) \
do { \
uint32_t *dw; \
STATIC_ASSERT(ARRAY_SIZE(dwords0) == ARRAY_SIZE(dwords1)); \
dw = pvr_csb_alloc_dwords(csb, ARRAY_SIZE(dwords0)); \
if (!dw) \
break; \
for (uint32_t i = 0; i < ARRAY_SIZE(dwords0); i++) \
dw[i] = (dwords0)[i] | (dwords1)[i]; \
} while (0)
/**
* \brief Packs a command/state into one or more dwords and stores them into
* the control stream pointed by the csb object.
*
* \param[in] csb Control Stream Builder object.
* \param[in] cmd Command/state type.
* \param[in,out] name Name to give to the command/state structure variable,
* which contains the information to be packed. This can be
* used by the caller to modify the command or state
* information before it's packed.
*/
#define pvr_csb_emit(csb, cmd, name) \
for (struct pvr_cmd_struct(cmd) \
name = { pvr_cmd_header(cmd) }, \
*_dst = pvr_csb_alloc_dwords(csb, pvr_cmd_length(cmd)); \
__builtin_expect(_dst != NULL, 1); \
({ \
pvr_cmd_pack(cmd)(_dst, &name); \
_dst = NULL; \
}))
/**
* \brief Stores dword into the control stream pointed by the csb object.
*
* \param[in] csb Control Stream Builder object.
* \param[in] dword Dword to store into control stream.
*/
#define pvr_csb_emit_dword(csb, dword) \
do { \
uint32_t *dw; \
STATIC_ASSERT(sizeof(dword) == sizeof(uint32_t)); \
dw = pvr_csb_alloc_dwords(csb, 1U); \
if (!dw) \
break; \
*dw = dword; \
} while (0)
#endif /* PVR_CSB_H */

Some files were not shown because too many files have changed in this diff Show More