#include "util/format_srgb.h"
#include "util/u_half.h"
-/* helper functions previously in tu_formats.c */
-
-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 util_format_channel_description *ch)
-{
- uint32_t packed;
-
- switch (ch->type) {
- case UTIL_FORMAT_TYPE_UNSIGNED:
- /* normalized, scaled, or pure integer */
- if (ch->normalized)
- packed = tu_pack_float32_for_unorm(val.float32, ch->size);
- else if (ch->pure_integer)
- packed = tu_pack_uint32_for_uint(val.uint32, ch->size);
- else
- packed = tu_pack_float32_for_uscaled(val.float32, ch->size);
- break;
- case UTIL_FORMAT_TYPE_SIGNED:
- /* normalized, scaled, or pure integer */
- if (ch->normalized)
- packed = tu_pack_float32_for_snorm(val.float32, ch->size);
- else if (ch->pure_integer)
- packed = tu_pack_int32_for_sint(val.int32, ch->size);
- else
- packed = tu_pack_float32_for_sscaled(val.float32, ch->size);
- break;
- case UTIL_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 util_format_channel_description *
-tu_get_format_channel_description(const struct util_format_description *desc,
- int comp)
-{
- switch (desc->swizzle[comp]) {
- case PIPE_SWIZZLE_X:
- return &desc->channel[0];
- case PIPE_SWIZZLE_Y:
- return &desc->channel[1];
- case PIPE_SWIZZLE_Z:
- return &desc->channel[2];
- case PIPE_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,
- enum util_format_colorspace colorspace)
-{
- assert(comp < 4);
-
- union tu_clear_component_value tmp;
- switch (colorspace) {
- case UTIL_FORMAT_COLORSPACE_ZS:
- assert(comp < 2);
- if (comp == 0)
- tmp.float32 = val->depthStencil.depth;
- else
- tmp.uint32 = val->depthStencil.stencil;
- break;
- case UTIL_FORMAT_COLORSPACE_SRGB:
- if (comp < 3) {
- tmp.float32 = util_format_linear_to_srgb_float(val->color.float32[comp]);
- break;
- }
- default:
- assert(comp < 4);
- tmp.uint32 = val->color.uint32[comp];
- break;
- }
-
- return tmp;
+ return _mesa_lroundevenf(CLAMP(val, 0.0f, 1.0f) * (float) ((1 << bits) - 1));
}
/* r2d_ = BLIT_OP_SCALE operations */
linear = util_format_linear_to_srgb_float(val->color.float32[i]);
if (ch->type == UTIL_FORMAT_TYPE_SIGNED)
- clear_value[i] = tu_pack_float32_for_snorm(linear, 8);
+ clear_value[i] = _mesa_lroundevenf(CLAMP(linear, -1.0f, 1.0f) * 127.0f);
else
clear_value[i] = tu_pack_float32_for_unorm(linear, 8);
} else if (ifmt == R2D_FLOAT16) {
r3d_common(struct tu_cmd_buffer *cmd, struct tu_cs *cs, bool blit, uint32_t num_rts,
bool layered_clear)
{
+ struct ir3_const_state dummy_const_state = {};
struct ir3_shader dummy_shader = {};
struct ir3_shader_variant vs = {
.regid = regid(1, 0),
},
.shader = &dummy_shader,
+ .const_state = &dummy_const_state,
};
if (layered_clear) {
vs = (struct ir3_shader_variant) {
.instrlen = 1,
.info.max_reg = 0,
.shader = &dummy_shader,
+ .const_state = &dummy_const_state,
};
}
.cmd = 4,
},
.shader = &dummy_shader,
+ .const_state = &dummy_const_state,
};
struct ir3_shader_variant gs_shader = {
.regid = regid(1, 0),
},
.shader = &dummy_shader,
+ .const_state = &dummy_const_state,
}, *gs = layered_clear ? &gs_shader : NULL;
#define GS_OFFSET (32 * sizeof(instr_t))
/* shaders */
- struct ts_cs_memory shaders = { };
+ struct tu_cs_memory shaders = { };
VkResult result = tu_cs_alloc(&cmd->sub_cs, 2 + layered_clear,
16 * sizeof(instr_t), &shaders);
assert(result == VK_SUCCESS);
tu_cs_emit_regs(cs, A6XX_PC_PRIMITIVE_CNTL_0());
tu_cs_emit_regs(cs, A6XX_VFD_CONTROL_0());
- tu6_emit_vpc(cs, &vs, gs, &fs, NULL);
+ tu6_emit_vpc(cs, &vs, NULL, NULL, gs, &fs);
/* REPL_MODE for varying with RECTLIST (2 vertices only) */
tu_cs_emit_regs(cs, A6XX_VPC_VARYING_INTERP_MODE(0, 0));
uint32_t offset_ubwc,
VkFilter filter)
{
- struct ts_cs_memory texture = { };
+ struct tu_cs_memory texture = { };
VkResult result = tu_cs_alloc(&cmd->sub_cs,
2, /* allocate space for a sampler too */
A6XX_TEX_CONST_DWORDS, &texture);
A6XX_TEX_CONST_0_SWIZ_W(vk_format == VK_FORMAT_R8_UNORM ? A6XX_TEX_X : A6XX_TEX_W);
desc[1] = A6XX_TEX_CONST_1_WIDTH(width) | A6XX_TEX_CONST_1_HEIGHT(height);
desc[2] =
- A6XX_TEX_CONST_2_FETCHSIZE(tu6_fetchsize(vk_format)) |
A6XX_TEX_CONST_2_PITCH(pitch) |
A6XX_TEX_CONST_2_TYPE(A6XX_TEX_2D);
desc[3] = 0;
uint32_t pitch = src_width * vk_format_get_blocksize(src_format);
uint32_t layer_size = src_height * pitch;
- /* note: the src_va/pitch alignment of 64 is for 2D engine,
- * it is also valid for 1cpp format with shader path (stencil aspect path)
- */
-
ops->setup(cmd, cs, dst_format, ROTATE_0, false, mask);
struct tu_image_view dst;
uint32_t pitch = dst_width * vk_format_get_blocksize(dst_format);
uint32_t layer_size = pitch * dst_height;
- /* note: the dst_va/pitch alignment of 64 is for 2D engine,
- * it is also valid for 1cpp format with shader path (stencil aspect)
- */
-
ops->setup(cmd, cs, dst_format, ROTATE_0, false, 0xf);
struct tu_image_view src;
tu_bo_list_add(&cmd->bo_list, buffer->bo, MSM_SUBMIT_BO_WRITE);
- struct ts_cs_memory tmp;
+ struct tu_cs_memory tmp;
VkResult result = tu_cs_alloc(&cmd->sub_cs, DIV_ROUND_UP(dataSize, 64), 64, &tmp);
if (result != VK_SUCCESS) {
cmd->record_result = result;
/* This clear path behaves like a draw, needs the same flush as tu_draw */
tu_emit_cache_flush_renderpass(cmd, cs);
+ /* disable all draw states so they don't interfere
+ * TODO: use and re-use draw states for this path
+ * we have to disable draw states individually to preserve
+ * input attachment states, because a secondary command buffer
+ * won't be able to restore them
+ */
+ tu_cs_emit_pkt7(cs, CP_SET_DRAW_STATE, 3 * (TU_DRAW_STATE_COUNT - 2));
+ for (uint32_t i = 0; i < TU_DRAW_STATE_COUNT; i++) {
+ if (i == TU_DRAW_STATE_INPUT_ATTACHMENTS_GMEM ||
+ i == TU_DRAW_STATE_INPUT_ATTACHMENTS_SYSMEM)
+ continue;
+ tu_cs_emit(cs, CP_SET_DRAW_STATE__0_GROUP_ID(i) |
+ CP_SET_DRAW_STATE__0_DISABLE);
+ tu_cs_emit_qw(cs, 0);
+ }
+ cmd->state.dirty |= TU_CMD_DIRTY_DRAW_STATE;
+
tu_cs_emit_pkt4(cs, REG_A6XX_SP_FS_OUTPUT_CNTL0, 2);
tu_cs_emit(cs, A6XX_SP_FS_OUTPUT_CNTL0_DEPTH_REGID(0xfc) |
A6XX_SP_FS_OUTPUT_CNTL0_SAMPMASK_REGID(0xfc) |
}
}
}
-
- cmd->state.dirty |= TU_CMD_DIRTY_PIPELINE |
- TU_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK |
- TU_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK |
- TU_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE |
- TU_CMD_DIRTY_DYNAMIC_VIEWPORT |
- TU_CMD_DIRTY_DYNAMIC_SCISSOR;
}
-/**
- * Pack a VkClearValue into a 128-bit buffer. format is respected except
- * for the component order. The components are always packed in WZYX order,
- * because gmem is tiled and tiled formats always have WZYX swap
- */
static void
-pack_gmem_clear_value(const VkClearValue *val, VkFormat format, uint32_t buf[4])
+pack_gmem_clear_value(const VkClearValue *val, VkFormat format, uint32_t clear_value[4])
{
- const struct util_format_description *desc = vk_format_description(format);
+ enum pipe_format pformat = vk_format_to_pipe_format(format);
switch (format) {
- case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
- buf[0] = float3_to_r11g11b10f(val->color.float32);
+ case VK_FORMAT_X8_D24_UNORM_PACK32:
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ clear_value[0] = tu_pack_float32_for_unorm(val->depthStencil.depth, 24) |
+ val->depthStencil.stencil << 24;
return;
- case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
- buf[0] = float3_to_rgb9e5(val->color.float32);
+ case VK_FORMAT_D16_UNORM:
+ clear_value[0] = tu_pack_float32_for_unorm(val->depthStencil.depth, 16);
+ return;
+ case VK_FORMAT_D32_SFLOAT:
+ clear_value[0] = fui(val->depthStencil.depth);
return;
+ case VK_FORMAT_S8_UINT:
+ clear_value[0] = val->depthStencil.stencil;
+ return;
+ /* these formats use a different base format when tiled
+ * the same format can be used for both because GMEM is always in WZYX order
+ */
+ case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
+ case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
+ pformat = PIPE_FORMAT_B5G5R5A1_UNORM;
default:
break;
}
- assert(desc && desc->layout == UTIL_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 util_format_channel_description *ch =
- tu_get_format_channel_description(desc, comp);
- if (!ch) {
- assert((format == VK_FORMAT_S8_UINT && comp == 0) ||
- (format == VK_FORMAT_X8_D24_UNORM_PACK32 && comp == 1));
- continue;
- }
+ VkClearColorValue color;
- union tu_clear_component_value v = tu_get_clear_component_value(
- val, comp, desc->colorspace);
-
- /* 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;
+ /**
+ * GMEM is tiled and wants the components in WZYX order,
+ * apply swizzle to the color before packing, to counteract
+ * deswizzling applied by packing functions
+ */
+ pipe_swizzle_4f(color.float32, val->color.float32,
+ util_format_description(pformat)->swizzle);
- buf[buf_offset] |= tu_pack_clear_component_value(v, ch) << bit_shift;
- bit_shift += ch->size;
- }
+ util_format_pack_rgba(pformat, clear_value, color.uint32, 1);
}
static void