diff --git a/hw/xbox/nv2a/pgraph/vk/debug.c b/hw/xbox/nv2a/pgraph/vk/debug.c index 90f5b15a84..5c31c9f119 100644 --- a/hw/xbox/nv2a/pgraph/vk/debug.c +++ b/hw/xbox/nv2a/pgraph/vk/debug.c @@ -81,3 +81,41 @@ void pgraph_vk_insert_debug_marker(PGRAPHVkState *r, VkCommandBuffer cmd, vkCmdInsertDebugUtilsLabelEXT(cmd, &label_info); free(buf); } + +void pgraph_vk_begin_debug_marker(PGRAPHVkState *r, VkCommandBuffer cmd, + float color[4], const char *format, ...) +{ + if (!r->debug_utils_extension_enabled) { + return; + } + + char *buf = NULL; + + va_list args; + va_start(args, format); + int err = vasprintf(&buf, format, args); + assert(err >= 0); + va_end(args); + + VkDebugUtilsLabelEXT label_info = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, + .pLabelName = buf, + }; + memcpy(label_info.color, color, 4 * sizeof(float)); + vkCmdBeginDebugUtilsLabelEXT(cmd, &label_info); + free(buf); + + r->debug_depth += 1; + assert(r->debug_depth < 10 && "Missing pgraph_vk_debug_marker_end?"); +} + +void pgraph_vk_end_debug_marker(PGRAPHVkState *r, VkCommandBuffer cmd) +{ + if (!r->debug_utils_extension_enabled) { + return; + } + + vkCmdEndDebugUtilsLabelEXT(cmd); + assert(r->debug_depth > 0); + r->debug_depth -= 1; +} diff --git a/hw/xbox/nv2a/pgraph/vk/display.c b/hw/xbox/nv2a/pgraph/vk/display.c index 19364aa3b0..f740b54523 100644 --- a/hw/xbox/nv2a/pgraph/vk/display.c +++ b/hw/xbox/nv2a/pgraph/vk/display.c @@ -919,6 +919,8 @@ static void render_display(PGRAPHState *pg, SurfaceBinding *surface) update_descriptor_set(pg, surface); VkCommandBuffer cmd = pgraph_vk_begin_single_time_commands(pg); + pgraph_vk_begin_debug_marker(r, cmd, RGBA_YELLOW, + "Display Surface %08"HWADDR_PRIx); pgraph_vk_transition_image_layout(pg, cmd, surface->image, surface->host_fmt.vk_format, @@ -994,6 +996,7 @@ static void render_display(PGRAPHState *pg, SurfaceBinding *surface) VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + pgraph_vk_end_debug_marker(r, cmd); pgraph_vk_end_single_time_commands(pg, cmd); nv2a_profile_inc_counter(NV2A_PROF_QUEUE_SUBMIT_5); diff --git a/hw/xbox/nv2a/pgraph/vk/draw.c b/hw/xbox/nv2a/pgraph/vk/draw.c index 5de1169041..16fdfca430 100644 --- a/hw/xbox/nv2a/pgraph/vk/draw.c +++ b/hw/xbox/nv2a/pgraph/vk/draw.c @@ -1263,9 +1263,9 @@ void pgraph_vk_finish(PGRAPHState *pg, FinishReason finish_reason) PGRAPHVkState *r = pg->vk_renderer_state; assert(!r->in_draw); + assert(r->debug_depth == 0); if (r->in_command_buffer) { - nv2a_profile_inc_counter(finish_reason_to_counter_enum[finish_reason]); if (r->in_render_pass) { @@ -1713,6 +1713,9 @@ void pgraph_vk_clear_surface(NV2AState *d, uint32_t parameter) write_zeta ? " zeta" : ""); begin_pre_draw(pg); + pgraph_vk_begin_debug_marker(r, r->command_buffer, + RGBA_BLUE, "Clear %08" HWADDR_PRIx, + binding->vram_addr); begin_draw(pg); // FIXME: What does hardware do when min <= max? @@ -1791,6 +1794,7 @@ void pgraph_vk_clear_surface(NV2AState *d, uint32_t parameter) 1, &clear_rect); } end_draw(pg); + pgraph_vk_end_debug_marker(r, r->command_buffer); pg->clearing = false; @@ -2082,6 +2086,8 @@ void pgraph_vk_flush_draw(NV2AState *d) copy_remapped_attributes_to_inline_buffer(pg, remap, 0, max_element); begin_pre_draw(pg); + pgraph_vk_begin_debug_marker(r, r->command_buffer, RGBA_BLUE, + "Draw Arrays"); begin_draw(pg); bind_vertex_buffer(pg, remap.attributes, 0); for (int i = 0; i < pg->draw_arrays_length; i++) { @@ -2091,6 +2097,7 @@ void pgraph_vk_flush_draw(NV2AState *d) vkCmdDraw(r->command_buffer, count, 1, start, 0); } end_draw(pg); + pgraph_vk_end_debug_marker(r, r->command_buffer); NV2A_VK_DGROUP_END(); } else if (pg->inline_elements_length) { @@ -2121,6 +2128,8 @@ void pgraph_vk_flush_draw(NV2AState *d) begin_pre_draw(pg); VkDeviceSize buffer_offset = pgraph_vk_update_index_buffer( pg, pg->inline_elements, index_data_size); + pgraph_vk_begin_debug_marker(r, r->command_buffer, RGBA_BLUE, + "Inline Elements"); begin_draw(pg); bind_vertex_buffer(pg, remap.attributes, 0); vkCmdBindIndexBuffer(r->command_buffer, @@ -2129,6 +2138,7 @@ void pgraph_vk_flush_draw(NV2AState *d) vkCmdDrawIndexed(r->command_buffer, pg->inline_elements_length, 1, 0, 0, 0); end_draw(pg); + pgraph_vk_end_debug_marker(r, r->command_buffer); NV2A_VK_DGROUP_END(); } else if (pg->inline_buffer_length) { @@ -2159,10 +2169,13 @@ void pgraph_vk_flush_draw(NV2AState *d) begin_pre_draw(pg); VkDeviceSize buffer_offset = pgraph_vk_update_vertex_inline_buffer( pg, data, sizes, r->num_active_vertex_attribute_descriptions); + pgraph_vk_begin_debug_marker(r, r->command_buffer, RGBA_BLUE, + "Inline Buffer"); begin_draw(pg); bind_inline_vertex_buffer(pg, buffer_offset); vkCmdDraw(r->command_buffer, pg->inline_buffer_length, 1, 0, 0); end_draw(pg); + pgraph_vk_end_debug_marker(r, r->command_buffer); NV2A_VK_DGROUP_END(); } else if (pg->inline_array_length) { @@ -2200,10 +2213,13 @@ void pgraph_vk_flush_draw(NV2AState *d) void *inline_array_data = pg->inline_array; VkDeviceSize buffer_offset = pgraph_vk_update_vertex_inline_buffer( pg, &inline_array_data, &inline_array_data_size, 1); + pgraph_vk_begin_debug_marker(r, r->command_buffer, RGBA_BLUE, + "Inline Array"); begin_draw(pg); bind_inline_vertex_buffer(pg, buffer_offset); vkCmdDraw(r->command_buffer, index_count, 1, 0, 0); end_draw(pg); + pgraph_vk_end_debug_marker(r, r->command_buffer); NV2A_VK_DGROUP_END(); } else { NV2A_VK_DPRINTF("EMPTY NV097_SET_BEGIN_END"); diff --git a/hw/xbox/nv2a/pgraph/vk/renderer.h b/hw/xbox/nv2a/pgraph/vk/renderer.h index 8a6b5090aa..250b92f695 100644 --- a/hw/xbox/nv2a/pgraph/vk/renderer.h +++ b/hw/xbox/nv2a/pgraph/vk/renderer.h @@ -321,6 +321,7 @@ typedef struct PGRAPHVkState { void *window; VkInstance instance; VkDebugUtilsMessengerEXT debug_messenger; + int debug_depth; bool debug_utils_extension_enabled; bool custom_border_color_extension_enabled; @@ -429,9 +430,19 @@ typedef struct PGRAPHVkState { void pgraph_vk_check_memory_budget(PGRAPHState *pg); // debug.c +#define RGBA_RED (float[4]){1,0,0,1} +#define RGBA_YELLOW (float[4]){1,1,0,1} +#define RGBA_GREEN (float[4]){0,1,0,1} +#define RGBA_BLUE (float[4]){0,0,1,1} +#define RGBA_PINK (float[4]){1,0,1,1} +#define RGBA_DEFAULT (float[4]){0,0,0,0} + void pgraph_vk_debug_init(void); void pgraph_vk_insert_debug_marker(PGRAPHVkState *r, VkCommandBuffer cmd, float color[4], const char *format, ...) __attribute__ ((format (printf, 4, 5))); +void pgraph_vk_begin_debug_marker(PGRAPHVkState *r, VkCommandBuffer cmd, + float color[4], const char *format, ...) __attribute__ ((format (printf, 4, 5))); +void pgraph_vk_end_debug_marker(PGRAPHVkState *r, VkCommandBuffer cmd); // instance.c void pgraph_vk_init_instance(PGRAPHState *pg, Error **errp); diff --git a/hw/xbox/nv2a/pgraph/vk/surface-compute.c b/hw/xbox/nv2a/pgraph/vk/surface-compute.c index 104f91d468..155eaa2e85 100644 --- a/hw/xbox/nv2a/pgraph/vk/surface-compute.c +++ b/hw/xbox/nv2a/pgraph/vk/surface-compute.c @@ -434,6 +434,7 @@ void pgraph_vk_pack_depth_stencil(PGRAPHState *pg, SurfaceBinding *surface, // FIXME: Smarter workgroup scaling + pgraph_vk_begin_debug_marker(r, cmd, RGBA_PINK, __func__); vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->pipeline); vkCmdBindDescriptorSets( cmd, VK_PIPELINE_BIND_POINT_COMPUTE, r->compute.pipeline_layout, 0, 1, @@ -449,6 +450,7 @@ void pgraph_vk_pack_depth_stencil(PGRAPHState *pg, SurfaceBinding *surface, // FIXME: Check max group count vkCmdDispatch(cmd, group_count, 1, 1); + pgraph_vk_end_debug_marker(r, cmd); } void pgraph_vk_unpack_depth_stencil(PGRAPHState *pg, SurfaceBinding *surface, @@ -505,6 +507,7 @@ void pgraph_vk_unpack_depth_stencil(PGRAPHState *pg, SurfaceBinding *surface, // FIXME: Smarter workgroup scaling + pgraph_vk_begin_debug_marker(r, cmd, RGBA_PINK, __func__); vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->pipeline); vkCmdBindDescriptorSets( cmd, VK_PIPELINE_BIND_POINT_COMPUTE, r->compute.pipeline_layout, 0, 1, @@ -518,6 +521,7 @@ void pgraph_vk_unpack_depth_stencil(PGRAPHState *pg, SurfaceBinding *surface, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(push_constants), push_constants); vkCmdDispatch(cmd, group_count, 1, 1); + pgraph_vk_end_debug_marker(r, cmd); } static void pipeline_cache_entry_init(Lru *lru, LruNode *node, void *state) diff --git a/hw/xbox/nv2a/pgraph/vk/surface.c b/hw/xbox/nv2a/pgraph/vk/surface.c index cadacb8ccf..f7f68bb0d4 100644 --- a/hw/xbox/nv2a/pgraph/vk/surface.c +++ b/hw/xbox/nv2a/pgraph/vk/surface.c @@ -191,6 +191,7 @@ static void download_surface_to_buffer(NV2AState *d, SurfaceBinding *surface, pgraph_apply_scaling_factor(pg, &scaled_width, &scaled_height); VkCommandBuffer cmd = pgraph_vk_begin_single_time_commands(pg); + pgraph_vk_begin_debug_marker(r, cmd, RGBA_RED, __func__); pgraph_vk_transition_image_layout( pg, cmd, surface->image, surface->host_fmt.vk_format, @@ -432,6 +433,7 @@ static void download_surface_to_buffer(NV2AState *d, SurfaceBinding *surface, &post_copy_dst_barrier, 0, NULL); nv2a_profile_inc_counter(NV2A_PROF_QUEUE_SUBMIT_1); + pgraph_vk_end_debug_marker(r, cmd); pgraph_vk_end_single_time_commands(pg, cmd); void *mapped_memory_ptr = NULL; @@ -782,6 +784,8 @@ static void create_surface_image(PGRAPHState *pg, SurfaceBinding *surface) // FIXME: Go right into main command buffer VkCommandBuffer cmd = pgraph_vk_begin_single_time_commands(pg); + pgraph_vk_begin_debug_marker(r, cmd, RGBA_RED, __func__); + pgraph_vk_transition_image_layout( pg, cmd, surface->image, surface->host_fmt.vk_format, VK_IMAGE_LAYOUT_UNDEFINED, @@ -789,6 +793,7 @@ static void create_surface_image(PGRAPHState *pg, SurfaceBinding *surface) VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); nv2a_profile_inc_counter(NV2A_PROF_QUEUE_SUBMIT_3); + pgraph_vk_end_debug_marker(r, cmd); pgraph_vk_end_single_time_commands(pg, cmd); nv2a_profile_inc_counter(NV2A_PROF_SURF_CREATE); } @@ -977,6 +982,7 @@ void pgraph_vk_upload_surface_data(NV2AState *d, SurfaceBinding *surface, vmaUnmapMemory(r->allocator, copy_buffer->allocation); VkCommandBuffer cmd = pgraph_vk_begin_single_time_commands(pg); + pgraph_vk_begin_debug_marker(r, cmd, RGBA_RED, __func__); VkBufferMemoryBarrier host_barrier = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, @@ -1226,6 +1232,7 @@ void pgraph_vk_upload_surface_data(NV2AState *d, SurfaceBinding *surface, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); nv2a_profile_inc_counter(NV2A_PROF_QUEUE_SUBMIT_2); + pgraph_vk_end_debug_marker(r, cmd); pgraph_vk_end_single_time_commands(pg, cmd); surface->initialized = true; diff --git a/hw/xbox/nv2a/pgraph/vk/texture.c b/hw/xbox/nv2a/pgraph/vk/texture.c index 3c4f095360..c5d3cf7fe2 100644 --- a/hw/xbox/nv2a/pgraph/vk/texture.c +++ b/hw/xbox/nv2a/pgraph/vk/texture.c @@ -556,6 +556,7 @@ static void upload_texture_image(PGRAPHState *pg, int texture_idx, // FIXME: Use nondraw. Need to fill and copy tex buffer at once VkCommandBuffer cmd = pgraph_vk_begin_single_time_commands(pg); + pgraph_vk_begin_debug_marker(r, cmd, RGBA_GREEN, __func__); VkBufferMemoryBarrier host_barrier = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, @@ -585,6 +586,7 @@ static void upload_texture_image(PGRAPHState *pg, int texture_idx, binding->current_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; nv2a_profile_inc_counter(NV2A_PROF_QUEUE_SUBMIT_4); + pgraph_vk_end_debug_marker(r, cmd); pgraph_vk_end_single_time_commands(pg, cmd); // Release decoded texture data @@ -621,6 +623,7 @@ static void copy_zeta_surface_to_texture(PGRAPHState *pg, SurfaceBinding *surfac surface->vram_addr, surface->width, surface->height); VkCommandBuffer cmd = pgraph_vk_begin_nondraw_commands(pg); + pgraph_vk_begin_debug_marker(r, cmd, RGBA_GREEN, __func__); unsigned int scaled_width = surface->width, scaled_height = surface->height; @@ -781,6 +784,7 @@ static void copy_zeta_surface_to_texture(PGRAPHState *pg, SurfaceBinding *surfac VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); texture->current_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + pgraph_vk_end_debug_marker(r, cmd); pgraph_vk_end_nondraw_commands(pg, cmd); texture->draw_time = surface->draw_time; @@ -795,6 +799,7 @@ static void copy_surface_to_texture(PGRAPHState *pg, SurfaceBinding *surface, return; } + PGRAPHVkState *r = pg->vk_renderer_state; TextureShape *state = &texture->key.state; VkColorFormatInfo vkf = kelvin_color_format_vk_map[state->color_format]; @@ -804,6 +809,7 @@ static void copy_surface_to_texture(PGRAPHState *pg, SurfaceBinding *surface, surface->vram_addr, surface->width, surface->height); VkCommandBuffer cmd = pgraph_vk_begin_nondraw_commands(pg); + pgraph_vk_begin_debug_marker(r, cmd, RGBA_GREEN, __func__); pgraph_vk_transition_image_layout( pg, cmd, surface->image, surface->host_fmt.vk_format, @@ -842,6 +848,7 @@ static void copy_surface_to_texture(PGRAPHState *pg, SurfaceBinding *surface, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); texture->current_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + pgraph_vk_end_debug_marker(r, cmd); pgraph_vk_end_nondraw_commands(pg, cmd); texture->draw_time = surface->draw_time; @@ -1001,6 +1008,7 @@ static void create_dummy_texture(PGRAPHState *pg) r->storage_buffers[BUFFER_STAGING_SRC].allocation); VkCommandBuffer cmd = pgraph_vk_begin_single_time_commands(pg); + pgraph_vk_begin_debug_marker(r, cmd, RGBA_GREEN, __func__); pgraph_vk_transition_image_layout( pg, cmd, texture_image, VK_FORMAT_R8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED, @@ -1026,6 +1034,8 @@ static void create_dummy_texture(PGRAPHState *pg) VK_FORMAT_R8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + pgraph_vk_end_debug_marker(r, cmd); pgraph_vk_end_single_time_commands(pg, cmd); r->dummy_texture = (TextureBinding){