From 58c9a6dc6b8ba8ae1d82496124bcfb42117bb55b Mon Sep 17 00:00:00 2001 From: Fabian Schmidt <165773884+fabian-lunarg@users.noreply.github.com> Date: Thu, 23 Jan 2025 08:17:38 +0100 Subject: [PATCH] Portable Acceleration Structures (#1955) - worked mostly on decode::VulkanAddressReplacer - enables portable replay of raytracing pipelines, when using RebindAllocator (-m rebind). - work on Acceleration Structures (AS): -> tracking, meta-commands, copies, query-pool handling and rebuild -> rebuild AS from original input-buffers when trimming. -> check AS- and scratch-buffer sizes, replace resources with shadow objects where required --- android/framework/util/CMakeLists.txt | 1 + framework/decode/metadata_consumer_base.h | 3 +- framework/decode/screenshot_handler.cpp | 36 +- framework/decode/screenshot_handler.h | 4 - framework/decode/vulkan_address_replacer.cpp | 956 ++++++++++--- framework/decode/vulkan_address_replacer.h | 210 ++- .../decode/vulkan_address_replacer_shaders.h | 1250 ++++++----------- framework/decode/vulkan_decoder_base.cpp | 29 +- .../decode/vulkan_device_address_tracker.cpp | 57 +- .../decode/vulkan_device_address_tracker.h | 26 +- framework/decode/vulkan_object_info.h | 8 +- framework/decode/vulkan_rebind_allocator.cpp | 8 +- framework/decode/vulkan_rebind_allocator.h | 3 + .../decode/vulkan_replay_consumer_base.cpp | 218 +-- .../decode/vulkan_replay_consumer_base.h | 5 +- .../encode/custom_vulkan_encoder_commands.h | 10 - framework/encode/vulkan_capture_manager.cpp | 59 +- framework/encode/vulkan_capture_manager.h | 13 +- framework/encode/vulkan_handle_wrappers.h | 7 +- framework/encode/vulkan_state_tracker.cpp | 108 +- framework/encode/vulkan_state_tracker.h | 14 + framework/encode/vulkan_state_writer.cpp | 50 +- framework/encode/vulkan_state_writer.h | 10 +- .../generated_vulkan_api_call_encoders.cpp | 7 +- .../vulkan_generators/capture_overrides.json | 2 + framework/graphics/test/main.cpp | 33 + framework/graphics/vulkan_device_util.cpp | 28 +- framework/graphics/vulkan_device_util.h | 4 + framework/util/CMakeLists.txt | 1 + framework/util/alignment_utils.h | 96 ++ framework/util/linear_hashmap.h | 25 +- 31 files changed, 2005 insertions(+), 1276 deletions(-) create mode 100644 framework/util/alignment_utils.h diff --git a/android/framework/util/CMakeLists.txt b/android/framework/util/CMakeLists.txt index b840d13f8a..83d0d27a85 100644 --- a/android/framework/util/CMakeLists.txt +++ b/android/framework/util/CMakeLists.txt @@ -2,6 +2,7 @@ add_library(gfxrecon_util STATIC "") target_sources(gfxrecon_util PRIVATE + ${GFXRECON_SOURCE_DIR}/framework/util/alignment_utils.h ${GFXRECON_SOURCE_DIR}/framework/util/argument_parser.h ${GFXRECON_SOURCE_DIR}/framework/util/argument_parser.cpp ${GFXRECON_SOURCE_DIR}/framework/util/buffer_writer.h diff --git a/framework/decode/metadata_consumer_base.h b/framework/decode/metadata_consumer_base.h index 546ae77227..80f7c28d95 100644 --- a/framework/decode/metadata_consumer_base.h +++ b/framework/decode/metadata_consumer_base.h @@ -116,8 +116,7 @@ class MetadataConsumerBase format::HandleId device_id, uint32_t info_count, StructPointerDecoder* geometry_infos, - StructPointerDecoder* range_infos, - std::vector>& instance_buffers_data) + StructPointerDecoder* range_infos) {} virtual void ProcessCopyVulkanAccelerationStructuresMetaCommand( diff --git a/framework/decode/screenshot_handler.cpp b/framework/decode/screenshot_handler.cpp index 27c7165c37..e0dbb35893 100644 --- a/framework/decode/screenshot_handler.cpp +++ b/framework/decode/screenshot_handler.cpp @@ -539,25 +539,6 @@ VkDeviceSize ScreenshotHandler::GetCopyBufferSize(VkDevice return memory_requirements.size; } -uint32_t ScreenshotHandler::GetMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& memory_properties, - uint32_t type_bits, - VkMemoryPropertyFlags property_flags) const -{ - uint32_t memory_type_index = std::numeric_limits::max(); - - for (uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i) - { - if ((type_bits & (1 << i)) && - ((memory_properties.memoryTypes[i].propertyFlags & property_flags) == property_flags)) - { - memory_type_index = i; - break; - } - } - - return memory_type_index; -} - VkResult ScreenshotHandler::CreateCopyResource(VkDevice device, const encode::VulkanDeviceTable* device_table, const VkPhysicalDeviceMemoryProperties& memory_properties, @@ -597,17 +578,17 @@ VkResult ScreenshotHandler::CreateCopyResource(VkDevice device_table->GetBufferMemoryRequirements(device, copy_resource->buffer, &memory_requirements); uint32_t memory_type_index = - GetMemoryTypeIndex(memory_properties, - memory_requirements.memoryTypeBits, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT); + graphics::GetMemoryTypeIndex(memory_properties, + memory_requirements.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT); if (memory_type_index == std::numeric_limits::max()) { /* fallback to coherent */ - memory_type_index = - GetMemoryTypeIndex(memory_properties, - memory_requirements.memoryTypeBits, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + memory_type_index = graphics::GetMemoryTypeIndex(memory_properties, + memory_requirements.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); } assert(memory_type_index != std::numeric_limits::max()); @@ -660,9 +641,8 @@ VkResult ScreenshotHandler::CreateCopyResource(VkDevice VkMemoryRequirements memory_requirements; device_table->GetImageMemoryRequirements(device, copy_resource->convert_image, &memory_requirements); - uint32_t memory_type_index = GetMemoryTypeIndex( + uint32_t memory_type_index = graphics::GetMemoryTypeIndex( memory_properties, memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - assert(memory_type_index != std::numeric_limits::max()); VkMemoryAllocateInfo allocate_info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; diff --git a/framework/decode/screenshot_handler.h b/framework/decode/screenshot_handler.h index e7c82236ab..af56b6fc2b 100644 --- a/framework/decode/screenshot_handler.h +++ b/framework/decode/screenshot_handler.h @@ -100,10 +100,6 @@ class ScreenshotHandler : public ScreenshotHandlerBase uint32_t width, uint32_t height) const; - uint32_t GetMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& memory_properties, - uint32_t type_bits, - VkMemoryPropertyFlags property_flags) const; - VkResult CreateCopyResource(VkDevice device, const encode::VulkanDeviceTable* device_table, const VkPhysicalDeviceMemoryProperties& memory_properties, diff --git a/framework/decode/vulkan_address_replacer.cpp b/framework/decode/vulkan_address_replacer.cpp index a68f901617..1a8b06c2b4 100644 --- a/framework/decode/vulkan_address_replacer.cpp +++ b/framework/decode/vulkan_address_replacer.cpp @@ -20,59 +20,83 @@ ** DEALINGS IN THE SOFTWARE. */ +#include "graphics/vulkan_struct_get_pnext.h" #include "decode/vulkan_address_replacer.h" #include "decode/vulkan_address_replacer_shaders.h" #include "decode/mark_injected_commands.h" +#include "util/alignment_utils.h" #include "util/logging.h" GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(decode) //! RAII helper to mark injected commands in scope -struct mark_injected_commands_helper_t +struct MarkInjectedCommandsHelper { - mark_injected_commands_helper_t() + MarkInjectedCommandsHelper() { // mark injected commands decode::BeginInjectedCommands(); } - ~mark_injected_commands_helper_t() + ~MarkInjectedCommandsHelper() { // mark end of injected commands decode::EndInjectedCommands(); } }; -inline uint32_t aligned_size(uint32_t size, uint32_t alignment) +//! RAII helper submit a command-buffer to a queue and synchronize via fence +struct QueueSubmitHelper { - return (size + alignment - 1) & ~(alignment - 1); -} + const encode::VulkanDeviceTable* device_table = nullptr; + VkDevice device = VK_NULL_HANDLE; + VkCommandBuffer command_buffer = VK_NULL_HANDLE; + VkFence fence = VK_NULL_HANDLE; + VkQueue queue = VK_NULL_HANDLE; + + QueueSubmitHelper(const encode::VulkanDeviceTable* device_table_, + VkDevice device_, + VkCommandBuffer command_buffer_, + VkQueue queue_, + VkFence fence_) : + device(device_), device_table(device_table_), command_buffer(command_buffer_), fence(fence_), queue(queue_) + { + MarkInjectedCommandsHelper mark_injected_commands_helper; -inline uint32_t div_up(uint32_t nom, uint32_t denom) -{ - GFXRECON_ASSERT(denom > 0) - return (nom + denom - 1) / denom; -} + device_table->ResetFences(device, 1, &fence); -uint32_t get_memory_type_index(const VkPhysicalDeviceMemoryProperties& memory_properties, - uint32_t type_bits, - VkMemoryPropertyFlags property_flags) -{ - uint32_t memory_type_index = std::numeric_limits::max(); + VkCommandBufferBeginInfo command_buffer_begin_info; + command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + command_buffer_begin_info.pNext = nullptr; + command_buffer_begin_info.flags = 0; + command_buffer_begin_info.pInheritanceInfo = nullptr; + device_table->BeginCommandBuffer(command_buffer, &command_buffer_begin_info); + } - for (uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i) + ~QueueSubmitHelper() { - if ((type_bits & (1 << i)) && - ((memory_properties.memoryTypes[i].propertyFlags & property_flags) == property_flags)) - { - memory_type_index = i; - break; - } - } + MarkInjectedCommandsHelper mark_injected_commands_helper; - return memory_type_index; -} + device_table->EndCommandBuffer(command_buffer); + + VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 0; + submit_info.pWaitSemaphores = nullptr; + submit_info.pWaitDstStageMask = nullptr; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer; + submit_info.signalSemaphoreCount = 0; + submit_info.pSignalSemaphores = nullptr; + + // submit + device_table->QueueSubmit(queue, 1, &submit_info, fence); + + // sync + device_table->WaitForFences(device, 1, &fence, VK_TRUE, std::numeric_limits::max()); + } +}; struct hashmap_t { @@ -96,61 +120,95 @@ decode::VulkanAddressReplacer::buffer_context_t::~buffer_context_t() { if (buffer != VK_NULL_HANDLE) { + // unmap/destroy buffer + resource_allocator->UnmapResourceMemoryDirect(allocator_data); resource_allocator->DestroyBufferDirect(buffer, nullptr, allocator_data); } if (device_memory != VK_NULL_HANDLE) { resource_allocator->FreeMemoryDirect(device_memory, nullptr, memory_data); } + + resource_allocator = nullptr; + buffer = VK_NULL_HANDLE; + device_memory = VK_NULL_HANDLE; + } +} + +decode::VulkanAddressReplacer::acceleration_structure_asset_t::~acceleration_structure_asset_t() +{ + if (handle != VK_NULL_HANDLE && destroy_fn != nullptr && device != VK_NULL_HANDLE) + { + destroy_fn(device, handle, nullptr); } } VulkanAddressReplacer::VulkanAddressReplacer(const VulkanDeviceInfo* device_info, const encode::VulkanDeviceTable* device_table, + const encode::VulkanInstanceTable* instance_table, const decode::CommonObjectInfoTable& object_table) : device_table_(device_table) { - GFXRECON_ASSERT(device_info != nullptr && device_table != nullptr) - - const VulkanPhysicalDeviceInfo* physical_device_info = object_table.GetVkPhysicalDeviceInfo(device_info->parent_id); - device_ = device_info->handle; - resource_allocator_ = device_info->allocator.get(); - get_device_address_fn_ = physical_device_info->parent_api_version >= VK_API_VERSION_1_2 + GFXRECON_ASSERT(device_info != nullptr && device_table != nullptr && instance_table != nullptr); + physical_device_info_ = object_table.GetVkPhysicalDeviceInfo(device_info->parent_id); + GFXRECON_ASSERT(physical_device_info_ != nullptr); + device_ = device_info->handle; + resource_allocator_ = device_info->allocator.get(); + get_device_address_fn_ = physical_device_info_->parent_api_version >= VK_API_VERSION_1_2 ? device_table->GetBufferDeviceAddress : device_table->GetBufferDeviceAddressKHR; - if (physical_device_info != nullptr && physical_device_info->capture_raytracing_properties && - physical_device_info->replay_device_info->raytracing_properties) - { - capture_ray_properties_ = *physical_device_info->capture_raytracing_properties; - replay_ray_properties_ = *physical_device_info->replay_device_info->raytracing_properties; + get_physical_device_properties_fn_ = instance_table->GetPhysicalDeviceProperties2; + SetRaytracingProperties(physical_device_info_); +} - if (capture_ray_properties_.shaderGroupHandleSize != replay_ray_properties_.shaderGroupHandleSize || - capture_ray_properties_.shaderGroupHandleAlignment != replay_ray_properties_.shaderGroupHandleAlignment || - capture_ray_properties_.shaderGroupBaseAlignment != replay_ray_properties_.shaderGroupBaseAlignment) +void VulkanAddressReplacer::SetRaytracingProperties(const decode::VulkanPhysicalDeviceInfo* physical_device_info) +{ + if (physical_device_info != nullptr) + { + physical_device_info_ = physical_device_info; + if (physical_device_info->capture_raytracing_properties) { - valid_sbt_alignment_ = false; + capture_ray_properties_ = *physical_device_info->capture_raytracing_properties; } - GFXRECON_ASSERT(physical_device_info->replay_device_info != nullptr); - GFXRECON_ASSERT(physical_device_info->replay_device_info->memory_properties.has_value()); - memory_properties_ = *physical_device_info->replay_device_info->memory_properties; + if (physical_device_info->replay_device_info != nullptr) + { + if (physical_device_info->replay_device_info->raytracing_properties) + { + replay_ray_properties_ = *physical_device_info->replay_device_info->raytracing_properties; + } + if (physical_device_info->replay_device_info->acceleration_structure_properties) + { + replay_acceleration_structure_properties_ = + *physical_device_info->replay_device_info->acceleration_structure_properties; + } + GFXRECON_ASSERT(physical_device_info_->replay_device_info->memory_properties.has_value()); + memory_properties_ = *physical_device_info_->replay_device_info->memory_properties; + } } -} -VulkanAddressReplacer::VulkanAddressReplacer(VulkanAddressReplacer&& other) noexcept : VulkanAddressReplacer() -{ - swap(*this, other); + if (capture_ray_properties_ && replay_ray_properties_) + { + if (capture_ray_properties_->shaderGroupHandleSize != replay_ray_properties_->shaderGroupHandleSize || + capture_ray_properties_->shaderGroupHandleAlignment != replay_ray_properties_->shaderGroupHandleAlignment || + capture_ray_properties_->shaderGroupBaseAlignment != replay_ray_properties_->shaderGroupBaseAlignment) + { + valid_sbt_alignment_ = false; + } + } } VulkanAddressReplacer::~VulkanAddressReplacer() { - mark_injected_commands_helper_t mark_injected_commands_helper; + MarkInjectedCommandsHelper mark_injected_commands_helper; // explicitly free resources here, in order to mark destruction API-calls as injected - pipeline_context_sbt_ = {}; - pipeline_context_bda_ = {}; - shadow_sbt_map_ = {}; + pipeline_sbt_context_map_ = {}; + build_as_context_map_ = {}; + + shadow_sbt_map_ = {}; + shadow_as_map_ = {}; if (pipeline_bda_ != VK_NULL_HANDLE) { @@ -164,6 +222,24 @@ VulkanAddressReplacer::~VulkanAddressReplacer() { device_table_->DestroyPipelineLayout(device_, pipeline_layout_, nullptr); } + + if (query_pool_ != VK_NULL_HANDLE) + { + device_table_->DestroyQueryPool(device_, query_pool_, nullptr); + } + if (fence_ != VK_NULL_HANDLE) + { + device_table_->DestroyFence(device_, fence_, nullptr); + } + if (command_buffer_ != VK_NULL_HANDLE) + { + GFXRECON_ASSERT(command_pool_ != VK_NULL_HANDLE); + device_table_->FreeCommandBuffers(device_, command_pool_, 1, &command_buffer_); + } + if (command_pool_ != VK_NULL_HANDLE) + { + device_table_->DestroyCommandPool(device_, command_pool_, nullptr); + } } void VulkanAddressReplacer::ProcessCmdTraceRays( @@ -196,14 +272,53 @@ void VulkanAddressReplacer::ProcessCmdTraceRays( } } - // TODO: testing only -> remove when closing issue #1526 - // valid_sbt_alignment_ = false; - // valid_group_handles = false; + // raytracing-pipeline properties not populated yet, check if we missed it + if (capture_ray_properties_ == std::nullopt || replay_ray_properties_ == std::nullopt) + { + SetRaytracingProperties(physical_device_info_); + + // capture does contain the call, bail out + if (capture_ray_properties_ == std::nullopt || replay_ray_properties_ == std::nullopt) + { + GFXRECON_LOG_ERROR_ONCE( + "VulkanAddressReplacer::ProcessCmdTraceRays: missing " + "VkPhysicalDeviceRayTracingPipelinePropertiesKHR for capture/replay, cannot proceed"); + return; + } + } + + std::unordered_set buffer_set; + auto address_remap = [&address_tracker, &buffer_set](VkStridedDeviceAddressRegionKHR* address_region) { + if (address_region->size > 0) + { + auto buffer_info = address_tracker.GetBufferByCaptureDeviceAddress(address_region->deviceAddress); + GFXRECON_ASSERT(buffer_info != nullptr); + + if (buffer_info->replay_address != 0) + { + // keep track of used handles + buffer_set.insert(buffer_info->handle); + + uint64_t offset = address_region->deviceAddress - buffer_info->capture_address; + + // in-place address-remap + address_region->deviceAddress = buffer_info->replay_address + offset; + return true; + } + } + return false; + }; + + // in-place remap: capture-addresses -> replay-addresses + address_remap(raygen_sbt); + address_remap(miss_sbt); + address_remap(hit_sbt); + address_remap(callable_sbt); if (!valid_sbt_alignment_ || !valid_group_handles) { // mark injected commands - mark_injected_commands_helper_t mark_injected_commands_helper; + MarkInjectedCommandsHelper mark_injected_commands_helper; if (pipeline_sbt_ == VK_NULL_HANDLE) { @@ -213,37 +328,6 @@ void VulkanAddressReplacer::ProcessCmdTraceRays( return; } } - std::unordered_set buffer_set; - - auto address_remap = [&address_tracker, &buffer_set](VkStridedDeviceAddressRegionKHR* address_region) { - if (address_region->size > 0) - { - auto buffer_info = address_tracker.GetBufferByCaptureDeviceAddress(address_region->deviceAddress); - GFXRECON_ASSERT(buffer_info != nullptr); - - if (buffer_info->replay_address != 0) - { - // keep track of used handles - buffer_set.insert(buffer_info->handle); - - uint64_t offset = address_region->deviceAddress - buffer_info->capture_address; - - // in-place address-remap - address_region->deviceAddress = buffer_info->replay_address + offset; - } - else - { - GFXRECON_LOG_INFO_ONCE( - "VulkanAddressReplacer::ProcessCmdTraceRays: missing buffer_info->replay_address, remap failed") - } - } - }; - - // in-place remap: capture-addresses -> replay-addresses - address_remap(raygen_sbt); - address_remap(miss_sbt); - address_remap(hit_sbt); - address_remap(callable_sbt); // prepare linear hashmap hashmap_sbt_.clear(); @@ -253,20 +337,22 @@ void VulkanAddressReplacer::ProcessCmdTraceRays( hashmap_sbt_.put(lhs, rhs); } - if (!create_buffer(hashmap_sbt_.get_storage(nullptr), pipeline_context_sbt_.hashmap_storage)) + // get a context for this command-buffer + auto& pipeline_context_sbt = pipeline_sbt_context_map_[command_buffer_info->handle]; + + if (!create_buffer(pipeline_context_sbt.hashmap_storage, hashmap_sbt_.get_storage(nullptr))) { GFXRECON_LOG_ERROR("VulkanAddressReplacer: hashmap-storage-buffer creation failed"); } - hashmap_sbt_.get_storage(pipeline_context_sbt_.hashmap_storage.mapped_data); + hashmap_sbt_.get_storage(pipeline_context_sbt.hashmap_storage.mapped_data); // input-handles constexpr uint32_t max_num_handles = 4; - if (!create_buffer(max_num_handles * sizeof(VkDeviceAddress), pipeline_context_sbt_.input_handle_buffer)) + if (!create_buffer(pipeline_context_sbt.input_handle_buffer, max_num_handles * sizeof(VkDeviceAddress))) { GFXRECON_LOG_ERROR("VulkanAddressReplacer: input-handle-buffer creation failed"); } - auto input_addresses = - reinterpret_cast(pipeline_context_sbt_.input_handle_buffer.mapped_data); + auto input_addresses = reinterpret_cast(pipeline_context_sbt.input_handle_buffer.mapped_data); uint32_t num_addresses = 0; for (const auto& region : { raygen_sbt, miss_sbt, hit_sbt, callable_sbt }) @@ -278,16 +364,17 @@ void VulkanAddressReplacer::ProcessCmdTraceRays( } replacer_params_t replacer_params = {}; - replacer_params.hashmap.storage = pipeline_context_sbt_.hashmap_storage.device_address; + replacer_params.hashmap.storage = pipeline_context_sbt.hashmap_storage.device_address; replacer_params.hashmap.size = hashmap_sbt_.size(); replacer_params.hashmap.capacity = hashmap_sbt_.capacity(); - replacer_params.input_handles = pipeline_context_sbt_.input_handle_buffer.device_address; + replacer_params.input_handles = pipeline_context_sbt.input_handle_buffer.device_address; replacer_params.num_handles = num_addresses; if (valid_sbt_alignment_) { - GFXRECON_LOG_INFO_ONCE("Replay adjusted mismatching raytracing shader-group-handles"); + GFXRECON_LOG_INFO_ONCE("VulkanAddressReplacer::ProcessCmdTraceRays: Replay is adjusting mismatching " + "raytracing shader-group-handles"); // rewrite group-handles in-place replacer_params.output_handles = replacer_params.input_handles; @@ -305,32 +392,32 @@ void VulkanAddressReplacer::ProcessCmdTraceRays( } else { - GFXRECON_LOG_INFO_ONCE( - "Replay adjusted a mismatching raytracing shader-binding-table using a shadow-buffer"); + GFXRECON_LOG_INFO_ONCE("VulkanAddressReplacer::ProcessCmdTraceRays: Replay is adjusting mismatching " + "raytracing shader-binding-tables using shadow-buffers"); // output-handles - if (!create_buffer(max_num_handles * sizeof(VkDeviceAddress), pipeline_context_sbt_.output_handle_buffer)) + if (!create_buffer(pipeline_context_sbt.output_handle_buffer, max_num_handles * sizeof(VkDeviceAddress))) { GFXRECON_LOG_ERROR("VulkanAddressReplacer: input-handle-buffer creation failed"); return; } // output to shadow-sbt-buffer - replacer_params.output_handles = pipeline_context_sbt_.output_handle_buffer.device_address; + replacer_params.output_handles = pipeline_context_sbt.output_handle_buffer.device_address; // find/create shadow-SBT-buffer uint32_t sbt_offset = 0; auto& shadow_buf_context = shadow_sbt_map_[command_buffer_info->handle]; - const uint32_t handle_size_aligned = aligned_size(replay_ray_properties_.shaderGroupHandleSize, - replay_ray_properties_.shaderGroupHandleAlignment); + const auto handle_size_aligned = static_cast(util::aligned_value( + replay_ray_properties_->shaderGroupHandleSize, replay_ray_properties_->shaderGroupHandleAlignment)); for (auto& region : { raygen_sbt, miss_sbt, hit_sbt, callable_sbt }) { if (region != nullptr) { uint32_t num_handles_limit = region->size / region->stride; - uint32_t group_size = aligned_size(num_handles_limit * handle_size_aligned, - replay_ray_properties_.shaderGroupBaseAlignment); + auto group_size = static_cast(util::aligned_value( + num_handles_limit * handle_size_aligned, replay_ray_properties_->shaderGroupBaseAlignment)); sbt_offset += group_size; // adjust group-size @@ -339,16 +426,19 @@ void VulkanAddressReplacer::ProcessCmdTraceRays( } } // raygen: stride == size - raygen_sbt->size = raygen_sbt->stride = replay_ray_properties_.shaderGroupBaseAlignment; + raygen_sbt->size = raygen_sbt->stride = replay_ray_properties_->shaderGroupBaseAlignment; - if (!create_buffer(sbt_offset, shadow_buf_context, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR)) + if (!create_buffer(shadow_buf_context, + sbt_offset, + VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, + replay_ray_properties_->shaderGroupBaseAlignment)) { GFXRECON_LOG_ERROR("VulkanAddressReplacer: shadow shader-binding-table creation failed"); return; } auto output_addresses = - reinterpret_cast(pipeline_context_sbt_.output_handle_buffer.mapped_data); + reinterpret_cast(pipeline_context_sbt.output_handle_buffer.mapped_data); uint32_t out_index = 0; sbt_offset = 0; for (auto& region : { raygen_sbt, miss_sbt, hit_sbt, callable_sbt }) @@ -374,7 +464,8 @@ void VulkanAddressReplacer::ProcessCmdTraceRays( &replacer_params); // run a single workgroup constexpr uint32_t wg_size = 32; - device_table_->CmdDispatch(command_buffer_info->handle, div_up(replacer_params.num_handles, wg_size), 1, 1); + device_table_->CmdDispatch( + command_buffer_info->handle, util::div_up(replacer_params.num_handles, wg_size), 1, 1); // post memory-barrier for (const auto& buf : buffer_set) @@ -409,13 +500,18 @@ void VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR( { GFXRECON_ASSERT(device_table_ != nullptr); - // TODO: testing only -> remove when closing issue #1526 - constexpr bool force_replace = false; + bool force_replace = false; std::unordered_set buffer_set; - auto address_remap = [&address_tracker, &buffer_set](VkDeviceAddress& capture_address) { + auto address_remap = [&address_tracker, &buffer_set](VkDeviceAddress& capture_address) -> bool { auto buffer_info = address_tracker.GetBufferByCaptureDeviceAddress(capture_address); + // skip over null-addresses + if (capture_address == 0) + { + return false; + } + if (buffer_info != nullptr && buffer_info->replay_address != 0) { // keep track of used handles @@ -425,12 +521,9 @@ void VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR( // in-place address-remap via const-cast capture_address = buffer_info->replay_address + offset; + return true; } - else - { - GFXRECON_LOG_WARNING( - "ProcessCmdBuildAccelerationStructuresKHR: missing buffer_info->replay_address, remap failed"); - } + return false; }; std::vector addresses_to_replace; @@ -440,9 +533,125 @@ void VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR( auto& build_geometry_info = build_geometry_infos[i]; auto range_info = build_range_infos[i]; + const VulkanBufferInfo* scratch_buffer_info = + address_tracker.GetBufferByCaptureDeviceAddress(build_geometry_info.scratchData.deviceAddress); + // check/correct scratch-address address_remap(build_geometry_info.scratchData.deviceAddress); + // check capture/replay acceleration-structure buffer-sizes + { + VkAccelerationStructureBuildSizesInfoKHR build_size_info = {}; + build_size_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR; + + { + std::vector primitive_counts(build_geometry_info.geometryCount); + for (uint32_t j = 0; j < build_geometry_info.geometryCount; ++j) + { + primitive_counts[j] = range_info->primitiveCount; + } + + MarkInjectedCommandsHelper mark_injected_commands_helper; + device_table_->GetAccelerationStructureBuildSizesKHR(device_, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, + &build_geometry_info, + primitive_counts.data(), + &build_size_info); + } + + // retrieve VkAccelerationStructureKHR -> VkBuffer -> check/correct size + auto* acceleration_structure_info = + address_tracker.GetAccelerationStructureByHandle(build_geometry_info.dstAccelerationStructure); + GFXRECON_ASSERT(acceleration_structure_info != nullptr); + auto* buffer_info = address_tracker.GetBufferByHandle(acceleration_structure_info->buffer); + bool as_buffer_usable = + buffer_info != nullptr && buffer_info->size >= build_size_info.accelerationStructureSize; + + // determine required size of scratch-buffer + uint32_t scratch_size = build_geometry_info.mode == VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR + ? build_size_info.buildScratchSize + : build_size_info.updateScratchSize; + bool scratch_buffer_usable = scratch_buffer_info != nullptr && scratch_buffer_info->size >= scratch_size; + + if (!as_buffer_usable || !scratch_buffer_usable) + { + MarkInjectedCommandsHelper mark_injected_commands_helper; + GFXRECON_LOG_INFO_ONCE( + "VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR: Replay is adjusting mismatching " + "acceleration-structures using shadow-structures and -buffers"); + + // now definitely requiring address-replacement + force_replace = true; + + auto& replacement_as = shadow_as_map_[build_geometry_info.dstAccelerationStructure]; + + if (replacement_as.handle == VK_NULL_HANDLE) + { + if (as_buffer_usable) + { + replacement_as.handle = build_geometry_info.dstAccelerationStructure; + auto accel_info = address_tracker.GetAccelerationStructureByHandle( + build_geometry_info.dstAccelerationStructure); + GFXRECON_ASSERT(accel_info != nullptr && accel_info->replay_address != 0); + replacement_as.address = accel_info->replay_address; + } + else + { + auto ret = create_acceleration_asset(replacement_as, + build_geometry_info.type, + build_size_info.accelerationStructureSize, + scratch_size); + if (!ret) + { + GFXRECON_LOG_ERROR("ProcessCmdBuildAccelerationStructuresKHR: creation of shadow " + "acceleration-structure failed"); + } + } + } + + // check/correct source acceleration-structure + swap_acceleration_structure_handle(build_geometry_info.srcAccelerationStructure); + + // hot swap acceleration-structure handle + build_geometry_info.dstAccelerationStructure = replacement_as.handle; + + // acceleration-structure properties not populated yet, check if we missed it + if (!replay_acceleration_structure_properties_) + { + SetRaytracingProperties(physical_device_info_); + + // capture did not contain the call, inject + if (!replay_acceleration_structure_properties_) + { + VkPhysicalDeviceAccelerationStructurePropertiesKHR as_properties = {}; + as_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR; + as_properties.pNext = nullptr; + + VkPhysicalDeviceProperties2 physical_device_properties = {}; + physical_device_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + physical_device_properties.pNext = &as_properties; + get_physical_device_properties_fn_(physical_device_info_->handle, &physical_device_properties); + replay_acceleration_structure_properties_ = as_properties; + } + } + + // create a replacement scratch-buffer + if (!create_buffer( + replacement_as.scratch, + scratch_size, + 0, + replay_acceleration_structure_properties_->minAccelerationStructureScratchOffsetAlignment, + false)) + { + GFXRECON_LOG_ERROR("ProcessCmdBuildAccelerationStructuresKHR: scratch-buffer creation failed"); + return; + } + + // hot swap scratch-buffer + build_geometry_info.scratchData.deviceAddress = replacement_as.scratch.device_address; + } + } + for (uint32_t j = 0; j < build_geometry_info.geometryCount; ++j) { auto geometry = const_cast(build_geometry_info.pGeometries != nullptr @@ -455,6 +664,7 @@ void VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR( auto& triangles = geometry->geometry.triangles; address_remap(triangles.vertexData.deviceAddress); address_remap(triangles.indexData.deviceAddress); + address_remap(triangles.transformData.deviceAddress); break; } case VK_GEOMETRY_TYPE_AABBS_KHR: @@ -494,50 +704,66 @@ void VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR( auto acceleration_structure_map = address_tracker.GetAccelerationStructureDeviceAddressMap(); for (const auto& [capture_address, replay_address] : acceleration_structure_map) { + auto* accel_info = address_tracker.GetAccelerationStructureByCaptureDeviceAddress(capture_address); + GFXRECON_ASSERT(accel_info != nullptr); + if (force_replace || capture_address != replay_address) { + auto new_address = replay_address; + + // extra look-up required for potentially replaced AS + if (accel_info != nullptr) + { + auto shadow_as_it = shadow_as_map_.find(accel_info->handle); + if (shadow_as_it != shadow_as_map_.end()) + { + new_address = shadow_as_it->second.address; + } + } + // store addresses we will need to replace - hashmap_bda_.put(capture_address, replay_address); + GFXRECON_ASSERT(new_address != 0); + hashmap_bda_.put(capture_address, new_address); } } if (!hashmap_bda_.empty()) { // mark injected commands - mark_injected_commands_helper_t mark_injected_commands_helper; + MarkInjectedCommandsHelper mark_injected_commands_helper; - if (pipeline_bda_ == VK_NULL_HANDLE) + if (pipeline_bda_ == VK_NULL_HANDLE && !init_pipeline()) { - if (!init_pipeline()) - { - GFXRECON_LOG_WARNING_ONCE( - "ProcessCmdBuildAccelerationStructuresKHR: internal pipeline-creation failed") - return; - } + GFXRECON_LOG_WARNING_ONCE("ProcessCmdBuildAccelerationStructuresKHR: internal pipeline-creation failed") + return; } - if (!create_buffer(hashmap_bda_.get_storage(nullptr), pipeline_context_bda_.hashmap_storage)) + auto& pipeline_context_bda = build_as_context_map_[command_buffer_info->handle]; + + if (!create_buffer(pipeline_context_bda.hashmap_storage, hashmap_bda_.get_storage(nullptr))) { GFXRECON_LOG_ERROR("VulkanAddressReplacer: hashmap-storage-buffer creation failed"); + return; } - hashmap_bda_.get_storage(pipeline_context_bda_.hashmap_storage.mapped_data); + hashmap_bda_.get_storage(pipeline_context_bda.hashmap_storage.mapped_data); uint32_t num_bytes = addresses_to_replace.size() * sizeof(VkDeviceAddress); - if (!create_buffer(num_bytes, pipeline_context_bda_.input_handle_buffer)) + if (!create_buffer(pipeline_context_bda.input_handle_buffer, num_bytes)) { GFXRECON_LOG_ERROR("VulkanAddressReplacer: input-handle-buffer creation failed"); + return; } - memcpy(pipeline_context_bda_.input_handle_buffer.mapped_data, addresses_to_replace.data(), num_bytes); + memcpy(pipeline_context_bda.input_handle_buffer.mapped_data, addresses_to_replace.data(), num_bytes); replacer_params_t replacer_params = {}; - replacer_params.hashmap.storage = pipeline_context_bda_.hashmap_storage.device_address; + replacer_params.hashmap.storage = pipeline_context_bda.hashmap_storage.device_address; replacer_params.hashmap.size = hashmap_bda_.size(); replacer_params.hashmap.capacity = hashmap_bda_.capacity(); // in-place - replacer_params.input_handles = pipeline_context_bda_.input_handle_buffer.device_address; - replacer_params.output_handles = pipeline_context_bda_.input_handle_buffer.device_address; + replacer_params.input_handles = pipeline_context_bda.input_handle_buffer.device_address; + replacer_params.output_handles = pipeline_context_bda.input_handle_buffer.device_address; replacer_params.num_handles = addresses_to_replace.size(); @@ -550,9 +776,10 @@ void VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR( 0, sizeof(replacer_params_t), &replacer_params); - // run a single workgroup + // dispatch workgroups constexpr uint32_t wg_size = 32; - device_table_->CmdDispatch(command_buffer_info->handle, div_up(replacer_params.num_handles, wg_size), 1, 1); + device_table_->CmdDispatch( + command_buffer_info->handle, util::div_up(replacer_params.num_handles, wg_size), 1, 1); // post memory-barrier for (const auto& buf : buffer_set) @@ -561,7 +788,7 @@ void VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR( buf, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_SHADER_WRITE_BIT, - VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_ACCESS_SHADER_READ_BIT); } @@ -579,6 +806,233 @@ void VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR( } } +void VulkanAddressReplacer::ProcessCmdCopyAccelerationStructuresKHR( + VkCopyAccelerationStructureInfoKHR* info, const decode::VulkanDeviceAddressTracker& address_tracker) +{ + if (info != nullptr) + { + VkDeviceSize compact_size = 0; + auto compact_size_it = as_compact_sizes_.find(info->src); + if (compact_size_it != as_compact_sizes_.end()) + { + compact_size = compact_size_it->second; + as_compact_sizes_.erase(info->src); + + auto* as_info = address_tracker.GetAccelerationStructureByHandle(info->dst); + GFXRECON_ASSERT(as_info != nullptr); + if (as_info != nullptr) + { + auto* buffer_info = address_tracker.GetBufferByHandle(as_info->buffer); + GFXRECON_ASSERT(buffer_info != nullptr); + if (buffer_info != nullptr) + { + if (buffer_info->size < compact_size) + { + // TODO: need replacement AS + } + } + } + } + + // correct in-place + swap_acceleration_structure_handle(info->src); + swap_acceleration_structure_handle(info->dst); + } +} + +void VulkanAddressReplacer::ProcessCmdWriteAccelerationStructuresPropertiesKHR( + uint32_t count, + VkAccelerationStructureKHR* acceleration_structures, + VkQueryType query_type, + VkQueryPool pool, + uint32_t first_query) +{ + for (uint32_t i = 0; i < count; ++i) + { + auto shadow_as_it = shadow_as_map_.find(acceleration_structures[i]); + if (shadow_as_it != shadow_as_map_.end()) + { + acceleration_structures[i] = shadow_as_it->second.handle; + } + + if (query_type == VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR) + { + // read back compacted size later + as_compact_queries_[pool][acceleration_structures[i]] = first_query + i; + } + } +} + +void VulkanAddressReplacer::ProcessUpdateDescriptorSets(uint32_t descriptor_write_count, + VkWriteDescriptorSet* descriptor_writes, + uint32_t descriptor_copy_count, + VkCopyDescriptorSet* descriptor_copies) +{ + GFXRECON_UNREFERENCED_PARAMETER(descriptor_copy_count); + GFXRECON_UNREFERENCED_PARAMETER(descriptor_copies); + + // bail out if we're not tracking any shadow acceleration-structures + if (shadow_as_map_.empty()) + { + return; + } + + for (uint32_t i = 0; i < descriptor_write_count; ++i) + { + VkWriteDescriptorSet& write = descriptor_writes[i]; + + if (write.descriptorType != VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) + { + continue; + } + + if (auto* write_as = graphics::vulkan_struct_get_pnext(&write)) + { + for (uint32_t j = 0; j < write_as->accelerationStructureCount; ++j) + { + auto acceleration_structure_it = shadow_as_map_.find(write_as->pAccelerationStructures[j]); + if (acceleration_structure_it != shadow_as_map_.end()) + { + // we found an existing replacement-structure -> swap + auto* out_array = const_cast(write_as->pAccelerationStructures); + out_array[j] = acceleration_structure_it->second.handle; + + GFXRECON_LOG_INFO_ONCE("VulkanAddressReplacer::ProcessUpdateDescriptorSets: Replay adjusted " + "AccelerationStructure handles") + } + } + } + } +} + +void VulkanAddressReplacer::ProcessGetQueryPoolResults(VkDevice device, + VkQueryPool query_pool, + uint32_t firstQuery, + uint32_t queryCount, + size_t dataSize, + void* pData, + VkDeviceSize stride, + VkQueryResultFlags flags) +{ + GFXRECON_UNREFERENCED_PARAMETER(device); + GFXRECON_UNREFERENCED_PARAMETER(firstQuery); + GFXRECON_UNREFERENCED_PARAMETER(queryCount); + GFXRECON_UNREFERENCED_PARAMETER(dataSize); + + // intercept queries containing acceleration-structure compaction-sizes + if (!as_compact_queries_.empty() && stride == sizeof(VkDeviceSize)) + { + bool is_synced = flags & VK_QUERY_RESULT_WAIT_BIT; + + auto it = as_compact_queries_.find(query_pool); + if (is_synced && it != as_compact_queries_.end()) + { + // assuming post-processing here, pData was already written + auto* result_array = reinterpret_cast(pData); + + for (const auto& [as, query_index] : it->second) + { + as_compact_sizes_[as] = result_array[query_index]; + } + } + as_compact_queries_.erase(query_pool); + } +} + +void VulkanAddressReplacer::ProcessBuildVulkanAccelerationStructuresMetaCommand( + uint32_t info_count, + VkAccelerationStructureBuildGeometryInfoKHR* geometry_infos, + VkAccelerationStructureBuildRangeInfoKHR** range_infos, + const decode::VulkanDeviceAddressTracker& address_tracker) +{ + if (info_count > 0 && init_queue_assets()) + { + // reset/submit/sync command-buffer + QueueSubmitHelper queue_submit_helper(device_table_, device_, command_buffer_, queue_, fence_); + + // dummy-wrapper + VulkanCommandBufferInfo command_buffer_info = {}; + command_buffer_info.handle = command_buffer_; + ProcessCmdBuildAccelerationStructuresKHR( + &command_buffer_info, info_count, geometry_infos, range_infos, address_tracker); + + // issue build-command + MarkInjectedCommandsHelper mark_injected_commands_helper; + device_table_->CmdBuildAccelerationStructuresKHR(command_buffer_, info_count, geometry_infos, range_infos); + } +} + +void VulkanAddressReplacer::ProcessCopyVulkanAccelerationStructuresMetaCommand( + uint32_t info_count, + VkCopyAccelerationStructureInfoKHR* copy_infos, + const decode::VulkanDeviceAddressTracker& address_tracker) +{ + if (copy_infos != nullptr && info_count > 0 && init_queue_assets()) + { + // reset/submit/sync command-buffer + QueueSubmitHelper queue_submit_helper(device_table_, device_, command_buffer_, queue_, fence_); + + for (uint32_t i = 0; i < info_count; ++i) + { + auto* copy_info = copy_infos + i; + + if (copy_info->src != VK_NULL_HANDLE && copy_info->dst != VK_NULL_HANDLE) + { + ProcessCmdCopyAccelerationStructuresKHR(copy_info, address_tracker); + + // issue copy command + MarkInjectedCommandsHelper mark_injected_commands_helper; + device_table_->CmdCopyAccelerationStructureKHR(command_buffer_, copy_info); + } + else + { + GFXRECON_LOG_ERROR("ProcessCopyVulkanAccelerationStructuresMetaCommand: missing handles"); + } + } + } +} + +void VulkanAddressReplacer::ProcessVulkanAccelerationStructuresWritePropertiesMetaCommand( + VkQueryType query_type, VkAccelerationStructureKHR acceleration_structure) +{ + if (init_queue_assets()) + { + // reset/submit/sync command-buffer + QueueSubmitHelper queue_submit_helper(device_table_, device_, command_buffer_, queue_, fence_); + + ProcessCmdWriteAccelerationStructuresPropertiesKHR(1, &acceleration_structure, query_type, query_pool_, 0); + + // issue vkCmdResetQueryPool and vkCmdWriteAccelerationStructuresPropertiesKHR + MarkInjectedCommandsHelper mark_injected_commands_helper; + device_table_->CmdResetQueryPool(command_buffer_, query_pool_, 0, 1); + device_table_->CmdWriteAccelerationStructuresPropertiesKHR( + command_buffer_, 1, &acceleration_structure, query_type, query_pool_, 0); + } + + VkDeviceSize compact_size = 0; + + // the above command-buffer is already synced here, retrieve result using vkGetQueryPoolResults + MarkInjectedCommandsHelper mark_injected_commands_helper; + device_table_->GetQueryPoolResults(device_, + query_pool_, + 0, + 1, + sizeof(VkDeviceSize), + &compact_size, + sizeof(VkDeviceSize), + VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); + + // apply usual post-processing of queries + ProcessGetQueryPoolResults(device_, + query_pool_, + 0, + 1, + sizeof(VkDeviceSize), + &compact_size, + sizeof(VkDeviceSize), + VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); +} + bool VulkanAddressReplacer::init_pipeline() { if (pipeline_sbt_ != VK_NULL_HANDLE) @@ -608,12 +1062,13 @@ bool VulkanAddressReplacer::init_pipeline() } auto create_pipeline = [this](VkPipelineLayout layout, const auto& spirv, VkPipeline& out_pipeline) -> VkResult { + using elem_t = typename std::decay_t::value_type; VkShaderModule compute_module = VK_NULL_HANDLE; VkShaderModuleCreateInfo shader_module_create_info = {}; shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; shader_module_create_info.pNext = VK_NULL_HANDLE; shader_module_create_info.flags = 0; - shader_module_create_info.codeSize = spirv.size(); + shader_module_create_info.codeSize = spirv.size() * sizeof(elem_t); shader_module_create_info.pCode = reinterpret_cast(spirv.data()); VkResult result = @@ -667,10 +1122,81 @@ bool VulkanAddressReplacer::init_pipeline() return true; } -bool VulkanAddressReplacer::create_buffer(size_t num_bytes, - VulkanAddressReplacer::buffer_context_t& buffer_context, - uint32_t usage_flags) +bool VulkanAddressReplacer::init_queue_assets() { + if (queue_ != VK_NULL_HANDLE) + { + return true; + }; + + VkCommandPoolCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + create_info.queueFamilyIndex = 0; + + VkResult result = device_table_->CreateCommandPool(device_, &create_info, nullptr, &command_pool_); + if (result != VK_SUCCESS) + { + GFXRECON_LOG_ERROR("VulkanAddressReplacer: internal command-pool creation failed"); + return false; + } + + VkCommandBufferAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + alloc_info.pNext = nullptr; + alloc_info.commandPool = command_pool_; + alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + alloc_info.commandBufferCount = 1; + result = device_table_->AllocateCommandBuffers(device_, &alloc_info, &command_buffer_); + if (result != VK_SUCCESS) + { + GFXRECON_LOG_ERROR("VulkanAddressReplacer: internal command-buffer creation failed"); + return false; + } + + VkFenceCreateInfo fence_create_info; + fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_create_info.pNext = nullptr; + fence_create_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; + result = device_table_->CreateFence(device_, &fence_create_info, nullptr, &fence_); + if (result != VK_SUCCESS) + { + GFXRECON_LOG_ERROR("VulkanAddressReplacer: internal fence creation failed"); + return false; + } + + VkQueryPoolCreateInfo pool_info; + pool_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + pool_info.pNext = nullptr; + pool_info.flags = 0; + pool_info.queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR; + pool_info.queryCount = 1; + pool_info.pipelineStatistics = 0; + result = device_table_->CreateQueryPool(device_, &pool_info, nullptr, &query_pool_); + if (result != VK_SUCCESS) + { + GFXRECON_LOG_ERROR("VulkanAddressReplacer: internal query-pool creation failed"); + return false; + } + + device_table_->GetDeviceQueue(device_, 0, 0, &queue_); + GFXRECON_ASSERT(queue_ != VK_NULL_HANDLE); + return queue_ != VK_NULL_HANDLE; +} + +bool VulkanAddressReplacer::create_buffer(VulkanAddressReplacer::buffer_context_t& buffer_context, + size_t num_bytes, + uint32_t usage_flags, + uint32_t min_alignment, + bool use_host_mem) +{ + GFXRECON_ASSERT(util::is_pow_2(min_alignment)); + + // 4kB min-size + constexpr uint32_t min_buffer_size = 1 << 12; + num_bytes = std::max(util::aligned_value(num_bytes, min_alignment), min_buffer_size); + // nothing to do if (num_bytes <= buffer_context.num_bytes) { @@ -700,18 +1226,20 @@ bool VulkanAddressReplacer::create_buffer(size_t VkMemoryRequirements memory_requirements; device_table_->GetBufferMemoryRequirements(device_, buffer_context.buffer, &memory_requirements); + VkMemoryPropertyFlags memory_property_flags = + use_host_mem ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT + : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + uint32_t memory_type_index = - get_memory_type_index(memory_properties_, - memory_requirements.memoryTypeBits, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT); + graphics::GetMemoryTypeIndex(memory_properties_, memory_requirements.memoryTypeBits, memory_property_flags); - if (memory_type_index == std::numeric_limits::max()) + if (memory_type_index == std::numeric_limits::max() && use_host_mem) { /* fallback to coherent */ memory_type_index = - get_memory_type_index(memory_properties_, - memory_requirements.memoryTypeBits, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + graphics::GetMemoryTypeIndex(memory_properties_, + memory_requirements.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); } GFXRECON_ASSERT(memory_type_index != std::numeric_limits::max()); @@ -734,13 +1262,12 @@ bool VulkanAddressReplacer::create_buffer(size_t return false; } - VkMemoryPropertyFlags memory_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - result = resource_allocator_->BindBufferMemory(buffer_context.buffer, + result = resource_allocator_->BindBufferMemory(buffer_context.buffer, buffer_context.device_memory, 0, buffer_context.allocator_data, buffer_context.memory_data, - &memory_flags); + &memory_property_flags); if (result != VK_SUCCESS) { return false; @@ -751,11 +1278,23 @@ bool VulkanAddressReplacer::create_buffer(size_t address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; address_info.buffer = buffer_context.buffer; buffer_context.device_address = get_device_address_fn_(device_, &address_info); + GFXRECON_ASSERT(buffer_context.device_address != 0); + + // ensure alignment for returned address + auto aligned_address = util::aligned_value(buffer_context.device_address, min_alignment); + GFXRECON_ASSERT(!min_alignment || !(aligned_address % min_alignment)); + auto offset = aligned_address - buffer_context.device_address; + buffer_context.device_address = aligned_address; - // map buffer - result = resource_allocator_->MapResourceMemoryDirect( - VK_WHOLE_SIZE, 0, &buffer_context.mapped_data, buffer_context.allocator_data); - return result == VK_SUCCESS; + if (use_host_mem) + { + // map buffer + result = resource_allocator_->MapResourceMemoryDirect( + VK_WHOLE_SIZE, 0, &buffer_context.mapped_data, buffer_context.allocator_data); + buffer_context.mapped_data = static_cast(buffer_context.mapped_data) + offset; + return result == VK_SUCCESS; + } + return true; } void VulkanAddressReplacer::barrier(VkCommandBuffer command_buffer, @@ -778,24 +1317,103 @@ void VulkanAddressReplacer::barrier(VkCommandBuffer command_buffer, command_buffer, src_stage, dst_stage, VkDependencyFlags(0), 0, nullptr, 1, &barrier, 0, nullptr); } -void swap(VulkanAddressReplacer& lhs, VulkanAddressReplacer& rhs) noexcept +bool VulkanAddressReplacer::swap_acceleration_structure_handle(VkAccelerationStructureKHR& handle) { - std::swap(lhs.device_table_, rhs.device_table_); - std::swap(lhs.memory_properties_, rhs.memory_properties_); - std::swap(lhs.capture_ray_properties_, rhs.capture_ray_properties_); - std::swap(lhs.replay_ray_properties_, rhs.replay_ray_properties_); - std::swap(lhs.valid_sbt_alignment_, rhs.valid_sbt_alignment_); - std::swap(lhs.device_, rhs.device_); - std::swap(lhs.get_device_address_fn_, rhs.get_device_address_fn_); - std::swap(lhs.resource_allocator_, rhs.resource_allocator_); - std::swap(lhs.pipeline_layout_, rhs.pipeline_layout_); - std::swap(lhs.pipeline_sbt_, rhs.pipeline_sbt_); - std::swap(lhs.pipeline_bda_, rhs.pipeline_bda_); - std::swap(lhs.pipeline_context_sbt_, rhs.pipeline_context_sbt_); - std::swap(lhs.pipeline_context_bda_, rhs.pipeline_context_bda_); - std::swap(lhs.hashmap_sbt_, rhs.hashmap_sbt_); - std::swap(lhs.hashmap_bda_, rhs.hashmap_bda_); - std::swap(lhs.shadow_sbt_map_, rhs.shadow_sbt_map_); + if (handle != VK_NULL_HANDLE) + { + auto shadow_as_it = shadow_as_map_.find(handle); + if (shadow_as_it != shadow_as_map_.end()) + { + handle = shadow_as_it->second.handle; + return true; + } + } + return false; +} + +void VulkanAddressReplacer::DestroyShadowResources(VkAccelerationStructureKHR handle) +{ + if (handle != VK_NULL_HANDLE) + { + auto remove_as_it = shadow_as_map_.find(handle); + + if (remove_as_it != shadow_as_map_.end()) + { + MarkInjectedCommandsHelper mark_injected_commands_helper; + shadow_as_map_.erase(remove_as_it); + } + } +} + +void VulkanAddressReplacer::DestroyShadowResources(VkCommandBuffer handle) +{ + if (handle != VK_NULL_HANDLE) + { + auto remove_context_it = build_as_context_map_.find(handle); + + if (remove_context_it != build_as_context_map_.end()) + { + MarkInjectedCommandsHelper mark_injected_commands_helper; + build_as_context_map_.erase(remove_context_it); + } + + auto shadow_sbt_it = shadow_sbt_map_.find(handle); + + if (shadow_sbt_it != shadow_sbt_map_.end()) + { + MarkInjectedCommandsHelper mark_injected_commands_helper; + shadow_sbt_map_.erase(shadow_sbt_it); + } + + auto pipeline_sbt_it = pipeline_sbt_context_map_.find(handle); + + if (pipeline_sbt_it != pipeline_sbt_context_map_.end()) + { + MarkInjectedCommandsHelper mark_injected_commands_helper; + pipeline_sbt_context_map_.erase(pipeline_sbt_it); + } + } +} + +bool VulkanAddressReplacer::create_acceleration_asset(VulkanAddressReplacer::acceleration_structure_asset_t& as_asset, + VkAccelerationStructureTypeKHR type, + size_t num_buffer_bytes, + size_t num_scratch_bytes) +{ + as_asset.device = device_; + as_asset.destroy_fn = device_table_->DestroyAccelerationStructureKHR; + + // create a replacement acceleration-structure with proper sized buffer + bool success = create_buffer( + as_asset.storage, num_buffer_bytes, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, 0, false); + + if (!success) + { + GFXRECON_LOG_ERROR("VulkanAddressReplacer::ProcessCmdBuildAccelerationStructuresKHR: " + "shadow-buffer creation failed"); + return false; + } + + VkAccelerationStructureCreateInfoKHR as_create_info = {}; + as_create_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + as_create_info.buffer = as_asset.storage.buffer; + as_create_info.size = num_buffer_bytes; + as_create_info.type = type; + + VkResult res = device_table_->CreateAccelerationStructureKHR(device_, &as_create_info, nullptr, &as_asset.handle); + + if (res != VK_SUCCESS || as_asset.handle == VK_NULL_HANDLE) + { + GFXRECON_LOG_ERROR("ProcessCmdBuildAccelerationStructuresKHR: shadow " + "acceleration-structure creation failed"); + return false; + } + VkAccelerationStructureDeviceAddressInfoKHR acceleration_address_info = {}; + acceleration_address_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; + acceleration_address_info.accelerationStructure = as_asset.handle; + as_asset.address = device_table_->GetAccelerationStructureDeviceAddressKHR(device_, &acceleration_address_info); + GFXRECON_ASSERT(as_asset.address != 0); + return true; } GFXRECON_END_NAMESPACE(decode) diff --git a/framework/decode/vulkan_address_replacer.h b/framework/decode/vulkan_address_replacer.h index eca38e0476..60b584a858 100644 --- a/framework/decode/vulkan_address_replacer.h +++ b/framework/decode/vulkan_address_replacer.h @@ -45,18 +45,26 @@ class VulkanAddressReplacer VulkanAddressReplacer(const VulkanDeviceInfo* device_info, const encode::VulkanDeviceTable* device_table, + const encode::VulkanInstanceTable* instance_table, const decode::CommonObjectInfoTable& object_table); //! prevent copying VulkanAddressReplacer(const VulkanAddressReplacer&) = delete; //! allow moving - VulkanAddressReplacer(VulkanAddressReplacer&& other) noexcept; + VulkanAddressReplacer(VulkanAddressReplacer&& other) noexcept = default; ~VulkanAddressReplacer(); /** - * @brief ProcessCmdTraceRays will check and potentially correct input-parameters to 'VkCmdTraceRays', + * @brief Set raytracing-related properties + * + * @param physical_device_info a physical-device info struct. + */ + void SetRaytracingProperties(const decode::VulkanPhysicalDeviceInfo* physical_device_info); + + /** + * @brief ProcessCmdTraceRays will check and potentially correct input-parameters to 'vkCmdTraceRays', * like buffer-device-addresses and shader-group-handles. * * Depending on capture- and replay-device-properties one of the following strategies will be used: @@ -89,7 +97,18 @@ class VulkanAddressReplacer /** * @brief ProcessCmdBuildAccelerationStructuresKHR will check - * and potentially correct input-parameters to 'VkCmdBuildAccelerationStructuresKHR' + * and potentially correct input-parameters to 'vkCmdBuildAccelerationStructuresKHR' + * + * Depending on capture- and replay-device-properties this includes the following: + * + * if replaying on same device/driver using the default-allocator (no -m rebind): + * - happy day, nothing to do! + * + * if replaying on a different device/driver and/or using the rebind-allocator (via -m rebind): + * - remap buffer-device-addresses for triangle-, aabb- and instance-geometries referenced in `build_geometry_infos` + * - check buffer-sizes for acceleration-structures and scratch-buffers + * - if necessary, create shadow acceleration-structures and -buffers, adjust references + * - apply in-place correction of acceleration-structure device-addresses referenced by top-level builds * * @param command_buffer_info a provided VulkanCommandBufferInfo * @param info_count number of elements in 'build_geometry_infos' @@ -103,7 +122,123 @@ class VulkanAddressReplacer VkAccelerationStructureBuildRangeInfoKHR** build_range_infos, const decode::VulkanDeviceAddressTracker& address_tracker); - friend void swap(VulkanAddressReplacer& lhs, VulkanAddressReplacer& rhs) noexcept; + /** + * @brief ProcessCmdCopyAccelerationStructuresKHR will check + * and potentially correct input-parameters to 'vkCmdCopyAccelerationStructuresKHR' + * + * @param info a provided VkCopyAccelerationStructureInfoKHR* + * @param address_tracker const reference to a VulkanDeviceAddressTracker, used for mapping device-addresses + */ + void ProcessCmdCopyAccelerationStructuresKHR(VkCopyAccelerationStructureInfoKHR* info, + const decode::VulkanDeviceAddressTracker& address_tracker); + + /** + * @brief ProcessCmdWriteAccelerationStructuresPropertiesKHR will check + * and potentially correct input-parameters to 'vkCmdWriteAccelerationStructuresPropertiesKHR' + * + * @param count element count in acceleration_structures + * @param acceleration_structures provided array of VkAccelerationStructureKHR-handles + * @param query_type the query's type + * @param pool provided VkQuerypool handle + * @param first_query index of first query + */ + void ProcessCmdWriteAccelerationStructuresPropertiesKHR(uint32_t count, + VkAccelerationStructureKHR* acceleration_structures, + VkQueryType query_type, + VkQueryPool pool, + uint32_t first_query); + + /** + * @brief ProcessUpdateDescriptorSets will check + * and potentially correct input-parameters to 'vkUpdateDescriptorSets' + * + * @param descriptor_write_count element count in descriptor_writes + * @param descriptor_writes provided array of VkWriteDescriptorSet + * @param descriptor_copy_count element count in descriptor_copies + * @param descriptor_copies provided array of VkCopyDescriptorSet + */ + void ProcessUpdateDescriptorSets(uint32_t descriptor_write_count, + VkWriteDescriptorSet* descriptor_writes, + uint32_t descriptor_copy_count, + VkCopyDescriptorSet* descriptor_copies); + + /** + * @brief ProcessGetQueryPoolResults will check for running queries and attempt to extract information + * about acceleration-structure compactions-sizes. + * + * Should be run after vkGetQueryPoolResults has returned. + * + * @param device a VkDevice handle + * @param query_pool a VkQueryPool handle + * @param firstQuery index for first query + * @param queryCount number of queries + * @param dataSize datasize in bytes + * @param pData provided data-pointer + * @param stride provided stride in bytes + * @param flags query result-flags + */ + void ProcessGetQueryPoolResults(VkDevice device, + VkQueryPool query_pool, + uint32_t firstQuery, + uint32_t queryCount, + size_t dataSize, + void* pData, + VkDeviceSize stride, + VkQueryResultFlags flags); + + /** + * @brief Process information contained in a metadata-block in order to build acceleration-structures. + * + * Will use an internal command-buffer, submit work to a VkQueue and perform host-synchronization. + * + * @param info_count element count in 'geometry_infos' + * @param geometry_infos provided array of VkAccelerationStructureBuildGeometryInfoKHR + * @param range_infos provided array of pointers to VkAccelerationStructureBuildRangeInfoKHR + * @param address_tracker const reference to a VulkanDeviceAddressTracker + */ + void + ProcessBuildVulkanAccelerationStructuresMetaCommand(uint32_t info_count, + VkAccelerationStructureBuildGeometryInfoKHR* geometry_infos, + VkAccelerationStructureBuildRangeInfoKHR** range_infos, + const decode::VulkanDeviceAddressTracker& address_tracker); + + /** + * @brief Process information contained in a metadata-block in order to copy acceleration-structures. + * + * @param info_count element count in 'copy_infos' + * @param copy_infos provided array of VkCopyAccelerationStructureInfoKHR + * @param address_tracker const reference to a VulkanDeviceAddressTracker + */ + void ProcessCopyVulkanAccelerationStructuresMetaCommand(uint32_t info_count, + VkCopyAccelerationStructureInfoKHR* copy_infos, + const decode::VulkanDeviceAddressTracker& address_tracker); + /** + * @brief Process information contained in a metadata-block in order to issue a query on internal an query-pool. + * + * Will use an internal command-buffer, submit work to a VkQueue and perform host-synchronization. + * + * @param query_type type of query + * @param acceleration_structure provided acceleration-structure handle + */ + void + ProcessVulkanAccelerationStructuresWritePropertiesMetaCommand(VkQueryType query_type, + VkAccelerationStructureKHR acceleration_structure); + + /** + * @brief DestroyShadowResources should be called upon destruction of provided VkAccelerationStructureKHR handle, + * allowing this class to free potential resources associated with it. + * + * @param handle a provided VkAccelerationStructureKHR handle + */ + void DestroyShadowResources(VkAccelerationStructureKHR handle); + + /** + * @brief DestroyShadowResources should be called upon destruction of provided VkCommandBuffer handle, + * allowing this class to free potential resources associated with it. + * + * @param handle a provided VkCommandBuffer handle + */ + void DestroyShadowResources(VkCommandBuffer handle); private: struct buffer_context_t @@ -126,9 +261,32 @@ class VulkanAddressReplacer buffer_context_t hashmap_storage = {}; }; + struct acceleration_structure_asset_t + { + VkAccelerationStructureKHR handle = VK_NULL_HANDLE; + VkDeviceAddress address = 0; + buffer_context_t storage = {}; + buffer_context_t scratch = {}; + + VkDevice device = VK_NULL_HANDLE; + PFN_vkDestroyAccelerationStructureKHR destroy_fn = nullptr; + ~acceleration_structure_asset_t(); + }; + [[nodiscard]] bool init_pipeline(); - [[nodiscard]] bool create_buffer(size_t num_bytes, buffer_context_t& buffer_context, uint32_t usage_flags = 0); + [[nodiscard]] bool init_queue_assets(); + + [[nodiscard]] bool create_buffer(buffer_context_t& buffer_context, + size_t num_bytes, + uint32_t usage_flags = 0, + uint32_t min_alignment = 0, + bool use_host_mem = true); + + [[nodiscard]] bool create_acceleration_asset(acceleration_structure_asset_t& as_asset, + VkAccelerationStructureTypeKHR type, + size_t num_buffer_bytes, + size_t num_scratch_bytes); void barrier(VkCommandBuffer command_buffer, VkBuffer buffer, @@ -137,14 +295,17 @@ class VulkanAddressReplacer VkPipelineStageFlags dst_stage, VkAccessFlags dst_access); - const encode::VulkanDeviceTable* device_table_ = nullptr; - VkPhysicalDeviceMemoryProperties memory_properties_ = {}; - VkPhysicalDeviceRayTracingPipelinePropertiesKHR capture_ray_properties_{}, replay_ray_properties_{}; - bool valid_sbt_alignment_ = true; + bool swap_acceleration_structure_handle(VkAccelerationStructureKHR& handle); + + const encode::VulkanDeviceTable* device_table_ = nullptr; + VkPhysicalDeviceMemoryProperties memory_properties_ = {}; + std::optional capture_ray_properties_{}, replay_ray_properties_{}; + std::optional replay_acceleration_structure_properties_{}; + bool valid_sbt_alignment_ = true; - VkDevice device_ = VK_NULL_HANDLE; - PFN_vkGetBufferDeviceAddress get_device_address_fn_ = nullptr; - decode::VulkanResourceAllocator* resource_allocator_ = nullptr; + const decode::VulkanPhysicalDeviceInfo* physical_device_info_ = nullptr; + VkDevice device_ = VK_NULL_HANDLE; + decode::VulkanResourceAllocator* resource_allocator_ = nullptr; // common layout used for all pipelines VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE; @@ -155,12 +316,33 @@ class VulkanAddressReplacer // pipeline dealing with buffer-device-addresses (BDA), replacing addresses VkPipeline pipeline_bda_ = VK_NULL_HANDLE; - pipeline_context_t pipeline_context_sbt_; - pipeline_context_t pipeline_context_bda_; + // required assets for submitting meta-commands + VkCommandPool command_pool_ = VK_NULL_HANDLE; + VkCommandBuffer command_buffer_ = VK_NULL_HANDLE; + VkFence fence_ = VK_NULL_HANDLE; + VkQueue queue_ = VK_NULL_HANDLE; + VkQueryPool query_pool_ = VK_NULL_HANDLE; util::linear_hashmap hashmap_sbt_; util::linear_hashmap hashmap_bda_; std::unordered_map shadow_sbt_map_; + + // pipeline-contexts dealing with shader-binding-tables, per command-buffer + std::unordered_map pipeline_sbt_context_map_; + + // resources related to acceleration-structures + std::unordered_map shadow_as_map_; + + // pipeline-contexts dealing with acceleration-structure builds, per command-buffer + std::unordered_map build_as_context_map_; + + // currently running compaction queries. pool -> AS -> query-pool-index + std::unordered_map> as_compact_queries_; + std::unordered_map as_compact_sizes_; + + // required function pointers + PFN_vkGetBufferDeviceAddress get_device_address_fn_ = nullptr; + PFN_vkGetPhysicalDeviceProperties2 get_physical_device_properties_fn_ = nullptr; }; GFXRECON_END_NAMESPACE(decode) GFXRECON_END_NAMESPACE(gfxrecon) diff --git a/framework/decode/vulkan_address_replacer_shaders.h b/framework/decode/vulkan_address_replacer_shaders.h index 5c6771c226..f90b5aec46 100644 --- a/framework/decode/vulkan_address_replacer_shaders.h +++ b/framework/decode/vulkan_address_replacer_shaders.h @@ -287,799 +287,467 @@ void main() } #endif // g_replacer_bda_comp -static const std::array g_replacer_sbt_comp = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x05, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0xb6, 0x14, 0x00, 0x00, 0x11, 0x00, - 0x02, 0x00, 0xe3, 0x14, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, - 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0xe4, 0x14, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, - 0x6e, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00, 0x04, 0x00, 0x07, 0x00, 0x47, 0x4c, 0x5f, 0x45, - 0x58, 0x54, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x45, 0x58, 0x54, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, - 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47, - 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, - 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, - 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, - 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, - 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x6d, 0x75, 0x72, 0x6d, - 0x75, 0x72, 0x5f, 0x33, 0x32, 0x5f, 0x73, 0x63, 0x72, 0x61, 0x6d, 0x62, 0x6c, 0x65, 0x28, 0x75, 0x31, 0x3b, 0x00, - 0x00, 0x05, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x11, 0x00, - 0x00, 0x00, 0x6d, 0x75, 0x72, 0x6d, 0x75, 0x72, 0x33, 0x5f, 0x33, 0x32, 0x28, 0x75, 0x31, 0x5b, 0x38, 0x5d, 0x3b, - 0x75, 0x31, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x79, 0x00, - 0x05, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x73, 0x65, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, - 0x00, 0x13, 0x00, 0x00, 0x00, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x68, - 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x65, 0x71, 0x75, 0x61, 0x6c, 0x28, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, - 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x74, 0x2d, 0x75, 0x31, 0x5b, - 0x38, 0x5d, 0x31, 0x3b, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x74, 0x2d, 0x75, 0x31, 0x5b, 0x38, 0x5d, - 0x31, 0x3b, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x6c, 0x68, 0x73, 0x00, 0x05, 0x00, 0x03, - 0x00, 0x17, 0x00, 0x00, 0x00, 0x72, 0x68, 0x73, 0x00, 0x05, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x69, 0x73, - 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x28, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, - 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x74, 0x2d, 0x75, 0x31, 0x5b, - 0x38, 0x5d, 0x31, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, - 0x00, 0x05, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x68, 0x61, 0x73, 0x68, 0x28, 0x73, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x68, 0x61, 0x6e, 0x64, - 0x6c, 0x65, 0x5f, 0x74, 0x2d, 0x75, 0x31, 0x5b, 0x38, 0x5d, 0x31, 0x3b, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, - 0x1f, 0x00, 0x00, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x00, 0x00, 0x00, - 0x00, 0x05, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, 0x68, 0x61, 0x73, 0x68, 0x6d, 0x61, 0x70, 0x5f, 0x74, 0x00, - 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x74, 0x6f, 0x72, 0x61, - 0x67, 0x65, 0x00, 0x06, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x63, 0x61, 0x70, - 0x61, 0x63, 0x69, 0x74, 0x79, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x25, 0x00, 0x00, 0x00, 0x73, 0x68, - 0x61, 0x64, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x74, - 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x26, 0x00, 0x00, 0x00, 0x68, 0x61, 0x73, 0x68, 0x6d, 0x61, 0x70, - 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x6b, 0x65, 0x79, 0x00, 0x06, 0x00, 0x05, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x28, 0x00, 0x00, 0x00, 0x48, 0x61, 0x73, 0x68, - 0x4d, 0x61, 0x70, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x05, 0x00, 0x13, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x67, 0x65, - 0x74, 0x28, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2d, 0x68, 0x61, 0x73, 0x68, 0x6d, 0x61, 0x70, 0x5f, 0x74, 0x2d, - 0x31, 0x2d, 0x75, 0x31, 0x2d, 0x75, 0x31, 0x31, 0x3b, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2d, 0x73, 0x68, 0x61, - 0x64, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x74, 0x2d, - 0x75, 0x31, 0x5b, 0x38, 0x5d, 0x31, 0x3b, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x68, 0x61, - 0x73, 0x68, 0x6d, 0x61, 0x70, 0x00, 0x05, 0x00, 0x03, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x79, 0x00, 0x05, - 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00, - 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, - 0x00, 0x05, 0x00, 0x05, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x61, 0x62, 0x6c, 0x65, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x86, - 0x00, 0x00, 0x00, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, - 0x8a, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, - 0x00, 0x9d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xac, 0x00, - 0x00, 0x00, 0x69, 0x64, 0x78, 0x00, 0x05, 0x00, 0x06, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x68, 0x61, 0x73, 0x68, 0x6d, - 0x61, 0x70, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0xb7, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x79, 0x00, 0x06, 0x00, 0x05, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x69, 0x74, - 0x65, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x67, 0x69, 0x64, 0x00, 0x05, - 0x00, 0x08, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, - 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0xe1, 0x00, 0x00, - 0x00, 0x68, 0x61, 0x73, 0x68, 0x6d, 0x61, 0x70, 0x5f, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0xe1, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x00, 0x06, 0x00, 0x05, 0x00, 0xe1, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, - 0xe1, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x00, 0x00, 0x00, - 0x00, 0x05, 0x00, 0x07, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x72, 0x5f, 0x70, - 0x61, 0x72, 0x61, 0x6d, 0x73, 0x5f, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x68, 0x61, 0x6e, - 0x64, 0x6c, 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x00, 0x06, 0x00, 0x07, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, - 0x07, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x68, 0x61, - 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x6e, 0x75, 0x6d, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x00, 0x05, 0x00, 0x06, 0x00, 0xe6, 0x00, 0x00, - 0x00, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, - 0x04, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0xe8, - 0x00, 0x00, 0x00, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x68, 0x61, 0x6e, - 0x64, 0x6c, 0x65, 0x5f, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x74, 0x72, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0xe9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x70, 0x63, 0x00, 0x00, 0x06, 0x00, 0x05, - 0x00, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x00, 0x00, 0x05, 0x00, - 0x03, 0x00, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x05, 0x01, 0x00, 0x00, 0x61, 0x72, 0x67, 0x00, - 0x05, 0x00, 0x03, 0x00, 0x08, 0x01, 0x00, 0x00, 0x61, 0x72, 0x67, 0x00, 0x47, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x26, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, - 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, - 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, - 0x05, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x48, - 0x00, 0x05, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x05, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x48, 0x00, 0x05, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, - 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x47, 0x00, 0x03, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0xe6, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xe7, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xea, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x03, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xeb, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x05, 0x01, - 0x00, 0x00, 0xec, 0x14, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x19, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x19, - 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x00, - 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x21, 0x00, 0x05, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x0d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, - 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x13, 0x00, 0x00, 0x00, 0x27, 0x00, 0x03, 0x00, 0x22, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00, 0x00, 0x1e, 0x00, - 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c, - 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, - 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, - 0x00, 0x25, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x03, 0x00, 0x27, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x1e, 0x00, - 0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0xe5, - 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x21, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x23, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, - 0x00, 0x51, 0x2d, 0x9e, 0xcc, 0x15, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x2b, - 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x93, 0x35, 0x87, 0x1b, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x0d, - 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x64, 0x6b, 0x54, 0xe6, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, - 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x62, - 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x6b, 0xca, 0xeb, - 0x85, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x35, 0xae, 0xb2, 0xc2, 0x2b, 0x00, - 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x85, - 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x90, 0x00, 0x00, 0x00, 0x29, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x0b, - 0x00, 0x0d, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x42, 0x00, - 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x42, - 0x00, 0x00, 0x00, 0x2c, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, - 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, - 0x00, 0x06, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, 0xb7, 0x00, - 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0xda, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x04, 0x00, 0xdb, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0x3b, 0x00, - 0x04, 0x00, 0xdb, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xdd, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00, 0xe1, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x03, 0x00, 0xe2, 0x00, 0x00, - 0x00, 0xe5, 0x14, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, 0xe3, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0xe2, 0x00, - 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x03, 0x00, 0xe4, 0x00, 0x00, 0x00, 0xe5, - 0x14, 0x00, 0x00, 0x1d, 0x00, 0x03, 0x00, 0xe5, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, - 0xe6, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0xe8, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x1e, 0x00, - 0x03, 0x00, 0xe9, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xe4, 0x00, 0x00, 0x00, 0xe5, - 0x14, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x03, 0x00, 0xea, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0xe2, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, - 0x00, 0xeb, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xec, 0x00, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xec, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0xef, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, - 0x00, 0xf7, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xfa, 0x00, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xe5, - 0x14, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x01, 0x01, 0x00, 0x00, 0xe5, 0x14, 0x00, 0x00, - 0xe8, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x04, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, - 0x00, 0x2c, 0x00, 0x06, 0x00, 0xda, 0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0xb3, 0x00, - 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, - 0x07, 0x00, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x85, 0x00, 0x00, - 0x00, 0xf6, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x04, 0x01, 0x00, 0x00, 0x05, 0x01, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x85, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xdd, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, - 0x42, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, - 0x00, 0x3e, 0x00, 0x03, 0x00, 0xd9, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, - 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xef, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xae, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, - 0x00, 0xf2, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xf4, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xf2, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 0xf4, - 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xf3, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0xf8, 0x00, 0x02, 0x00, - 0xf4, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xf7, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, - 0x00, 0x83, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0xe1, 0x00, 0x00, 0x00, 0xf9, 0x00, - 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xfa, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0xed, - 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0xe2, 0x00, 0x00, 0x00, - 0xfc, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, - 0x00, 0xd9, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xfc, 0x00, - 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x06, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x06, - 0x00, 0xe8, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x90, 0x01, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x3e, - 0x00, 0x03, 0x00, 0x05, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, - 0x07, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x90, 0x01, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, - 0x00, 0x03, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x08, 0x01, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x3d, 0x00, - 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x39, 0x00, 0x06, 0x00, 0x13, - 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, - 0x3e, 0x00, 0x03, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, - 0x00, 0x0c, 0x01, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0d, 0x01, - 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0xa8, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0e, - 0x01, 0x00, 0x00, 0x0d, 0x01, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfa, 0x00, 0x04, 0x00, 0x0e, 0x01, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x02, - 0x00, 0x0f, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0xed, 0x00, - 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x12, - 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, - 0xd9, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x12, 0x01, 0x00, - 0x00, 0x83, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x06, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x15, 0x01, - 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x13, - 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x01, 0x01, 0x00, 0x00, - 0x17, 0x01, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x90, 0x01, 0x04, 0x00, 0xe8, 0x00, 0x00, - 0x00, 0x18, 0x01, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x05, 0x00, 0x17, 0x01, 0x00, 0x00, 0x18, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x10, 0x01, 0x00, 0x00, 0xf8, - 0x00, 0x02, 0x00, 0x10, 0x01, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00, - 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x31, 0x00, - 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x00, 0xc2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, - 0x00, 0x37, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3d, 0x00, - 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x37, - 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x3f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, - 0x00, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, - 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x43, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x43, 0x00, 0x00, 0x00, 0xf6, - 0x00, 0x04, 0x00, 0x45, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, - 0x47, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x47, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x48, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x49, 0x00, - 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x49, 0x00, 0x00, 0x00, 0x44, - 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x4d, 0x00, 0x00, - 0x00, 0x0f, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x4d, 0x00, - 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x4e, - 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x05, 0x00, 0x06, 0x00, - 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3f, - 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, - 0x3f, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, - 0x00, 0x54, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x3f, 0x00, - 0x00, 0x00, 0xc2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x57, - 0x00, 0x00, 0x00, 0xc5, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, - 0x58, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, - 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, - 0x3f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x46, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, - 0x00, 0x46, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x41, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x60, - 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, - 0x43, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x45, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x63, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x64, 0x00, - 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x64, - 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, - 0xc2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, - 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc6, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x3e, - 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x6b, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, - 0x00, 0x6b, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x6c, 0x00, - 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc2, - 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, - 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x05, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x3e, 0x00, - 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x72, - 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, - 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc2, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x3d, - 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x05, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, - 0x00, 0x3f, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x78, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, - 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, - 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x85, 0x00, 0x00, 0x00, 0x86, - 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x85, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, - 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x7e, 0x00, - 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00, 0xf8, - 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, - 0x7b, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x0c, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x82, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x7e, 0x00, - 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x84, - 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x86, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, - 0x00, 0x84, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x87, 0x00, - 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x3e, - 0x00, 0x03, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x8b, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0xab, 0x00, 0x05, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x8f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, - 0x8f, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x8e, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x90, 0x00, 0x00, - 0x00, 0xf8, 0x00, 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xf8, 0x00, - 0x02, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x7b, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, - 0x60, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, - 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x94, 0x00, - 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, - 0xf8, 0x00, 0x02, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x39, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, - 0x00, 0x18, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x99, 0x00, - 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, - 0xf8, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x1f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x39, - 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, - 0x9d, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, - 0x00, 0x13, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x37, 0x00, - 0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, 0x2b, - 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, - 0xac, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x1c, 0x00, - 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0xa1, - 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, - 0xa2, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xa3, 0x00, 0x00, - 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0xaa, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x42, - 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x00, 0x00, - 0xf5, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, - 0x00, 0xa7, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xf8, - 0x00, 0x02, 0x00, 0xa9, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x98, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, - 0xaa, 0x00, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xac, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0xf9, 0x00, - 0x02, 0x00, 0xae, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xae, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xaf, 0x00, 0x00, 0x00, - 0xf8, 0x00, 0x02, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, - 0x00, 0x2a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb4, 0x00, - 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb5, - 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, - 0xb5, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xac, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, - 0x00, 0x51, 0x00, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x41, - 0x00, 0x06, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, - 0xbb, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x06, 0x00, 0x26, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x90, 0x01, 0x04, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xbf, 0x00, - 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xb9, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x41, - 0x00, 0x05, 0x00, 0x85, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, - 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x39, 0x00, 0x05, - 0x00, 0x14, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xf7, 0x00, - 0x03, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc3, - 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, - 0x98, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x85, 0x00, 0x00, - 0x00, 0xc7, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, - 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x39, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0xc9, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, - 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xc9, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, - 0x00, 0xcb, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xca, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x85, 0x00, - 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x13, - 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, - 0xce, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, - 0x00, 0xcf, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xf8, 0x00, - 0x02, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xc9, - 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, - 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, - 0x00, 0xd2, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x85, 0x00, - 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x13, - 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x00, 0x00, - 0xf8, 0x00, 0x02, 0x00, 0xd2, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, - 0x00, 0xc4, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb1, 0x00, - 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x03, 0x00, 0xac, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xae, 0x00, 0x00, - 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +static const std::array g_replacer_sbt_comp = { + 0x07230203, 0x00010300, 0x0008000b, 0x00000427, 0x00000000, 0x00020011, 0x00000001, 0x00020011, 0x000014b6, + 0x00020011, 0x000014e3, 0x0008000a, 0x5f565053, 0x5f545845, 0x63736564, 0x74706972, 0x695f726f, 0x7865646e, + 0x00676e69, 0x0009000a, 0x5f565053, 0x5f52484b, 0x73796870, 0x6c616369, 0x6f74735f, 0x65676172, 0x6675625f, + 0x00726566, 0x0006000b, 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x000014e4, + 0x00000001, 0x0006000f, 0x00000005, 0x00000004, 0x6e69616d, 0x00000000, 0x00000108, 0x00060010, 0x00000004, + 0x00000011, 0x00000020, 0x00000001, 0x00000001, 0x00030003, 0x00000002, 0x000001cc, 0x00070004, 0x455f4c47, + 0x625f5458, 0x65666675, 0x65725f72, 0x65726566, 0x0065636e, 0x00080004, 0x455f4c47, 0x625f5458, 0x65666675, + 0x65725f72, 0x65726566, 0x3265636e, 0x00000000, 0x000a0004, 0x475f4c47, 0x4c474f4f, 0x70635f45, 0x74735f70, + 0x5f656c79, 0x656e696c, 0x7269645f, 0x69746365, 0x00006576, 0x00080004, 0x475f4c47, 0x4c474f4f, 0x6e695f45, + 0x64756c63, 0x69645f65, 0x74636572, 0x00657669, 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00080005, + 0x00000025, 0x64616873, 0x675f7265, 0x70756f72, 0x6e61685f, 0x5f656c64, 0x00000074, 0x00050006, 0x00000025, + 0x00000000, 0x61746164, 0x00000000, 0x00060005, 0x00000026, 0x68736168, 0x5f70616d, 0x6d657469, 0x0000745f, + 0x00040006, 0x00000026, 0x00000000, 0x0079656b, 0x00050006, 0x00000026, 0x00000001, 0x756c6176, 0x00000065, + 0x00060005, 0x00000028, 0x68736148, 0x5370614d, 0x61726f74, 0x00006567, 0x00040006, 0x00000028, 0x00000000, + 0x00000076, 0x00080005, 0x00000108, 0x475f6c67, 0x61626f6c, 0x766e496c, 0x7461636f, 0x496e6f69, 0x00000044, + 0x00050005, 0x0000010d, 0x68736168, 0x5f70616d, 0x00000074, 0x00050006, 0x0000010d, 0x00000000, 0x726f7473, + 0x00656761, 0x00050006, 0x0000010d, 0x00000001, 0x657a6973, 0x00000000, 0x00060006, 0x0000010d, 0x00000002, + 0x61706163, 0x79746963, 0x00000000, 0x00070005, 0x0000010f, 0x6c706572, 0x72656361, 0x7261705f, 0x5f736d61, + 0x00000074, 0x00090006, 0x0000010f, 0x00000000, 0x64616873, 0x675f7265, 0x70756f72, 0x6e61685f, 0x5f656c64, + 0x0070616d, 0x00070006, 0x0000010f, 0x00000001, 0x75706e69, 0x61685f74, 0x656c646e, 0x00000073, 0x00070006, + 0x0000010f, 0x00000002, 0x7074756f, 0x685f7475, 0x6c646e61, 0x00007365, 0x00060006, 0x0000010f, 0x00000003, + 0x5f6d756e, 0x646e6168, 0x0073656c, 0x00060005, 0x00000112, 0x72646441, 0x41737365, 0x79617272, 0x00000000, + 0x00040006, 0x00000112, 0x00000000, 0x00000076, 0x00080005, 0x00000114, 0x64616873, 0x675f7265, 0x70756f72, + 0x6e61685f, 0x5f656c64, 0x00000074, 0x00050006, 0x00000114, 0x00000000, 0x61746164, 0x00000000, 0x00060005, + 0x00000115, 0x756f7247, 0x6e614870, 0x50656c64, 0x00007274, 0x00070006, 0x00000115, 0x00000000, 0x756f7267, + 0x61685f70, 0x656c646e, 0x00000000, 0x00030005, 0x00000117, 0x00006370, 0x00050006, 0x00000117, 0x00000000, + 0x61726170, 0x0000736d, 0x00030005, 0x00000119, 0x00000000, 0x00040047, 0x00000024, 0x00000006, 0x00000004, + 0x00050048, 0x00000025, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x00000026, 0x00000000, 0x00000023, + 0x00000000, 0x00050048, 0x00000026, 0x00000001, 0x00000023, 0x00000020, 0x00040047, 0x00000027, 0x00000006, + 0x00000040, 0x00030047, 0x00000028, 0x00000002, 0x00040048, 0x00000028, 0x00000000, 0x00000018, 0x00050048, + 0x00000028, 0x00000000, 0x00000023, 0x00000000, 0x00040047, 0x00000108, 0x0000000b, 0x0000001c, 0x00050048, + 0x0000010d, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x0000010d, 0x00000001, 0x00000023, 0x00000008, + 0x00050048, 0x0000010d, 0x00000002, 0x00000023, 0x0000000c, 0x00050048, 0x0000010f, 0x00000000, 0x00000023, + 0x00000000, 0x00050048, 0x0000010f, 0x00000001, 0x00000023, 0x00000010, 0x00050048, 0x0000010f, 0x00000002, + 0x00000023, 0x00000018, 0x00050048, 0x0000010f, 0x00000003, 0x00000023, 0x00000020, 0x00040047, 0x00000111, + 0x00000006, 0x00000008, 0x00030047, 0x00000112, 0x00000002, 0x00040048, 0x00000112, 0x00000000, 0x00000018, + 0x00050048, 0x00000112, 0x00000000, 0x00000023, 0x00000000, 0x00040047, 0x00000113, 0x00000006, 0x00000004, + 0x00050048, 0x00000114, 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x00000115, 0x00000002, 0x00050048, + 0x00000115, 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x00000117, 0x00000002, 0x00050048, 0x00000117, + 0x00000000, 0x00000023, 0x00000000, 0x00040047, 0x0000016e, 0x0000000b, 0x00000019, 0x00020013, 0x00000002, + 0x00030021, 0x00000003, 0x00000002, 0x00040015, 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, + 0x00000007, 0x00000006, 0x0004002b, 0x00000006, 0x0000000c, 0x00000008, 0x0004001c, 0x0000000d, 0x00000006, + 0x0000000c, 0x00020014, 0x00000014, 0x00030027, 0x00000022, 0x000014e5, 0x0004001c, 0x00000024, 0x00000006, + 0x0000000c, 0x0003001e, 0x00000025, 0x00000024, 0x0004001e, 0x00000026, 0x00000025, 0x00000025, 0x0003001d, + 0x00000027, 0x00000026, 0x0003001e, 0x00000028, 0x00000027, 0x00040020, 0x00000022, 0x000014e5, 0x00000028, + 0x0004002b, 0x00000006, 0x0000002e, 0xcc9e2d51, 0x00040015, 0x00000032, 0x00000020, 0x00000001, 0x0004002b, + 0x00000032, 0x00000033, 0x0000000f, 0x0004002b, 0x00000032, 0x00000036, 0x00000011, 0x0004002b, 0x00000006, + 0x00000039, 0x1b873593, 0x0004002b, 0x00000006, 0x00000042, 0x00000000, 0x00040020, 0x0000004c, 0x00000007, + 0x0000000d, 0x0004002b, 0x00000032, 0x00000054, 0x0000000d, 0x0004002b, 0x00000032, 0x00000057, 0x00000013, + 0x0004002b, 0x00000006, 0x0000005b, 0x00000005, 0x0004002b, 0x00000006, 0x0000005d, 0xe6546b64, 0x0004002b, + 0x00000032, 0x00000060, 0x00000001, 0x0004002b, 0x00000006, 0x00000062, 0x00000020, 0x0004002b, 0x00000032, + 0x00000066, 0x00000010, 0x0004002b, 0x00000006, 0x0000006a, 0x85ebca6b, 0x0004002b, 0x00000006, 0x00000071, + 0xc2b2ae35, 0x0004002b, 0x00000032, 0x00000083, 0x00000000, 0x0003002a, 0x00000014, 0x00000090, 0x00030029, + 0x00000014, 0x00000094, 0x000b002c, 0x0000000d, 0x00000097, 0x00000042, 0x00000042, 0x00000042, 0x00000042, + 0x00000042, 0x00000042, 0x00000042, 0x00000042, 0x0004002b, 0x00000032, 0x000000a5, 0x00000002, 0x0004002b, + 0x00000006, 0x000000b3, 0x00000001, 0x00040020, 0x000000bc, 0x000014e5, 0x00000026, 0x0004002b, 0x00000032, + 0x000000ca, 0x00000003, 0x0004002b, 0x00000032, 0x000000cd, 0x00000004, 0x0004002b, 0x00000032, 0x000000d0, + 0x00000005, 0x0004002b, 0x00000032, 0x000000d3, 0x00000006, 0x0004002b, 0x00000032, 0x000000d6, 0x00000007, + 0x00040017, 0x00000106, 0x00000006, 0x00000003, 0x00040020, 0x00000107, 0x00000001, 0x00000106, 0x0004003b, + 0x00000107, 0x00000108, 0x00000001, 0x00040020, 0x00000109, 0x00000001, 0x00000006, 0x0005001e, 0x0000010d, + 0x00000022, 0x00000006, 0x00000006, 0x00030027, 0x0000010e, 0x000014e5, 0x0006001e, 0x0000010f, 0x0000010d, + 0x0000010e, 0x0000010e, 0x00000006, 0x00030027, 0x00000110, 0x000014e5, 0x0003001d, 0x00000111, 0x00000110, + 0x0003001e, 0x00000112, 0x00000111, 0x0004001c, 0x00000113, 0x00000006, 0x0000000c, 0x0003001e, 0x00000114, + 0x00000113, 0x0003001e, 0x00000115, 0x00000114, 0x00040020, 0x00000110, 0x000014e5, 0x00000115, 0x00040020, + 0x0000010e, 0x000014e5, 0x00000112, 0x0003001e, 0x00000117, 0x0000010f, 0x00040020, 0x00000118, 0x00000009, + 0x00000117, 0x0004003b, 0x00000118, 0x00000119, 0x00000009, 0x00040020, 0x0000011a, 0x00000009, 0x00000006, + 0x00040020, 0x00000122, 0x00000009, 0x0000010d, 0x00040020, 0x00000125, 0x00000009, 0x0000010e, 0x00040020, + 0x00000129, 0x000014e5, 0x00000110, 0x00040020, 0x0000012c, 0x000014e5, 0x00000114, 0x00040020, 0x0000015b, + 0x000014e5, 0x00000113, 0x00040020, 0x0000015e, 0x000014e5, 0x00000006, 0x0006002c, 0x00000106, 0x0000016e, + 0x00000062, 0x000000b3, 0x000000b3, 0x00030001, 0x00000014, 0x000003b7, 0x00050036, 0x00000002, 0x00000004, + 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x0000004c, 0x000002df, 0x00000007, 0x0004003b, + 0x0000004c, 0x000002dc, 0x00000007, 0x0004003b, 0x0000004c, 0x000002d9, 0x00000007, 0x0004003b, 0x0000004c, + 0x000002d6, 0x00000007, 0x0004003b, 0x0000004c, 0x000002d3, 0x00000007, 0x0004003b, 0x0000004c, 0x000002d0, + 0x00000007, 0x0004003b, 0x0000004c, 0x000002cd, 0x00000007, 0x0004003b, 0x0000004c, 0x000002ca, 0x00000007, + 0x0004003b, 0x0000004c, 0x000002c7, 0x00000007, 0x0004003b, 0x0000004c, 0x000002c4, 0x00000007, 0x0004003b, + 0x0000004c, 0x00000209, 0x00000007, 0x000300f7, 0x0000016f, 0x00000000, 0x000300fb, 0x00000042, 0x00000170, + 0x000200f8, 0x00000170, 0x00050041, 0x00000109, 0x0000010a, 0x00000108, 0x00000042, 0x0004003d, 0x00000006, + 0x0000010b, 0x0000010a, 0x00060041, 0x0000011a, 0x0000011b, 0x00000119, 0x00000083, 0x000000ca, 0x0004003d, + 0x00000006, 0x0000011c, 0x0000011b, 0x000500ae, 0x00000014, 0x0000011d, 0x0000010b, 0x0000011c, 0x000300f7, + 0x0000011f, 0x00000000, 0x000400fa, 0x0000011d, 0x0000011e, 0x0000011f, 0x000200f8, 0x0000011e, 0x000200f9, + 0x0000016f, 0x000200f8, 0x0000011f, 0x00060041, 0x00000122, 0x00000123, 0x00000119, 0x00000083, 0x00000083, + 0x0004003d, 0x0000010d, 0x00000124, 0x00000123, 0x00060041, 0x00000125, 0x00000126, 0x00000119, 0x00000083, + 0x00000060, 0x0004003d, 0x0000010e, 0x00000127, 0x00000126, 0x00060041, 0x00000129, 0x0000012a, 0x00000127, + 0x00000083, 0x0000010b, 0x0006003d, 0x00000110, 0x0000012b, 0x0000012a, 0x00000002, 0x00000008, 0x00050041, + 0x0000012c, 0x0000012d, 0x0000012b, 0x00000083, 0x0006003d, 0x00000114, 0x0000012e, 0x0000012d, 0x00000002, + 0x00000010, 0x00050051, 0x00000022, 0x00000131, 0x00000124, 0x00000000, 0x00050051, 0x00000006, 0x00000136, + 0x00000124, 0x00000002, 0x00050051, 0x00000113, 0x0000013a, 0x0000012e, 0x00000000, 0x00050051, 0x00000006, + 0x0000013c, 0x0000013a, 0x00000000, 0x00050051, 0x00000006, 0x0000013e, 0x0000013a, 0x00000001, 0x00050051, + 0x00000006, 0x00000140, 0x0000013a, 0x00000002, 0x00050051, 0x00000006, 0x00000142, 0x0000013a, 0x00000003, + 0x00050051, 0x00000006, 0x00000144, 0x0000013a, 0x00000004, 0x00050051, 0x00000006, 0x00000146, 0x0000013a, + 0x00000005, 0x00050051, 0x00000006, 0x00000148, 0x0000013a, 0x00000006, 0x00050051, 0x00000006, 0x0000014a, + 0x0000013a, 0x00000007, 0x000b0050, 0x0000000d, 0x0000037c, 0x0000013c, 0x0000013e, 0x00000140, 0x00000142, + 0x00000144, 0x00000146, 0x00000148, 0x0000014a, 0x000300f7, 0x000001de, 0x00000000, 0x000300fb, 0x00000042, + 0x00000187, 0x000200f8, 0x00000187, 0x000300f7, 0x000001ff, 0x00000000, 0x000300fb, 0x00000042, 0x000001ea, + 0x000200f8, 0x000001ea, 0x000200f9, 0x000001eb, 0x000200f8, 0x000001eb, 0x000700f5, 0x00000006, 0x000003b1, + 0x00000042, 0x000001ea, 0x000001fb, 0x000001f9, 0x000500b0, 0x00000014, 0x000001ee, 0x000003b1, 0x0000000c, + 0x000400f6, 0x000001fc, 0x000001f9, 0x00000000, 0x000400fa, 0x000001ee, 0x000001ef, 0x000001fc, 0x000200f8, + 0x000001ef, 0x0003003e, 0x000002dc, 0x0000037c, 0x00050041, 0x00000007, 0x000002de, 0x000002dc, 0x000003b1, + 0x0004003d, 0x00000006, 0x000001f2, 0x000002de, 0x0003003e, 0x000002df, 0x00000097, 0x00050041, 0x00000007, + 0x000002e1, 0x000002df, 0x000003b1, 0x0004003d, 0x00000006, 0x000001f5, 0x000002e1, 0x000500ab, 0x00000014, + 0x000001f6, 0x000001f2, 0x000001f5, 0x000300f7, 0x000001f8, 0x00000000, 0x000400fa, 0x000001f6, 0x000001f7, + 0x000001f8, 0x000200f8, 0x000001f7, 0x000200f9, 0x000001fc, 0x000200f8, 0x000001f8, 0x000200f9, 0x000001f9, + 0x000200f8, 0x000001f9, 0x00050080, 0x00000006, 0x000001fb, 0x000003b1, 0x00000060, 0x000200f9, 0x000001eb, + 0x000200f8, 0x000001fc, 0x000700f5, 0x00000014, 0x000003b5, 0x000003b7, 0x000001eb, 0x00000090, 0x000001f7, + 0x000700f5, 0x00000014, 0x000003b2, 0x00000090, 0x000001eb, 0x00000094, 0x000001f7, 0x000300f7, 0x000001fe, + 0x00000000, 0x000400fa, 0x000003b2, 0x000001ff, 0x000001fe, 0x000200f8, 0x000001fe, 0x000200f9, 0x000001ff, + 0x000200f8, 0x000001ff, 0x000700f5, 0x00000014, 0x000003b4, 0x000003b5, 0x000001fc, 0x00000094, 0x000001fe, + 0x000400a8, 0x00000014, 0x00000189, 0x000003b4, 0x000300f7, 0x0000018d, 0x00000000, 0x000400fa, 0x00000189, + 0x0000018a, 0x0000018d, 0x000200f8, 0x0000018a, 0x000500aa, 0x00000014, 0x0000018c, 0x00000136, 0x00000042, + 0x000200f9, 0x0000018d, 0x000200f8, 0x0000018d, 0x000700f5, 0x00000014, 0x0000018e, 0x000003b4, 0x000001ff, + 0x0000018c, 0x0000018a, 0x000300f7, 0x00000190, 0x00000000, 0x000400fa, 0x0000018e, 0x0000018f, 0x00000190, + 0x000200f8, 0x0000018f, 0x000200f9, 0x000001de, 0x000200f8, 0x00000190, 0x000200f9, 0x0000020d, 0x000200f8, + 0x0000020d, 0x000700f5, 0x00000006, 0x000003b9, 0x00000042, 0x00000190, 0x0000021f, 0x00000211, 0x000700f5, + 0x00000006, 0x000003b8, 0x00000042, 0x00000190, 0x00000222, 0x00000211, 0x000500b0, 0x00000014, 0x00000210, + 0x000003b8, 0x0000000c, 0x000400f6, 0x00000223, 0x00000211, 0x00000000, 0x000400fa, 0x00000210, 0x00000211, + 0x00000223, 0x000200f8, 0x00000211, 0x0003003e, 0x00000209, 0x0000037c, 0x00050041, 0x00000007, 0x00000213, + 0x00000209, 0x000003b8, 0x0004003d, 0x00000006, 0x00000214, 0x00000213, 0x00050084, 0x00000006, 0x0000023a, + 0x00000214, 0x0000002e, 0x000500c4, 0x00000006, 0x0000023c, 0x0000023a, 0x00000033, 0x000500c2, 0x00000006, + 0x0000023e, 0x0000023a, 0x00000036, 0x000500c5, 0x00000006, 0x0000023f, 0x0000023c, 0x0000023e, 0x00050084, + 0x00000006, 0x00000241, 0x0000023f, 0x00000039, 0x000500c6, 0x00000006, 0x00000217, 0x000003b9, 0x00000241, + 0x000500c4, 0x00000006, 0x00000219, 0x00000217, 0x00000054, 0x000500c2, 0x00000006, 0x0000021b, 0x00000217, + 0x00000057, 0x000500c5, 0x00000006, 0x0000021c, 0x00000219, 0x0000021b, 0x00050084, 0x00000006, 0x0000021e, + 0x0000021c, 0x0000005b, 0x00050080, 0x00000006, 0x0000021f, 0x0000021e, 0x0000005d, 0x00050080, 0x00000006, + 0x00000222, 0x000003b8, 0x00000060, 0x000200f9, 0x0000020d, 0x000200f8, 0x00000223, 0x000500c6, 0x00000006, + 0x00000225, 0x000003b9, 0x00000062, 0x000500c2, 0x00000006, 0x00000227, 0x00000225, 0x00000066, 0x000500c6, + 0x00000006, 0x00000229, 0x00000225, 0x00000227, 0x00050084, 0x00000006, 0x0000022b, 0x00000229, 0x0000006a, + 0x000500c2, 0x00000006, 0x0000022d, 0x0000022b, 0x00000054, 0x000500c6, 0x00000006, 0x0000022f, 0x0000022b, + 0x0000022d, 0x00050084, 0x00000006, 0x00000231, 0x0000022f, 0x00000071, 0x000500c2, 0x00000006, 0x00000233, + 0x00000231, 0x00000066, 0x000500c6, 0x00000006, 0x00000235, 0x00000231, 0x00000233, 0x000200f9, 0x00000192, + 0x000200f8, 0x00000192, 0x000700f5, 0x00000014, 0x000003e2, 0x000003b7, 0x00000223, 0x00000426, 0x000001d8, + 0x000700f5, 0x00000014, 0x000003d0, 0x000003b7, 0x00000223, 0x000003ca, 0x000001d8, 0x000700f5, 0x00000014, + 0x000003c1, 0x000003b7, 0x00000223, 0x000003be, 0x000001d8, 0x000700f5, 0x00000006, 0x000003ba, 0x00000235, + 0x00000223, 0x000001da, 0x000001d8, 0x000400f6, 0x000001db, 0x000001d8, 0x00000000, 0x000200f9, 0x00000193, + 0x000200f8, 0x00000193, 0x00050082, 0x00000006, 0x00000195, 0x00000136, 0x000000b3, 0x000500c7, 0x00000006, + 0x00000197, 0x000003ba, 0x00000195, 0x00060041, 0x000000bc, 0x0000019a, 0x00000131, 0x00000083, 0x00000197, + 0x0006003d, 0x00000026, 0x0000019b, 0x0000019a, 0x00000002, 0x00000010, 0x00050051, 0x00000025, 0x0000019c, + 0x0000019b, 0x00000000, 0x00050051, 0x00000024, 0x0000019e, 0x0000019c, 0x00000000, 0x00050051, 0x00000006, + 0x000001a0, 0x0000019e, 0x00000000, 0x00050051, 0x00000006, 0x000001a2, 0x0000019e, 0x00000001, 0x00050051, + 0x00000006, 0x000001a4, 0x0000019e, 0x00000002, 0x00050051, 0x00000006, 0x000001a6, 0x0000019e, 0x00000003, + 0x00050051, 0x00000006, 0x000001a8, 0x0000019e, 0x00000004, 0x00050051, 0x00000006, 0x000001aa, 0x0000019e, + 0x00000005, 0x00050051, 0x00000006, 0x000001ac, 0x0000019e, 0x00000006, 0x00050051, 0x00000006, 0x000001ae, + 0x0000019e, 0x00000007, 0x00050051, 0x00000025, 0x000001b0, 0x0000019b, 0x00000001, 0x00050051, 0x00000024, + 0x000001b2, 0x000001b0, 0x00000000, 0x00050051, 0x00000006, 0x000001b4, 0x000001b2, 0x00000000, 0x00050051, + 0x00000006, 0x000001b6, 0x000001b2, 0x00000001, 0x00050051, 0x00000006, 0x000001b8, 0x000001b2, 0x00000002, + 0x00050051, 0x00000006, 0x000001ba, 0x000001b2, 0x00000003, 0x00050051, 0x00000006, 0x000001bc, 0x000001b2, + 0x00000004, 0x00050051, 0x00000006, 0x000001be, 0x000001b2, 0x00000005, 0x00050051, 0x00000006, 0x000001c0, + 0x000001b2, 0x00000006, 0x00050051, 0x00000006, 0x000001c2, 0x000001b2, 0x00000007, 0x000b0050, 0x0000000d, + 0x0000038d, 0x000001a0, 0x000001a2, 0x000001a4, 0x000001a6, 0x000001a8, 0x000001aa, 0x000001ac, 0x000001ae, + 0x000300f7, 0x00000262, 0x00000000, 0x000300fb, 0x00000042, 0x0000024d, 0x000200f8, 0x0000024d, 0x000200f9, + 0x0000024e, 0x000200f8, 0x0000024e, 0x000700f5, 0x00000006, 0x000003bb, 0x00000042, 0x0000024d, 0x0000025e, + 0x0000025c, 0x000500b0, 0x00000014, 0x00000251, 0x000003bb, 0x0000000c, 0x000400f6, 0x0000025f, 0x0000025c, + 0x00000000, 0x000400fa, 0x00000251, 0x00000252, 0x0000025f, 0x000200f8, 0x00000252, 0x0003003e, 0x000002d6, + 0x0000038d, 0x00050041, 0x00000007, 0x000002d8, 0x000002d6, 0x000003bb, 0x0004003d, 0x00000006, 0x00000255, + 0x000002d8, 0x0003003e, 0x000002d9, 0x00000097, 0x00050041, 0x00000007, 0x000002db, 0x000002d9, 0x000003bb, + 0x0004003d, 0x00000006, 0x00000258, 0x000002db, 0x000500ab, 0x00000014, 0x00000259, 0x00000255, 0x00000258, + 0x000300f7, 0x0000025b, 0x00000000, 0x000400fa, 0x00000259, 0x0000025a, 0x0000025b, 0x000200f8, 0x0000025a, + 0x000200f9, 0x0000025f, 0x000200f8, 0x0000025b, 0x000200f9, 0x0000025c, 0x000200f8, 0x0000025c, 0x00050080, + 0x00000006, 0x0000025e, 0x000003bb, 0x00000060, 0x000200f9, 0x0000024e, 0x000200f8, 0x0000025f, 0x000700f5, + 0x00000014, 0x000003bf, 0x000003c1, 0x0000024e, 0x00000090, 0x0000025a, 0x000700f5, 0x00000014, 0x000003bc, + 0x00000090, 0x0000024e, 0x00000094, 0x0000025a, 0x000300f7, 0x00000261, 0x00000000, 0x000400fa, 0x000003bc, + 0x00000262, 0x00000261, 0x000200f8, 0x00000261, 0x000200f9, 0x00000262, 0x000200f8, 0x00000262, 0x000700f5, + 0x00000014, 0x000003be, 0x000003bf, 0x0000025f, 0x00000094, 0x00000261, 0x000300f7, 0x000001d7, 0x00000000, + 0x000400fa, 0x000003be, 0x000001c7, 0x000001c8, 0x000200f8, 0x000001c7, 0x000200f9, 0x000001db, 0x000200f8, + 0x000001c8, 0x000300f7, 0x00000280, 0x00000000, 0x000300fb, 0x00000042, 0x0000026b, 0x000200f8, 0x0000026b, + 0x000200f9, 0x0000026c, 0x000200f8, 0x0000026c, 0x000700f5, 0x00000006, 0x000003c7, 0x00000042, 0x0000026b, + 0x0000027c, 0x0000027a, 0x000500b0, 0x00000014, 0x0000026f, 0x000003c7, 0x0000000c, 0x000400f6, 0x0000027d, + 0x0000027a, 0x00000000, 0x000400fa, 0x0000026f, 0x00000270, 0x0000027d, 0x000200f8, 0x00000270, 0x0003003e, + 0x000002d0, 0x0000037c, 0x00050041, 0x00000007, 0x000002d2, 0x000002d0, 0x000003c7, 0x0004003d, 0x00000006, + 0x00000273, 0x000002d2, 0x0003003e, 0x000002d3, 0x0000038d, 0x00050041, 0x00000007, 0x000002d5, 0x000002d3, + 0x000003c7, 0x0004003d, 0x00000006, 0x00000276, 0x000002d5, 0x000500ab, 0x00000014, 0x00000277, 0x00000273, + 0x00000276, 0x000300f7, 0x00000279, 0x00000000, 0x000400fa, 0x00000277, 0x00000278, 0x00000279, 0x000200f8, + 0x00000278, 0x000200f9, 0x0000027d, 0x000200f8, 0x00000279, 0x000200f9, 0x0000027a, 0x000200f8, 0x0000027a, + 0x00050080, 0x00000006, 0x0000027c, 0x000003c7, 0x00000060, 0x000200f9, 0x0000026c, 0x000200f8, 0x0000027d, + 0x000700f5, 0x00000014, 0x000003cb, 0x000003d0, 0x0000026c, 0x00000090, 0x00000278, 0x000700f5, 0x00000014, + 0x000003c8, 0x00000090, 0x0000026c, 0x00000094, 0x00000278, 0x000300f7, 0x0000027f, 0x00000000, 0x000400fa, + 0x000003c8, 0x00000280, 0x0000027f, 0x000200f8, 0x0000027f, 0x000200f9, 0x00000280, 0x000200f8, 0x00000280, + 0x000700f5, 0x00000014, 0x000003ca, 0x000003cb, 0x0000027d, 0x00000094, 0x0000027f, 0x000300f7, 0x000001d1, + 0x00000000, 0x000400fa, 0x000003ca, 0x000001cc, 0x000001d1, 0x000200f8, 0x000001cc, 0x000b0050, 0x0000000d, + 0x000003a7, 0x000001b4, 0x000001b6, 0x000001b8, 0x000001ba, 0x000001bc, 0x000001be, 0x000001c0, 0x000001c2, + 0x000300f7, 0x000002a1, 0x00000000, 0x000300fb, 0x00000042, 0x0000028c, 0x000200f8, 0x0000028c, 0x000200f9, + 0x0000028d, 0x000200f8, 0x0000028d, 0x000700f5, 0x00000006, 0x000003d6, 0x00000042, 0x0000028c, 0x0000029d, + 0x0000029b, 0x000500b0, 0x00000014, 0x00000290, 0x000003d6, 0x0000000c, 0x000400f6, 0x0000029e, 0x0000029b, + 0x00000000, 0x000400fa, 0x00000290, 0x00000291, 0x0000029e, 0x000200f8, 0x00000291, 0x0003003e, 0x000002ca, + 0x000003a7, 0x00050041, 0x00000007, 0x000002cc, 0x000002ca, 0x000003d6, 0x0004003d, 0x00000006, 0x00000294, + 0x000002cc, 0x0003003e, 0x000002cd, 0x00000097, 0x00050041, 0x00000007, 0x000002cf, 0x000002cd, 0x000003d6, + 0x0004003d, 0x00000006, 0x00000297, 0x000002cf, 0x000500ab, 0x00000014, 0x00000298, 0x00000294, 0x00000297, + 0x000300f7, 0x0000029a, 0x00000000, 0x000400fa, 0x00000298, 0x00000299, 0x0000029a, 0x000200f8, 0x00000299, + 0x000200f9, 0x0000029e, 0x000200f8, 0x0000029a, 0x000200f9, 0x0000029b, 0x000200f8, 0x0000029b, 0x00050080, + 0x00000006, 0x0000029d, 0x000003d6, 0x00000060, 0x000200f9, 0x0000028d, 0x000200f8, 0x0000029e, 0x000700f5, + 0x00000014, 0x000003da, 0x000003e2, 0x0000028d, 0x00000090, 0x00000299, 0x000700f5, 0x00000014, 0x000003d7, + 0x00000090, 0x0000028d, 0x00000094, 0x00000299, 0x000300f7, 0x000002a0, 0x00000000, 0x000400fa, 0x000003d7, + 0x000002a1, 0x000002a0, 0x000200f8, 0x000002a0, 0x000200f9, 0x000002a1, 0x000200f8, 0x000002a1, 0x000700f5, + 0x00000014, 0x000003d9, 0x000003da, 0x0000029e, 0x00000094, 0x000002a0, 0x000400a8, 0x00000014, 0x000001d0, + 0x000003d9, 0x000200f9, 0x000001d1, 0x000200f8, 0x000001d1, 0x000700f5, 0x00000014, 0x00000426, 0x000003e2, + 0x00000280, 0x000003d9, 0x000002a1, 0x000700f5, 0x00000014, 0x000001d2, 0x000003ca, 0x00000280, 0x000001d0, + 0x000002a1, 0x000300f7, 0x000001d6, 0x00000000, 0x000400fa, 0x000001d2, 0x000001d3, 0x000001d6, 0x000200f8, + 0x000001d3, 0x000200f9, 0x000001db, 0x000200f8, 0x000001d6, 0x000200f9, 0x000001d7, 0x000200f8, 0x000001d7, + 0x000200f9, 0x000001d8, 0x000200f8, 0x000001d8, 0x00050080, 0x00000006, 0x000001da, 0x00000197, 0x00000060, + 0x000200f9, 0x00000192, 0x000200f8, 0x000001db, 0x000700f5, 0x00000006, 0x00000402, 0x00000042, 0x000001c7, + 0x000001b4, 0x000001d3, 0x000700f5, 0x00000006, 0x00000400, 0x00000042, 0x000001c7, 0x000001b6, 0x000001d3, + 0x000700f5, 0x00000006, 0x000003fe, 0x00000042, 0x000001c7, 0x000001b8, 0x000001d3, 0x000700f5, 0x00000006, + 0x000003fc, 0x00000042, 0x000001c7, 0x000001ba, 0x000001d3, 0x000700f5, 0x00000006, 0x000003fa, 0x00000042, + 0x000001c7, 0x000001bc, 0x000001d3, 0x000700f5, 0x00000006, 0x000003f8, 0x00000042, 0x000001c7, 0x000001be, + 0x000001d3, 0x000700f5, 0x00000006, 0x000003f6, 0x00000042, 0x000001c7, 0x000001c0, 0x000001d3, 0x000700f5, + 0x00000006, 0x000003f4, 0x00000042, 0x000001c7, 0x000001c2, 0x000001d3, 0x000300f7, 0x000001dd, 0x00000000, + 0x000400fa, 0x00000094, 0x000001de, 0x000001dd, 0x000200f8, 0x000001dd, 0x000200f9, 0x000001de, 0x000200f8, + 0x000001de, 0x000900f5, 0x00000006, 0x00000401, 0x00000042, 0x0000018f, 0x00000402, 0x000001db, 0x00000402, + 0x000001dd, 0x000900f5, 0x00000006, 0x000003ff, 0x00000042, 0x0000018f, 0x00000400, 0x000001db, 0x00000400, + 0x000001dd, 0x000900f5, 0x00000006, 0x000003fd, 0x00000042, 0x0000018f, 0x000003fe, 0x000001db, 0x000003fe, + 0x000001dd, 0x000900f5, 0x00000006, 0x000003fb, 0x00000042, 0x0000018f, 0x000003fc, 0x000001db, 0x000003fc, + 0x000001dd, 0x000900f5, 0x00000006, 0x000003f9, 0x00000042, 0x0000018f, 0x000003fa, 0x000001db, 0x000003fa, + 0x000001dd, 0x000900f5, 0x00000006, 0x000003f7, 0x00000042, 0x0000018f, 0x000003f8, 0x000001db, 0x000003f8, + 0x000001dd, 0x000900f5, 0x00000006, 0x000003f5, 0x00000042, 0x0000018f, 0x000003f6, 0x000001db, 0x000003f6, + 0x000001dd, 0x000900f5, 0x00000006, 0x000003f3, 0x00000042, 0x0000018f, 0x000003f4, 0x000001db, 0x000003f4, + 0x000001dd, 0x000b0050, 0x0000000d, 0x00000362, 0x00000401, 0x000003ff, 0x000003fd, 0x000003fb, 0x000003f9, + 0x000003f7, 0x000003f5, 0x000003f3, 0x000300f7, 0x000002c2, 0x00000000, 0x000300fb, 0x00000042, 0x000002ad, + 0x000200f8, 0x000002ad, 0x000200f9, 0x000002ae, 0x000200f8, 0x000002ae, 0x000700f5, 0x00000006, 0x00000403, + 0x00000042, 0x000002ad, 0x000002be, 0x000002bc, 0x000500b0, 0x00000014, 0x000002b1, 0x00000403, 0x0000000c, + 0x000400f6, 0x000002bf, 0x000002bc, 0x00000000, 0x000400fa, 0x000002b1, 0x000002b2, 0x000002bf, 0x000200f8, + 0x000002b2, 0x0003003e, 0x000002c4, 0x00000362, 0x00050041, 0x00000007, 0x000002c6, 0x000002c4, 0x00000403, + 0x0004003d, 0x00000006, 0x000002b5, 0x000002c6, 0x0003003e, 0x000002c7, 0x00000097, 0x00050041, 0x00000007, + 0x000002c9, 0x000002c7, 0x00000403, 0x0004003d, 0x00000006, 0x000002b8, 0x000002c9, 0x000500ab, 0x00000014, + 0x000002b9, 0x000002b5, 0x000002b8, 0x000300f7, 0x000002bb, 0x00000000, 0x000400fa, 0x000002b9, 0x000002ba, + 0x000002bb, 0x000200f8, 0x000002ba, 0x000200f9, 0x000002bf, 0x000200f8, 0x000002bb, 0x000200f9, 0x000002bc, + 0x000200f8, 0x000002bc, 0x00050080, 0x00000006, 0x000002be, 0x00000403, 0x00000060, 0x000200f9, 0x000002ae, + 0x000200f8, 0x000002bf, 0x000700f5, 0x00000014, 0x00000407, 0x000003b7, 0x000002ae, 0x00000090, 0x000002ba, + 0x000700f5, 0x00000014, 0x00000404, 0x00000090, 0x000002ae, 0x00000094, 0x000002ba, 0x000300f7, 0x000002c1, + 0x00000000, 0x000400fa, 0x00000404, 0x000002c2, 0x000002c1, 0x000200f8, 0x000002c1, 0x000200f9, 0x000002c2, + 0x000200f8, 0x000002c2, 0x000700f5, 0x00000014, 0x00000406, 0x00000407, 0x000002bf, 0x00000094, 0x000002c1, + 0x000400a8, 0x00000014, 0x00000150, 0x00000406, 0x000300f7, 0x00000152, 0x00000000, 0x000400fa, 0x00000150, + 0x00000151, 0x00000152, 0x000200f8, 0x00000151, 0x00060041, 0x00000125, 0x00000153, 0x00000119, 0x00000083, + 0x000000a5, 0x0004003d, 0x0000010e, 0x00000154, 0x00000153, 0x00060041, 0x00000129, 0x00000156, 0x00000154, + 0x00000083, 0x0000010b, 0x0006003d, 0x00000110, 0x00000157, 0x00000156, 0x00000002, 0x00000008, 0x00050041, + 0x0000012c, 0x00000159, 0x00000157, 0x00000083, 0x00050041, 0x0000015b, 0x0000015c, 0x00000159, 0x00000083, + 0x00050041, 0x0000015e, 0x0000015f, 0x0000015c, 0x00000083, 0x0005003e, 0x0000015f, 0x00000401, 0x00000002, + 0x00000004, 0x00050041, 0x0000015e, 0x00000161, 0x0000015c, 0x00000060, 0x0005003e, 0x00000161, 0x000003ff, + 0x00000002, 0x00000004, 0x00050041, 0x0000015e, 0x00000163, 0x0000015c, 0x000000a5, 0x0005003e, 0x00000163, + 0x000003fd, 0x00000002, 0x00000004, 0x00050041, 0x0000015e, 0x00000165, 0x0000015c, 0x000000ca, 0x0005003e, + 0x00000165, 0x000003fb, 0x00000002, 0x00000004, 0x00050041, 0x0000015e, 0x00000167, 0x0000015c, 0x000000cd, + 0x0005003e, 0x00000167, 0x000003f9, 0x00000002, 0x00000004, 0x00050041, 0x0000015e, 0x00000169, 0x0000015c, + 0x000000d0, 0x0005003e, 0x00000169, 0x000003f7, 0x00000002, 0x00000004, 0x00050041, 0x0000015e, 0x0000016b, + 0x0000015c, 0x000000d3, 0x0005003e, 0x0000016b, 0x000003f5, 0x00000002, 0x00000004, 0x00050041, 0x0000015e, + 0x0000016d, 0x0000015c, 0x000000d6, 0x0005003e, 0x0000016d, 0x000003f3, 0x00000002, 0x00000004, 0x000200f9, + 0x00000152, 0x000200f8, 0x00000152, 0x000200f9, 0x0000016f, 0x000200f8, 0x0000016f, 0x000100fd, 0x00010038 }; -const std::array g_replacer_bda_comp = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x05, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x1b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0xb6, 0x14, 0x00, 0x00, 0x11, 0x00, - 0x02, 0x00, 0xe3, 0x14, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, - 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0xe4, 0x14, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, - 0x6e, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00, 0x04, 0x00, 0x07, 0x00, 0x47, 0x4c, 0x5f, 0x45, - 0x58, 0x54, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x45, 0x58, 0x54, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, - 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x32, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47, - 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, - 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, - 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, - 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, - 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x6d, 0x75, 0x72, 0x6d, - 0x75, 0x72, 0x5f, 0x33, 0x32, 0x5f, 0x73, 0x63, 0x72, 0x61, 0x6d, 0x62, 0x6c, 0x65, 0x28, 0x75, 0x31, 0x3b, 0x00, - 0x00, 0x05, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x11, 0x00, - 0x00, 0x00, 0x6d, 0x75, 0x72, 0x6d, 0x75, 0x72, 0x33, 0x5f, 0x33, 0x32, 0x28, 0x75, 0x31, 0x5b, 0x32, 0x5d, 0x3b, - 0x75, 0x31, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x79, 0x00, - 0x05, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x73, 0x65, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, - 0x00, 0x13, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x00, 0x06, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x17, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x65, 0x71, 0x75, 0x61, 0x6c, 0x28, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2d, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x2d, 0x75, - 0x31, 0x5b, 0x32, 0x5d, 0x31, 0x3b, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2d, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x2d, 0x75, - 0x31, 0x5b, 0x32, 0x5d, 0x31, 0x3b, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x6c, 0x68, 0x73, - 0x00, 0x05, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0x72, 0x68, 0x73, 0x00, 0x05, 0x00, 0x0e, 0x00, 0x1c, 0x00, - 0x00, 0x00, 0x69, 0x73, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x28, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2d, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x5f, 0x74, 0x2d, 0x75, 0x31, 0x5b, 0x32, 0x5d, 0x31, 0x3b, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x1b, 0x00, 0x00, - 0x00, 0x68, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x68, 0x61, 0x73, 0x68, 0x28, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x2d, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x2d, 0x75, 0x31, 0x5b, 0x32, 0x5d, 0x31, 0x3b, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, 0x68, 0x61, 0x73, 0x68, 0x6d, 0x61, - 0x70, 0x5f, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, - 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x00, 0x06, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x25, 0x00, - 0x00, 0x00, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x00, 0x06, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x26, 0x00, 0x00, 0x00, 0x68, 0x61, 0x73, - 0x68, 0x6d, 0x61, 0x70, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x26, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x79, 0x00, 0x06, 0x00, 0x05, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x28, 0x00, 0x00, 0x00, - 0x48, 0x61, 0x73, 0x68, 0x4d, 0x61, 0x70, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x00, 0x00, 0x06, 0x00, 0x04, - 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x05, 0x00, 0x14, 0x00, 0x2c, 0x00, - 0x00, 0x00, 0x67, 0x65, 0x74, 0x28, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2d, 0x68, 0x61, 0x73, 0x68, 0x6d, 0x61, - 0x70, 0x5f, 0x74, 0x2d, 0x31, 0x2d, 0x75, 0x31, 0x2d, 0x75, 0x31, 0x31, 0x3b, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x2d, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x5f, 0x74, 0x2d, 0x75, 0x31, 0x5b, 0x32, 0x5d, 0x31, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, - 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x68, 0x61, 0x73, 0x68, 0x6d, 0x61, 0x70, 0x00, 0x05, 0x00, 0x03, 0x00, 0x2b, - 0x00, 0x00, 0x00, 0x6b, 0x65, 0x79, 0x00, 0x05, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x4b, 0x00, 0x00, - 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x69, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x86, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x61, 0x62, 0x6c, - 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x61, 0x62, - 0x6c, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xac, 0x00, 0x00, 0x00, 0x69, 0x64, 0x78, 0x00, 0x05, 0x00, 0x06, 0x00, 0xb7, - 0x00, 0x00, 0x00, 0x68, 0x61, 0x73, 0x68, 0x6d, 0x61, 0x70, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x00, 0x00, - 0x06, 0x00, 0x04, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x79, 0x00, 0x06, 0x00, 0x05, - 0x00, 0xb7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, - 0x04, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x69, 0x74, 0x65, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xd9, - 0x00, 0x00, 0x00, 0x67, 0x69, 0x64, 0x00, 0x05, 0x00, 0x08, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x47, - 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x00, 0x00, - 0x00, 0x05, 0x00, 0x05, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x68, 0x61, 0x73, 0x68, 0x6d, 0x61, 0x70, 0x5f, 0x74, 0x00, - 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x74, 0x6f, 0x72, 0x61, - 0x67, 0x65, 0x00, 0x06, 0x00, 0x05, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x63, 0x61, 0x70, - 0x61, 0x63, 0x69, 0x74, 0x79, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x72, 0x65, - 0x70, 0x6c, 0x61, 0x63, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x5f, 0x74, 0x00, 0x00, 0x00, 0x06, - 0x00, 0x0a, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x00, 0x00, - 0x00, 0x06, 0x00, 0x07, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, - 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x00, 0x00, - 0x06, 0x00, 0x06, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6e, 0x75, 0x6d, 0x5f, 0x68, 0x61, 0x6e, - 0x64, 0x6c, 0x65, 0x73, 0x00, 0x05, 0x00, 0x06, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x74, - 0x00, 0x06, 0x00, 0x05, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x74, 0x72, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, - 0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xeb, 0x00, - 0x00, 0x00, 0x70, 0x63, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0x61, 0x72, 0x61, 0x6d, 0x73, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x04, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x00, 0x00, 0x05, 0x00, 0x03, - 0x00, 0x05, 0x01, 0x00, 0x00, 0x61, 0x72, 0x67, 0x00, 0x05, 0x00, 0x03, 0x00, 0x08, 0x01, 0x00, 0x00, 0x61, 0x72, - 0x67, 0x00, 0x47, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x48, - 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x05, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x48, 0x00, 0x05, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, - 0x00, 0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe3, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe3, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xe5, 0x00, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x05, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x47, 0x00, 0x04, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, - 0x05, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x00, 0x03, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xe9, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xea, 0x00, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x05, 0x01, 0x00, 0x00, 0xec, 0x14, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, - 0x1a, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x1c, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x21, 0x00, - 0x05, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1e, - 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, - 0x00, 0x21, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, - 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x27, 0x00, 0x03, 0x00, 0x22, - 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, - 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x03, 0x00, 0x27, - 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x21, 0x00, 0x05, - 0x00, 0x29, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x2b, 0x00, - 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x51, 0x2d, 0x9e, 0xcc, 0x15, 0x00, 0x04, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, - 0x33, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, - 0x00, 0x11, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x93, 0x35, - 0x87, 0x1b, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, - 0x32, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, - 0x00, 0x57, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5b, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x64, - 0x6b, 0x54, 0xe6, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, - 0x00, 0x32, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, - 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x6b, 0xca, 0xeb, 0x85, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x71, - 0x00, 0x00, 0x00, 0x35, 0xae, 0xb2, 0xc2, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x85, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, - 0x00, 0x2a, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x29, 0x00, 0x03, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x42, - 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, - 0x97, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, - 0x04, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xb8, - 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xbc, 0x00, 0x00, 0x00, - 0xe5, 0x14, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0xda, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xdb, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xda, 0x00, - 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xdb, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x04, 0x00, 0xdd, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00, - 0xe1, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x03, - 0x00, 0xe2, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, 0xe3, 0x00, 0x00, 0x00, 0xe1, 0x00, - 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x03, 0x00, 0xe4, - 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00, 0x00, 0x1d, 0x00, 0x03, 0x00, 0xe5, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, - 0x1e, 0x00, 0x03, 0x00, 0xe6, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0xe7, 0x00, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0xe8, 0x00, 0x00, 0x00, 0xe7, 0x00, - 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0xe9, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xe4, - 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x03, 0x00, 0xea, 0x00, 0x00, 0x00, - 0xe4, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xe2, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00, 0x00, 0xe6, 0x00, 0x00, - 0x00, 0x1e, 0x00, 0x03, 0x00, 0xeb, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xec, 0x00, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xec, 0x00, 0x00, 0x00, 0xed, - 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xef, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x04, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x20, 0x00, - 0x04, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xfe, - 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x01, 0x01, 0x00, 0x00, - 0xe5, 0x14, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x04, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x00, 0x2c, 0x00, 0x06, 0x00, 0xda, 0x00, 0x00, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0xb3, - 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, - 0x00, 0x07, 0x00, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x85, 0x00, - 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x04, 0x01, 0x00, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x85, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xdd, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, - 0x00, 0x42, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0xde, 0x00, - 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xd9, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, - 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xef, 0x00, 0x00, 0x00, - 0xf0, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, - 0x00, 0x06, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xae, 0x00, 0x05, 0x00, 0x14, 0x00, - 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xf4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xf2, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, - 0xf4, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xf3, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0xf8, 0x00, 0x02, - 0x00, 0xf4, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xf7, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xed, 0x00, - 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0xe1, 0x00, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xfa, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, - 0xed, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0xe2, 0x00, 0x00, - 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xfd, 0x00, - 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xfc, - 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x06, 0x00, 0xe4, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, - 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x3d, 0x00, - 0x06, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x90, 0x01, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x03, 0x00, 0x05, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, - 0x00, 0x07, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x90, 0x01, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x09, 0x01, - 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x08, 0x01, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x3d, - 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x39, 0x00, 0x06, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x0a, 0x01, 0x00, - 0x00, 0x3e, 0x00, 0x03, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, - 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0d, - 0x01, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0xa8, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x0e, 0x01, 0x00, 0x00, 0x0d, 0x01, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfa, 0x00, 0x04, 0x00, 0x0e, 0x01, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0xf8, 0x00, - 0x02, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0xed, - 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0xe2, 0x00, 0x00, 0x00, - 0x12, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, - 0x00, 0xd9, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x12, 0x01, - 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x06, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x15, - 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x01, 0x01, 0x00, - 0x00, 0x17, 0x01, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x90, 0x01, 0x04, 0x00, 0xe8, 0x00, - 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x05, 0x00, 0x17, 0x01, 0x00, 0x00, 0x18, - 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x10, 0x01, 0x00, 0x00, - 0xf8, 0x00, 0x02, 0x00, 0x10, 0x01, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x37, 0x00, - 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3d, - 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x31, 0x00, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x31, - 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, - 0x00, 0x36, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x34, 0x00, - 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3d, - 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3c, 0x00, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, - 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, - 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, - 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3e, 0x00, - 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00, 0x42, - 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x43, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x43, 0x00, 0x00, 0x00, - 0xf6, 0x00, 0x04, 0x00, 0x45, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, - 0x00, 0x47, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x47, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, - 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x49, - 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x49, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x4d, 0x00, - 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x4d, - 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, - 0x4e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x39, 0x00, 0x05, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x3d, 0x00, - 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x05, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, - 0x3f, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, - 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x53, 0x00, - 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x3f, - 0x00, 0x00, 0x00, 0xc2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, - 0x57, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, - 0x00, 0x58, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x3d, 0x00, - 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, - 0x00, 0x3f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x46, 0x00, 0x00, 0x00, 0xf8, 0x00, - 0x02, 0x00, 0x46, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x41, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, - 0x60, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x41, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, - 0x00, 0x43, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x45, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, - 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x64, - 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, - 0x00, 0xc2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x66, 0x00, - 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc6, - 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x6b, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6c, 0x00, - 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x6c, - 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, - 0xc2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, - 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc6, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x3e, - 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, - 0x00, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x73, 0x00, - 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc2, - 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, - 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x05, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x3e, 0x00, - 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x78, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, - 0x36, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, - 0x00, 0x37, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x13, 0x00, - 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x85, 0x00, 0x00, 0x00, - 0x86, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x85, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0xf9, 0x00, - 0x02, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x7e, - 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00, - 0xf8, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x7b, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x81, 0x00, - 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x82, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x7e, - 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x84, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x86, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, - 0x00, 0x41, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x83, 0x00, - 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x87, - 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x03, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x8b, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x3d, 0x00, - 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0xab, 0x00, 0x05, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, - 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, - 0x00, 0x8f, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x8e, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x90, 0x00, - 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x8f, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xf8, - 0x00, 0x02, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, - 0x7b, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0xf9, 0x00, - 0x02, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x94, - 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, - 0x00, 0xf8, 0x00, 0x02, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x39, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x99, 0x00, - 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x99, - 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, - 0x00, 0xf8, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x9d, 0x00, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x1f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, - 0x39, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, - 0x00, 0x9d, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, - 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x37, - 0x00, 0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x2b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, - 0x00, 0xac, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xb9, 0x00, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x1c, - 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, - 0xa1, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, - 0x00, 0xa2, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xa3, 0x00, - 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0xaa, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, - 0x42, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x00, - 0x00, 0xf5, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x2d, 0x00, - 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, - 0xf8, 0x00, 0x02, 0x00, 0xa9, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x98, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, - 0x00, 0xaa, 0x00, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xac, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0xf9, - 0x00, 0x02, 0x00, 0xae, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xae, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, - 0xb0, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xaf, 0x00, 0x00, - 0x00, 0xf8, 0x00, 0x02, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb2, 0x00, - 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb4, - 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0xb5, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, - 0x00, 0xb5, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xac, 0x00, 0x00, 0x00, 0xb6, 0x00, - 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x06, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, - 0x00, 0xbb, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x06, 0x00, 0x26, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0xbd, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x90, 0x01, 0x04, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xbf, - 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xb9, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x85, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, - 0x00, 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x39, 0x00, - 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xf7, - 0x00, 0x03, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xc2, 0x00, 0x00, 0x00, - 0xc3, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, - 0x00, 0x98, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x85, 0x00, - 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x13, - 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x39, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, - 0xc9, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, - 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xc9, 0x00, 0x00, 0x00, 0xca, 0x00, - 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xca, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x85, - 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, - 0x13, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x39, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, - 0x00, 0xce, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x04, 0x00, 0x14, 0x00, - 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xf8, - 0x00, 0x02, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, - 0xc9, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, - 0x00, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xd1, 0x00, - 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x85, - 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, - 0x13, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x00, - 0x00, 0xf8, 0x00, 0x02, 0x00, 0xd2, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xf8, 0x00, - 0x02, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb1, - 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, - 0x00, 0x3e, 0x00, 0x03, 0x00, 0xac, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xae, 0x00, - 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +const std::array g_replacer_bda_comp = { + 0x07230203, 0x00010300, 0x0008000b, 0x00000358, 0x00000000, 0x00020011, 0x00000001, 0x00020011, 0x000014b6, + 0x00020011, 0x000014e3, 0x0008000a, 0x5f565053, 0x5f545845, 0x63736564, 0x74706972, 0x695f726f, 0x7865646e, + 0x00676e69, 0x0009000a, 0x5f565053, 0x5f52484b, 0x73796870, 0x6c616369, 0x6f74735f, 0x65676172, 0x6675625f, + 0x00726566, 0x0006000b, 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x000014e4, + 0x00000001, 0x0006000f, 0x00000005, 0x00000004, 0x6e69616d, 0x00000000, 0x000000eb, 0x00060010, 0x00000004, + 0x00000011, 0x00000020, 0x00000001, 0x00000001, 0x00030003, 0x00000002, 0x000001cc, 0x00070004, 0x455f4c47, + 0x625f5458, 0x65666675, 0x65725f72, 0x65726566, 0x0065636e, 0x00080004, 0x455f4c47, 0x625f5458, 0x65666675, + 0x65725f72, 0x65726566, 0x3265636e, 0x00000000, 0x000a0004, 0x475f4c47, 0x4c474f4f, 0x70635f45, 0x74735f70, + 0x5f656c79, 0x656e696c, 0x7269645f, 0x69746365, 0x00006576, 0x00080004, 0x475f4c47, 0x4c474f4f, 0x6e695f45, + 0x64756c63, 0x69645f65, 0x74636572, 0x00657669, 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00080005, + 0x00000025, 0x66667562, 0x645f7265, 0x63697665, 0x64615f65, 0x73657264, 0x00745f73, 0x00050006, 0x00000025, + 0x00000000, 0x61746164, 0x00000000, 0x00060005, 0x00000026, 0x68736168, 0x5f70616d, 0x6d657469, 0x0000745f, + 0x00040006, 0x00000026, 0x00000000, 0x0079656b, 0x00050006, 0x00000026, 0x00000001, 0x756c6176, 0x00000065, + 0x00060005, 0x00000028, 0x68736148, 0x5370614d, 0x61726f74, 0x00006567, 0x00040006, 0x00000028, 0x00000000, + 0x00000076, 0x00080005, 0x000000eb, 0x475f6c67, 0x61626f6c, 0x766e496c, 0x7461636f, 0x496e6f69, 0x00000044, + 0x00050005, 0x000000f0, 0x68736168, 0x5f70616d, 0x00000074, 0x00050006, 0x000000f0, 0x00000000, 0x726f7473, + 0x00656761, 0x00050006, 0x000000f0, 0x00000001, 0x657a6973, 0x00000000, 0x00060006, 0x000000f0, 0x00000002, + 0x61706163, 0x79746963, 0x00000000, 0x00070005, 0x000000f2, 0x6c706572, 0x72656361, 0x7261705f, 0x5f736d61, + 0x00000074, 0x000a0006, 0x000000f2, 0x00000000, 0x66667562, 0x645f7265, 0x63697665, 0x64615f65, 0x73657264, + 0x616d5f73, 0x00000070, 0x00070006, 0x000000f2, 0x00000001, 0x75706e69, 0x61685f74, 0x656c646e, 0x00000073, + 0x00070006, 0x000000f2, 0x00000002, 0x7074756f, 0x685f7475, 0x6c646e61, 0x00007365, 0x00060006, 0x000000f2, + 0x00000003, 0x5f6d756e, 0x646e6168, 0x0073656c, 0x00060005, 0x000000f5, 0x72646441, 0x41737365, 0x79617272, + 0x00000000, 0x00040006, 0x000000f5, 0x00000000, 0x00000076, 0x00080005, 0x000000f7, 0x66667562, 0x645f7265, + 0x63697665, 0x64615f65, 0x73657264, 0x00745f73, 0x00050006, 0x000000f7, 0x00000000, 0x61746164, 0x00000000, + 0x00080005, 0x000000f8, 0x66667542, 0x65447265, 0x65636976, 0x72646441, 0x50737365, 0x00007274, 0x00090006, + 0x000000f8, 0x00000000, 0x66667562, 0x645f7265, 0x63697665, 0x64615f65, 0x73657264, 0x00000073, 0x00030005, + 0x000000fa, 0x00006370, 0x00050006, 0x000000fa, 0x00000000, 0x61726170, 0x0000736d, 0x00030005, 0x000000fc, + 0x00000000, 0x00040047, 0x00000024, 0x00000006, 0x00000004, 0x00050048, 0x00000025, 0x00000000, 0x00000023, + 0x00000000, 0x00050048, 0x00000026, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x00000026, 0x00000001, + 0x00000023, 0x00000008, 0x00040047, 0x00000027, 0x00000006, 0x00000010, 0x00030047, 0x00000028, 0x00000002, + 0x00040048, 0x00000028, 0x00000000, 0x00000018, 0x00050048, 0x00000028, 0x00000000, 0x00000023, 0x00000000, + 0x00040047, 0x000000eb, 0x0000000b, 0x0000001c, 0x00050048, 0x000000f0, 0x00000000, 0x00000023, 0x00000000, + 0x00050048, 0x000000f0, 0x00000001, 0x00000023, 0x00000008, 0x00050048, 0x000000f0, 0x00000002, 0x00000023, + 0x0000000c, 0x00050048, 0x000000f2, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x000000f2, 0x00000001, + 0x00000023, 0x00000010, 0x00050048, 0x000000f2, 0x00000002, 0x00000023, 0x00000018, 0x00050048, 0x000000f2, + 0x00000003, 0x00000023, 0x00000020, 0x00040047, 0x000000f4, 0x00000006, 0x00000008, 0x00030047, 0x000000f5, + 0x00000002, 0x00040048, 0x000000f5, 0x00000000, 0x00000018, 0x00050048, 0x000000f5, 0x00000000, 0x00000023, + 0x00000000, 0x00040047, 0x000000f6, 0x00000006, 0x00000004, 0x00050048, 0x000000f7, 0x00000000, 0x00000023, + 0x00000000, 0x00030047, 0x000000f8, 0x00000002, 0x00050048, 0x000000f8, 0x00000000, 0x00000023, 0x00000000, + 0x00030047, 0x000000fa, 0x00000002, 0x00050048, 0x000000fa, 0x00000000, 0x00000023, 0x00000000, 0x00040047, + 0x0000013b, 0x0000000b, 0x00000019, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00040015, + 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, 0x00000006, 0x0004002b, 0x00000006, + 0x0000000c, 0x00000002, 0x0004001c, 0x0000000d, 0x00000006, 0x0000000c, 0x00020014, 0x00000014, 0x00030027, + 0x00000022, 0x000014e5, 0x0004001c, 0x00000024, 0x00000006, 0x0000000c, 0x0003001e, 0x00000025, 0x00000024, + 0x0004001e, 0x00000026, 0x00000025, 0x00000025, 0x0003001d, 0x00000027, 0x00000026, 0x0003001e, 0x00000028, + 0x00000027, 0x00040020, 0x00000022, 0x000014e5, 0x00000028, 0x0004002b, 0x00000006, 0x0000002e, 0xcc9e2d51, + 0x00040015, 0x00000032, 0x00000020, 0x00000001, 0x0004002b, 0x00000032, 0x00000033, 0x0000000f, 0x0004002b, + 0x00000032, 0x00000036, 0x00000011, 0x0004002b, 0x00000006, 0x00000039, 0x1b873593, 0x0004002b, 0x00000006, + 0x00000042, 0x00000000, 0x00040020, 0x0000004c, 0x00000007, 0x0000000d, 0x0004002b, 0x00000032, 0x00000054, + 0x0000000d, 0x0004002b, 0x00000032, 0x00000057, 0x00000013, 0x0004002b, 0x00000006, 0x0000005b, 0x00000005, + 0x0004002b, 0x00000006, 0x0000005d, 0xe6546b64, 0x0004002b, 0x00000032, 0x00000060, 0x00000001, 0x0004002b, + 0x00000006, 0x00000062, 0x00000008, 0x0004002b, 0x00000032, 0x00000066, 0x00000010, 0x0004002b, 0x00000006, + 0x0000006a, 0x85ebca6b, 0x0004002b, 0x00000006, 0x00000071, 0xc2b2ae35, 0x0004002b, 0x00000032, 0x00000083, + 0x00000000, 0x0003002a, 0x00000014, 0x00000090, 0x00030029, 0x00000014, 0x00000094, 0x0005002c, 0x0000000d, + 0x00000097, 0x00000042, 0x00000042, 0x0004002b, 0x00000032, 0x000000a5, 0x00000002, 0x0004002b, 0x00000006, + 0x000000b3, 0x00000001, 0x00040020, 0x000000bc, 0x000014e5, 0x00000026, 0x00040017, 0x000000e9, 0x00000006, + 0x00000003, 0x00040020, 0x000000ea, 0x00000001, 0x000000e9, 0x0004003b, 0x000000ea, 0x000000eb, 0x00000001, + 0x00040020, 0x000000ec, 0x00000001, 0x00000006, 0x0005001e, 0x000000f0, 0x00000022, 0x00000006, 0x00000006, + 0x00030027, 0x000000f1, 0x000014e5, 0x0006001e, 0x000000f2, 0x000000f0, 0x000000f1, 0x000000f1, 0x00000006, + 0x00030027, 0x000000f3, 0x000014e5, 0x0003001d, 0x000000f4, 0x000000f3, 0x0003001e, 0x000000f5, 0x000000f4, + 0x0004001c, 0x000000f6, 0x00000006, 0x0000000c, 0x0003001e, 0x000000f7, 0x000000f6, 0x0003001e, 0x000000f8, + 0x000000f7, 0x00040020, 0x000000f3, 0x000014e5, 0x000000f8, 0x00040020, 0x000000f1, 0x000014e5, 0x000000f5, + 0x0003001e, 0x000000fa, 0x000000f2, 0x00040020, 0x000000fb, 0x00000009, 0x000000fa, 0x0004003b, 0x000000fb, + 0x000000fc, 0x00000009, 0x0004002b, 0x00000032, 0x000000fd, 0x00000003, 0x00040020, 0x000000fe, 0x00000009, + 0x00000006, 0x00040020, 0x00000106, 0x00000009, 0x000000f0, 0x00040020, 0x00000109, 0x00000009, 0x000000f1, + 0x00040020, 0x0000010d, 0x000014e5, 0x000000f3, 0x00040020, 0x00000110, 0x000014e5, 0x000000f7, 0x00040020, + 0x00000133, 0x000014e5, 0x000000f6, 0x00040020, 0x00000136, 0x000014e5, 0x00000006, 0x0004002b, 0x00000006, + 0x0000013a, 0x00000020, 0x0006002c, 0x000000e9, 0x0000013b, 0x0000013a, 0x000000b3, 0x000000b3, 0x00030001, + 0x00000014, 0x000002f4, 0x00050036, 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, + 0x0004003b, 0x0000004c, 0x00000294, 0x00000007, 0x0004003b, 0x0000004c, 0x00000291, 0x00000007, 0x0004003b, + 0x0000004c, 0x0000028e, 0x00000007, 0x0004003b, 0x0000004c, 0x0000028b, 0x00000007, 0x0004003b, 0x0000004c, + 0x00000288, 0x00000007, 0x0004003b, 0x0000004c, 0x00000285, 0x00000007, 0x0004003b, 0x0000004c, 0x00000282, + 0x00000007, 0x0004003b, 0x0000004c, 0x0000027f, 0x00000007, 0x0004003b, 0x0000004c, 0x0000027c, 0x00000007, + 0x0004003b, 0x0000004c, 0x00000279, 0x00000007, 0x0004003b, 0x0000004c, 0x000001be, 0x00000007, 0x000300f7, + 0x0000013c, 0x00000000, 0x000300fb, 0x00000042, 0x0000013d, 0x000200f8, 0x0000013d, 0x00050041, 0x000000ec, + 0x000000ed, 0x000000eb, 0x00000042, 0x0004003d, 0x00000006, 0x000000ee, 0x000000ed, 0x00060041, 0x000000fe, + 0x000000ff, 0x000000fc, 0x00000083, 0x000000fd, 0x0004003d, 0x00000006, 0x00000100, 0x000000ff, 0x000500ae, + 0x00000014, 0x00000101, 0x000000ee, 0x00000100, 0x000300f7, 0x00000103, 0x00000000, 0x000400fa, 0x00000101, + 0x00000102, 0x00000103, 0x000200f8, 0x00000102, 0x000200f9, 0x0000013c, 0x000200f8, 0x00000103, 0x00060041, + 0x00000106, 0x00000107, 0x000000fc, 0x00000083, 0x00000083, 0x0004003d, 0x000000f0, 0x00000108, 0x00000107, + 0x00060041, 0x00000109, 0x0000010a, 0x000000fc, 0x00000083, 0x00000060, 0x0004003d, 0x000000f1, 0x0000010b, + 0x0000010a, 0x00060041, 0x0000010d, 0x0000010e, 0x0000010b, 0x00000083, 0x000000ee, 0x0006003d, 0x000000f3, + 0x0000010f, 0x0000010e, 0x00000002, 0x00000008, 0x00050041, 0x00000110, 0x00000111, 0x0000010f, 0x00000083, + 0x0006003d, 0x000000f7, 0x00000112, 0x00000111, 0x00000002, 0x00000010, 0x00050051, 0x00000022, 0x00000115, + 0x00000108, 0x00000000, 0x00050051, 0x00000006, 0x0000011a, 0x00000108, 0x00000002, 0x00050051, 0x000000f6, + 0x0000011e, 0x00000112, 0x00000000, 0x00050051, 0x00000006, 0x00000120, 0x0000011e, 0x00000000, 0x00050051, + 0x00000006, 0x00000122, 0x0000011e, 0x00000001, 0x00050050, 0x0000000d, 0x000002dd, 0x00000120, 0x00000122, + 0x000300f7, 0x00000193, 0x00000000, 0x000300fb, 0x00000042, 0x00000154, 0x000200f8, 0x00000154, 0x000300f7, + 0x000001b4, 0x00000000, 0x000300fb, 0x00000042, 0x0000019f, 0x000200f8, 0x0000019f, 0x000200f9, 0x000001a0, + 0x000200f8, 0x000001a0, 0x000700f5, 0x00000006, 0x000002ee, 0x00000042, 0x0000019f, 0x000001b0, 0x000001ae, + 0x000500b0, 0x00000014, 0x000001a3, 0x000002ee, 0x0000000c, 0x000400f6, 0x000001b1, 0x000001ae, 0x00000000, + 0x000400fa, 0x000001a3, 0x000001a4, 0x000001b1, 0x000200f8, 0x000001a4, 0x0003003e, 0x00000291, 0x000002dd, + 0x00050041, 0x00000007, 0x00000293, 0x00000291, 0x000002ee, 0x0004003d, 0x00000006, 0x000001a7, 0x00000293, + 0x0003003e, 0x00000294, 0x00000097, 0x00050041, 0x00000007, 0x00000296, 0x00000294, 0x000002ee, 0x0004003d, + 0x00000006, 0x000001aa, 0x00000296, 0x000500ab, 0x00000014, 0x000001ab, 0x000001a7, 0x000001aa, 0x000300f7, + 0x000001ad, 0x00000000, 0x000400fa, 0x000001ab, 0x000001ac, 0x000001ad, 0x000200f8, 0x000001ac, 0x000200f9, + 0x000001b1, 0x000200f8, 0x000001ad, 0x000200f9, 0x000001ae, 0x000200f8, 0x000001ae, 0x00050080, 0x00000006, + 0x000001b0, 0x000002ee, 0x00000060, 0x000200f9, 0x000001a0, 0x000200f8, 0x000001b1, 0x000700f5, 0x00000014, + 0x000002f2, 0x000002f4, 0x000001a0, 0x00000090, 0x000001ac, 0x000700f5, 0x00000014, 0x000002ef, 0x00000090, + 0x000001a0, 0x00000094, 0x000001ac, 0x000300f7, 0x000001b3, 0x00000000, 0x000400fa, 0x000002ef, 0x000001b4, + 0x000001b3, 0x000200f8, 0x000001b3, 0x000200f9, 0x000001b4, 0x000200f8, 0x000001b4, 0x000700f5, 0x00000014, + 0x000002f1, 0x000002f2, 0x000001b1, 0x00000094, 0x000001b3, 0x000400a8, 0x00000014, 0x00000156, 0x000002f1, + 0x000300f7, 0x0000015a, 0x00000000, 0x000400fa, 0x00000156, 0x00000157, 0x0000015a, 0x000200f8, 0x00000157, + 0x000500aa, 0x00000014, 0x00000159, 0x0000011a, 0x00000042, 0x000200f9, 0x0000015a, 0x000200f8, 0x0000015a, + 0x000700f5, 0x00000014, 0x0000015b, 0x000002f1, 0x000001b4, 0x00000159, 0x00000157, 0x000300f7, 0x0000015d, + 0x00000000, 0x000400fa, 0x0000015b, 0x0000015c, 0x0000015d, 0x000200f8, 0x0000015c, 0x000200f9, 0x00000193, + 0x000200f8, 0x0000015d, 0x000200f9, 0x000001c2, 0x000200f8, 0x000001c2, 0x000700f5, 0x00000006, 0x000002f6, + 0x00000042, 0x0000015d, 0x000001d4, 0x000001c6, 0x000700f5, 0x00000006, 0x000002f5, 0x00000042, 0x0000015d, + 0x000001d7, 0x000001c6, 0x000500b0, 0x00000014, 0x000001c5, 0x000002f5, 0x0000000c, 0x000400f6, 0x000001d8, + 0x000001c6, 0x00000000, 0x000400fa, 0x000001c5, 0x000001c6, 0x000001d8, 0x000200f8, 0x000001c6, 0x0003003e, + 0x000001be, 0x000002dd, 0x00050041, 0x00000007, 0x000001c8, 0x000001be, 0x000002f5, 0x0004003d, 0x00000006, + 0x000001c9, 0x000001c8, 0x00050084, 0x00000006, 0x000001ef, 0x000001c9, 0x0000002e, 0x000500c4, 0x00000006, + 0x000001f1, 0x000001ef, 0x00000033, 0x000500c2, 0x00000006, 0x000001f3, 0x000001ef, 0x00000036, 0x000500c5, + 0x00000006, 0x000001f4, 0x000001f1, 0x000001f3, 0x00050084, 0x00000006, 0x000001f6, 0x000001f4, 0x00000039, + 0x000500c6, 0x00000006, 0x000001cc, 0x000002f6, 0x000001f6, 0x000500c4, 0x00000006, 0x000001ce, 0x000001cc, + 0x00000054, 0x000500c2, 0x00000006, 0x000001d0, 0x000001cc, 0x00000057, 0x000500c5, 0x00000006, 0x000001d1, + 0x000001ce, 0x000001d0, 0x00050084, 0x00000006, 0x000001d3, 0x000001d1, 0x0000005b, 0x00050080, 0x00000006, + 0x000001d4, 0x000001d3, 0x0000005d, 0x00050080, 0x00000006, 0x000001d7, 0x000002f5, 0x00000060, 0x000200f9, + 0x000001c2, 0x000200f8, 0x000001d8, 0x000500c6, 0x00000006, 0x000001da, 0x000002f6, 0x00000062, 0x000500c2, + 0x00000006, 0x000001dc, 0x000001da, 0x00000066, 0x000500c6, 0x00000006, 0x000001de, 0x000001da, 0x000001dc, + 0x00050084, 0x00000006, 0x000001e0, 0x000001de, 0x0000006a, 0x000500c2, 0x00000006, 0x000001e2, 0x000001e0, + 0x00000054, 0x000500c6, 0x00000006, 0x000001e4, 0x000001e0, 0x000001e2, 0x00050084, 0x00000006, 0x000001e6, + 0x000001e4, 0x00000071, 0x000500c2, 0x00000006, 0x000001e8, 0x000001e6, 0x00000066, 0x000500c6, 0x00000006, + 0x000001ea, 0x000001e6, 0x000001e8, 0x000200f9, 0x0000015f, 0x000200f8, 0x0000015f, 0x000700f5, 0x00000014, + 0x0000031f, 0x000002f4, 0x000001d8, 0x00000357, 0x0000018d, 0x000700f5, 0x00000014, 0x0000030d, 0x000002f4, + 0x000001d8, 0x00000307, 0x0000018d, 0x000700f5, 0x00000014, 0x000002fe, 0x000002f4, 0x000001d8, 0x000002fb, + 0x0000018d, 0x000700f5, 0x00000006, 0x000002f7, 0x000001ea, 0x000001d8, 0x0000018f, 0x0000018d, 0x000400f6, + 0x00000190, 0x0000018d, 0x00000000, 0x000200f9, 0x00000160, 0x000200f8, 0x00000160, 0x00050082, 0x00000006, + 0x00000162, 0x0000011a, 0x000000b3, 0x000500c7, 0x00000006, 0x00000164, 0x000002f7, 0x00000162, 0x00060041, + 0x000000bc, 0x00000167, 0x00000115, 0x00000083, 0x00000164, 0x0006003d, 0x00000026, 0x00000168, 0x00000167, + 0x00000002, 0x00000010, 0x00050051, 0x00000025, 0x00000169, 0x00000168, 0x00000000, 0x00050051, 0x00000024, + 0x0000016b, 0x00000169, 0x00000000, 0x00050051, 0x00000006, 0x0000016d, 0x0000016b, 0x00000000, 0x00050051, + 0x00000006, 0x0000016f, 0x0000016b, 0x00000001, 0x00050051, 0x00000025, 0x00000171, 0x00000168, 0x00000001, + 0x00050051, 0x00000024, 0x00000173, 0x00000171, 0x00000000, 0x00050051, 0x00000006, 0x00000175, 0x00000173, + 0x00000000, 0x00050051, 0x00000006, 0x00000177, 0x00000173, 0x00000001, 0x00050050, 0x0000000d, 0x000002e2, + 0x0000016d, 0x0000016f, 0x000300f7, 0x00000217, 0x00000000, 0x000300fb, 0x00000042, 0x00000202, 0x000200f8, + 0x00000202, 0x000200f9, 0x00000203, 0x000200f8, 0x00000203, 0x000700f5, 0x00000006, 0x000002f8, 0x00000042, + 0x00000202, 0x00000213, 0x00000211, 0x000500b0, 0x00000014, 0x00000206, 0x000002f8, 0x0000000c, 0x000400f6, + 0x00000214, 0x00000211, 0x00000000, 0x000400fa, 0x00000206, 0x00000207, 0x00000214, 0x000200f8, 0x00000207, + 0x0003003e, 0x0000028b, 0x000002e2, 0x00050041, 0x00000007, 0x0000028d, 0x0000028b, 0x000002f8, 0x0004003d, + 0x00000006, 0x0000020a, 0x0000028d, 0x0003003e, 0x0000028e, 0x00000097, 0x00050041, 0x00000007, 0x00000290, + 0x0000028e, 0x000002f8, 0x0004003d, 0x00000006, 0x0000020d, 0x00000290, 0x000500ab, 0x00000014, 0x0000020e, + 0x0000020a, 0x0000020d, 0x000300f7, 0x00000210, 0x00000000, 0x000400fa, 0x0000020e, 0x0000020f, 0x00000210, + 0x000200f8, 0x0000020f, 0x000200f9, 0x00000214, 0x000200f8, 0x00000210, 0x000200f9, 0x00000211, 0x000200f8, + 0x00000211, 0x00050080, 0x00000006, 0x00000213, 0x000002f8, 0x00000060, 0x000200f9, 0x00000203, 0x000200f8, + 0x00000214, 0x000700f5, 0x00000014, 0x000002fc, 0x000002fe, 0x00000203, 0x00000090, 0x0000020f, 0x000700f5, + 0x00000014, 0x000002f9, 0x00000090, 0x00000203, 0x00000094, 0x0000020f, 0x000300f7, 0x00000216, 0x00000000, + 0x000400fa, 0x000002f9, 0x00000217, 0x00000216, 0x000200f8, 0x00000216, 0x000200f9, 0x00000217, 0x000200f8, + 0x00000217, 0x000700f5, 0x00000014, 0x000002fb, 0x000002fc, 0x00000214, 0x00000094, 0x00000216, 0x000300f7, + 0x0000018c, 0x00000000, 0x000400fa, 0x000002fb, 0x0000017c, 0x0000017d, 0x000200f8, 0x0000017c, 0x000200f9, + 0x00000190, 0x000200f8, 0x0000017d, 0x000300f7, 0x00000235, 0x00000000, 0x000300fb, 0x00000042, 0x00000220, + 0x000200f8, 0x00000220, 0x000200f9, 0x00000221, 0x000200f8, 0x00000221, 0x000700f5, 0x00000006, 0x00000304, + 0x00000042, 0x00000220, 0x00000231, 0x0000022f, 0x000500b0, 0x00000014, 0x00000224, 0x00000304, 0x0000000c, + 0x000400f6, 0x00000232, 0x0000022f, 0x00000000, 0x000400fa, 0x00000224, 0x00000225, 0x00000232, 0x000200f8, + 0x00000225, 0x0003003e, 0x00000285, 0x000002dd, 0x00050041, 0x00000007, 0x00000287, 0x00000285, 0x00000304, + 0x0004003d, 0x00000006, 0x00000228, 0x00000287, 0x0003003e, 0x00000288, 0x000002e2, 0x00050041, 0x00000007, + 0x0000028a, 0x00000288, 0x00000304, 0x0004003d, 0x00000006, 0x0000022b, 0x0000028a, 0x000500ab, 0x00000014, + 0x0000022c, 0x00000228, 0x0000022b, 0x000300f7, 0x0000022e, 0x00000000, 0x000400fa, 0x0000022c, 0x0000022d, + 0x0000022e, 0x000200f8, 0x0000022d, 0x000200f9, 0x00000232, 0x000200f8, 0x0000022e, 0x000200f9, 0x0000022f, + 0x000200f8, 0x0000022f, 0x00050080, 0x00000006, 0x00000231, 0x00000304, 0x00000060, 0x000200f9, 0x00000221, + 0x000200f8, 0x00000232, 0x000700f5, 0x00000014, 0x00000308, 0x0000030d, 0x00000221, 0x00000090, 0x0000022d, + 0x000700f5, 0x00000014, 0x00000305, 0x00000090, 0x00000221, 0x00000094, 0x0000022d, 0x000300f7, 0x00000234, + 0x00000000, 0x000400fa, 0x00000305, 0x00000235, 0x00000234, 0x000200f8, 0x00000234, 0x000200f9, 0x00000235, + 0x000200f8, 0x00000235, 0x000700f5, 0x00000014, 0x00000307, 0x00000308, 0x00000232, 0x00000094, 0x00000234, + 0x000300f7, 0x00000186, 0x00000000, 0x000400fa, 0x00000307, 0x00000181, 0x00000186, 0x000200f8, 0x00000181, + 0x00050050, 0x0000000d, 0x000002ea, 0x00000175, 0x00000177, 0x000300f7, 0x00000256, 0x00000000, 0x000300fb, + 0x00000042, 0x00000241, 0x000200f8, 0x00000241, 0x000200f9, 0x00000242, 0x000200f8, 0x00000242, 0x000700f5, + 0x00000006, 0x00000313, 0x00000042, 0x00000241, 0x00000252, 0x00000250, 0x000500b0, 0x00000014, 0x00000245, + 0x00000313, 0x0000000c, 0x000400f6, 0x00000253, 0x00000250, 0x00000000, 0x000400fa, 0x00000245, 0x00000246, + 0x00000253, 0x000200f8, 0x00000246, 0x0003003e, 0x0000027f, 0x000002ea, 0x00050041, 0x00000007, 0x00000281, + 0x0000027f, 0x00000313, 0x0004003d, 0x00000006, 0x00000249, 0x00000281, 0x0003003e, 0x00000282, 0x00000097, + 0x00050041, 0x00000007, 0x00000284, 0x00000282, 0x00000313, 0x0004003d, 0x00000006, 0x0000024c, 0x00000284, + 0x000500ab, 0x00000014, 0x0000024d, 0x00000249, 0x0000024c, 0x000300f7, 0x0000024f, 0x00000000, 0x000400fa, + 0x0000024d, 0x0000024e, 0x0000024f, 0x000200f8, 0x0000024e, 0x000200f9, 0x00000253, 0x000200f8, 0x0000024f, + 0x000200f9, 0x00000250, 0x000200f8, 0x00000250, 0x00050080, 0x00000006, 0x00000252, 0x00000313, 0x00000060, + 0x000200f9, 0x00000242, 0x000200f8, 0x00000253, 0x000700f5, 0x00000014, 0x00000317, 0x0000031f, 0x00000242, + 0x00000090, 0x0000024e, 0x000700f5, 0x00000014, 0x00000314, 0x00000090, 0x00000242, 0x00000094, 0x0000024e, + 0x000300f7, 0x00000255, 0x00000000, 0x000400fa, 0x00000314, 0x00000256, 0x00000255, 0x000200f8, 0x00000255, + 0x000200f9, 0x00000256, 0x000200f8, 0x00000256, 0x000700f5, 0x00000014, 0x00000316, 0x00000317, 0x00000253, + 0x00000094, 0x00000255, 0x000400a8, 0x00000014, 0x00000185, 0x00000316, 0x000200f9, 0x00000186, 0x000200f8, + 0x00000186, 0x000700f5, 0x00000014, 0x00000357, 0x0000031f, 0x00000235, 0x00000316, 0x00000256, 0x000700f5, + 0x00000014, 0x00000187, 0x00000307, 0x00000235, 0x00000185, 0x00000256, 0x000300f7, 0x0000018b, 0x00000000, + 0x000400fa, 0x00000187, 0x00000188, 0x0000018b, 0x000200f8, 0x00000188, 0x000200f9, 0x00000190, 0x000200f8, + 0x0000018b, 0x000200f9, 0x0000018c, 0x000200f8, 0x0000018c, 0x000200f9, 0x0000018d, 0x000200f8, 0x0000018d, + 0x00050080, 0x00000006, 0x0000018f, 0x00000164, 0x00000060, 0x000200f9, 0x0000015f, 0x000200f8, 0x00000190, + 0x000700f5, 0x00000006, 0x00000333, 0x00000042, 0x0000017c, 0x00000175, 0x00000188, 0x000700f5, 0x00000006, + 0x00000331, 0x00000042, 0x0000017c, 0x00000177, 0x00000188, 0x000300f7, 0x00000192, 0x00000000, 0x000400fa, + 0x00000094, 0x00000193, 0x00000192, 0x000200f8, 0x00000192, 0x000200f9, 0x00000193, 0x000200f8, 0x00000193, + 0x000900f5, 0x00000006, 0x00000332, 0x00000042, 0x0000015c, 0x00000333, 0x00000190, 0x00000333, 0x00000192, + 0x000900f5, 0x00000006, 0x00000330, 0x00000042, 0x0000015c, 0x00000331, 0x00000190, 0x00000331, 0x00000192, + 0x00050050, 0x0000000d, 0x000002d5, 0x00000332, 0x00000330, 0x000300f7, 0x00000277, 0x00000000, 0x000300fb, + 0x00000042, 0x00000262, 0x000200f8, 0x00000262, 0x000200f9, 0x00000263, 0x000200f8, 0x00000263, 0x000700f5, + 0x00000006, 0x00000334, 0x00000042, 0x00000262, 0x00000273, 0x00000271, 0x000500b0, 0x00000014, 0x00000266, + 0x00000334, 0x0000000c, 0x000400f6, 0x00000274, 0x00000271, 0x00000000, 0x000400fa, 0x00000266, 0x00000267, + 0x00000274, 0x000200f8, 0x00000267, 0x0003003e, 0x00000279, 0x000002d5, 0x00050041, 0x00000007, 0x0000027b, + 0x00000279, 0x00000334, 0x0004003d, 0x00000006, 0x0000026a, 0x0000027b, 0x0003003e, 0x0000027c, 0x00000097, + 0x00050041, 0x00000007, 0x0000027e, 0x0000027c, 0x00000334, 0x0004003d, 0x00000006, 0x0000026d, 0x0000027e, + 0x000500ab, 0x00000014, 0x0000026e, 0x0000026a, 0x0000026d, 0x000300f7, 0x00000270, 0x00000000, 0x000400fa, + 0x0000026e, 0x0000026f, 0x00000270, 0x000200f8, 0x0000026f, 0x000200f9, 0x00000274, 0x000200f8, 0x00000270, + 0x000200f9, 0x00000271, 0x000200f8, 0x00000271, 0x00050080, 0x00000006, 0x00000273, 0x00000334, 0x00000060, + 0x000200f9, 0x00000263, 0x000200f8, 0x00000274, 0x000700f5, 0x00000014, 0x00000338, 0x000002f4, 0x00000263, + 0x00000090, 0x0000026f, 0x000700f5, 0x00000014, 0x00000335, 0x00000090, 0x00000263, 0x00000094, 0x0000026f, + 0x000300f7, 0x00000276, 0x00000000, 0x000400fa, 0x00000335, 0x00000277, 0x00000276, 0x000200f8, 0x00000276, + 0x000200f9, 0x00000277, 0x000200f8, 0x00000277, 0x000700f5, 0x00000014, 0x00000337, 0x00000338, 0x00000274, + 0x00000094, 0x00000276, 0x000400a8, 0x00000014, 0x00000128, 0x00000337, 0x000300f7, 0x0000012a, 0x00000000, + 0x000400fa, 0x00000128, 0x00000129, 0x0000012a, 0x000200f8, 0x00000129, 0x00060041, 0x00000109, 0x0000012b, + 0x000000fc, 0x00000083, 0x000000a5, 0x0004003d, 0x000000f1, 0x0000012c, 0x0000012b, 0x00060041, 0x0000010d, + 0x0000012e, 0x0000012c, 0x00000083, 0x000000ee, 0x0006003d, 0x000000f3, 0x0000012f, 0x0000012e, 0x00000002, + 0x00000008, 0x00050041, 0x00000110, 0x00000131, 0x0000012f, 0x00000083, 0x00050041, 0x00000133, 0x00000134, + 0x00000131, 0x00000083, 0x00050041, 0x00000136, 0x00000137, 0x00000134, 0x00000083, 0x0005003e, 0x00000137, + 0x00000332, 0x00000002, 0x00000004, 0x00050041, 0x00000136, 0x00000139, 0x00000134, 0x00000060, 0x0005003e, + 0x00000139, 0x00000330, 0x00000002, 0x00000004, 0x000200f9, 0x0000012a, 0x000200f8, 0x0000012a, 0x000200f9, + 0x0000013c, 0x000200f8, 0x0000013c, 0x000100fd, 0x00010038 }; GFXRECON_END_NAMESPACE(decode) diff --git a/framework/decode/vulkan_decoder_base.cpp b/framework/decode/vulkan_decoder_base.cpp index fed5c31f5a..b809cd4715 100644 --- a/framework/decode/vulkan_decoder_base.cpp +++ b/framework/decode/vulkan_decoder_base.cpp @@ -578,35 +578,12 @@ void VulkanDecoderBase::DispatchVulkanAccelerationStructuresBuildMetaCommand(con std::size_t bytes_read = ValueDecoder::DecodeHandleIdValue(parameter_buffer, buffer_size, &device_id); bytes_read += pInfos.Decode(parameter_buffer + bytes_read, buffer_size - bytes_read); - bytes_read += ppRangeInfos.Decode(parameter_buffer + bytes_read, buffer_size - bytes_read); - - std::vector> instance_buffers; - if (bytes_read < buffer_size) - { - for (uint32_t i = 0; i < pInfos.GetLength(); ++i) - { - if (pInfos.GetPointer()[i].type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR) - { - continue; - } - - uint32_t geometry_count = pInfos.GetPointer()[i].geometryCount; - for (uint32_t g = 0; g < geometry_count; ++g) - { - instance_buffers.emplace_back(ppRangeInfos.GetPointer()[g]->primitiveCount); - util::platform::MemoryCopy(instance_buffers.back().data(), - instance_buffers.back().size() * sizeof(VkAccelerationStructureInstanceKHR), - parameter_buffer + bytes_read, - instance_buffers.back().size() * sizeof(VkAccelerationStructureInstanceKHR)); - bytes_read += instance_buffers.back().size() * sizeof(VkAccelerationStructureInstanceKHR); - } - } - } + ppRangeInfos.Decode(parameter_buffer + bytes_read, buffer_size - bytes_read); for (auto consumer : consumers_) { consumer->ProcessBuildVulkanAccelerationStructuresMetaCommand( - device_id, pInfos.GetLength(), &pInfos, &ppRangeInfos, instance_buffers); + device_id, pInfos.GetLength(), &pInfos, &ppRangeInfos); } } @@ -617,7 +594,7 @@ void VulkanDecoderBase::DispatchVulkanAccelerationStructuresCopyMetaCommand(cons StructPointerDecoder pInfos; std::size_t bytes_read = ValueDecoder::DecodeHandleIdValue(parameter_buffer, buffer_size, &device_id); - pInfos.Decode(parameter_buffer + bytes_read, buffer_size - bytes_read); + bytes_read += pInfos.Decode(parameter_buffer + bytes_read, buffer_size - bytes_read); for (auto consumer : consumers_) { diff --git a/framework/decode/vulkan_device_address_tracker.cpp b/framework/decode/vulkan_device_address_tracker.cpp index bab13b5993..bd257944a9 100644 --- a/framework/decode/vulkan_device_address_tracker.cpp +++ b/framework/decode/vulkan_device_address_tracker.cpp @@ -27,14 +27,15 @@ GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(decode) VulkanDeviceAddressTracker::VulkanDeviceAddressTracker(const VulkanObjectInfoTable& object_info_table) : - _object_info_table(object_info_table) + object_info_table_(object_info_table) {} void decode::VulkanDeviceAddressTracker::TrackBuffer(const decode::VulkanBufferInfo* buffer_info) { if (buffer_info != nullptr && buffer_info->capture_address != 0) { - _buffer_capture_addresses[buffer_info->capture_address] = buffer_info->capture_id; + buffer_capture_addresses_[buffer_info->capture_address] = buffer_info->capture_id; + buffer_handles_[buffer_info->handle] = buffer_info->capture_id; } } @@ -42,7 +43,7 @@ void VulkanDeviceAddressTracker::RemoveBuffer(const VulkanBufferInfo* buffer_inf { if (buffer_info != nullptr) { - _buffer_capture_addresses.erase(buffer_info->capture_address); + buffer_capture_addresses_.erase(buffer_info->capture_address); } } @@ -51,8 +52,12 @@ void VulkanDeviceAddressTracker::TrackAccelerationStructure( { if (acceleration_structure_info != nullptr && acceleration_structure_info->capture_address != 0) { - _acceleration_structure_capture_addresses[acceleration_structure_info->capture_address] = + // track device address + acceleration_structure_capture_addresses_[acceleration_structure_info->capture_address] = acceleration_structure_info->capture_id; + + // track vulkan-handle + acceleration_structure_handles_[acceleration_structure_info->handle] = acceleration_structure_info->capture_id; } } @@ -61,14 +66,25 @@ void VulkanDeviceAddressTracker::RemoveAccelerationStructure( { if (acceleration_structure_info != nullptr) { - _acceleration_structure_capture_addresses.erase(acceleration_structure_info->capture_id); + acceleration_structure_capture_addresses_.erase(acceleration_structure_info->capture_id); } } const decode::VulkanBufferInfo* decode::VulkanDeviceAddressTracker::GetBufferByCaptureDeviceAddress(VkDeviceAddress capture_address) const { - return GetBufferInfo(capture_address, _buffer_capture_addresses); + return GetBufferInfo(capture_address, buffer_capture_addresses_); +} + +const VulkanBufferInfo* VulkanDeviceAddressTracker::GetBufferByHandle(VkBuffer handle) const +{ + auto handle_it = buffer_handles_.find(handle); + if (handle_it != buffer_handles_.end()) + { + const auto& [h, handle_id] = *handle_it; + return object_info_table_.GetVkBufferInfo(handle_id); + } + return nullptr; } const VulkanBufferInfo* @@ -93,7 +109,7 @@ VulkanDeviceAddressTracker::GetBufferInfo(VkDeviceAddress } // found_address is lower or equal to device_address const auto& [found_address, buffer_handle] = *address_it; - const VulkanBufferInfo* found_buffer = _object_info_table.GetVkBufferInfo(buffer_handle); + const VulkanBufferInfo* found_buffer = object_info_table_.GetVkBufferInfo(buffer_handle); if (found_buffer != nullptr) { @@ -109,28 +125,35 @@ VulkanDeviceAddressTracker::GetBufferInfo(VkDeviceAddress const VulkanAccelerationStructureKHRInfo* VulkanDeviceAddressTracker::GetAccelerationStructureByCaptureDeviceAddress(VkDeviceAddress capture_address) const { - auto address_it = _acceleration_structure_capture_addresses.find(capture_address); - if (address_it != _acceleration_structure_capture_addresses.end()) + auto address_it = acceleration_structure_capture_addresses_.find(capture_address); + if (address_it != acceleration_structure_capture_addresses_.end()) { const auto& [found_address, acceleration_structure_handle] = *address_it; - const VulkanAccelerationStructureKHRInfo* found_acceleration_structure_info = - _object_info_table.GetVkAccelerationStructureKHRInfo(acceleration_structure_handle); + return object_info_table_.GetVkAccelerationStructureKHRInfo(acceleration_structure_handle); + } + return nullptr; +} - if (found_acceleration_structure_info != nullptr) - { - return found_acceleration_structure_info; - } +[[nodiscard]] const VulkanAccelerationStructureKHRInfo* +VulkanDeviceAddressTracker::GetAccelerationStructureByHandle(VkAccelerationStructureKHR handle) const +{ + auto handle_it = acceleration_structure_handles_.find(handle); + if (handle_it != acceleration_structure_handles_.end()) + { + const auto& [h, handle_id] = *handle_it; + return object_info_table_.GetVkAccelerationStructureKHRInfo(handle_id); } return nullptr; } + std::unordered_map VulkanDeviceAddressTracker::GetAccelerationStructureDeviceAddressMap() const { std::unordered_map ret; - for (const auto& [address, handleId] : _acceleration_structure_capture_addresses) + for (const auto& [address, handleId] : acceleration_structure_capture_addresses_) { const VulkanAccelerationStructureKHRInfo* acceleration_structure_info = - _object_info_table.GetVkAccelerationStructureKHRInfo(handleId); + object_info_table_.GetVkAccelerationStructureKHRInfo(handleId); if (acceleration_structure_info != nullptr && acceleration_structure_info->replay_address != 0) { diff --git a/framework/decode/vulkan_device_address_tracker.h b/framework/decode/vulkan_device_address_tracker.h index c73857a4a2..f5b4c04f66 100644 --- a/framework/decode/vulkan_device_address_tracker.h +++ b/framework/decode/vulkan_device_address_tracker.h @@ -81,6 +81,14 @@ class VulkanDeviceAddressTracker */ [[nodiscard]] const VulkanBufferInfo* GetBufferByCaptureDeviceAddress(VkDeviceAddress capture_address) const; + /** + * @brief Retrieve a buffer info-struct by providing its vulkan-handle. + * + * @param handle a capture-time VkBuffer handle. + * @return a const-pointer to a found BufferInfo or nullptr. + */ + [[nodiscard]] const VulkanBufferInfo* GetBufferByHandle(VkBuffer handle) const; + /** * @brief Retrieve an acceleration-structure by providing a capture-time VkDeviceAddress. * @@ -90,6 +98,15 @@ class VulkanDeviceAddressTracker [[nodiscard]] const VulkanAccelerationStructureKHRInfo* GetAccelerationStructureByCaptureDeviceAddress(VkDeviceAddress capture_address) const; + /** + * @brief Retrieve an acceleration-structure info-struct by providing its vulkan-handle. + * + * @param handle a replay-time VkAccelerationStructureKHR handle. + * @return a const-pointer to a found AccelerationStructureKHRInfo or nullptr. + */ + [[nodiscard]] const VulkanAccelerationStructureKHRInfo* + GetAccelerationStructureByHandle(VkAccelerationStructureKHR handle) const; + /** * @brief Create and return a lookup-table containing all internally stored acceleration-structure addresses. * @@ -104,9 +121,12 @@ class VulkanDeviceAddressTracker [[nodiscard]] const VulkanBufferInfo* GetBufferInfo(VkDeviceAddress device_address, const buffer_address_map_t& address_map) const; - const VulkanObjectInfoTable& _object_info_table; - buffer_address_map_t _buffer_capture_addresses; - std::unordered_map _acceleration_structure_capture_addresses; + const VulkanObjectInfoTable& object_info_table_; + buffer_address_map_t buffer_capture_addresses_; + std::unordered_map acceleration_structure_capture_addresses_; + + std::unordered_map buffer_handles_; + std::unordered_map acceleration_structure_handles_; }; GFXRECON_END_NAMESPACE(decode) diff --git a/framework/decode/vulkan_object_info.h b/framework/decode/vulkan_object_info.h index 4d18a647d3..76f43e09a0 100644 --- a/framework/decode/vulkan_object_info.h +++ b/framework/decode/vulkan_object_info.h @@ -166,7 +166,8 @@ struct VulkanReplayDeviceInfo std::optional memory_properties; // extensions - std::optional raytracing_properties; + std::optional raytracing_properties; + std::optional acceleration_structure_properties; }; template @@ -707,6 +708,11 @@ struct VulkanAccelerationStructureKHRInfo : public VulkanObjectInfosize, min_buffer_alignment_); + result = functions_.create_buffer(device_, &modified_info, nullptr, buffer); if (result >= 0) { @@ -557,6 +559,7 @@ VkResult VulkanRebindAllocator::BindBufferMemory(VkBuffer VkMemoryRequirements requirements; functions_.get_buffer_memory_requirements(device_, buffer, &requirements); + requirements.alignment = std::max(requirements.alignment, min_buffer_alignment_); VmaAllocationCreateInfo create_info; create_info.flags = 0; @@ -640,6 +643,7 @@ VkResult VulkanRebindAllocator::BindBufferMemory2(uint32_t VkMemoryRequirements requirements; functions_.get_buffer_memory_requirements(device_, buffer, &requirements); + requirements.alignment = std::max(requirements.alignment, min_buffer_alignment_); VmaAllocationCreateInfo create_info; create_info.flags = 0; diff --git a/framework/decode/vulkan_rebind_allocator.h b/framework/decode/vulkan_rebind_allocator.h index cb5eac68ae..5615c2a9c9 100644 --- a/framework/decode/vulkan_rebind_allocator.h +++ b/framework/decode/vulkan_rebind_allocator.h @@ -446,6 +446,9 @@ class VulkanRebindAllocator : public VulkanResourceAllocator VkCommandPool cmd_pool_ = VK_NULL_HANDLE; VkQueue staging_queue_ = VK_NULL_HANDLE; uint32_t staging_queue_family_{}; + + //! define a general minimum alignment for buffers + uint32_t min_buffer_alignment_ = 128; }; GFXRECON_END_NAMESPACE(decode) diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index f2eac5805a..608adc1ee0 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -1401,6 +1401,14 @@ void VulkanReplayConsumerBase::SetPhysicalDeviceProperties(VulkanPhysicalDeviceI physical_device_info->replay_device_info->raytracing_properties = *ray_replay_props; physical_device_info->replay_device_info->raytracing_properties->pNext = nullptr; } + + if (auto acceleration_structure_replay_props = + graphics::vulkan_struct_get_pnext(replay_properties)) + { + physical_device_info->replay_device_info->acceleration_structure_properties = + *acceleration_structure_replay_props; + physical_device_info->replay_device_info->acceleration_structure_properties->pNext = nullptr; + } } void VulkanReplayConsumerBase::SetPhysicalDeviceMemoryProperties( @@ -3508,6 +3516,9 @@ VkResult VulkanReplayConsumerBase::OverrideGetQueryPoolResults(PFN_vkGetQueryPoo } while (((original_result == VK_SUCCESS) && (result == VK_NOT_READY)) && (++retries <= kMaxQueryPoolResultsRetries)); + auto& address_replacer = GetDeviceAddressReplacer(device_info); + address_replacer.ProcessGetQueryPoolResults( + device, query_pool, firstQuery, queryCount, dataSize, pData->GetOutputPointer(), stride, flags); return result; } @@ -4294,27 +4305,33 @@ void VulkanReplayConsumerBase::OverrideFreeCommandBuffers(PFN_vkFreeCommandBuffe uint32_t command_buffer_count, HandlePointerDecoder* pCommandBuffers) { - assert((device_info != nullptr) && (pCommandBuffers != nullptr) && - (pCommandBuffers->GetHandlePointer() != nullptr)); + GFXRECON_ASSERT((device_info != nullptr) && (pCommandBuffers != nullptr) && + (pCommandBuffers->GetHandlePointer() != nullptr)); - if (options_.dumping_resources && command_pool_info != nullptr) + if (command_pool_info != nullptr) { const format::HandleId* cmd_buf_handles = pCommandBuffers->GetPointer(); for (uint32_t i = 0; i < command_buffer_count; ++i) { - auto it = command_pool_info->child_ids.find(cmd_buf_handles[i]); - if (it != command_pool_info->child_ids.end()) + if (options_.dumping_resources) { - if (options_.dumping_resources) + auto it = command_pool_info->child_ids.find(cmd_buf_handles[i]); + if (it != command_pool_info->child_ids.end()) { VulkanCommandBufferInfo* cb_info = object_info_table_->GetVkCommandBufferInfo(*it); assert(cb_info != nullptr); resource_dumper_->ResetCommandBuffer(cb_info->handle); } } + + // free potential shadow-resources associated with this command-buffer + VulkanCommandBufferInfo* cb_info = object_info_table_->GetVkCommandBufferInfo(cmd_buf_handles[i]); + if (cb_info != nullptr) + { + GetDeviceAddressReplacer(device_info).DestroyShadowResources(cb_info->handle); + } } } - const VkCommandBuffer* in_pCommandBuffers = pCommandBuffers->GetHandlePointer(); func(device_info->handle, command_pool_info->handle, command_buffer_count, in_pCommandBuffers); } @@ -7702,6 +7719,13 @@ VkResult VulkanReplayConsumerBase::OverrideCreateAccelerationStructureKHR( auto replay_create_info = pCreateInfo->GetPointer(); VkDevice device = device_info->handle; + // keep track of associated buffer + auto* acceleration_structure_info = + reinterpret_cast(pAccelerationStructureKHR->GetConsumerData(0)); + GFXRECON_ASSERT(acceleration_structure_info); + acceleration_structure_info->type = replay_create_info->type; + acceleration_structure_info->buffer = replay_create_info->buffer; + if (device_info->property_feature_info.feature_accelerationStructureCaptureReplay) { // Set opaque device address @@ -7725,7 +7749,6 @@ VkResult VulkanReplayConsumerBase::OverrideCreateAccelerationStructureKHR( { result = func(device, replay_create_info, GetAllocationCallbacks(pAllocator), replay_accel_struct); } - return result; } @@ -7749,6 +7772,9 @@ void VulkanReplayConsumerBase::OverrideDestroyAccelerationStructureKHR( // remove from address-tracking GetDeviceAddressTracker(device_info).RemoveAccelerationStructure(acceleration_structure_info); + + // free potential shadow-resources + GetDeviceAddressReplacer(device_info).DestroyShadowResources(acceleration_structure); } func(device_info->handle, acceleration_structure, GetAllocationCallbacks(pAllocator)); } @@ -7782,17 +7808,19 @@ void VulkanReplayConsumerBase::OverrideCmdCopyAccelerationStructureKHR( VulkanCommandBufferInfo* command_buffer_info, StructPointerDecoder* pInfo) { + GFXRECON_ASSERT(command_buffer_info != nullptr && pInfo != nullptr) VulkanDeviceInfo* device_info = object_info_table_->GetVkDeviceInfo(command_buffer_info->parent_id); - if (device_info->allocator->SupportsOpaqueDeviceAddresses()) - { - VkCommandBuffer command_buffer = command_buffer_info->handle; - VkCopyAccelerationStructureInfoKHR* info = pInfo->GetPointer(); - func(command_buffer, info); - } - else if (!loading_trim_state_) + GFXRECON_ASSERT(device_info != nullptr) + + VkCommandBuffer command_buffer = command_buffer_info->handle; + VkCopyAccelerationStructureInfoKHR* info = pInfo->GetPointer(); + { - // TODO: raytracing delegate-hook (issue #1526) + const auto& address_tracker = GetDeviceAddressTracker(device_info); + auto& address_replacer = GetDeviceAddressReplacer(device_info); + address_replacer.ProcessCmdCopyAccelerationStructuresKHR(info, address_tracker); } + func(command_buffer, info); } void VulkanReplayConsumerBase::OverrideCmdWriteAccelerationStructuresPropertiesKHR( @@ -7804,18 +7832,20 @@ void VulkanReplayConsumerBase::OverrideCmdWriteAccelerationStructuresPropertiesK gfxrecon::decode::VulkanQueryPoolInfo* query_pool_info, uint32_t firstQuery) { + GFXRECON_ASSERT(command_buffer_info != nullptr) VulkanDeviceInfo* device_info = object_info_table_->GetVkDeviceInfo(command_buffer_info->parent_id); - if (device_info->allocator->SupportsOpaqueDeviceAddresses()) - { - VkCommandBuffer command_buffer = command_buffer_info->handle; - const VkAccelerationStructureKHR* acceleration_structs = pAccelerationStructures->GetHandlePointer(); - VkQueryPool query_pool = query_pool_info->handle; - func(command_buffer, count, acceleration_structs, queryType, query_pool, firstQuery); - } - else if (!loading_trim_state_) + GFXRECON_ASSERT(device_info != nullptr) + + VkCommandBuffer command_buffer = command_buffer_info->handle; + VkAccelerationStructureKHR* acceleration_structs = pAccelerationStructures->GetHandlePointer(); + VkQueryPool query_pool = query_pool_info->handle; + { - // TODO: raytracing delegate-hook (issue #1526) + auto& address_replacer = GetDeviceAddressReplacer(device_info); + address_replacer.ProcessCmdWriteAccelerationStructuresPropertiesKHR( + count, acceleration_structs, queryType, query_pool, firstQuery); } + func(command_buffer, count, acceleration_structs, queryType, query_pool, firstQuery); } VkResult VulkanReplayConsumerBase::OverrideCreateRayTracingPipelinesKHR( @@ -7845,7 +7875,6 @@ VkResult VulkanReplayConsumerBase::OverrideCreateRayTracingPipelinesKHR( VkPipelineCache overridePipelineCache = in_pipelineCache; // If there is no pipeline cache and we want to create a new one - if (in_pipelineCache == VK_NULL_HANDLE && options_.add_new_pipeline_caches) { overridePipelineCache = CreateNewPipelineCache(device_info, *pPipelines->GetPointer()); @@ -7863,8 +7892,8 @@ VkResult VulkanReplayConsumerBase::OverrideCreateRayTracingPipelinesKHR( &pPipelines->GetPointer()[createInfoCount]); } - // NOTE: this is almost never true, even on newest desktop-drivers - // TODO: consider removing all of the feature_rayTracingPipelineShaderGroupHandleCaptureReplay logic here + // NOTE: as of early 2025, rayTracingPipelineShaderGroupHandleCaptureReplay is not widely supported. + // e.g. newest nvidia desktop-drivers do not support this feature if (device_info->property_feature_info.feature_rayTracingPipelineShaderGroupHandleCaptureReplay) { // Modify pipeline create infos with capture replay flag and data. @@ -8023,7 +8052,7 @@ VkResult VulkanReplayConsumerBase::OverrideCreateRayTracingPipelinesKHR( for (uint32_t i = 0; i < createInfoCount; ++i) { - VulkanPipelineInfo* pipeline_info = reinterpret_cast(pPipelines->GetConsumerData(i)); + auto* pipeline_info = reinterpret_cast(pPipelines->GetConsumerData(i)); const Decoded_VkPipelineShaderStageCreateInfo* stages_info_meta = create_info_meta[i].pStages->GetMetaStructPointer(); @@ -8042,7 +8071,6 @@ VkResult VulkanReplayConsumerBase::OverrideCreateRayTracingPipelinesKHR( } // If a pipeline cache was created, track it to know when to destroy it/save it to file - if (in_pipelineCache != overridePipelineCache && result == VK_SUCCESS) { TrackNewPipelineCache(device_info, @@ -8051,7 +8079,6 @@ VkResult VulkanReplayConsumerBase::OverrideCreateRayTracingPipelinesKHR( pPipelines->GetHandlePointer(), createInfoCount); } - return result; } @@ -8614,20 +8641,23 @@ void VulkanReplayConsumerBase::OverrideCmdTraceRaysKHR( VkStridedDeviceAddressRegionKHR* in_pHitShaderBindingTable = pHitShaderBindingTable->GetPointer(); VkStridedDeviceAddressRegionKHR* in_pCallableShaderBindingTable = pCallableShaderBindingTable->GetPointer(); - // identify buffer(s) by their device-address - const auto& address_tracker = GetDeviceAddressTracker(device_info); - auto& address_replacer = GetDeviceAddressReplacer(device_info); + if (!device_info->allocator->SupportsOpaqueDeviceAddresses()) + { + // identify buffer(s) by their device-address + const auto& address_tracker = GetDeviceAddressTracker(device_info); + auto& address_replacer = GetDeviceAddressReplacer(device_info); - auto bound_pipeline = GetObjectInfoTable().GetVkPipelineInfo(command_buffer_info->bound_pipeline_id); - GFXRECON_ASSERT(bound_pipeline != nullptr) + auto bound_pipeline = GetObjectInfoTable().GetVkPipelineInfo(command_buffer_info->bound_pipeline_id); + GFXRECON_ASSERT(bound_pipeline != nullptr) - address_replacer.ProcessCmdTraceRays(command_buffer_info, - in_pRaygenShaderBindingTable, - in_pMissShaderBindingTable, - in_pHitShaderBindingTable, - in_pCallableShaderBindingTable, - address_tracker, - bound_pipeline->shader_group_handle_map); + address_replacer.ProcessCmdTraceRays(command_buffer_info, + in_pRaygenShaderBindingTable, + in_pMissShaderBindingTable, + in_pHitShaderBindingTable, + in_pCallableShaderBindingTable, + address_tracker, + bound_pipeline->shader_group_handle_map); + } func(commandBuffer, in_pRaygenShaderBindingTable, @@ -9425,9 +9455,12 @@ VulkanAddressReplacer& VulkanReplayConsumerBase::GetDeviceAddressReplacer(const auto it = _device_address_replacers.find(device_info); if (it == _device_address_replacers.end()) { - auto [new_it, success] = _device_address_replacers.insert( - { device_info, - VulkanAddressReplacer(device_info, GetDeviceTable(device_info->handle), *object_info_table_) }); + auto [new_it, success] = + _device_address_replacers.insert({ device_info, + VulkanAddressReplacer(device_info, + GetDeviceTable(device_info->handle), + GetInstanceTable(device_info->parent), + *object_info_table_) }); GFXRECON_ASSERT(success); return new_it->second; } @@ -9624,69 +9657,65 @@ void VulkanReplayConsumerBase::Process_vkCreateRayTracingPipelinesKHR( void VulkanReplayConsumerBase::ProcessCopyVulkanAccelerationStructuresMetaCommand( format::HandleId device, StructPointerDecoder* copy_infos) { - VulkanDeviceInfo* device_info = GetObjectInfoTable().GetVkDeviceInfo(device); - GFXRECON_ASSERT(device_info != nullptr); - - auto allocator = device_info->allocator.get(); - GFXRECON_ASSERT(allocator != nullptr); - - if (allocator->SupportsOpaqueDeviceAddresses() || !loading_trim_state_) + if (loading_trim_state_) { - return; - } + VulkanDeviceInfo* device_info = GetObjectInfoTable().GetVkDeviceInfo(device); + GFXRECON_ASSERT(device_info != nullptr); - MapStructArrayHandles(copy_infos->GetMetaStructPointer(), copy_infos->GetLength(), GetObjectInfoTable()); + if (!device_info->allocator->SupportsOpaqueDeviceAddresses()) + { + MapStructArrayHandles(copy_infos->GetMetaStructPointer(), copy_infos->GetLength(), GetObjectInfoTable()); - // TODO: implement - // acceleration_structure_builders_[device]->ProcessCopyVulkanAccelerationStructuresMetaCommand( - // copy_infos->GetLength(), copy_infos->GetPointer()); + const auto& address_tracker = GetDeviceAddressTracker(device_info); + auto& address_replacer = GetDeviceAddressReplacer(device_info); + address_replacer.ProcessCopyVulkanAccelerationStructuresMetaCommand( + copy_infos->GetLength(), copy_infos->GetPointer(), address_tracker); + } + } } void VulkanReplayConsumerBase::ProcessBuildVulkanAccelerationStructuresMetaCommand( format::HandleId device, uint32_t info_count, StructPointerDecoder* pInfos, - StructPointerDecoder* ppRangeInfos, - std::vector>& instance_buffers_data) + StructPointerDecoder* ppRangeInfos) { - VulkanDeviceInfo* device_info = GetObjectInfoTable().GetVkDeviceInfo(device); - GFXRECON_ASSERT(device_info != nullptr); - - auto allocator = device_info->allocator.get(); - GFXRECON_ASSERT(allocator != nullptr); - - if (allocator->SupportsOpaqueDeviceAddresses() || !loading_trim_state_) + if (loading_trim_state_) { - return; - } + VulkanDeviceInfo* device_info = GetObjectInfoTable().GetVkDeviceInfo(device); + GFXRECON_ASSERT(device_info != nullptr); + + if (!device_info->allocator->SupportsOpaqueDeviceAddresses()) + { + MapStructArrayHandles(pInfos->GetMetaStructPointer(), pInfos->GetLength(), GetObjectInfoTable()); - MapStructArrayHandles(pInfos->GetMetaStructPointer(), pInfos->GetLength(), GetObjectInfoTable()); + VkAccelerationStructureBuildGeometryInfoKHR* build_geometry_infos = pInfos->GetPointer(); + VkAccelerationStructureBuildRangeInfoKHR** range_infos = ppRangeInfos->GetPointer(); - // TODO: implement - // acceleration_structure_builders_[device]->ProcessBuildVulkanAccelerationStructuresMetaCommand( - // info_count, pInfos->GetPointer(), ppRangeInfos->GetPointer(), instance_buffers_data); + GetDeviceAddressReplacer(device_info) + .ProcessBuildVulkanAccelerationStructuresMetaCommand( + info_count, pInfos->GetPointer(), ppRangeInfos->GetPointer(), GetDeviceAddressTracker(device_info)); + } + } } void VulkanReplayConsumerBase::ProcessVulkanAccelerationStructuresWritePropertiesMetaCommand( format::HandleId device_id, VkQueryType query_type, format::HandleId acceleration_structure_id) { - VulkanDeviceInfo* device_info = GetObjectInfoTable().GetVkDeviceInfo(device_id); - GFXRECON_ASSERT(device_info != nullptr); - - auto allocator = device_info->allocator.get(); - GFXRECON_ASSERT(allocator != nullptr); - - if (allocator->SupportsOpaqueDeviceAddresses() || !loading_trim_state_) + if (loading_trim_state_) { - return; - } + VulkanDeviceInfo* device_info = GetObjectInfoTable().GetVkDeviceInfo(device_id); + GFXRECON_ASSERT(device_info != nullptr); - VkAccelerationStructureKHR acceleration_structure = MapHandle( - acceleration_structure_id, &VulkanObjectInfoTable::GetVkAccelerationStructureKHRInfo); + if (!device_info->allocator->SupportsOpaqueDeviceAddresses()) + { + VkAccelerationStructureKHR acceleration_structure = MapHandle( + acceleration_structure_id, &VulkanObjectInfoTable::GetVkAccelerationStructureKHRInfo); - // TODO: implement - // acceleration_structure_builders_[device_id]->ProcessVulkanAccelerationStructuresWritePropertiesMetaCommand( - // query_type, acceleration_structure); + GetDeviceAddressReplacer(device_info) + .ProcessVulkanAccelerationStructuresWritePropertiesMetaCommand(query_type, acceleration_structure); + } + } } void VulkanReplayConsumerBase::OverrideUpdateDescriptorSets( @@ -9697,8 +9726,17 @@ void VulkanReplayConsumerBase::OverrideUpdateDescriptorSets( uint32_t descriptor_copy_count, StructPointerDecoder* p_pescriptor_copies) { - const VkWriteDescriptorSet* in_pDescriptorWrites = p_descriptor_writes->GetPointer(); - const VkCopyDescriptorSet* in_pDescriptorCopies = p_pescriptor_copies->GetPointer(); + GFXRECON_ASSERT(device_info != nullptr); + + VkWriteDescriptorSet* in_pDescriptorWrites = p_descriptor_writes->GetPointer(); + VkCopyDescriptorSet* in_pDescriptorCopies = p_pescriptor_copies->GetPointer(); + + { + // check/correct specific resource handles (i.e. VkAccelerationStructure) + auto& address_replacer = GetDeviceAddressReplacer(device_info); + address_replacer.ProcessUpdateDescriptorSets( + descriptor_write_count, in_pDescriptorWrites, descriptor_copy_count, in_pDescriptorCopies); + } func( device_info->handle, descriptor_write_count, in_pDescriptorWrites, descriptor_copy_count, in_pDescriptorCopies); diff --git a/framework/decode/vulkan_replay_consumer_base.h b/framework/decode/vulkan_replay_consumer_base.h index cd45c3bdfa..15d38a3258 100644 --- a/framework/decode/vulkan_replay_consumer_base.h +++ b/framework/decode/vulkan_replay_consumer_base.h @@ -205,11 +205,10 @@ class VulkanReplayConsumerBase : public VulkanConsumer format::HandleId device, uint32_t info_count, StructPointerDecoder* pInfos, - StructPointerDecoder* ppRangeInfos, - std::vector>& instance_buffers_data) override; + StructPointerDecoder* ppRangeInfos) override; void ProcessCopyVulkanAccelerationStructuresMetaCommand( - format::HandleId device, StructPointerDecoder* copy_infos) override; + format::HandleId device, StructPointerDecoder* copy_info) override; void ProcessVulkanAccelerationStructuresWritePropertiesMetaCommand( format::HandleId device_id, VkQueryType query_type, format::HandleId acceleration_structure_id) override; diff --git a/framework/encode/custom_vulkan_encoder_commands.h b/framework/encode/custom_vulkan_encoder_commands.h index e3660a94e5..42d73156d8 100644 --- a/framework/encode/custom_vulkan_encoder_commands.h +++ b/framework/encode/custom_vulkan_encoder_commands.h @@ -1020,16 +1020,6 @@ struct CustomEncoderPreCall -struct CustomEncoderPreCall -{ - template - static void Dispatch(VulkanCaptureManager* manager, Args... args) - { - manager->PreProcess_vkGetRayTracingShaderGroupHandlesKHR(args...); - } -}; - template <> struct CustomEncoderPostCall { diff --git a/framework/encode/vulkan_capture_manager.cpp b/framework/encode/vulkan_capture_manager.cpp index 3dd770ef45..3727388f73 100644 --- a/framework/encode/vulkan_capture_manager.cpp +++ b/framework/encode/vulkan_capture_manager.cpp @@ -951,11 +951,40 @@ void VulkanCaptureManager::OverrideCmdBuildAccelerationStructuresKHR( { state_tracker_->TrackAccelerationStructureBuildCommand(commandBuffer, infoCount, pInfos, ppBuildRangeInfos); } - const VulkanDeviceTable* device_table = vulkan_wrappers::GetDeviceTable(commandBuffer); device_table->CmdBuildAccelerationStructuresKHR(commandBuffer, infoCount, pInfos, ppBuildRangeInfos); } +void VulkanCaptureManager::OverrideCmdCopyAccelerationStructureKHR(VkCommandBuffer command_buffer, + const VkCopyAccelerationStructureInfoKHR* pInfo) +{ + if (IsCaptureModeTrack()) + { + state_tracker_->TrackAccelerationStructureCopyCommand(command_buffer, pInfo); + } + const VulkanDeviceTable* device_table = vulkan_wrappers::GetDeviceTable(command_buffer); + device_table->CmdCopyAccelerationStructureKHR(command_buffer, pInfo); +} + +void VulkanCaptureManager::OverrideCmdWriteAccelerationStructuresPropertiesKHR( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery) +{ + if (IsCaptureModeTrack()) + { + state_tracker_->TrackWriteAccelerationStructuresPropertiesCommand( + commandBuffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery); + } + + const VulkanDeviceTable* device_table = vulkan_wrappers::GetDeviceTable(commandBuffer); + device_table->CmdWriteAccelerationStructuresPropertiesKHR( + commandBuffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery); +} + VkResult VulkanCaptureManager::OverrideAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, @@ -1131,6 +1160,15 @@ void VulkanCaptureManager::OverrideGetPhysicalDeviceProperties2(VkPhysicalDevice state_tracker_->TrackRayTracingPipelineProperties(physicalDevice, raytracing_props); } } + + if (auto acceleration_props = + graphics::vulkan_struct_get_pnext(pProperties)) + { + if (IsCaptureModeTrack()) + { + state_tracker_->TrackAccelerationStructureProperties(physicalDevice, acceleration_props); + } + } } VkResult VulkanCaptureManager::OverrideGetPhysicalDeviceToolPropertiesEXT( @@ -1288,11 +1326,6 @@ VulkanCaptureManager::OverrideCreateRayTracingPipelinesKHR(VkDevice } else { - GFXRECON_LOG_ERROR_ONCE( - "The capturing application used vkCreateRayTracingPipelinesKHR, which may require the " - "rayTracingPipelineShaderGroupHandleCaptureReplay feature for accurate capture and replay. The capturing " - "device does not support this feature, so replay may fail."); - if (deferred_operation_wrapper) { deferred_operation_wrapper->create_infos.clear(); @@ -1379,7 +1412,6 @@ VulkanCaptureManager::OverrideCreateRayTracingPipelinesKHR(VkDevice } } } - return result; } @@ -2495,19 +2527,6 @@ void VulkanCaptureManager::PreProcess_vkGetAccelerationStructureDeviceAddressKHR } } -void VulkanCaptureManager::PreProcess_vkGetRayTracingShaderGroupHandlesKHR( - VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) -{ - auto device_wrapper = vulkan_wrappers::GetWrapper(device); - if (!device_wrapper->property_feature_info.feature_rayTracingPipelineShaderGroupHandleCaptureReplay) - { - GFXRECON_LOG_WARNING_ONCE( - "The application is using vkGetRayTracingShaderGroupHandlesKHR, which may require the " - "rayTracingPipelineShaderGroupHandleCaptureReplay feature for accurate capture and replay. The capture " - "device does not support this feature, so replay of the captured file may fail."); - } -} - void VulkanCaptureManager::PreProcess_vkGetAndroidHardwareBufferPropertiesANDROID( VkDevice device, const struct AHardwareBuffer* hardware_buffer, diff --git a/framework/encode/vulkan_capture_manager.h b/framework/encode/vulkan_capture_manager.h index f4916da2f8..b928248475 100644 --- a/framework/encode/vulkan_capture_manager.h +++ b/framework/encode/vulkan_capture_manager.h @@ -298,6 +298,16 @@ class VulkanCaptureManager : public ApiCaptureManager const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); + void OverrideCmdCopyAccelerationStructureKHR(VkCommandBuffer command_buffer, + const VkCopyAccelerationStructureInfoKHR* pInfo); + + void OverrideCmdWriteAccelerationStructuresPropertiesKHR(VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); + VkResult OverrideAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, @@ -1260,9 +1270,6 @@ class VulkanCaptureManager : public ApiCaptureManager PreProcess_vkGetAccelerationStructureDeviceAddressKHR(VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); - void PreProcess_vkGetRayTracingShaderGroupHandlesKHR( - VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); - void PreProcess_vkGetAndroidHardwareBufferPropertiesANDROID(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties); diff --git a/framework/encode/vulkan_handle_wrappers.h b/framework/encode/vulkan_handle_wrappers.h index 6c6143aa52..71859385be 100644 --- a/framework/encode/vulkan_handle_wrappers.h +++ b/framework/encode/vulkan_handle_wrappers.h @@ -146,8 +146,9 @@ struct PhysicalDeviceWrapper : public HandleWrapper std::unique_ptr queue_family_properties2; std::vector> queue_family_checkpoint_properties; - // Track RayTracingPipelinePropertiesKHR - std::optional ray_tracing_pipeline_properties; + // Track RayTracingPipeline / AccelerationStructure properties + std::optional ray_tracing_pipeline_properties; + std::optional acceleration_structure_properties; }; struct InstanceWrapper : public HandleWrapper @@ -586,7 +587,7 @@ struct AccelerationStructureKHRWrapper : public HandleWrapper geometry_info_memory; std::vector build_range_infos; - std::vector input_buffers; + std::unordered_map input_buffers; }; std::optional latest_update_command_{ std::nullopt }; std::optional latest_build_command_{ std::nullopt }; diff --git a/framework/encode/vulkan_state_tracker.cpp b/framework/encode/vulkan_state_tracker.cpp index 3d9a2d846a..065436c6ef 100644 --- a/framework/encode/vulkan_state_tracker.cpp +++ b/framework/encode/vulkan_state_tracker.cpp @@ -433,6 +433,8 @@ void VulkanStateTracker::TrackAccelerationStructureBuildCommand( continue; } + std::vector to_extract = { build_info.scratchData.deviceAddress }; + auto wrapper = vulkan_wrappers::GetWrapper( build_info.dstAccelerationStructure); @@ -442,24 +444,26 @@ void VulkanStateTracker::TrackAccelerationStructureBuildCommand( { auto geometry = build_info.pGeometries != nullptr ? build_info.pGeometries + g : build_info.ppGeometries[g]; - std::vector to_extract; switch (geometry->geometryType) { case VkGeometryTypeKHR::VK_GEOMETRY_TYPE_TRIANGLES_KHR: { - to_extract = { geometry->geometry.triangles.vertexData.deviceAddress, - geometry->geometry.triangles.indexData.deviceAddress, - geometry->geometry.triangles.transformData.deviceAddress }; + for (const auto& address : { geometry->geometry.triangles.vertexData.deviceAddress, + geometry->geometry.triangles.indexData.deviceAddress, + geometry->geometry.triangles.transformData.deviceAddress }) + { + to_extract.push_back(address); + } break; } case VkGeometryTypeKHR::VK_GEOMETRY_TYPE_AABBS_KHR: { - to_extract = { geometry->geometry.aabbs.data.deviceAddress }; + to_extract.push_back(geometry->geometry.aabbs.data.deviceAddress); break; } case VkGeometryTypeKHR::VK_GEOMETRY_TYPE_INSTANCES_KHR: { - to_extract = { geometry->geometry.instances.data.deviceAddress }; + to_extract.push_back(geometry->geometry.instances.data.deviceAddress); break; } case VK_GEOMETRY_TYPE_MAX_ENUM_KHR: @@ -479,7 +483,7 @@ void VulkanStateTracker::TrackAccelerationStructureBuildCommand( GFXRECON_ASSERT(target_buffer_wrapper != nullptr); vulkan_wrappers::AccelerationStructureKHRWrapper::ASInputBuffer& buffer = - dst_command.input_buffers.emplace_back(); + dst_command.input_buffers[target_buffer_wrapper->handle_id]; buffer.capture_address = address; buffer.handle = target_buffer_wrapper->handle; @@ -533,6 +537,46 @@ void VulkanStateTracker::TrackAccelerationStructureBuildCommand( } } +void VulkanStateTracker::TrackAccelerationStructureCopyCommand(VkCommandBuffer command_buffer, + const VkCopyAccelerationStructureInfoKHR* info) +{ + // TODO: Support other types of copies (clone, serialize, deserialize) + if (info == nullptr || info->mode != VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR) + { + return; + } + auto wrapper = vulkan_wrappers::GetWrapper(info->src); + if (!wrapper->latest_copy_command_) + { + wrapper->latest_copy_command_ = + vulkan_wrappers::AccelerationStructureKHRWrapper::AccelerationStructureCopyCommandData{}; + } + wrapper->latest_copy_command_->device = wrapper->device->handle_id; + wrapper->latest_copy_command_->info = *info; +} + +void VulkanStateTracker::TrackWriteAccelerationStructuresPropertiesCommand( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery) +{ + auto* cmd_buf_wrapper = vulkan_wrappers::GetWrapper(commandBuffer); + auto* query_pool_wrapper = vulkan_wrappers::GetWrapper(queryPool); + + for (uint32_t i = 0; i < accelerationStructureCount; ++i) + { + auto* wrapper = + vulkan_wrappers::GetWrapper(pAccelerationStructures[i]); + wrapper->latest_write_properties_command_ = + vulkan_wrappers::AccelerationStructureKHRWrapper::AccelerationStructureWritePropertiesCommandData{}; + wrapper->latest_write_properties_command_->device = wrapper->device->handle_id; + wrapper->latest_write_properties_command_->query_type = queryType; + } +} + void VulkanStateTracker::TrackImageMemoryBinding( VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset, const void* bind_info_pnext) { @@ -1812,16 +1856,24 @@ void VulkanStateTracker::TrackRayTracingPipelineProperties( wrapper->ray_tracing_pipeline_properties->pNext = nullptr; } +void VulkanStateTracker::TrackAccelerationStructureProperties( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceAccelerationStructurePropertiesKHR* acceleration_structure_properties) +{ + auto wrapper = vulkan_wrappers::GetWrapper(physicalDevice); + wrapper->acceleration_structure_properties = *acceleration_structure_properties; + wrapper->acceleration_structure_properties->pNext = nullptr; +} + void VulkanStateTracker::TrackRayTracingShaderGroupHandles(VkDevice device, VkPipeline pipeline, size_t data_size, const void* data) { assert((device != VK_NULL_HANDLE) && (pipeline != VK_NULL_HANDLE)); - - auto wrapper = vulkan_wrappers::GetWrapper(pipeline); - const uint8_t* byte_data = reinterpret_cast(data); - wrapper->device_id = vulkan_wrappers::GetWrappedId(device); + auto wrapper = vulkan_wrappers::GetWrapper(pipeline); + auto* byte_data = reinterpret_cast(data); + wrapper->device_id = vulkan_wrappers::GetWrappedId(device); wrapper->shader_group_handle_data.assign(byte_data, byte_data + data_size); } @@ -1979,23 +2031,23 @@ void gfxrecon::encode::VulkanStateTracker::DestroyState(vulkan_wrappers::BufferW { continue; } - for (vulkan_wrappers::AccelerationStructureKHRWrapper::ASInputBuffer& buffer : (*command)->input_buffers) - { - if (wrapper->handle_id == buffer.handle_id) - { - buffer.destroyed = true; - auto [resource_util, created] = resource_utils_.try_emplace( - buffer.bind_device->handle, - graphics::VulkanResourcesUtil(buffer.bind_device->handle, - buffer.bind_device->physical_device->handle, - buffer.bind_device->layer_table, - *buffer.bind_device->physical_device->layer_table_ref, - buffer.bind_device->physical_device->memory_properties)); - buffer.bind_device->layer_table.GetBufferMemoryRequirements( - buffer.bind_device->handle, buffer.handle, &buffer.memory_requirements); - resource_util->second.ReadFromBufferResource( - buffer.handle, buffer.created_size, 0, buffer.queue_family_index, buffer.bytes); - } + + auto it = (*command)->input_buffers.find(wrapper->handle_id); + if (it != (*command)->input_buffers.end()) + { + vulkan_wrappers::AccelerationStructureKHRWrapper::ASInputBuffer& buffer = it->second; + buffer.destroyed = true; + auto [resource_util, created] = resource_utils_.try_emplace( + buffer.bind_device->handle, + graphics::VulkanResourcesUtil(buffer.bind_device->handle, + buffer.bind_device->physical_device->handle, + buffer.bind_device->layer_table, + *buffer.bind_device->physical_device->layer_table_ref, + buffer.bind_device->physical_device->memory_properties)); + buffer.bind_device->layer_table.GetBufferMemoryRequirements( + buffer.bind_device->handle, buffer.handle, &buffer.memory_requirements); + resource_util->second.ReadFromBufferResource( + buffer.handle, buffer.created_size, 0, buffer.queue_family_index, buffer.bytes); } } }); diff --git a/framework/encode/vulkan_state_tracker.h b/framework/encode/vulkan_state_tracker.h index 05f7056d5a..4b9a9b20c7 100644 --- a/framework/encode/vulkan_state_tracker.h +++ b/framework/encode/vulkan_state_tracker.h @@ -454,11 +454,25 @@ class VulkanStateTracker const VkAccelerationStructureBuildGeometryInfoKHR* infos, const VkAccelerationStructureBuildRangeInfoKHR* const* pp_buildRange_infos); + void TrackAccelerationStructureCopyCommand(VkCommandBuffer command_buffer, + const VkCopyAccelerationStructureInfoKHR* info); + + void TrackWriteAccelerationStructuresPropertiesCommand(VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); + void TrackDeviceMemoryDeviceAddress(VkDevice device, VkDeviceMemory memory, VkDeviceAddress address); void TrackRayTracingPipelineProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceRayTracingPipelinePropertiesKHR* ray_properties); + void TrackAccelerationStructureProperties( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceAccelerationStructurePropertiesKHR* acceleration_structure_properties); + void TrackRayTracingShaderGroupHandles(VkDevice device, VkPipeline pipeline, size_t data_size, const void* data); void TrackAcquireFullScreenExclusiveMode(VkDevice device, VkSwapchainKHR swapchain); diff --git a/framework/encode/vulkan_state_writer.cpp b/framework/encode/vulkan_state_writer.cpp index afe054fb97..49174700da 100644 --- a/framework/encode/vulkan_state_writer.cpp +++ b/framework/encode/vulkan_state_writer.cpp @@ -137,7 +137,7 @@ uint64_t VulkanStateWriter::WriteState(const VulkanStateTable& state_table, uint StandardCreateWrite(state_table); // physical-device / raytracing properties - WriteRayTracingPipelinePropertiesState(state_table); + WriteRayTracingPropertiesState(state_table); // Utility object creation. StandardCreateWrite(state_table); @@ -1430,7 +1430,7 @@ void VulkanStateWriter::BeginAccelerationStructuresSection(format::HandleId devi begin_cmd.thread_id = thread_id_; begin_cmd.device_id = device_id; begin_cmd.max_resource_size = max_resource_size; - // Our buffers should not need staging copy as the memroy should be host visible and coherent + // Our buffers should not need staging copy as the memory should be host visible and coherent begin_cmd.max_copy_size = 0; output_stream_->Write(&begin_cmd, sizeof(begin_cmd)); @@ -1660,7 +1660,6 @@ void VulkanStateWriter::WriteTlasToBlasDependenciesMetadata(const VulkanStateTab }); } -// Rename this to represent the whole acc structure prepare process void VulkanStateWriter::WriteAccelerationStructureStateMetaCommands(const VulkanStateTable& state_table) { struct AccelerationStructureCommands @@ -1668,7 +1667,7 @@ void VulkanStateWriter::WriteAccelerationStructureStateMetaCommands(const Vulkan std::vector blas_build; std::vector tlas_build; std::vector write_properties; - AccelerationStructureCopyCommandData copies; + std::vector copy_infos; std::vector blas_update; std::vector tlas_update; }; @@ -1697,8 +1696,7 @@ void VulkanStateWriter::WriteAccelerationStructureStateMetaCommands(const Vulkan if (wrapper->latest_build_command_) { build_container->push_back(&wrapper->latest_build_command_.value()); - for (const vulkan_wrappers::AccelerationStructureKHRWrapper::ASInputBuffer& buffer : - wrapper->latest_build_command_->input_buffers) + for (const auto& [handle_id, buffer] : wrapper->latest_build_command_->input_buffers) { max_resource_size = std::max(max_resource_size, buffer.bytes.size()); } @@ -1707,8 +1705,7 @@ void VulkanStateWriter::WriteAccelerationStructureStateMetaCommands(const Vulkan if (wrapper->latest_update_command_) { update_container->push_back(&wrapper->latest_update_command_.value()); - for (const vulkan_wrappers::AccelerationStructureKHRWrapper::ASInputBuffer& buffer : - wrapper->latest_update_command_->input_buffers) + for (const auto& [handle_id, buffer] : wrapper->latest_update_command_->input_buffers) { max_resource_size = std::max(max_resource_size, buffer.bytes.size()); } @@ -1716,7 +1713,13 @@ void VulkanStateWriter::WriteAccelerationStructureStateMetaCommands(const Vulkan if (wrapper->latest_copy_command_) { - per_device_container.copies.infos.push_back(wrapper->latest_copy_command_.value().info); + // filter out stale handles + auto get_id = vulkan_wrappers::GetWrappedId; + if (get_id(wrapper->latest_copy_command_->info.src, false) != 0 && + get_id(wrapper->latest_copy_command_->info.dst, false) != 0) + { + per_device_container.copy_infos.push_back(wrapper->latest_copy_command_.value().info); + } } if (wrapper->latest_write_properties_command_) @@ -1740,7 +1743,7 @@ void VulkanStateWriter::WriteAccelerationStructureStateMetaCommands(const Vulkan EncodeAccelerationStructureWritePropertiesCommand(device, cmd_properties); } - EncodeAccelerationStructureCopyMetaCommand(device, command.copies); + EncodeAccelerationStructuresCopyMetaCommand(device, command.copy_infos); for (auto& tlas_build : command.tlas_build) { @@ -1763,7 +1766,7 @@ void VulkanStateWriter::WriteAccelerationStructureStateMetaCommands(const Vulkan void VulkanStateWriter::WriteAccelerationStructureBuildState(const gfxrecon::format::HandleId& device, AccelerationStructureBuildCommandData& command) { - for (ASInputBuffer& buffer : command.input_buffers) + for (auto& [handle_id, buffer] : command.input_buffers) { if (buffer.destroyed) { @@ -1775,7 +1778,7 @@ void VulkanStateWriter::WriteAccelerationStructureBuildState(const gfxrecon::for UpdateAddresses(command); EncodeAccelerationStructureBuildMetaCommand(device, command); - for (ASInputBuffer& buffer : command.input_buffers) + for (auto& [handle_id, buffer] : command.input_buffers) { if (buffer.destroyed) { @@ -1825,7 +1828,7 @@ void VulkanStateWriter::UpdateAddresses(AccelerationStructureBuildCommandData& c } } - for (const ASInputBuffer& buffer : command.input_buffers) + for (const auto& [handle_id, buffer] : command.input_buffers) { if (buffer.destroyed) { @@ -1870,8 +1873,8 @@ void VulkanStateWriter::EncodeAccelerationStructureBuildMetaCommand( ++blocks_written_; } -void VulkanStateWriter::EncodeAccelerationStructureCopyMetaCommand(format::HandleId device_id, - const AccelerationStructureCopyCommandData& command) +void VulkanStateWriter::EncodeAccelerationStructuresCopyMetaCommand( + format::HandleId device_id, const std::vector& infos) { parameter_stream_.Clear(); @@ -1882,15 +1885,12 @@ void VulkanStateWriter::EncodeAccelerationStructureCopyMetaCommand(format::Handl format::ApiFamilyId::ApiFamily_Vulkan, format::MetaDataType::kVulkanCopyAccelerationStructuresCommand); encoder_.EncodeHandleIdValue(device_id); - EncodeStructArray(&encoder_, command.infos.data(), command.infos.size()); - + EncodeStructArray(&encoder_, infos.data(), infos.size()); header.meta_header.block_header.size += parameter_stream_.GetDataSize(); output_stream_->Write(&header, sizeof(header)); output_stream_->Write(parameter_stream_.GetData(), parameter_stream_.GetDataSize()); - parameter_stream_.Clear(); - ++blocks_written_; } @@ -1938,7 +1938,7 @@ void VulkanStateWriter::WriteGetAccelerationStructureDeviceAddressKHRCall( parameter_stream_.Clear(); } -void VulkanStateWriter::WriteRayTracingPipelinePropertiesState(const VulkanStateTable& state_table) +void VulkanStateWriter::WriteRayTracingPropertiesState(const VulkanStateTable& state_table) { state_table.VisitWrappers([&](const vulkan_wrappers::PhysicalDeviceWrapper* wrapper) { assert(wrapper != nullptr); @@ -1947,9 +1947,17 @@ void VulkanStateWriter::WriteRayTracingPipelinePropertiesState(const VulkanState { parameter_stream_.Clear(); encoder_.EncodeHandleIdValue(wrapper->handle_id); + + // pNext-chaining + auto pipeline_props = *wrapper->ray_tracing_pipeline_properties; + pipeline_props.pNext = wrapper->acceleration_structure_properties + ? (void*)&wrapper->acceleration_structure_properties.value() + : nullptr; + VkPhysicalDeviceProperties2 properties2 = {}; properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - properties2.pNext = (void*)&wrapper->ray_tracing_pipeline_properties.value(); + properties2.pNext = &pipeline_props; + EncodeStructPtr(&encoder_, &properties2); WriteFunctionCall(format::ApiCall_vkGetPhysicalDeviceProperties2, ¶meter_stream_); parameter_stream_.Clear(); diff --git a/framework/encode/vulkan_state_writer.h b/framework/encode/vulkan_state_writer.h index 2e53a2f351..5122ee4eee 100644 --- a/framework/encode/vulkan_state_writer.h +++ b/framework/encode/vulkan_state_writer.h @@ -156,7 +156,7 @@ class VulkanStateWriter void WriteDeviceMemoryState(const VulkanStateTable& state_table); - void WriteRayTracingPipelinePropertiesState(const VulkanStateTable& state_table); + void WriteRayTracingPropertiesState(const VulkanStateTable& state_table); void WriteRayTracingShaderGroupHandlesState(const VulkanStateTable& state_table); @@ -383,12 +383,8 @@ class VulkanStateWriter void EncodeAccelerationStructureBuildMetaCommand(format::HandleId device_id, const AccelerationStructureBuildCommandData& command); - struct AccelerationStructureCopyCommandData - { - std::vector infos; - }; - void EncodeAccelerationStructureCopyMetaCommand(format::HandleId device_id, - const AccelerationStructureCopyCommandData& command); + void EncodeAccelerationStructuresCopyMetaCommand(format::HandleId device_id, + const std::vector& infos); struct AccelerationStructureWritePropertiesCommandData { diff --git a/framework/generated/generated_vulkan_api_call_encoders.cpp b/framework/generated/generated_vulkan_api_call_encoders.cpp index faa5fe4b27..8c67208945 100644 --- a/framework/generated/generated_vulkan_api_call_encoders.cpp +++ b/framework/generated/generated_vulkan_api_call_encoders.cpp @@ -25774,10 +25774,7 @@ VKAPI_ATTR void VKAPI_CALL CmdCopyAccelerationStructureKHR( manager->EndCommandApiCallCapture(commandBuffer, TrackCmdCopyAccelerationStructureKHRHandles, pInfo); } - auto handle_unwrap_memory = manager->GetHandleUnwrapMemory(); - const VkCopyAccelerationStructureInfoKHR* pInfo_unwrapped = vulkan_wrappers::UnwrapStructPtrHandles(pInfo, handle_unwrap_memory); - - vulkan_wrappers::GetDeviceTable(commandBuffer)->CmdCopyAccelerationStructureKHR(commandBuffer, pInfo_unwrapped); + manager->OverrideCmdCopyAccelerationStructureKHR(commandBuffer, pInfo); CustomEncoderPostCall::Dispatch(manager, commandBuffer, pInfo); } @@ -25929,7 +25926,7 @@ VKAPI_ATTR void VKAPI_CALL CmdWriteAccelerationStructuresPropertiesKHR( manager->EndCommandApiCallCapture(commandBuffer, TrackCmdWriteAccelerationStructuresPropertiesKHRHandles, accelerationStructureCount, pAccelerationStructures, queryPool); } - vulkan_wrappers::GetDeviceTable(commandBuffer)->CmdWriteAccelerationStructuresPropertiesKHR(commandBuffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery); + manager->OverrideCmdWriteAccelerationStructuresPropertiesKHR(commandBuffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery); CustomEncoderPostCall::Dispatch(manager, commandBuffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery); } diff --git a/framework/generated/khronos_generators/vulkan_generators/capture_overrides.json b/framework/generated/khronos_generators/vulkan_generators/capture_overrides.json index dfe43ff1a7..946e1266d3 100644 --- a/framework/generated/khronos_generators/vulkan_generators/capture_overrides.json +++ b/framework/generated/khronos_generators/vulkan_generators/capture_overrides.json @@ -13,6 +13,8 @@ "vkGetPhysicalDeviceQueueFamilyProperties2": "manager->OverrideGetPhysicalDeviceQueueFamilyProperties2", "vkGetPhysicalDeviceQueueFamilyProperties2KHR": "manager->OverrideGetPhysicalDeviceQueueFamilyProperties2KHR", "vkCmdBuildAccelerationStructuresKHR": "manager->OverrideCmdBuildAccelerationStructuresKHR", + "vkCmdCopyAccelerationStructureKHR": "manager->OverrideCmdCopyAccelerationStructureKHR", + "vkCmdWriteAccelerationStructuresPropertiesKHR": "manager->OverrideCmdWriteAccelerationStructuresPropertiesKHR", "vkGetPhysicalDeviceProperties2": "manager->OverrideGetPhysicalDeviceProperties2", "vkGetPhysicalDeviceProperties2KHR": "manager->OverrideGetPhysicalDeviceProperties2" } diff --git a/framework/graphics/test/main.cpp b/framework/graphics/test/main.cpp index d7f8c7c0ee..170bc886eb 100644 --- a/framework/graphics/test/main.cpp +++ b/framework/graphics/test/main.cpp @@ -24,4 +24,37 @@ /////////////////////////////////////////////////////////////////////////////// #define CATCH_CONFIG_MAIN +#include #include + +#include "graphics/vulkan_shader_group_handle.h" + +TEST_CASE("vulkan_shader_group_handle - create empty handles", "[]") +{ + gfxrecon::graphics::shader_group_handle_t one, two; + + // check for all zeros + uint8_t data[gfxrecon::graphics::shader_group_handle_t::MAX_HANDLE_SIZE] = {}; + REQUIRE(memcmp(one.data, data, gfxrecon::graphics::shader_group_handle_t::MAX_HANDLE_SIZE) == 0); + + REQUIRE(one == two); + REQUIRE_FALSE(one != two); + + auto three = one; + REQUIRE(one == three); +} + +TEST_CASE("vulkan_shader_group_handle - create handles", "[]") +{ + std::vector data(32); + std::iota(data.begin(), data.end(), 0); + gfxrecon::graphics::shader_group_handle_t one(data.data(), data.size()); + + data[31] = 99; + gfxrecon::graphics::shader_group_handle_t two(data.data(), data.size()); + REQUIRE(one != two); + + // check hashing via std::hash + std::hash hasher; + REQUIRE(hasher(one) != hasher(two)); +} \ No newline at end of file diff --git a/framework/graphics/vulkan_device_util.cpp b/framework/graphics/vulkan_device_util.cpp index be77b31f3f..eb20ff6111 100644 --- a/framework/graphics/vulkan_device_util.cpp +++ b/framework/graphics/vulkan_device_util.cpp @@ -28,6 +28,25 @@ GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(graphics) +uint32_t GetMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& memory_properties, + uint32_t type_bits, + VkMemoryPropertyFlags property_flags) +{ + uint32_t memory_type_index = std::numeric_limits::max(); + + for (uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i) + { + if ((type_bits & (1 << i)) && + ((memory_properties.memoryTypes[i].propertyFlags & property_flags) == property_flags)) + { + memory_type_index = i; + break; + } + } + + return memory_type_index; +} + // Query specific physical device features struct // Requires Vulkan version >= 1.1 or VK_KHR_get_physical_device_properties2 // feature_struct sType must be set, pNext must be nullptr @@ -184,8 +203,7 @@ VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(uint32_t rayTracingPipelineShaderGroupHandleCaptureReplay_original = rt_pipeline_features->rayTracingPipelineShaderGroupHandleCaptureReplay; - if (rt_pipeline_features->rayTracingPipeline && - !rt_pipeline_features->rayTracingPipelineShaderGroupHandleCaptureReplay) + if (rt_pipeline_features->rayTracingPipeline) { VkPhysicalDeviceRayTracingPipelineFeaturesKHR supported_features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR, nullptr @@ -193,13 +211,11 @@ VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(uint32_t GetPhysicalDeviceFeatures( instance_api_version, instance_table, physical_device, supported_features); - rt_pipeline_features->rayTracingPipelineShaderGroupHandleCaptureReplay = + result.feature_rayTracingPipelineShaderGroupHandleCaptureReplay = + rt_pipeline_features->rayTracingPipelineShaderGroupHandleCaptureReplay && supported_features.rayTracingPipelineShaderGroupHandleCaptureReplay; } - result.feature_rayTracingPipelineShaderGroupHandleCaptureReplay = - rt_pipeline_features->rayTracingPipelineShaderGroupHandleCaptureReplay; - // retrieve raytracing-pipeline-properties VkPhysicalDeviceRayTracingPipelinePropertiesKHR rt_properties{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR, nullptr diff --git a/framework/graphics/vulkan_device_util.h b/framework/graphics/vulkan_device_util.h index 3472d253c9..eaa91dace1 100644 --- a/framework/graphics/vulkan_device_util.h +++ b/framework/graphics/vulkan_device_util.h @@ -37,6 +37,10 @@ struct VulkanReplayDeviceInfo; GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(graphics) +uint32_t GetMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& memory_properties, + uint32_t type_bits, + VkMemoryPropertyFlags property_flags); + struct VulkanDevicePropertyFeatureInfo { uint32_t property_shaderGroupHandleSize{ 0 }; diff --git a/framework/util/CMakeLists.txt b/framework/util/CMakeLists.txt index 5289d49de4..9c30d3491e 100644 --- a/framework/util/CMakeLists.txt +++ b/framework/util/CMakeLists.txt @@ -30,6 +30,7 @@ add_library(gfxrecon_util STATIC "") target_sources(gfxrecon_util PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/alignment_utils.h ${CMAKE_CURRENT_LIST_DIR}/argument_parser.h ${CMAKE_CURRENT_LIST_DIR}/argument_parser.cpp ${CMAKE_CURRENT_LIST_DIR}/buffer_writer.h diff --git a/framework/util/alignment_utils.h b/framework/util/alignment_utils.h new file mode 100644 index 0000000000..303b68945b --- /dev/null +++ b/framework/util/alignment_utils.h @@ -0,0 +1,96 @@ +/* +** Copyright (c) 2025 LunarG, Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and associated documentation files (the "Software"), +** to deal in the Software without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Software, and to permit persons to whom the +** Software is furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +*/ + +#ifndef GFXRECON_UTIL_ALIGNED_VALUE_H +#define GFXRECON_UTIL_ALIGNED_VALUE_H + +#include "util/defines.h" +#include "util/logging.h" + +GFXRECON_BEGIN_NAMESPACE(gfxrecon) +GFXRECON_BEGIN_NAMESPACE(util) + +/** + * @brief is_pow_2 can be used to determine if value is a power-of-two. + * + * @param v an integer-value + * @return true, if provided value is a power-of-two. + */ +inline constexpr bool is_pow_2(uint64_t value) +{ + return !(value & (value - 1)); +} + +/** + * @brief next_pow_2 will return the next power of two, following a provided value. + * it will return value, if that was already a power-of-two. + * + * @param v provided integer-value + * @return v, if that already was a power-of-two, otherwise the next power-of-two following it. + */ +inline constexpr uint64_t next_pow_2(uint64_t v) +{ + if (is_pow_2(v)) + { + return v; + } + v--; + v |= v >> 1U; + v |= v >> 2U; + v |= v >> 4U; + v |= v >> 8U; + v |= v >> 16U; + v |= v >> 32U; + v++; + return v; +} + +/** + * @brief Return a value, equal or larger to a provided value, which is aligned to a provided alignment. + * + * @param value provided integer-value + * @param alignment provided alignment, needs to be a power-of-two + * @return an aligned value. + */ +inline constexpr uint64_t aligned_value(uint64_t value, uint64_t alignment) +{ + GFXRECON_ASSERT(is_pow_2(alignment)); + return alignment ? (value + alignment - 1) & ~(alignment - 1) : value; +} + +/** + * @brief Perform an integer-division, round up to the next value. + * + * @param nom provided nominator + * @param denom provided denominator + * @return result of integer-division, rounded to next value. + */ +inline constexpr uint32_t div_up(uint32_t nom, uint32_t denom) +{ + GFXRECON_ASSERT(denom > 0); + return (nom + denom - 1) / denom; +} + +GFXRECON_END_NAMESPACE(util) +GFXRECON_END_NAMESPACE(gfxrecon) + +#endif // #define GFXRECON_UTIL_ALIGNED_VALUE_H diff --git a/framework/util/linear_hashmap.h b/framework/util/linear_hashmap.h index ccb319b2ff..0138a3e251 100644 --- a/framework/util/linear_hashmap.h +++ b/framework/util/linear_hashmap.h @@ -23,6 +23,7 @@ #ifndef GFXRECONSTRUCT_UTIL_LINEAR_HASHMAP_H #define GFXRECONSTRUCT_UTIL_LINEAR_HASHMAP_H +#include "util/alignment_utils.h" #include "util/defines.h" #include "util/hash.h" #include @@ -33,28 +34,6 @@ GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(util) -inline constexpr bool is_pow_2(uint64_t v) -{ - return !(v & (v - 1)); -} - -inline constexpr uint64_t next_pow_2(uint64_t v) -{ - if (is_pow_2(v)) - { - return v; - } - v--; - v |= v >> 1U; - v |= v >> 2U; - v |= v >> 4U; - v |= v >> 8U; - v |= v >> 16U; - v |= v >> 32U; - v++; - return v; -} - /** * @brief linear_hashmap is a hashmap using open addressing with linear probing. * it can be used for POD key/value pairs and operates on a single array without chaining. @@ -84,7 +63,7 @@ class linear_hashmap } explicit linear_hashmap(uint64_t min_capacity) : - m_capacity(next_pow_2(min_capacity)), m_storage(std::make_unique(m_capacity)) + m_capacity(util::next_pow_2(min_capacity)), m_storage(std::make_unique(m_capacity)) { clear(); }