[Mesa-dev] [PATCH crucible] clear: check for invalid offsets in memory
Lionel Landwerlin
lionel.g.landwerlin at intel.com
Tue Nov 21 23:40:44 UTC 2017
Trying to detect cases where we read/write at the wrong offsets in
images.
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103197
---
src/tests/func/renderpass/clear.c | 235 ++++++++++++++++++++++++++++++++++++++
1 file changed, 235 insertions(+)
diff --git a/src/tests/func/renderpass/clear.c b/src/tests/func/renderpass/clear.c
index 56854b4..00543bf 100644
--- a/src/tests/func/renderpass/clear.c
+++ b/src/tests/func/renderpass/clear.c
@@ -48,6 +48,8 @@ check_requirements(uint32_t num_color_attachments)
}
}
+#define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1))
+
static void
test_color8(void)
{
@@ -247,6 +249,227 @@ test_color8(void)
t_end(result);
}
+static void
+test_color8_shared_memory(void)
+{
+ static const uint32_t num_attachments = 3;
+ static const uint32_t width = 64;
+ static const uint32_t height = 64;
+
+ VkFormat formats[num_attachments];
+ VkImage images[num_attachments];
+ VkImageView att_views[num_attachments];
+ VkAttachmentDescription att_descs[num_attachments];
+ VkAttachmentReference att_references[num_attachments];
+ VkClearValue clear_values[num_attachments];
+
+ VkBuffer dest_buffers[num_attachments];
+ cru_image_t *ref_images[num_attachments];
+ cru_image_t *actual_images[num_attachments];
+
+ check_requirements(num_attachments);
+
+ for (uint32_t i = 0; i < num_attachments; ++i) {
+ formats[i] = VK_FORMAT_R8G8B8A8_UNORM;
+
+ images[i] = qoCreateImage(t_device,
+ .imageType = VK_IMAGE_TYPE_2D,
+ .format = formats[i],
+ .mipLevels = 1,
+ .arrayLayers = 1,
+ .extent = {
+ .width = width,
+ .height = height,
+ .depth = 1,
+ },
+ .samples = 1,
+ .tiling = VK_IMAGE_TILING_OPTIMAL,
+ .usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
+ }
+
+ VkMemoryRequirements mem_reqs =
+ qoGetImageMemoryRequirements(t_device, images[0]);
+ mem_reqs.size = 3 * ALIGN(mem_reqs.size, mem_reqs.alignment);
+
+ uint32_t type_index = UINT32_MAX;
+ const VkPhysicalDeviceMemoryProperties *props = t_physical_dev_mem_props;
+ for (uint32_t i = 0; i < props->memoryTypeCount; i++) {
+ if (mem_reqs.memoryTypeBits & (1 << i)) {
+ type_index = i;
+ break;
+ }
+ }
+ assert(type_index < props->memoryTypeCount);
+
+ VkDeviceMemory mem;
+ VkResult res = vkAllocateMemory(t_device, &(VkMemoryAllocateInfo) {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .allocationSize = mem_reqs.size,
+ .memoryTypeIndex = type_index,
+ },
+ NULL,
+ &mem);
+ assert(res == VK_SUCCESS);
+
+ for (uint32_t i = 0; i < num_attachments; ++i) {
+ qoBindImageMemory(t_device, images[i], mem, i * (mem_reqs.size / 3));
+
+ att_views[i] = qoCreateImageView(t_device,
+ .image = images[i],
+ .viewType = VK_IMAGE_VIEW_TYPE_2D,
+ .format = formats[i],
+ .subresourceRange = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ });
+
+ att_descs[i] = (VkAttachmentDescription) {
+ .format = formats[i],
+ .samples = 1,
+ .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
+ .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ .finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ };
+
+ att_references[i] = (VkAttachmentReference) {
+ .attachment = i,
+ .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ };
+
+ clear_values[i] = (VkClearValue) {
+ .color = {
+ .float32 = {
+ i == 0 ? 1.0f : 0.0f,
+ i == 1 ? 1.0f : 0.0f,
+ i == 2 ? 1.0f : 0.0f,
+ 1.0,
+ },
+ },
+ };
+
+ // Converting normalized float to normalized unorm8 requires rounding
+ // to the nearest int.
+ const uint8_t clear_value_u8[] = {
+ roundf(255 * clear_values[i].color.float32[0]),
+ roundf(255 * clear_values[i].color.float32[1]),
+ roundf(255 * clear_values[i].color.float32[2]),
+ roundf(255 * clear_values[i].color.float32[3]),
+ };
+
+ const cru_format_info_t *format_info = t_format_info(formats[i]);
+
+ size_t dest_buffer_size = format_info->cpp * width * height;
+
+ dest_buffers[i] = qoCreateBuffer(t_device,
+ .size = dest_buffer_size,
+ .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+
+ VkDeviceMemory dest_buffer_mem =
+ qoAllocBufferMemory(t_device, dest_buffers[i],
+ .properties = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+
+ qoBindBufferMemory(t_device, dest_buffers[i], dest_buffer_mem,
+ /*offset*/ 0);
+
+ void *dest_buffer_map = qoMapMemory(t_device, dest_buffer_mem,
+ /*offset*/ 0, dest_buffer_size, /*flags*/ 0);
+
+ actual_images[i] = t_new_cru_image_from_pixels(dest_buffer_map,
+ formats[i], width, height);
+
+ void *ref_image_mem = xmalloc(dest_buffer_size);
+ t_cleanup_push_free(ref_image_mem);
+
+ ref_images[i] = t_new_cru_image_from_pixels(ref_image_mem,
+ formats[i], width, height);
+
+ for (uint32_t j = 0; j < width * height; ++j) {
+ uint8_t *pixel_u8 = ref_image_mem + format_info->cpp * j;
+
+ pixel_u8[0] = clear_value_u8[0];
+ pixel_u8[1] = clear_value_u8[1];
+ pixel_u8[2] = clear_value_u8[2];
+ pixel_u8[3] = clear_value_u8[3];
+ }
+ }
+
+ VkRenderPass pass = qoCreateRenderPass(t_device,
+ .attachmentCount = num_attachments,
+ .pAttachments = att_descs,
+ .subpassCount = 1,
+ .pSubpasses = (VkSubpassDescription[]) {
+ {
+ .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
+ .colorAttachmentCount = num_attachments,
+ .pColorAttachments = att_references,
+ },
+ });
+
+ VkFramebuffer fb = qoCreateFramebuffer(t_device,
+ .renderPass = pass,
+ .attachmentCount = num_attachments,
+ .pAttachments = att_views,
+ .width = width,
+ .height = height,
+ .layers = 1);
+
+ VkCommandBuffer cmd = qoAllocateCommandBuffer(t_device, t_cmd_pool);
+
+ qoBeginCommandBuffer(cmd);
+ vkCmdBeginRenderPass(cmd,
+ &(VkRenderPassBeginInfo) {
+ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ .renderPass = pass,
+ .framebuffer = fb,
+ .renderArea = {{0, 0}, {width, height}},
+ .clearValueCount = num_attachments,
+ .pClearValues = clear_values,
+ },
+ VK_SUBPASS_CONTENTS_INLINE);
+ vkCmdEndRenderPass(cmd);
+
+ for (uint32_t i = 0; i < num_attachments; ++i) {
+
+ vkCmdCopyImageToBuffer(cmd, images[i],
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ dest_buffers[i],
+ /*regionCount*/ 1,
+ &(VkBufferImageCopy) {
+ .bufferOffset = 0,
+ .imageSubresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .baseArrayLayer= 0,
+ .layerCount = 1,
+ },
+ .imageOffset = { 0, 0, 0 },
+ .imageExtent = { width, height, 1 },
+ });
+ }
+
+ qoEndCommandBuffer(cmd);
+ qoQueueSubmit(t_queue, 1, &cmd, VK_NULL_HANDLE);
+ qoQueueWaitIdle(t_queue);
+
+ test_result_t result = TEST_RESULT_PASS;
+
+ for (uint32_t i = 0; i < num_attachments; ++i) {
+ t_dump_image_f(ref_images[i], "attachment%02d.ref.png", i);
+ t_dump_image_f(actual_images[i], "attachment%02d.actual.png", i);
+
+ if (!cru_image_compare(ref_images[i], actual_images[i])) {
+ result = TEST_RESULT_FAIL;
+ }
+ }
+
+ t_end(result);
+}
+
static void
test_color_render_area(void)
{
@@ -328,6 +551,18 @@ test_define {
.no_image = true,
};
+/// Create a render pass that clears each attachment to a unique clear
+/// color using VK_ATTACHMENT_LOAD_OP_CLEAR. Submit a command buffer
+/// that trivially begins then ends the render pass. Then confirm that
+/// each attachment is filled with the expected clear color. All the
+/// attachments are stored within the same memory object (allowing
+/// detection of reading/writing at the wrong offset in memory).
+test_define {
+ .name = "func.renderpass.clear.color08-shared-memory",
+ .start = test_color8_shared_memory,
+ .no_image = true,
+};
+
/// Submit two renderpasses that draw to the same framebuffer. The first
/// clears the whole framebuffer. The second clears a subrect of the
/// framebuffer to a different color using VkRenderPassBeginInfo::renderArea.
--
2.15.0
More information about the mesa-dev
mailing list