Files
third_party_mesa3d/src/imagination/vulkan/pvr_common.h
Simon Perretta f0b47cfd65 pvr: Add support for generating transfer fragment programs
Co-authored-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com>
Co-authored-by: Rajnesh Kanwal <rajnesh.kanwal@imgtec.com>
Signed-off-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com>
Signed-off-by: Rajnesh Kanwal <rajnesh.kanwal@imgtec.com>
Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Acked-by: Frank Binns <frank.binns@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21550>
2023-04-19 11:01:05 +00:00

483 lines
14 KiB
C

/*
* Copyright © 2023 Imagination Technologies Ltd.
*
* based in part on anv driver which is:
* Copyright © 2015 Intel Corporation
*
* based in part on radv driver which is:
* Copyright © 2016 Red Hat.
* Copyright © 2016 Bas Nieuwenhuizen
*
* 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_COMMON_H
#define PVR_COMMON_H
#include <stdbool.h>
#include <stdint.h>
#include <vulkan/vulkan.h>
/* FIXME: Rename this, and ensure it only contains what's
* relevant for the driver/compiler interface (no Vulkan types).
*/
#include "pvr_limits.h"
#include "pvr_types.h"
#include "util/list.h"
#include "vk_object.h"
#include "vk_sync.h"
#define VK_VENDOR_ID_IMAGINATION 0x1010
#define PVR_WORKGROUP_DIMENSIONS 3U
#define PVR_SAMPLER_DESCRIPTOR_SIZE 4U
#define PVR_IMAGE_DESCRIPTOR_SIZE 4U
#define PVR_STATE_PBE_DWORDS 2U
#define PVR_PIPELINE_LAYOUT_SUPPORTED_DESCRIPTOR_TYPE_COUNT \
(uint32_t)(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + 1U)
#define PVR_TRANSFER_MAX_LAYERS 1U
#define PVR_TRANSFER_MAX_LOADS 4U
#define PVR_TRANSFER_MAX_IMAGES \
(PVR_TRANSFER_MAX_LAYERS * PVR_TRANSFER_MAX_LOADS)
/* TODO: move into a common surface library? */
enum pvr_memlayout {
PVR_MEMLAYOUT_UNDEFINED = 0, /* explicitly treat 0 as undefined */
PVR_MEMLAYOUT_LINEAR,
PVR_MEMLAYOUT_TWIDDLED,
PVR_MEMLAYOUT_3DTWIDDLED,
};
enum pvr_texture_state {
PVR_TEXTURE_STATE_SAMPLE,
PVR_TEXTURE_STATE_STORAGE,
PVR_TEXTURE_STATE_ATTACHMENT,
PVR_TEXTURE_STATE_MAX_ENUM,
};
enum pvr_sub_cmd_type {
PVR_SUB_CMD_TYPE_INVALID = 0, /* explicitly treat 0 as invalid */
PVR_SUB_CMD_TYPE_GRAPHICS,
PVR_SUB_CMD_TYPE_COMPUTE,
PVR_SUB_CMD_TYPE_TRANSFER,
PVR_SUB_CMD_TYPE_OCCLUSION_QUERY,
PVR_SUB_CMD_TYPE_EVENT,
};
enum pvr_event_type {
PVR_EVENT_TYPE_SET,
PVR_EVENT_TYPE_RESET,
PVR_EVENT_TYPE_WAIT,
PVR_EVENT_TYPE_BARRIER,
};
enum pvr_depth_stencil_usage {
PVR_DEPTH_STENCIL_USAGE_UNDEFINED = 0, /* explicitly treat 0 as undefined */
PVR_DEPTH_STENCIL_USAGE_NEEDED,
PVR_DEPTH_STENCIL_USAGE_NEVER,
};
enum pvr_job_type {
PVR_JOB_TYPE_GEOM,
PVR_JOB_TYPE_FRAG,
PVR_JOB_TYPE_COMPUTE,
PVR_JOB_TYPE_TRANSFER,
PVR_JOB_TYPE_OCCLUSION_QUERY,
PVR_JOB_TYPE_MAX
};
enum pvr_pipeline_type {
PVR_PIPELINE_TYPE_INVALID = 0, /* explicitly treat 0 as undefined */
PVR_PIPELINE_TYPE_GRAPHICS,
PVR_PIPELINE_TYPE_COMPUTE,
};
enum pvr_pipeline_stage_bits {
PVR_PIPELINE_STAGE_GEOM_BIT = BITFIELD_BIT(PVR_JOB_TYPE_GEOM),
PVR_PIPELINE_STAGE_FRAG_BIT = BITFIELD_BIT(PVR_JOB_TYPE_FRAG),
PVR_PIPELINE_STAGE_COMPUTE_BIT = BITFIELD_BIT(PVR_JOB_TYPE_COMPUTE),
PVR_PIPELINE_STAGE_TRANSFER_BIT = BITFIELD_BIT(PVR_JOB_TYPE_TRANSFER),
/* Note that this doesn't map to VkPipelineStageFlagBits so be careful with
* this.
*/
PVR_PIPELINE_STAGE_OCCLUSION_QUERY_BIT =
BITFIELD_BIT(PVR_JOB_TYPE_OCCLUSION_QUERY),
};
#define PVR_PIPELINE_STAGE_ALL_GRAPHICS_BITS \
(PVR_PIPELINE_STAGE_GEOM_BIT | PVR_PIPELINE_STAGE_FRAG_BIT)
#define PVR_PIPELINE_STAGE_ALL_BITS \
(PVR_PIPELINE_STAGE_ALL_GRAPHICS_BITS | PVR_PIPELINE_STAGE_COMPUTE_BIT | \
PVR_PIPELINE_STAGE_TRANSFER_BIT)
#define PVR_NUM_SYNC_PIPELINE_STAGES 4U
/* Warning: Do not define an invalid stage as 0 since other code relies on 0
* being the first shader stage. This allows for stages to be split or added
* in the future. Defining 0 as invalid will very likely cause problems.
*/
enum pvr_stage_allocation {
PVR_STAGE_ALLOCATION_VERTEX_GEOMETRY,
PVR_STAGE_ALLOCATION_FRAGMENT,
PVR_STAGE_ALLOCATION_COMPUTE,
PVR_STAGE_ALLOCATION_COUNT
};
enum pvr_resolve_op {
PVR_RESOLVE_BLEND,
PVR_RESOLVE_MIN,
PVR_RESOLVE_MAX,
PVR_RESOLVE_SAMPLE0,
PVR_RESOLVE_SAMPLE1,
PVR_RESOLVE_SAMPLE2,
PVR_RESOLVE_SAMPLE3,
PVR_RESOLVE_SAMPLE4,
PVR_RESOLVE_SAMPLE5,
PVR_RESOLVE_SAMPLE6,
PVR_RESOLVE_SAMPLE7,
};
enum pvr_alpha_type {
PVR_ALPHA_NONE,
PVR_ALPHA_SOURCE,
PVR_ALPHA_PREMUL_SOURCE,
PVR_ALPHA_GLOBAL,
PVR_ALPHA_PREMUL_SOURCE_WITH_GLOBAL,
PVR_ALPHA_CUSTOM,
PVR_ALPHA_AATEXT,
};
enum pvr_event_state {
PVR_EVENT_STATE_SET_BY_HOST,
PVR_EVENT_STATE_RESET_BY_HOST,
PVR_EVENT_STATE_SET_BY_DEVICE,
PVR_EVENT_STATE_RESET_BY_DEVICE
};
enum pvr_deferred_cs_command_type {
PVR_DEFERRED_CS_COMMAND_TYPE_DBSC,
PVR_DEFERRED_CS_COMMAND_TYPE_DBSC2,
};
enum pvr_query_type {
PVR_QUERY_TYPE_AVAILABILITY_WRITE,
PVR_QUERY_TYPE_RESET_QUERY_POOL,
PVR_QUERY_TYPE_COPY_QUERY_RESULTS,
};
union pvr_sampler_descriptor {
uint32_t words[PVR_SAMPLER_DESCRIPTOR_SIZE];
struct {
/* Packed PVRX(TEXSTATE_SAMPLER). */
uint64_t sampler_word;
uint32_t compare_op;
/* TODO: Figure out what this word is for and rename.
* Sampler state word 1?
*/
uint32_t word3;
} data;
};
struct pvr_sampler {
struct vk_object_base base;
union pvr_sampler_descriptor descriptor;
};
struct pvr_descriptor_size_info {
/* Non-spillable size for storage in the common store. */
uint32_t primary;
/* Spillable size to accommodate limitation of the common store. */
uint32_t secondary;
uint32_t alignment;
};
struct pvr_descriptor_set_layout_binding {
VkDescriptorType type;
/* "M" in layout(set = N, binding = M)
* Can be used to index bindings in the descriptor_set_layout. Not the
* original user specified binding number as those might be non-contiguous.
*/
uint32_t binding_number;
uint32_t descriptor_count;
/* Index into the flattened descriptor set */
uint16_t descriptor_index;
/* Mask of enum pvr_stage_allocation. */
uint8_t shader_stage_mask;
struct {
uint32_t primary;
uint32_t secondary;
} per_stage_offset_in_dwords[PVR_STAGE_ALLOCATION_COUNT];
bool has_immutable_samplers;
/* Index at which the samplers can be found in the descriptor_set_layout.
* 0 when the samplers are at index 0 or no samplers are present.
*/
uint32_t immutable_samplers_index;
};
/* All sizes are in dwords. */
struct pvr_descriptor_set_layout_mem_layout {
uint32_t primary_offset;
uint32_t primary_size;
uint32_t secondary_offset;
uint32_t secondary_size;
uint32_t primary_dynamic_size;
uint32_t secondary_dynamic_size;
};
struct pvr_descriptor_set_layout {
struct vk_object_base base;
/* Total amount of descriptors contained in this set. */
uint32_t descriptor_count;
/* Count of dynamic buffers. */
uint32_t dynamic_buffer_count;
uint32_t total_dynamic_size_in_dwords;
uint32_t binding_count;
struct pvr_descriptor_set_layout_binding *bindings;
uint32_t immutable_sampler_count;
const struct pvr_sampler **immutable_samplers;
/* Shader stages requiring access to descriptors in this set. */
/* Mask of enum pvr_stage_allocation. */
uint8_t shader_stage_mask;
/* Count of each VkDescriptorType per shader stage. Dynamically allocated
* arrays per stage as to not hard code the max descriptor type here.
*
* Note: when adding a new type, it might not numerically follow the
* previous type so a sparse array will be created. You might want to
* readjust how these arrays are created and accessed.
*/
uint32_t *per_stage_descriptor_count[PVR_STAGE_ALLOCATION_COUNT];
uint32_t total_size_in_dwords;
struct pvr_descriptor_set_layout_mem_layout
memory_layout_in_dwords_per_stage[PVR_STAGE_ALLOCATION_COUNT];
};
struct pvr_descriptor_pool {
struct vk_object_base base;
VkAllocationCallbacks alloc;
/* Saved information from pCreateInfo. */
uint32_t max_sets;
uint32_t total_size_in_dwords;
uint32_t current_size_in_dwords;
/* Derived and other state. */
/* List of the descriptor sets created using this pool. */
struct list_head descriptor_sets;
};
struct pvr_descriptor {
VkDescriptorType type;
union {
struct {
struct pvr_buffer_view *bview;
pvr_dev_addr_t buffer_dev_addr;
VkDeviceSize buffer_desc_range;
VkDeviceSize buffer_whole_range;
};
struct {
VkImageLayout layout;
const struct pvr_image_view *iview;
const struct pvr_sampler *sampler;
};
};
};
struct pvr_descriptor_set {
struct vk_object_base base;
const struct pvr_descriptor_set_layout *layout;
const struct pvr_descriptor_pool *pool;
struct pvr_bo *pvr_bo;
/* Links this descriptor set into pvr_descriptor_pool::descriptor_sets list.
*/
struct list_head link;
/* Array of size layout::descriptor_count. */
struct pvr_descriptor descriptors[0];
};
struct pvr_event {
struct vk_object_base base;
enum pvr_event_state state;
struct vk_sync *sync;
};
#define PVR_MAX_DYNAMIC_BUFFERS \
(PVR_MAX_DESCRIPTOR_SET_UNIFORM_DYNAMIC_BUFFERS + \
PVR_MAX_DESCRIPTOR_SET_STORAGE_DYNAMIC_BUFFERS)
struct pvr_descriptor_state {
struct pvr_descriptor_set *descriptor_sets[PVR_MAX_DESCRIPTOR_SETS];
uint32_t valid_mask;
uint32_t dynamic_offsets[PVR_MAX_DYNAMIC_BUFFERS];
};
#undef PVR_MAX_DYNAMIC_BUFFERS
/**
* \brief Indicates the layout of shared registers allocated by the driver.
*
* 'present' fields indicate if a certain resource was allocated for, and
* whether it will be present in the shareds.
* 'offset' fields indicate at which shared reg the resource starts at.
*/
struct pvr_sh_reg_layout {
/* If this is present, it will always take up 2 sh regs in size and contain
* the device address of the descriptor set addrs table.
*/
struct {
bool present;
uint32_t offset;
} descriptor_set_addrs_table;
/* If this is present, it will always take up 2 sh regs in size and contain
* the device address of the push constants buffer.
*/
struct {
bool present;
uint32_t offset;
} push_consts;
/* If this is present, it will always take up 2 sh regs in size and contain
* the device address of the blend constants buffer.
*/
struct {
bool present;
uint32_t offset;
} blend_consts;
};
struct pvr_pipeline_layout {
struct vk_object_base base;
uint32_t set_count;
/* Contains set_count amount of descriptor set layouts. */
struct pvr_descriptor_set_layout *set_layout[PVR_MAX_DESCRIPTOR_SETS];
VkShaderStageFlags push_constants_shader_stages;
uint32_t vert_push_constants_offset;
uint32_t frag_push_constants_offset;
uint32_t compute_push_constants_offset;
/* Mask of enum pvr_stage_allocation. */
uint8_t shader_stage_mask;
/* Per stage masks indicating which set in the layout contains any
* descriptor of the appropriate types: VK..._{SAMPLER, SAMPLED_IMAGE,
* UNIFORM_TEXEL_BUFFER, UNIFORM_BUFFER, STORAGE_BUFFER}.
* Shift by the set's number to check the mask (1U << set_num).
*/
uint32_t per_stage_descriptor_masks[PVR_STAGE_ALLOCATION_COUNT];
/* Array of descriptor offsets at which the set's descriptors' start, per
* stage, within all the sets in the pipeline layout per descriptor type.
* Note that we only store into for specific descriptor types
* VK_DESCRIPTOR_TYPE_{SAMPLER, SAMPLED_IMAGE, UNIFORM_TEXEL_BUFFER,
* UNIFORM_BUFFER, STORAGE_BUFFER}, the rest will be 0.
*/
uint32_t
descriptor_offsets[PVR_MAX_DESCRIPTOR_SETS][PVR_STAGE_ALLOCATION_COUNT]
[PVR_PIPELINE_LAYOUT_SUPPORTED_DESCRIPTOR_TYPE_COUNT];
/* There is no accounting for dynamics in here. They will be garbage values.
*/
struct pvr_descriptor_set_layout_mem_layout
register_layout_in_dwords_per_stage[PVR_STAGE_ALLOCATION_COUNT]
[PVR_MAX_DESCRIPTOR_SETS];
/* TODO: Consider whether this needs to be here. */
struct pvr_sh_reg_layout sh_reg_layout_per_stage[PVR_STAGE_ALLOCATION_COUNT];
/* All sizes in dwords. */
struct pvr_pipeline_layout_reg_info {
uint32_t primary_dynamic_size_in_dwords;
uint32_t secondary_dynamic_size_in_dwords;
} per_stage_reg_info[PVR_STAGE_ALLOCATION_COUNT];
};
static int pvr_compare_layout_binding(const void *a, const void *b)
{
uint32_t binding_a;
uint32_t binding_b;
binding_a = ((struct pvr_descriptor_set_layout_binding *)a)->binding_number;
binding_b = ((struct pvr_descriptor_set_layout_binding *)b)->binding_number;
if (binding_a < binding_b)
return -1;
if (binding_a > binding_b)
return 1;
return 0;
}
/* This function does not assume that the binding will always exist for a
* particular binding_num. Caller should check before using the return pointer.
*/
static struct pvr_descriptor_set_layout_binding *
pvr_get_descriptor_binding(const struct pvr_descriptor_set_layout *layout,
const uint32_t binding_num)
{
struct pvr_descriptor_set_layout_binding binding;
binding.binding_number = binding_num;
return bsearch(&binding,
layout->bindings,
layout->binding_count,
sizeof(binding),
pvr_compare_layout_binding);
}
#endif /* PVR_COMMON_H */