mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-28 14:00:30 +01:00
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.
This commit is contained in:
parent
6545461041
commit
15319963fa
3 changed files with 224 additions and 46 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue