aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2019-02-13 10:23:32 -0800
committerChia-I Wu <[email protected]>2019-03-11 10:02:13 -0700
commit15319963fa45ae3fa8b6a097fa9ed0b8751807cc (patch)
treed72836618e2440464bb95bfc8833ab39ef2a158f /src
parent6545461041c42022cc66811205339098b4c6973b (diff)
turnip: fix VkClearValue packing
Add tu_pack_clear_value to correctly pack VkClearValue according to VkFormat. It ignores the component order defined by VkFormat, and always packs to WZYX order.
Diffstat (limited to 'src')
-rw-r--r--src/freedreno/vulkan/tu_cmd_buffer.c23
-rw-r--r--src/freedreno/vulkan/tu_formats.c210
-rw-r--r--src/freedreno/vulkan/tu_private.h37
3 files changed, 224 insertions, 46 deletions
diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c
index 59e31b39b7b..51f97971335 100644
--- a/src/freedreno/vulkan/tu_cmd_buffer.c
+++ b/src/freedreno/vulkan/tu_cmd_buffer.c
@@ -617,17 +617,21 @@ tu6_emit_blit_info(struct tu_cmd_buffer *cmd,
static void
tu6_emit_blit_clear(struct tu_cmd_buffer *cmd,
struct tu_cs *cs,
+ const struct tu_image_view *iview,
uint32_t gmem_offset,
const VkClearValue *clear_value)
{
const enum a6xx_tile_mode tile_mode = TILE6_LINEAR;
const enum a3xx_msaa_samples samples = tu6_msaa_samples(1);
const enum a6xx_color_fmt format = RB6_R8G8B8A8_UNORM;
+ /* must be WZYX; other values are ignored */
+ const enum a3xx_color_swap swap = WZYX;
tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_DST_INFO, 1);
tu_cs_emit(cs, A6XX_RB_BLIT_DST_INFO_TILE_MODE(tile_mode) |
A6XX_RB_BLIT_DST_INFO_SAMPLES(samples) |
- A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format));
+ A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format) |
+ A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(swap));
tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_INFO, 1);
tu_cs_emit(cs, A6XX_RB_BLIT_INFO_GMEM | A6XX_RB_BLIT_INFO_CLEAR_MASK(0xf));
@@ -638,14 +642,10 @@ tu6_emit_blit_clear(struct tu_cmd_buffer *cmd,
tu_cs_emit_pkt4(cs, REG_A6XX_RB_UNKNOWN_88D0, 1);
tu_cs_emit(cs, 0);
- /* att->clear_value? */
- uint32_t clear_vals[4] = {
- ((int) (clear_value->color.float32[0] * 255) << 24) |
- ((int) (clear_value->color.float32[1] * 255) << 16) |
- ((int) (clear_value->color.float32[2] * 255) << 8) |
- ((int) (clear_value->color.float32[3] * 255) << 0),
- 0, 0, 0
- };
+ /* pack clear_value into WZYX order */
+ uint32_t clear_vals[4] = { 0 };
+ tu_pack_clear_value(clear_value, iview->vk_format, clear_vals);
+
tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_CLEAR_COLOR_DW0, 4);
tu_cs_emit(cs, clear_vals[0]);
tu_cs_emit(cs, clear_vals[1]);
@@ -753,13 +753,14 @@ tu6_emit_tile_load(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
if (a == VK_ATTACHMENT_UNUSED)
continue;
+ const struct tu_image_view *iview = fb->attachments[a].attachment;
const struct tu_attachment_state *att = attachments + a;
if (att->pending_clear_aspects) {
assert(att->pending_clear_aspects == VK_IMAGE_ASPECT_COLOR_BIT);
- tu6_emit_blit_clear(cmd, cs, tiling->gmem_offsets[gmem_index++],
+ tu6_emit_blit_clear(cmd, cs, iview,
+ tiling->gmem_offsets[gmem_index++],
&att->clear_value);
} else {
- const struct tu_image_view *iview = fb->attachments[a].attachment;
tu6_emit_blit_info(cmd, cs, iview,
tiling->gmem_offsets[gmem_index++],
A6XX_RB_BLIT_INFO_UNK0 | A6XX_RB_BLIT_INFO_GMEM);
diff --git a/src/freedreno/vulkan/tu_formats.c b/src/freedreno/vulkan/tu_formats.c
index 7f936f5f114..00a45aaac01 100644
--- a/src/freedreno/vulkan/tu_formats.c
+++ b/src/freedreno/vulkan/tu_formats.c
@@ -337,6 +337,216 @@ tu6_get_native_format(VkFormat format)
return (fmt && fmt->present) ? fmt : NULL;
}
+static uint32_t
+tu_pack_mask(int bits)
+{
+ assert(bits <= 32);
+ return (1ull << bits) - 1;
+}
+
+static uint32_t
+tu_pack_float32_for_unorm(float val, int bits)
+{
+ const uint32_t max = tu_pack_mask(bits);
+ if (val < 0.0f)
+ return 0;
+ else if (val > 1.0f)
+ return max;
+ else
+ return _mesa_lroundevenf(val * (float) max);
+}
+
+static uint32_t
+tu_pack_float32_for_snorm(float val, int bits)
+{
+ const int32_t max = tu_pack_mask(bits - 1);
+ int32_t tmp;
+ if (val < -1.0f)
+ tmp = -max;
+ else if (val > 1.0f)
+ tmp = max;
+ else
+ tmp = _mesa_lroundevenf(val * (float) max);
+
+ return tmp & tu_pack_mask(bits);
+}
+
+static uint32_t
+tu_pack_float32_for_uscaled(float val, int bits)
+{
+ const uint32_t max = tu_pack_mask(bits);
+ if (val < 0.0f)
+ return 0;
+ else if (val > (float) max)
+ return max;
+ else
+ return (uint32_t) val;
+}
+
+static uint32_t
+tu_pack_float32_for_sscaled(float val, int bits)
+{
+ const int32_t max = tu_pack_mask(bits - 1);
+ const int32_t min = -max - 1;
+ int32_t tmp;
+ if (val < (float) min)
+ tmp = min;
+ else if (val > (float) max)
+ tmp = max;
+ else
+ tmp = (int32_t) val;
+
+ return tmp & tu_pack_mask(bits);
+}
+
+static uint32_t
+tu_pack_uint32_for_uint(uint32_t val, int bits)
+{
+ return val & tu_pack_mask(bits);
+}
+
+static uint32_t
+tu_pack_int32_for_sint(int32_t val, int bits)
+{
+ return val & tu_pack_mask(bits);
+}
+
+static uint32_t
+tu_pack_float32_for_sfloat(float val, int bits)
+{
+ assert(bits == 16 || bits == 32);
+ return bits == 16 ? util_float_to_half(val) : fui(val);
+}
+
+union tu_clear_component_value {
+ float float32;
+ int32_t int32;
+ uint32_t uint32;
+};
+
+static uint32_t
+tu_pack_clear_component_value(union tu_clear_component_value val,
+ const struct vk_format_channel_description *ch)
+{
+ uint32_t packed;
+
+ switch (ch->type) {
+ case VK_FORMAT_TYPE_UNSIGNED:
+ /* normalized, scaled, or pure integer */
+ assert(ch->normalized + ch->scaled + ch->pure_integer == 1);
+ if (ch->normalized)
+ packed = tu_pack_float32_for_unorm(val.float32, ch->size);
+ else if (ch->scaled)
+ packed = tu_pack_float32_for_uscaled(val.float32, ch->size);
+ else
+ packed = tu_pack_uint32_for_uint(val.uint32, ch->size);
+ break;
+ case VK_FORMAT_TYPE_SIGNED:
+ /* normalized, scaled, or pure integer */
+ assert(ch->normalized + ch->scaled + ch->pure_integer == 1);
+ if (ch->normalized)
+ packed = tu_pack_float32_for_snorm(val.float32, ch->size);
+ else if (ch->scaled)
+ packed = tu_pack_float32_for_sscaled(val.float32, ch->size);
+ else
+ packed = tu_pack_int32_for_sint(val.int32, ch->size);
+ break;
+ case VK_FORMAT_TYPE_FLOAT:
+ packed = tu_pack_float32_for_sfloat(val.float32, ch->size);
+ break;
+ default:
+ unreachable("unexpected channel type");
+ packed = 0;
+ break;
+ }
+
+ assert((packed & tu_pack_mask(ch->size)) == packed);
+ return packed;
+}
+
+static const struct vk_format_channel_description *
+tu_get_format_channel_description(const struct vk_format_description *desc,
+ int comp)
+{
+ switch (desc->swizzle[comp]) {
+ case VK_SWIZZLE_X:
+ return &desc->channel[0];
+ case VK_SWIZZLE_Y:
+ return &desc->channel[1];
+ case VK_SWIZZLE_Z:
+ return &desc->channel[2];
+ case VK_SWIZZLE_W:
+ return &desc->channel[3];
+ default:
+ return NULL;
+ }
+}
+
+static union tu_clear_component_value
+tu_get_clear_component_value(const VkClearValue *val, int comp, bool color)
+{
+ union tu_clear_component_value tmp;
+ if (color) {
+ assert(comp < 4);
+ tmp.uint32 = val->color.uint32[comp];
+ } else {
+ assert(comp < 2);
+ if (comp == 0)
+ tmp.float32 = val->depthStencil.depth;
+ else
+ tmp.uint32 = val->depthStencil.stencil;
+ }
+
+ return tmp;
+}
+
+/**
+ * Pack a VkClearValue into a 128-bit buffer. \a format is respected except
+ * for the component order. The components are always packed in WZYX order
+ * (i.e., msb is white and lsb is red).
+ *
+ * Return the number of uint32_t's used.
+ */
+int
+tu_pack_clear_value(const VkClearValue *val, VkFormat format, uint32_t buf[4])
+{
+ const struct vk_format_description *desc = vk_format_description(format);
+ assert(desc && desc->layout == VK_FORMAT_LAYOUT_PLAIN);
+
+ /* S8_UINT is special and has no depth */
+ const int max_components =
+ format == VK_FORMAT_S8_UINT ? 2 : desc->nr_channels;
+
+ int buf_offset = 0;
+ int bit_shift = 0;
+ for (int comp = 0; comp < max_components; comp++) {
+ const struct vk_format_channel_description *ch =
+ tu_get_format_channel_description(desc, comp);
+ if (!ch) {
+ assert(format == VK_FORMAT_S8_UINT && comp == 0);
+ continue;
+ }
+
+ union tu_clear_component_value v = tu_get_clear_component_value(
+ val, comp, desc->colorspace != VK_FORMAT_COLORSPACE_ZS);
+
+ /* move to the next uint32_t when there is not enough space */
+ assert(ch->size <= 32);
+ if (bit_shift + ch->size > 32) {
+ buf_offset++;
+ bit_shift = 0;
+ }
+
+ if (bit_shift == 0)
+ buf[buf_offset] = 0;
+
+ buf[buf_offset] |= tu_pack_clear_component_value(v, ch) << bit_shift;
+ bit_shift += ch->size;
+ }
+
+ return buf_offset + 1;
+}
+
static void
tu_physical_device_get_format_properties(
struct tu_physical_device *physical_device,
diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h
index 62f7cf28004..808fee6cbe8 100644
--- a/src/freedreno/vulkan/tu_private.h
+++ b/src/freedreno/vulkan/tu_private.h
@@ -983,41 +983,8 @@ tu_graphics_pipeline_create(
const VkAllocationCallbacks *alloc,
VkPipeline *pPipeline);
-struct vk_format_description;
-uint32_t
-tu_translate_buffer_dataformat(const struct vk_format_description *desc,
- int first_non_void);
-uint32_t
-tu_translate_buffer_numformat(const struct vk_format_description *desc,
- int first_non_void);
-uint32_t
-tu_translate_colorformat(VkFormat format);
-uint32_t
-tu_translate_color_numformat(VkFormat format,
- const struct vk_format_description *desc,
- int first_non_void);
-uint32_t
-tu_colorformat_endian_swap(uint32_t colorformat);
-unsigned
-tu_translate_colorswap(VkFormat format, bool do_endian_swap);
-uint32_t
-tu_translate_dbformat(VkFormat format);
-uint32_t
-tu_translate_tex_dataformat(VkFormat format,
- const struct vk_format_description *desc,
- int first_non_void);
-uint32_t
-tu_translate_tex_numformat(VkFormat format,
- const struct vk_format_description *desc,
- int first_non_void);
-bool
-tu_format_pack_clear_color(VkFormat format,
- uint32_t clear_vals[2],
- VkClearColorValue *value);
-bool
-tu_is_colorbuffer_format_supported(VkFormat format, bool *blendable);
-bool
-tu_dcc_formats_compatible(VkFormat format1, VkFormat format2);
+int
+tu_pack_clear_value(const VkClearValue *val, VkFormat format, uint32_t buf[4]);
struct tu_image_level
{