diff --git a/src/imagination/common/pvr_device_info.c b/src/imagination/common/pvr_device_info.c
index c1dd1dbd01a..85161bb5027 100644
--- a/src/imagination/common/pvr_device_info.c
+++ b/src/imagination/common/pvr_device_info.c
@@ -151,6 +151,7 @@ const struct pvr_device_features pvr_device_features_33_V_11_3 = {
.has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
+ .has_tpu_border_colour_enhanced = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_usc_f16sop_u8 = true,
@@ -235,6 +236,7 @@ const struct pvr_device_features pvr_device_features_36_V_104_796 = {
.has_tile_size_16x16 = true,
.has_tile_size_x = true,
.has_tile_size_y = true,
+ .has_tpu_border_colour_enhanced = true,
.has_tpu_extended_integer_lookup = true,
.has_tpu_image_state_v2 = true,
.has_usc_f16sop_u8 = true,
diff --git a/src/imagination/common/pvr_device_info.h b/src/imagination/common/pvr_device_info.h
index ed8286d5e1d..8fdb26d551c 100644
--- a/src/imagination/common/pvr_device_info.h
+++ b/src/imagination/common/pvr_device_info.h
@@ -286,6 +286,7 @@ struct pvr_device_features {
bool has_tile_size_x : 1;
bool has_tile_size_y : 1;
bool has_tpu_array_textures : 1;
+ bool has_tpu_border_colour_enhanced : 1;
bool has_tpu_extended_integer_lookup : 1;
bool has_tpu_image_state_v2 : 1;
bool has_usc_f16sop_u8 : 1;
diff --git a/src/imagination/csbgen/rogue_texstate.xml b/src/imagination/csbgen/rogue_texstate.xml
index 79c91eb56f0..dd181556758 100644
--- a/src/imagination/csbgen/rogue_texstate.xml
+++ b/src/imagination/csbgen/rogue_texstate.xml
@@ -267,7 +267,9 @@ SOFTWARE.
-
+
+
+
@@ -325,7 +327,9 @@ SOFTWARE.
-
+
+
+
diff --git a/src/imagination/vulkan/meson.build b/src/imagination/vulkan/meson.build
index fa034c95b09..6a16acf82fd 100644
--- a/src/imagination/vulkan/meson.build
+++ b/src/imagination/vulkan/meson.build
@@ -39,6 +39,7 @@ pvr_files = files(
'winsys/pvr_winsys_helper.c',
'pvr_blit.c',
'pvr_bo.c',
+ 'pvr_border.c',
'pvr_clear.c',
'pvr_cmd_buffer.c',
'pvr_csb.c',
@@ -111,7 +112,7 @@ endif
libvulkan_powervr_mesa = shared_library(
'vulkan_powervr_mesa',
- [pvr_files, pvr_entrypoints],
+ [pvr_files, pvr_entrypoints, u_format_pack_h],
include_directories : [
pvr_includes,
inc_gallium_aux,
diff --git a/src/imagination/vulkan/pvr_border.c b/src/imagination/vulkan/pvr_border.c
new file mode 100644
index 00000000000..f2d874f183d
--- /dev/null
+++ b/src/imagination/vulkan/pvr_border.c
@@ -0,0 +1,1147 @@
+/*
+ * Copyright © 2023 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include
+#include
+#include
+
+#include "hwdef/rogue_hw_utils.h"
+#include "pvr_border.h"
+#include "pvr_csb.h"
+#include "pvr_device_info.h"
+#include "pvr_private.h"
+#include "util/bitset.h"
+#include "util/format_r11g11b10f.h"
+#include "util/format_rgb9e5.h"
+#include "util/format/format_utils.h"
+#include "util/format/u_format_pack.h"
+#include "util/macros.h"
+#include "util/u_endian.h"
+#include "vk_sampler.h"
+#include "vk_util.h"
+
+#define PVR_BORDER_COLOR_TABLE_NR_FORMATS \
+ (PVRX(TEXSTATE_IMAGE_WORD0_TEXFORMAT_MAX_SIZE) + 1)
+
+/* TODO: Eliminate all of these format-wrangling macros & functions by encoding
+ * our internal formats in a csv (a la src/mesa/main/formats.csv)
+ */
+
+#define intx(i, b) (i & BITFIELD_MASK(b))
+#define normx(n, b) _mesa_float_to_unorm(n, b)
+#define snormx(s, b) _mesa_float_to_snorm(s, b)
+
+#define int1(i) intx(i, 1)
+#define int2(i) intx(i, 2)
+#define int3(i) intx(i, 3)
+#define int4(i) intx(i, 4)
+#define int5(i) intx(i, 5)
+#define int6(i) intx(i, 6)
+#define int8(i) intx(i, 8)
+#define int10(i) intx(i, 10)
+#define int16(i) intx(i, 16)
+#define int24(i) intx(i, 24)
+#define int32(i) intx(i, 32)
+
+#define norm1(n) normx(n, 1)
+#define norm2(n) normx(n, 2)
+#define norm3(n) normx(n, 3)
+#define norm4(n) normx(n, 4)
+#define norm5(n) normx(n, 5)
+#define norm6(n) normx(n, 6)
+#define norm8(n) normx(n, 8)
+#define norm10(n) normx(n, 10)
+#define norm16(n) normx(n, 16)
+#define norm24(n) normx(n, 24)
+#define norm32(n) normx(n, 32)
+
+#define snorm5(s) snormx(s, 5)
+#define snorm8(s) snormx(s, 8)
+#define snorm16(s) snormx(s, 16)
+#define snorm32(s) snormx(s, 32)
+
+#define zero8 (0)
+#define zero10 (0)
+#define zero24 (0)
+#define zero32 (0)
+
+#define float10(f) f32_to_uf10(f)
+#define float11(f) f32_to_uf11(f)
+#define float16(f) ((uint32_t)_mesa_float_to_half(f))
+#define float32(f) ((uint32_t)(f))
+
+union pvr_border_color_table_value {
+ struct {
+ uint32_t w0, w1, w2, w3;
+ };
+ uint32_t arr[4];
+ uint8_t bytes[16];
+} PACKED;
+static_assert(sizeof(union pvr_border_color_table_value) ==
+ 4 * sizeof(uint32_t),
+ "pvr_border_color_table_value must be 4 x u32");
+
+struct pvr_border_color_table_entry {
+ union pvr_border_color_table_value formats[PVR_BORDER_COLOR_TABLE_NR_FORMATS];
+ union pvr_border_color_table_value
+ compressed_formats[PVR_BORDER_COLOR_TABLE_NR_FORMATS];
+} PACKED;
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i8(const uint32_t i0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int8(i0),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i8i8(const uint32_t i0, const uint32_t i1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int8(i0) | int8(i1) << 8,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i8i8i8(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int8(i0) | int8(i1) << 8 | int8(i2) << 16,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i8i8i8i8(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2,
+ const uint32_t i3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int8(i0) | int8(i1) << 8 | int8(i2) << 16 | int8(i3) << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i8i8i8x8(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int8(i0) | int8(i1) << 8 | int8(i2) << 16 | zero8 << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i16(const uint32_t i0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int16(i0),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i16i16(const uint32_t i0, const uint32_t i1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int16(i0) | int16(i1) << 16,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i16i16i16(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int16(i0) | int16(i1) << 16,
+ .w1 = int16(i2),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i16i16i16i16(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2,
+ const uint32_t i3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int16(i0) | int16(i1) << 16,
+ .w1 = int16(i2) | int16(i3) << 16,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i32(const uint32_t i0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int32(i0),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i32i32(const uint32_t i0, const uint32_t i1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int32(i0),
+ .w1 = int32(i1),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i32i32i32(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int32(i0),
+ .w1 = int32(i1),
+ .w2 = int32(i2),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i32i32i32i32(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2,
+ const uint32_t i3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int32(i0),
+ .w1 = int32(i1),
+ .w2 = int32(i2),
+ .w3 = int32(i3),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i4i4i4i4(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2,
+ const uint32_t i3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int4(i0) | int4(i1) << 4 | int4(i2) << 8 | int4(i3) << 12,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i2i3i3i8(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2,
+ const uint32_t i3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int2(i0) | int3(i1) << 2 | int3(i2) << 5 | int8(i3) << 8,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i5i5i5i1(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2,
+ const uint32_t i3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int5(i0) | int5(i1) << 5 | int5(i2) << 10 | int1(i3) << 15,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i1i5i5i5(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2,
+ const uint32_t i3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int1(i0) | int5(i1) << 1 | int5(i2) << 6 | int5(i3) << 11,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i5i6i5(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int5(i0) | int6(i1) << 5 | int5(i2) << 11,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i6i5i5(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int6(i0) | int5(i1) << 6 | int5(i2) << 11,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i5i5i6(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int5(i0) | int5(i1) << 5 | int6(i2) << 10,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i10i10i10i2(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2,
+ const uint32_t i3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int10(i0) | int10(i1) << 10 | int10(i2) << 20 | int2(i3) << 30,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_x10x10x10i2(const uint32_t i3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = zero10 | zero10 << 10 | zero10 << 20 | int2(i3) << 30,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i2i10i10i10(const uint32_t i0,
+ const uint32_t i1,
+ const uint32_t i2,
+ const uint32_t i3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int2(i0) | int10(i1) << 2 | int10(i2) << 12 | int10(i3) << 22,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i2x10x10x10(const uint32_t i0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int2(i0) | zero10 << 2 | zero10 << 12 | zero10 << 22,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i24i8(const uint32_t i0, const uint32_t i1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int24(i0) | int8(i1) << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i24x8(const uint32_t i0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int24(i0) | zero8 << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_x24i8(const uint32_t i1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = zero24 | int8(i1) << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_i8i24(const uint32_t i0, const uint32_t i1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = int8(i0) | int24(i1) << 8,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_x32i8x24(const uint32_t i1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = zero32,
+ .w1 = int8(i1) | zero24 << 8,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n8(const float n0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm8(n0),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n8n8(const float n0, const float n1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm8(n0) | norm8(n1) << 8,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n8n8n8(const float n0, const float n1, const float n2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm8(n0) | norm8(n1) << 8 | norm8(n2) << 16,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n8n8n8n8(const float n0,
+ const float n1,
+ const float n2,
+ const float n3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm8(n0) | norm8(n1) << 8 | norm8(n2) << 16 | norm8(n3) << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n8n8n8x8(const float n0, const float n1, const float n2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm8(n0) | norm8(n1) << 8 | norm8(n2) << 16 | zero8 << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n8s8s8x8(const float n0, const float s1, const float s2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm8(n0) | snorm8(s1) << 8 | snorm8(s2) << 16 | zero8 << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s8(const float s0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm8(s0),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s8s8(const float s0, const float s1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm8(s0) | snorm8(s1) << 8,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s8s8s8(const float s0, const float s1, const float s2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm8(s0) | snorm8(s1) << 8 | snorm8(s2) << 16,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s8s8s8s8(const float s0,
+ const float s1,
+ const float s2,
+ const float s3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm8(s0) | snorm8(s1) << 8 | snorm8(s2) << 16 | snorm8(s3) << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n16(const float n0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm16(n0),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n16n16(const float n0, const float n1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm16(n0) | norm16(n1) << 16,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n16n16n16(const float n0, const float n1, const float n2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm16(n0) | norm16(n1) << 16,
+ .w1 = norm16(n2),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n16n16n16n16(const float n0,
+ const float n1,
+ const float n2,
+ const float n3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm16(n0) | norm16(n1) << 16,
+ .w1 = norm16(n2) | norm16(n3) << 16,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s16(const float s0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm16(s0),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s16s16(const float s0, const float s1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm16(s0) | snorm16(s1) << 16,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s16s16s16(const float s0, const float s1, const float s2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm16(s0) | snorm16(s1) << 16,
+ .w1 = snorm16(s2),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s16s16s16s16(const float s0,
+ const float s1,
+ const float s2,
+ const float s3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm16(s0) | snorm16(s1) << 16,
+ .w1 = snorm16(s2) | snorm16(s3) << 16,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n32(const float n0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm32(n0),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n32n32(const float n0, const float n1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm32(n0),
+ .w1 = norm32(n1),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n32n32n32(const float n0, const float n1, const float n2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm32(n0),
+ .w1 = norm32(n1),
+ .w2 = norm32(n2),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n32n32n32n32(const float n0,
+ const float n1,
+ const float n2,
+ const float n3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm32(n0),
+ .w1 = norm32(n1),
+ .w2 = norm32(n2),
+ .w3 = norm32(n3),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s32(const float s0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm32(s0),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s32s32(const float s0, const float s1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm32(s0),
+ .w1 = snorm32(s1),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s32s32s32(const float s0, const float s1, const float s2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm32(s0),
+ .w1 = snorm32(s1),
+ .w2 = snorm32(s2),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s32s32s32s32(const float s0,
+ const float s1,
+ const float s2,
+ const float s3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm32(s0),
+ .w1 = snorm32(s1),
+ .w2 = snorm32(s2),
+ .w3 = snorm32(s3),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n4n4n4n4(const float n0,
+ const float n1,
+ const float n2,
+ const float n3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm4(n0) | norm4(n1) << 4 | norm4(n2) << 8 | norm4(n3) << 12,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n2n3n3n8(const float n0,
+ const float n1,
+ const float n2,
+ const float n3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm2(n0) | norm3(n1) << 2 | norm3(n2) << 5 | norm8(n3) << 8,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n5n5n5n1(const float n0,
+ const float n1,
+ const float n2,
+ const float n3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm5(n0) | norm5(n1) << 5 | norm5(n2) << 10 | norm1(n3) << 15,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n1n5n5n5(const float n0,
+ const float n1,
+ const float n2,
+ const float n3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm1(n0) | norm5(n1) << 1 | norm5(n2) << 6 | norm5(n3) << 11,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n5n6n5(const float n0, const float n1, const float n2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm5(n0) | norm6(n1) << 5 | norm5(n2) << 11,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n6s5s5(const float n0, const float s1, const float s2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm6(n0) | snorm5(s1) << 6 | snorm5(s2) << 11,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_s5s5n6(const float s0, const float s1, const float n2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = snorm5(s0) | snorm5(s1) << 5 | norm6(n2) << 10,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n10n10n10n2(const float n0,
+ const float n1,
+ const float n2,
+ const float n3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm10(n0) | norm10(n1) << 10 | norm10(n2) << 20 | norm2(n3) << 30,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f10f10f10n2(const float f0,
+ const float f1,
+ const float f2,
+ const float n3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float10(f0) | float10(f1) << 10 | float10(f2) << 20 |
+ norm2(n3) << 30,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n2n10n10n10(const float n0,
+ const float n1,
+ const float n2,
+ const float n3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm2(n0) | norm10(n1) << 2 | norm10(n2) << 12 | norm10(n3) << 22,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n2f10f10f10(const float n0,
+ const float f1,
+ const float f2,
+ const float f3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm2(n0) | float10(f1) << 2 | float10(f2) << 12 |
+ float10(f3) << 22,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n24n8(const float n0, const float n1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm24(n0) | norm8(n1) << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n24x8(const float n0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm24(n0) | zero8 << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_x24n8(const float n1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = zero24 | norm8(n1) << 24,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_n8n24(const float n0, const float n1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = norm8(n0) | norm24(n1) << 8,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f32n8x24(const float f0, const float n1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float32(f0),
+ .w1 = norm8(n1) | zero24 << 8,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f32x8x24(const float f0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float32(f0),
+ .w1 = zero8 | zero24 << 8,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_x32n8x24(const float n1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = zero32,
+ .w1 = norm8(n1) | zero24 << 8,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f16(const float f0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float16(f0),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f16f16(const float f0, const float f1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float16(f0) | float16(f1) << 16,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f16f16f16(const float f0, const float f1, const float f2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float16(f0) | float16(f1) << 16,
+ .w1 = float16(f2),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f16f16f16f16(const float f0,
+ const float f1,
+ const float f2,
+ const float f3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float16(f0) | float16(f1) << 16,
+ .w1 = float16(f2) | float16(f3) << 16,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f32(const float f0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float32(f0),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_g32(const float g0)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float32(g0) & 0x7fffffff,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f32f32(const float f0, const float f1)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float32(f0),
+ .w1 = float32(f1),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f32f32f32(const float f0, const float f1, const float f2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float32(f0),
+ .w1 = float32(f1),
+ .w2 = float32(f2),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f32f32f32f32(const float f0,
+ const float f1,
+ const float f2,
+ const float f3)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float32(f0),
+ .w1 = float32(f1),
+ .w2 = float32(f2),
+ .w3 = float32(f3),
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f10f11f11(const float f0, const float f1, const float f2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float10(f0) | float11(f1) << 10 | float11(f2) << 21,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_f11f11f10(const float f0, const float f1, const float f2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float11(f0) | float11(f1) << 11 | float10(f2) << 22,
+ };
+}
+
+static inline union pvr_border_color_table_value
+pvr_pack_border_color_e9e9e9x5(const float f0, const float f1, const float f2)
+{
+ return (union pvr_border_color_table_value){
+ .w0 = float3_to_rgb9e5((float[3]){ f0, f1, f2 }),
+ };
+}
+
+#define PACK(format_, layout_, channels_...) \
+ entry->formats[PVRX(TEXSTATE_FORMAT_##format_)] = \
+ pvr_pack_border_color_##layout_(channels_)
+
+/* clang-format off */
+#define UDEF(format_) \
+ entry->formats[PVRX(TEXSTATE_FORMAT_##format_)] = \
+ (union pvr_border_color_table_value){ 0 }
+/* clang-format on */
+
+static void
+pvr_pack_border_color_ints(struct pvr_border_color_table_entry *const entry,
+ const uint32_t color[const static 4])
+{
+ const uint32_t r = color[0];
+ const uint32_t g = color[1];
+ const uint32_t b = color[2];
+ const uint32_t a = color[3];
+
+ /* 0 */ PACK(U8, i8, r);
+ /* 1 */ PACK(S8, i8, r);
+ /* 7 */ PACK(U8U8, i8i8, g, r);
+ /* 8 */ PACK(S8S8, i8i8, g, r);
+ /* 9 */ PACK(U16, i16, r);
+ /* 10 */ PACK(S16, i16, r);
+ /* 11 */ UDEF(F16);
+ /* 12 */ PACK(U8U8U8U8, i8i8i8i8, a, b, g, r);
+ /* 13 */ PACK(S8S8S8S8, i8i8i8i8, a, b, g, r);
+ /* 14 */ PACK(A2R10B10G10, i10i10i10i2, r, g, b, a);
+ /* 15 */ PACK(U16U16, i16i16, g, r);
+ /* 16 */ PACK(S16S16, i16i16, g, r);
+ /* 17 */ UDEF(F16F16);
+ /* 18 */ UDEF(F32);
+ /* 22 */ PACK(ST8U24, i24i8, g, r);
+ /* 23 */ PACK(U8X24, x24i8, r);
+ /* 24 */ PACK(U32, i32, r);
+ /* 25 */ PACK(S32, i32, r);
+ /* 26 */ UDEF(SE9995);
+ /* 28 */ UDEF(F16F16F16F16);
+ /* 29 */ PACK(U16U16U16U16, i16i16i16i16, a, b, g, r);
+ /* 30 */ PACK(S16S16S16S16, i16i16i16i16, a, b, g, r);
+ /* 35 */ PACK(U32U32, i32i32, g, r);
+ /* 36 */ PACK(S32S32, i32i32, g, r);
+ /* 61 */ UDEF(F32F32F32F32);
+ /* 62 */ PACK(U32U32U32U32, i32i32i32i32, a, b, g, r);
+ /* 63 */ PACK(S32S32S32S32, i32i32i32i32, a, b, g, r);
+ /* 64 */ UDEF(F32F32F32);
+ /* 65 */ PACK(U32U32U32, i32i32i32, b, g, r);
+ /* 66 */ PACK(S32S32S32, i32i32i32, b, g, r);
+ /* 88 */ UDEF(F10F11F11);
+}
+
+static void
+pvr_pack_border_color_floats(struct pvr_border_color_table_entry *const entry,
+ const float color[const static 4])
+{
+ const float r = color[0];
+ const float g = color[1];
+ const float b = color[2];
+ const float a = color[3];
+
+ /* 0 */ PACK(U8, n8, r);
+ /* 1 */ PACK(S8, s8, r);
+ /* 2 */ PACK(A4R4G4B4, n4n4n4n4, b, g, r, a);
+ /* 4 */ PACK(A1R5G5B5, n5n5n5n1, b, g, r, a);
+ /* 5 */ PACK(R5G6B5, n5n6n5, b, g, r);
+ /* 7 */ PACK(U8U8, n8n8, g, r);
+ /* 8 */ PACK(S8S8, s8s8, g, r);
+ /* 9 */ PACK(U16, n16, r);
+ /* 10 */ PACK(S16, s16, r);
+ /* 11 */ PACK(F16, f16, r);
+ /* 12 */ PACK(U8U8U8U8, n8n8n8n8, a, b, g, r);
+ /* 13 */ PACK(S8S8S8S8, s8s8s8s8, a, b, g, r);
+ /* 14 */ PACK(A2R10B10G10, n10n10n10n2, r, g, b, a);
+ /* 15 */ PACK(U16U16, n16n16, g, r);
+ /* 16 */ PACK(S16S16, s16s16, g, r);
+ /* 17 */ PACK(F16F16, f16f16, g, r);
+ /* 18 */ PACK(F32, f32, r);
+ /* 22 */ PACK(ST8U24, n24n8, g, r);
+ /* 26 */ PACK(SE9995, e9e9e9x5, r, g, b);
+ /* 28 */ PACK(F16F16F16F16, f16f16f16f16, a, b, g, r);
+ /* 29 */ PACK(U16U16U16U16, n16n16n16n16, a, b, g, r);
+ /* 30 */ PACK(S16S16S16S16, s16s16s16s16, a, b, g, r);
+ /* 34 */ PACK(F32F32, f32f32, g, r);
+ /* 61 */ PACK(F32F32F32F32, f32f32f32f32, a, b, g, r);
+ /* 64 */ PACK(F32F32F32, f32f32f32, b, g, r);
+ /* 88 */ PACK(F10F11F11, f11f11f10, b, g, r);
+}
+
+#undef PACK
+#undef UDEF
+
+#define PACKC(format_, layout_, channels_...) \
+ entry->compressed_formats[PVRX(TEXSTATE_FORMAT_COMPRESSED_##format_)] = \
+ pvr_pack_border_color_##layout_(channels_)
+
+static void pvr_pack_border_color_compressed(
+ struct pvr_border_color_table_entry *const entry,
+ const VkClearColorValue color[const static 4])
+{
+ const uint32_t r = color->uint32[0];
+ const uint32_t g = color->uint32[1];
+ const uint32_t b = color->uint32[2];
+ const uint32_t a = color->uint32[3];
+
+ /* 68 */ PACKC(ETC2_RGB, i8i8i8i8, a, b, g, r);
+ /* 69 */ PACKC(ETC2A_RGBA, i8i8i8i8, a, b, g, r);
+ /* 70 */ PACKC(ETC2_PUNCHTHROUGHA, i8i8i8i8, a, b, g, r);
+ /* 71 */ PACKC(EAC_R11_UNSIGNED, i16i16i16i16, a, b, g, r);
+ /* 72 */ PACKC(EAC_R11_SIGNED, i16i16i16i16, a, b, g, r);
+ /* 73 */ PACKC(EAC_RG11_UNSIGNED, i16i16i16i16, a, b, g, r);
+ /* 74 */ PACKC(EAC_RG11_SIGNED, i16i16i16i16, a, b, g, r);
+}
+
+#undef PACKC
+
+static int32_t
+pvr_border_color_table_alloc_entry(struct pvr_border_color_table *const table)
+{
+ const int32_t index = BITSET_FFS(table->unused_entries);
+
+ /* BITSET_FFS() returns 0 if there are no set bits; we have to determine
+ * whether a value of 0 means "no set bits" or "zero is the first set bit".
+ */
+ if (index == 0 && !pvr_border_color_table_is_index_valid(table, 0)) {
+ return -1;
+ }
+
+ BITSET_CLEAR(table->unused_entries, index);
+
+ return index;
+}
+
+static void
+pvr_border_color_table_free_entry(struct pvr_border_color_table *const table,
+ const uint32_t index)
+{
+ assert(BITSET_TEST(table->unused_entries, index));
+ BITSET_SET(table->unused_entries, index);
+}
+
+static void
+pvr_border_color_table_fill_entry(struct pvr_border_color_table *const table,
+ const struct pvr_device *const device,
+ const uint32_t index,
+ const VkClearColorValue *const color,
+ const bool is_int)
+{
+ struct pvr_border_color_table_entry *const entries = table->table->bo->map;
+ const struct pvr_device_info *const dev_info = &device->pdevice->dev_info;
+ struct pvr_border_color_table_entry *entry;
+
+ assert(pvr_border_color_table_is_index_valid(table, index));
+ assert(entries);
+
+ entry = &entries[index];
+ memset(entry, 0, sizeof(*entry));
+
+ if (is_int)
+ pvr_pack_border_color_ints(entry, color->uint32);
+ else
+ pvr_pack_border_color_floats(entry, color->float32);
+
+ if (PVR_HAS_FEATURE(dev_info, tpu_border_colour_enhanced)) {
+ pvr_pack_border_color_compressed(entry, color);
+ } else {
+ pvr_finishme("Devices without tpu_border_colour_enhanced require entries "
+ "for compressed formats to be stored in the table "
+ "pre-compressed.");
+ }
+}
+
+VkResult pvr_border_color_table_init(struct pvr_border_color_table *const table,
+ struct pvr_device *const device)
+{
+ const struct pvr_device_info *const dev_info = &device->pdevice->dev_info;
+ const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info);
+ const uint32_t table_size = sizeof(struct pvr_border_color_table_entry) *
+ PVR_BORDER_COLOR_TABLE_NR_ENTRIES;
+
+ VkResult result;
+
+ /* Initialize to ones so ffs can be used to find unused entries. */
+ BITSET_ONES(table->unused_entries);
+
+ result = pvr_bo_alloc(device,
+ device->heaps.general_heap,
+ table_size,
+ cache_line_size,
+ PVR_BO_ALLOC_FLAG_CPU_MAPPED,
+ &table->table);
+ if (result != VK_SUCCESS)
+ return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ BITSET_CLEAR_RANGE(table->unused_entries,
+ 0,
+ PVR_BORDER_COLOR_TABLE_NR_BUILTIN_ENTRIES - 1);
+
+ for (uint32_t i = 0; i < PVR_BORDER_COLOR_TABLE_NR_BUILTIN_ENTRIES; i++) {
+ const VkClearColorValue color = vk_border_color_value(i);
+ const bool is_int = vk_border_color_is_int(i);
+
+ pvr_border_color_table_fill_entry(table, device, i, &color, is_int);
+ }
+
+ pvr_bo_cpu_unmap(device, table->table);
+
+ return VK_SUCCESS;
+}
+
+void pvr_border_color_table_finish(struct pvr_border_color_table *const table,
+ struct pvr_device *const device)
+{
+ pvr_bo_free(device, table->table);
+}
+
+VkResult pvr_border_color_table_get_or_create_entry(
+ UNUSED struct pvr_border_color_table *const table,
+ const struct VkSamplerCreateInfo *const sampler_create_info,
+ uint32_t *const index_out)
+{
+ const VkBorderColor vk_type = sampler_create_info->borderColor;
+
+ if (vk_type <= PVR_BORDER_COLOR_TABLE_NR_BUILTIN_ENTRIES) {
+ *index_out = vk_type;
+ return VK_SUCCESS;
+ }
+
+ pvr_finishme("VK_EXT_custom_border_color is currently unsupported.");
+ return vk_error(NULL, VK_ERROR_EXTENSION_NOT_PRESENT);
+}
diff --git a/src/imagination/vulkan/pvr_border.h b/src/imagination/vulkan/pvr_border.h
new file mode 100644
index 00000000000..4c190f0d0ba
--- /dev/null
+++ b/src/imagination/vulkan/pvr_border.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2023 Imagination Technologies Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef PVR_BORDER_H
+#define PVR_BORDER_H
+
+#include
+#include
+#include
+
+#include "pvr_csb.h"
+#include "util/bitset.h"
+
+#define PVR_BORDER_COLOR_TABLE_NR_ENTRIES \
+ (PVRX(TEXSTATE_SAMPLER_BORDERCOLOR_INDEX_MAX_SIZE) + 1)
+
+#define PVR_BORDER_COLOR_TABLE_NR_BUILTIN_ENTRIES \
+ (VK_BORDER_COLOR_INT_OPAQUE_WHITE + 1U)
+
+#define PVR_BORDER_COLOR_TABLE_NR_CUSTOM_ENTRIES \
+ (PVR_BORDER_COLOR_TABLE_NR_ENTRIES - \
+ PVR_BORDER_COLOR_TABLE_NR_BUILTIN_ENTRIES)
+
+/* Forward declaration from "pvr_bo.h" */
+struct pvr_bo;
+
+/* Forward declaration from "pvr_private.h" */
+struct pvr_device;
+
+struct pvr_border_color_table {
+ BITSET_DECLARE(unused_entries, PVR_BORDER_COLOR_TABLE_NR_ENTRIES);
+
+ /* Contains an array of:
+ * PVR_BORDER_COLOR_TABLE_NR_ENTRIES x struct pvr_border_color_table_entry
+ */
+ struct pvr_bo *table;
+};
+
+VkResult pvr_border_color_table_init(struct pvr_border_color_table *table,
+ struct pvr_device *device);
+void pvr_border_color_table_finish(struct pvr_border_color_table *table,
+ struct pvr_device *device);
+
+VkResult pvr_border_color_table_get_or_create_entry(
+ struct pvr_border_color_table *table,
+ const struct VkSamplerCreateInfo *sampler_create_info,
+ uint32_t *index_out);
+
+static inline bool pvr_border_color_table_is_index_valid(
+ const struct pvr_border_color_table *const table,
+ const uint32_t index)
+{
+ return !BITSET_TEST(table->unused_entries, index);
+}
+
+#endif /* PVR_BORDER_H */
diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c
index a52f439e9bc..ac6b75d7bb9 100644
--- a/src/imagination/vulkan/pvr_cmd_buffer.c
+++ b/src/imagination/vulkan/pvr_cmd_buffer.c
@@ -1436,11 +1436,6 @@ static VkResult pvr_sub_cmd_gfx_job_init(const struct pvr_device_info *dev_info,
job->ctrl_stream_addr = pvr_csb_get_start_address(&sub_cmd->control_stream);
- /* FIXME: Need to set up the border color table at device creation
- * time. Set to invalid for the time being.
- */
- job->border_colour_table_addr = PVR_DEV_ADDR_INVALID;
-
if (sub_cmd->depth_bias_bo)
job->depth_bias_table_addr = sub_cmd->depth_bias_bo->dev_addr;
else
diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c
index f533daa1bc9..2aede42234f 100644
--- a/src/imagination/vulkan/pvr_device.c
+++ b/src/imagination/vulkan/pvr_device.c
@@ -41,6 +41,7 @@
#include "hwdef/rogue_hw_utils.h"
#include "pipe/p_defines.h"
#include "pvr_bo.h"
+#include "pvr_border.h"
#include "pvr_clear.h"
#include "pvr_csb.h"
#include "pvr_csb_enum_helpers.h"
@@ -1876,6 +1877,10 @@ VkResult pvr_CreateDevice(VkPhysicalDevice physicalDevice,
if (result != VK_SUCCESS)
goto err_pvr_spm_finish_scratch_buffer_store;
+ result = pvr_border_color_table_init(&device->border_color_table, device);
+ if (result != VK_SUCCESS)
+ goto err_pvr_robustness_buffer_finish;
+
/* FIXME: Move this to a later stage and possibly somewhere other than
* pvr_device. The purpose of this is so that we don't have to get the size
* on each kick.
@@ -1891,6 +1896,9 @@ VkResult pvr_CreateDevice(VkPhysicalDevice physicalDevice,
return VK_SUCCESS;
+err_pvr_robustness_buffer_finish:
+ pvr_robustness_buffer_finish(device);
+
err_pvr_spm_finish_scratch_buffer_store:
pvr_spm_finish_scratch_buffer_store(device);
@@ -1954,6 +1962,7 @@ void pvr_DestroyDevice(VkDevice _device,
if (!device)
return;
+ pvr_border_color_table_finish(&device->border_color_table, device);
pvr_robustness_buffer_finish(device);
pvr_spm_finish_scratch_buffer_store(device);
pvr_queues_destroy(device);
@@ -2987,10 +2996,12 @@ VkResult pvr_CreateSampler(VkDevice _device,
VkSampler *pSampler)
{
PVR_FROM_HANDLE(pvr_device, device, _device);
+ uint32_t border_color_table_index;
struct pvr_sampler *sampler;
float lod_rounding_bias;
VkFilter min_filter;
VkFilter mag_filter;
+ VkResult result;
float min_lod;
float max_lod;
@@ -3001,12 +3012,21 @@ VkResult pvr_CreateSampler(VkDevice _device,
pAllocator,
sizeof(*sampler),
VK_OBJECT_TYPE_SAMPLER);
- if (!sampler)
- return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
+ if (!sampler) {
+ result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
+ goto err_out;
+ }
mag_filter = pCreateInfo->magFilter;
min_filter = pCreateInfo->minFilter;
+ result =
+ pvr_border_color_table_get_or_create_entry(&device->border_color_table,
+ pCreateInfo,
+ &border_color_table_index);
+ if (result != VK_SUCCESS)
+ goto err_free_sampler;
+
if (PVR_HAS_QUIRK(&device->pdevice->dev_info, 51025)) {
/* The min/mag filters may need adjustment here, the GPU should decide
* which of the two filters to use based on the clamped LOD value: LOD
@@ -3108,7 +3128,7 @@ VkResult pvr_CreateSampler(VkDevice _device,
word.maxlod = util_unsigned_fixed(CLAMP(max_lod, 0.0f, lod_clamp_max),
PVRX(TEXSTATE_CLAMP_FRACTIONAL_BITS));
- word.bordercolor_index = pCreateInfo->borderColor;
+ word.bordercolor_index = border_color_table_index;
if (pCreateInfo->unnormalizedCoordinates)
word.non_normalized_coords = true;
@@ -3117,6 +3137,12 @@ VkResult pvr_CreateSampler(VkDevice _device,
*pSampler = pvr_sampler_to_handle(sampler);
return VK_SUCCESS;
+
+err_free_sampler:
+ vk_object_free(&device->vk, pAllocator, sampler);
+
+err_out:
+ return result;
}
void pvr_DestroySampler(VkDevice _device,
diff --git a/src/imagination/vulkan/pvr_job_compute.c b/src/imagination/vulkan/pvr_job_compute.c
index c22960b21fd..ef00dd6d5d3 100644
--- a/src/imagination/vulkan/pvr_job_compute.c
+++ b/src/imagination/vulkan/pvr_job_compute.c
@@ -41,7 +41,8 @@ pvr_submit_info_stream_init(struct pvr_compute_ctx *ctx,
struct pvr_sub_cmd_compute *sub_cmd,
struct pvr_winsys_compute_submit_info *submit_info)
{
- const struct pvr_physical_device *const pdevice = ctx->device->pdevice;
+ const struct pvr_device *const device = ctx->device;
+ const struct pvr_physical_device *const pdevice = device->pdevice;
const struct pvr_device_runtime_info *const dev_runtime_info =
&pdevice->dev_runtime_info;
const struct pvr_device_info *const dev_info = &pdevice->dev_info;
@@ -49,13 +50,11 @@ pvr_submit_info_stream_init(struct pvr_compute_ctx *ctx,
uint32_t *stream_ptr = (uint32_t *)submit_info->fw_stream;
- /* FIXME: Need to set up the border color table at device creation time. Set
- * to invalid for the time being.
- */
pvr_csb_pack ((uint64_t *)stream_ptr,
CR_TPU_BORDER_COLOUR_TABLE_CDM,
value) {
- value.border_colour_table_address = PVR_DEV_ADDR_INVALID;
+ value.border_colour_table_address =
+ device->border_color_table.table->vma->dev_addr;
}
stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_CDM);
diff --git a/src/imagination/vulkan/pvr_job_render.c b/src/imagination/vulkan/pvr_job_render.c
index b8ab0c9945c..d325e1ff2e6 100644
--- a/src/imagination/vulkan/pvr_job_render.c
+++ b/src/imagination/vulkan/pvr_job_render.c
@@ -938,7 +938,8 @@ static void pvr_geom_state_stream_init(struct pvr_render_ctx *ctx,
struct pvr_render_job *job,
struct pvr_winsys_geometry_state *state)
{
- const struct pvr_device_info *dev_info = &ctx->device->pdevice->dev_info;
+ const struct pvr_device *const device = ctx->device;
+ const struct pvr_device_info *const dev_info = &device->pdevice->dev_info;
uint32_t *stream_ptr = (uint32_t *)state->fw_stream;
@@ -950,7 +951,8 @@ static void pvr_geom_state_stream_init(struct pvr_render_ctx *ctx,
pvr_csb_pack ((uint64_t *)stream_ptr,
CR_TPU_BORDER_COLOUR_TABLE_VDM,
value) {
- value.border_colour_table_address = job->border_colour_table_addr;
+ value.border_colour_table_address =
+ device->border_color_table.table->vma->dev_addr;
}
stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_VDM);
@@ -1058,7 +1060,8 @@ static void pvr_frag_state_stream_init(struct pvr_render_ctx *ctx,
struct pvr_render_job *job,
struct pvr_winsys_fragment_state *state)
{
- const struct pvr_physical_device *const pdevice = ctx->device->pdevice;
+ const struct pvr_device *const device = ctx->device;
+ const struct pvr_physical_device *const pdevice = device->pdevice;
const struct pvr_device_runtime_info *dev_runtime_info =
&pdevice->dev_runtime_info;
const struct pvr_device_info *dev_info = &pdevice->dev_info;
@@ -1203,7 +1206,8 @@ static void pvr_frag_state_stream_init(struct pvr_render_ctx *ctx,
pvr_csb_pack ((uint64_t *)stream_ptr,
CR_TPU_BORDER_COLOUR_TABLE_PDM,
value) {
- value.border_colour_table_address = job->border_colour_table_addr;
+ value.border_colour_table_address =
+ device->border_color_table.table->vma->dev_addr;
}
stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_PDM);
diff --git a/src/imagination/vulkan/pvr_job_render.h b/src/imagination/vulkan/pvr_job_render.h
index 5754306731d..a214d5e5239 100644
--- a/src/imagination/vulkan/pvr_job_render.h
+++ b/src/imagination/vulkan/pvr_job_render.h
@@ -88,7 +88,6 @@ struct pvr_render_job {
pvr_dev_addr_t ctrl_stream_addr;
- pvr_dev_addr_t border_colour_table_addr;
pvr_dev_addr_t depth_bias_table_addr;
pvr_dev_addr_t scissor_table_addr;
diff --git a/src/imagination/vulkan/pvr_private.h b/src/imagination/vulkan/pvr_private.h
index b691411c115..19e7507e8dd 100644
--- a/src/imagination/vulkan/pvr_private.h
+++ b/src/imagination/vulkan/pvr_private.h
@@ -38,6 +38,7 @@
#include "compiler/shader_enums.h"
#include "hwdef/rogue_hw_defs.h"
+#include "pvr_border.h"
#include "pvr_clear.h"
#include "pvr_common.h"
#include "pvr_csb.h"
@@ -277,6 +278,8 @@ struct pvr_device {
struct pvr_bo *robustness_buffer;
struct vk_sync *presignaled_sync;
+
+ struct pvr_border_color_table border_color_table;
};
struct pvr_device_memory {