v3dv: always flush draw calls if we are doing sRGB blending
Not quite sure why this is required though. Conversion from/to
sRGB happens on tile loads and stores, with the tile buffer
being always linear, so there should be no difference.
Fixes all test failures in:
dEQP-VK.pipeline.blend.format.r8g8b8a8_srgb.*
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index e21eb33..037c4f2 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -1719,6 +1719,26 @@
if (cmd_buffer->state.pipeline == pipeline)
return;
+
+ /* Enable always flush if we are blending to sRGB render targets. This
+ * fixes test failures in:
+ * dEQP-VK.pipeline.blend.format.r8g8b8a8_srgb.*
+ *
+ * FIXME: not sure why we need this. The tile buffer is always linear, with
+ * conversion from/to sRGB happening on tile load/store operations. This
+ * means that when we enable flushing the only difference is that we convert
+ * to sRGB on the store after each draw call and we convert from sRGB on the
+ * load before each draw call, but the blend happens in linear format in the
+ * tile buffer anyway, which is the same scenario as if we didn't flush.
+ */
+ assert(pipeline->subpass);
+ if (pipeline->subpass->has_srgb_rt && pipeline->blend.enables) {
+ assert(cmd_buffer->state.job);
+ cmd_buffer->state.job->always_flush = true;
+ perf_debug("flushing draw calls for subpass %d because bound pipeline "
+ "uses sRGB blending\n", cmd_buffer->state.subpass_idx);
+ }
+
cmd_buffer->state.pipeline = pipeline;
cmd_buffer_bind_pipeline_static_state(cmd_buffer, &pipeline->dynamic_state);
diff --git a/src/broadcom/vulkan/v3dv_pass.c b/src/broadcom/vulkan/v3dv_pass.c
index d50ece0..87e08bd 100644
--- a/src/broadcom/vulkan/v3dv_pass.c
+++ b/src/broadcom/vulkan/v3dv_pass.c
@@ -22,6 +22,7 @@
*/
#include "v3dv_private.h"
+#include "vk_format_info.h"
static uint32_t
num_subpass_attachments(const VkSubpassDescription *desc)
@@ -143,10 +144,16 @@
p += desc->colorAttachmentCount;
for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
+ const uint32_t attachment_idx =
+ desc->pColorAttachments[j].attachment;
subpass->color_attachments[j] = (struct v3dv_subpass_attachment) {
- .attachment = desc->pColorAttachments[j].attachment,
+ .attachment = attachment_idx,
.layout = desc->pColorAttachments[j].layout,
};
+ if (attachment_idx != VK_ATTACHMENT_UNUSED) {
+ VkFormat format = pass->attachments[attachment_idx].desc.format;
+ subpass->has_srgb_rt |= vk_format_is_srgb(format);
+ }
}
}
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index 823d81c..0040719 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -98,6 +98,11 @@
#define v3dv_assert(x)
#endif
+#define perf_debug(...) do { \
+ if (unlikely(V3D_DEBUG & V3D_DEBUG_PERF)) \
+ fprintf(stderr, __VA_ARGS__); \
+} while (0)
+
#define for_each_bit(b, dword) \
for (uint32_t __dword = (dword); \
(b) = __builtin_ffs(__dword) - 1, __dword; __dword &= ~(1 << (b)))
@@ -387,6 +392,8 @@
struct v3dv_subpass_attachment *resolve_attachments;
struct v3dv_subpass_attachment ds_attachment;
+
+ bool has_srgb_rt;
};
struct v3dv_render_pass_attachment {
diff --git a/src/broadcom/vulkan/vk_format_info.h b/src/broadcom/vulkan/vk_format_info.h
index fee432d..e473e3d 100644
--- a/src/broadcom/vulkan/vk_format_info.h
+++ b/src/broadcom/vulkan/vk_format_info.h
@@ -96,6 +96,12 @@
}
static inline bool
+vk_format_is_srgb(VkFormat format)
+{
+ return util_format_is_srgb(vk_format_to_pipe_format(format));
+}
+
+static inline bool
vk_format_is_depth_or_stencil(VkFormat format)
{
const VkImageAspectFlags aspects = vk_format_aspects(format);