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:
Chia-I Wu 2019-02-13 10:23:32 -08:00
parent 6545461041
commit 15319963fa
3 changed files with 224 additions and 46 deletions

View file

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

View file

@ -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,

View file

@ -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
{