diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index e40d5c23b6..5d13e16720 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -356,9 +356,14 @@ static bool vulkan_find_extensions(const char * const *exts, unsigned num_exts, return true; } -static bool vulkan_find_instance_extensions(const char * const *exts, unsigned num_exts) +static bool vulkan_find_instance_extensions( + const char **enabled, unsigned *inout_enabled_count, + const char **exts, unsigned num_exts, + const char **optional_exts, unsigned num_optional_exts) { uint32_t property_count; + unsigned i; + unsigned count = *inout_enabled_count; bool ret = true; VkExtensionProperties *properties = NULL; @@ -380,13 +385,21 @@ static bool vulkan_find_instance_extensions(const char * const *exts, unsigned n if (!vulkan_find_extensions(exts, num_exts, properties, property_count)) { - RARCH_ERR("[Vulkan]: Could not find instance extensions. Will attempt without them.\n"); + RARCH_ERR("[Vulkan]: Could not find required instance extensions. Will attempt without them.\n"); ret = false; goto end; } + memcpy((void*)(enabled + count), exts, num_exts * sizeof(*exts)); + count += num_exts; + + for (i = 0; i < num_optional_exts; i++) + if (vulkan_find_extensions(&optional_exts[i], 1, properties, property_count)) + enabled[count++] = optional_exts[i]; + end: free(properties); + *inout_enabled_count = count; return ret; } @@ -828,6 +841,16 @@ static bool vulkan_context_init_device(gfx_ctx_vulkan_data_t *vk) return true; } +#ifdef VULKAN_HDR_SWAPCHAIN +#define VULKAN_COLORSPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace" +#endif + +static const char *vulkan_optional_instance_extensions[] = { +#ifdef VULKAN_HDR_SWAPCHAIN + VULKAN_COLORSPACE_EXTENSION_NAME +#endif +}; + static VkInstance vulkan_context_create_instance_wrapper(void *opaque, const VkInstanceCreateInfo *create_info) { VkResult res; @@ -836,44 +859,48 @@ static VkInstance vulkan_context_create_instance_wrapper(void *opaque, const VkI gfx_ctx_vulkan_data_t *vk = (gfx_ctx_vulkan_data_t *)opaque; VkInstanceCreateInfo info = *create_info; VkInstance instance = VK_NULL_HANDLE; - const char **instance_extensions = (const char**)malloc((info.enabledExtensionCount + 3) * sizeof(const char *)); - const char **instance_layers = (const char**)malloc((info.enabledLayerCount + 1) * sizeof(const char *)); + const char **instance_extensions = (const char**)malloc((info.enabledExtensionCount + 3 + + ARRAY_SIZE(vulkan_optional_device_extensions)) * sizeof(const char *)); + const char **instance_layers = (const char**)malloc((info.enabledLayerCount + 1) * sizeof(const char *)); + + const char *required_extensions[3]; + uint32_t required_extension_count = 0; memcpy((void*)instance_extensions, info.ppEnabledExtensionNames, info.enabledExtensionCount * sizeof(const char *)); memcpy((void*)instance_layers, info.ppEnabledLayerNames, info.enabledLayerCount * sizeof(const char *)); info.ppEnabledExtensionNames = instance_extensions; info.ppEnabledLayerNames = instance_layers; - instance_extensions[info.enabledExtensionCount++] = "VK_KHR_surface"; + required_extensions[required_extension_count++] = "VK_KHR_surface"; switch (vk->wsi_type) { case VULKAN_WSI_WAYLAND: - instance_extensions[info.enabledExtensionCount++] = "VK_KHR_wayland_surface"; + required_extensions[required_extension_count++] = "VK_KHR_wayland_surface"; break; case VULKAN_WSI_ANDROID: - instance_extensions[info.enabledExtensionCount++] = "VK_KHR_android_surface"; + required_extensions[required_extension_count++] = "VK_KHR_android_surface"; break; case VULKAN_WSI_WIN32: - instance_extensions[info.enabledExtensionCount++] = "VK_KHR_win32_surface"; + required_extensions[required_extension_count++] = "VK_KHR_win32_surface"; break; case VULKAN_WSI_XLIB: - instance_extensions[info.enabledExtensionCount++] = "VK_KHR_xlib_surface"; + required_extensions[required_extension_count++] = "VK_KHR_xlib_surface"; break; case VULKAN_WSI_XCB: - instance_extensions[info.enabledExtensionCount++] = "VK_KHR_xcb_surface"; + required_extensions[required_extension_count++] = "VK_KHR_xcb_surface"; break; case VULKAN_WSI_MIR: - instance_extensions[info.enabledExtensionCount++] = "VK_KHR_mir_surface"; + required_extensions[required_extension_count++] = "VK_KHR_mir_surface"; break; case VULKAN_WSI_DISPLAY: - instance_extensions[info.enabledExtensionCount++] = "VK_KHR_display"; + required_extensions[required_extension_count++] = "VK_KHR_display"; break; case VULKAN_WSI_MVK_MACOS: - instance_extensions[info.enabledExtensionCount++] = "VK_MVK_macos_surface"; + required_extensions[required_extension_count++] = "VK_MVK_macos_surface"; break; case VULKAN_WSI_MVK_IOS: - instance_extensions[info.enabledExtensionCount++] = "VK_MVK_ios_surface"; + required_extensions[required_extension_count++] = "VK_MVK_ios_surface"; break; case VULKAN_WSI_NONE: default: @@ -882,22 +909,35 @@ static VkInstance vulkan_context_create_instance_wrapper(void *opaque, const VkI #ifdef VULKAN_DEBUG instance_layers[info.enabledLayerCount++] = "VK_LAYER_KHRONOS_validation"; - instance_extensions[info.enabledExtensionCount++] = "VK_EXT_debug_utils"; + required_extensions[required_extension_count++] = "VK_EXT_debug_utils"; #endif layer_count = ARRAY_SIZE(properties); vkEnumerateInstanceLayerProperties(&layer_count, properties); - /* Be careful about validating supported instance extensions when using explicit layers. - * If core wants to enable debug layers, we'll have to do deeper validation and query - * supported extensions per-layer which is annoying. vkCreateInstance will validate this on its own anyways. */ - if ( (info.enabledLayerCount == 0) - && !vulkan_find_instance_extensions(info.ppEnabledExtensionNames, info.enabledExtensionCount)) + if (!(vulkan_find_instance_extensions( + instance_extensions, &info.enabledExtensionCount, + required_extensions, required_extension_count, + vulkan_optional_instance_extensions, + ARRAY_SIZE(vulkan_optional_instance_extensions)))) { RARCH_ERR("[Vulkan]: Instance does not support required extensions.\n"); goto end; } +#ifdef VULKAN_HDR_SWAPCHAIN + /* Check if HDR colorspace extension was enabled */ + vk->context.flags &= ~VK_CTX_FLAG_HDR_SUPPORT; + for (i = 0; i < info.enabledExtensionCount; i++) + { + if (string_is_equal(instance_extensions[i], VULKAN_COLORSPACE_EXTENSION_NAME)) + { + vk->context.flags |= VK_CTX_FLAG_HDR_SUPPORT; + break; + } + } +#endif + if (info.pApplicationInfo) { uint32_t supported_instance_version = VK_API_VERSION_1_0; @@ -2069,27 +2109,33 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, } #ifdef VULKAN_HDR_SWAPCHAIN - if (settings->bools.video_hdr_enable) - vk->context.flags |= VK_CTX_FLAG_HDR_ENABLE; - else - vk->context.flags &= ~VK_CTX_FLAG_HDR_ENABLE; - - video_driver_unset_hdr_support(); - - for (i = 0; i < format_count; i++) + if (vk->context.flags & VK_CTX_FLAG_HDR_SUPPORT) { - if ( (vulkan_is_hdr10_format(formats[i].format)) - && (formats[i].colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT)) - { - format = formats[i]; - video_driver_set_hdr_support(); - break; - } - } + if (settings->bools.video_hdr_enable) + vk->context.flags |= VK_CTX_FLAG_HDR_ENABLE; + else + vk->context.flags &= ~VK_CTX_FLAG_HDR_ENABLE; - if ( (!(vk->context.flags & VK_CTX_FLAG_HDR_ENABLE)) - || (format.format == VK_FORMAT_UNDEFINED)) + video_driver_unset_hdr_support(); + + for (i = 0; i < format_count; i++) + { + if ( (vulkan_is_hdr10_format(formats[i].format)) + && (formats[i].colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT)) + { + format = formats[i]; + video_driver_set_hdr_support(); + break; + } + } + + if (!vulkan_is_hdr10_format(format.format)) + vk->context.flags &= ~VK_CTX_FLAG_HDR_ENABLE; + } + else + { vk->context.flags &= ~VK_CTX_FLAG_HDR_ENABLE; + } if (!(vk->context.flags & VK_CTX_FLAG_HDR_ENABLE)) #endif /* VULKAN_HDR_SWAPCHAIN */ @@ -2203,8 +2249,9 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, info.imageExtent.height = swapchain_size.height; info.imageArrayLayers = 1; info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - | VK_IMAGE_USAGE_TRANSFER_SRC_BIT - | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT; info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; info.queueFamilyIndexCount = 0; info.pQueueFamilyIndices = NULL; diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index cba04993e3..1681b723ac 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -294,6 +294,8 @@ enum vulkan_context_flags VK_CTX_FLAG_SWAPCHAIN_IS_SRGB = (1 << 2), VK_CTX_FLAG_SWAP_INTERVAL_EMULATION_LOCK = (1 << 3), VK_CTX_FLAG_HAS_ACQUIRED_SWAPCHAIN = (1 << 4), + /* Whether HDR colorspaces are supported by the instance */ + VK_CTX_FLAG_HDR_SUPPORT = (1 << 5), }; enum vulkan_emulated_mailbox_flags @@ -554,7 +556,9 @@ typedef struct vk struct vk_per_frame *chain; struct vk_image *backbuffer; #ifdef VULKAN_HDR_SWAPCHAIN + VkRenderPass readback_render_pass; struct vk_image main_buffer; + struct vk_image readback_image; #endif /* VULKAN_HDR_SWAPCHAIN */ unsigned video_width; @@ -603,6 +607,7 @@ typedef struct vk VkPipeline rgb565_to_rgba8888; #ifdef VULKAN_HDR_SWAPCHAIN VkPipeline hdr; + VkPipeline hdr_to_sdr; /* for readback */ #endif /* VULKAN_HDR_SWAPCHAIN */ VkDescriptorSetLayout set_layout; VkPipelineLayout layout; diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 4d8a6c3015..870e58566a 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -1972,9 +1972,9 @@ static void vulkan_init_render_pass( attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - /* The image layout will be attachment_optimal - * when we're executing the renderpass. */ - attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + /* We don't care about the initial layout as we'll overwrite contents anyway */ + attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + /* After we're done rendering, automatically transition the image to attachment_optimal */ attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; /* Color attachment reference */ @@ -2010,6 +2010,65 @@ static void vulkan_init_render_pass( &rp_info, NULL, &vk->render_pass); } + +static void vulkan_init_hdr_readback_render_pass(vk_t *vk) +{ + VkRenderPassCreateInfo rp_info; + VkAttachmentReference color_ref; + VkAttachmentDescription attachment; + VkSubpassDescription subpass; + + attachment.flags = 0; + /* Use BGRA as backbuffer format so CPU can just memcpy transfer results */ + attachment.format = VK_FORMAT_B8G8R8A8_UNORM; + /* Not multisampled. */ + attachment.samples = VK_SAMPLE_COUNT_1_BIT; + /* When starting the frame, we want tiles to be cleared. */ + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + /* When end the frame, we want tiles to be written out. */ + attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + /* Don't care about stencil since we're not using it. */ + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + + /* We don't care about the initial layout as we'll overwrite contents anyway */ + attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + /* After we're done rendering, automatically transition the image as a source for transfers */ + attachment.finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + + /* Color attachment reference */ + color_ref.attachment = 0; + color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + /* We have one subpass. + * This subpass has 1 color attachment. */ + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = NULL; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &color_ref; + subpass.pResolveAttachments = NULL; + subpass.pDepthStencilAttachment = NULL; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = NULL; + + /* Finally, create the renderpass. */ + rp_info.sType = + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + rp_info.pNext = NULL; + rp_info.flags = 0; + rp_info.attachmentCount = 1; + rp_info.pAttachments = &attachment; + rp_info.subpassCount = 1; + rp_info.pSubpasses = &subpass; + rp_info.dependencyCount = 0; + rp_info.pDependencies = NULL; + + vkCreateRenderPass(vk->context->device, + &rp_info, NULL, &vk->readback_render_pass); +} + static void vulkan_init_framebuffers( vk_t *vk) { @@ -2128,6 +2187,9 @@ static void vulkan_init_pipelines(vk_t *vk) static const uint32_t hdr_frag[] = #include "vulkan_shaders/hdr.frag.inc" ; + static const uint32_t hdr_tonemap_frag[] = +#include "vulkan_shaders/hdr_tonemap.frag.inc" + ; #endif /* VULKAN_HDR_SWAPCHAIN */ static const uint32_t alpha_blend_vert[] = @@ -2347,6 +2409,8 @@ static void vulkan_init_pipelines(vk_t *vk) vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); #ifdef VULKAN_HDR_SWAPCHAIN +if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT) +{ blend_attachment.blendEnable = VK_FALSE; /* HDR pipeline. */ @@ -2370,7 +2434,23 @@ static void vulkan_init_pipelines(vk_t *vk) vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); + /* HDR->SDR tonemapping readback pipeline. */ + module_info.codeSize = sizeof(hdr_tonemap_frag); + module_info.pCode = hdr_tonemap_frag; + shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + shader_stages[1].pName = "main"; + vkCreateShaderModule(vk->context->device, + &module_info, NULL, &shader_stages[1].module); + + pipe.renderPass = vk->readback_render_pass; + vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, + 1, &pipe, NULL, &vk->pipelines.hdr_to_sdr); + + vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); + + pipe.renderPass = vk->render_pass; blend_attachment.blendEnable = VK_TRUE; +} #endif /* VULKAN_HDR_SWAPCHAIN */ vkDestroyShaderModule(vk->context->device, shader_stages[0].module, NULL); @@ -2657,8 +2737,13 @@ static void vulkan_deinit_pipelines(vk_t *vk) vkDestroyPipeline(vk->context->device, vk->pipelines.rgb565_to_rgba8888, NULL); #ifdef VULKAN_HDR_SWAPCHAIN +if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT) +{ vkDestroyPipeline(vk->context->device, vk->pipelines.hdr, NULL); + vkDestroyPipeline(vk->context->device, + vk->pipelines.hdr_to_sdr, NULL); +} #endif /* VULKAN_HDR_SWAPCHAIN */ for (i = 0; i < (int)ARRAY_SIZE(vk->display.pipelines); i++) @@ -2684,6 +2769,11 @@ static void vulkan_deinit_framebuffers(vk_t *vk) } #ifdef VULKAN_HDR_SWAPCHAIN +static void vulkan_deinit_hdr_readback_render_pass(vk_t *vk) +{ + vkDestroyRenderPass(vk->context->device, vk->readback_render_pass, NULL); +} + static void vulkan_set_hdr_max_nits(void* data, float max_nits) { vk_t *vk = (vk_t*)data; @@ -3017,9 +3107,14 @@ static void vulkan_free(void *data) vulkan_filter_chain_free((vulkan_filter_chain_t*)vk->filter_chain); #ifdef VULKAN_HDR_SWAPCHAIN - vulkan_destroy_buffer(vk->context->device, &vk->hdr.ubo); - vulkan_destroy_hdr_buffer(vk->context->device, &vk->main_buffer); - video_driver_unset_hdr_support(); + if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT) + { + vulkan_destroy_buffer(vk->context->device, &vk->hdr.ubo); + vulkan_destroy_hdr_buffer(vk->context->device, &vk->main_buffer); + vulkan_destroy_hdr_buffer(vk->context->device, &vk->readback_image); + vulkan_deinit_hdr_readback_render_pass(vk); + video_driver_unset_hdr_support(); + } #endif /* VULKAN_HDR_SWAPCHAIN */ if (vk->ctx_driver && vk->ctx_driver->destroy) @@ -3364,6 +3459,10 @@ static void *vulkan_init(const video_info_t *video, vk->num_swapchain_images = vk->context->num_swapchain_images; vulkan_init_render_pass(vk); +#ifdef VULKAN_HDR_SWAPCHAIN + if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT) + vulkan_init_hdr_readback_render_pass(vk); +#endif vulkan_init_framebuffers(vk); vulkan_init_pipelines(vk); vulkan_init_samplers(vk); @@ -3462,6 +3561,10 @@ static void vulkan_check_swapchain(vk_t *vk) vulkan_deinit_textures(vk); vulkan_deinit_buffers(vk); vulkan_deinit_command_buffers(vk); +#ifdef VULKAN_HDR_SWAPCHAIN + if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT) + vulkan_deinit_hdr_readback_render_pass(vk); +#endif if (vk->context) { int i; @@ -3474,6 +3577,10 @@ static void vulkan_check_swapchain(vk_t *vk) vk->num_swapchain_images = vk->context->num_swapchain_images; vulkan_init_render_pass(vk); +#ifdef VULKAN_HDR_SWAPCHAIN + if (vk->context->flags & VK_CTX_FLAG_HDR_SUPPORT) + vulkan_init_hdr_readback_render_pass(vk); +#endif vulkan_init_framebuffers(vk); vulkan_init_pipelines(vk); vulkan_init_samplers(vk); @@ -3788,7 +3895,7 @@ static void vulkan_set_viewport(void *data, unsigned viewport_width, vk->tracker.dirty |= VULKAN_DIRTY_DYNAMIC_BIT; } -static void vulkan_readback(vk_t *vk) +static void vulkan_readback(vk_t *vk, struct vk_image *readback_image) { VkBufferImageCopy region; struct vk_texture *staging; @@ -3825,7 +3932,7 @@ static void vulkan_readback(vk_t *vk) VK_FORMAT_B8G8R8A8_UNORM, /* Formats don't matter for readback since it's a raw copy. */ NULL, NULL, VULKAN_TEXTURE_READBACK); - vkCmdCopyImageToBuffer(vk->cmd, vk->backbuffer->image, + vkCmdCopyImageToBuffer(vk->cmd, readback_image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, staging->buffer, 1, ®ion); @@ -4044,6 +4151,210 @@ static void vulkan_draw_quad(vk_t *vk, const struct vk_draw_quad *quad) } #endif +static void vulkan_init_render_target(struct vk_image* image, uint32_t width, uint32_t height, VkFormat format, VkRenderPass render_pass, vulkan_context_t* ctx) +{ + VkMemoryRequirements mem_reqs; + VkImageCreateInfo image_info; + VkMemoryAllocateInfo alloc; + VkImageViewCreateInfo view; + VkFramebufferCreateInfo info; + + memset(image, 0, sizeof(struct vk_image)); + + /* Create the image */ + image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_info.pNext = NULL; + image_info.flags = 0; + image_info.imageType = VK_IMAGE_TYPE_2D; + image_info.format = format; + image_info.extent.width = width; + image_info.extent.height = height; + image_info.extent.depth = 1; + image_info.mipLevels = 1; + image_info.arrayLayers = 1; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_info.queueFamilyIndexCount= 0; + image_info.pQueueFamilyIndices = NULL; + image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + vkCreateImage(ctx->device, &image_info, NULL, &image->image); + vulkan_debug_mark_image(ctx->device, image->image); + vkGetImageMemoryRequirements(ctx->device, image->image, &mem_reqs); + alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc.pNext = NULL; + alloc.allocationSize = mem_reqs.size; + alloc.memoryTypeIndex = vulkan_find_memory_type( + &ctx->memory_properties, + mem_reqs.memoryTypeBits, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + vkAllocateMemory(ctx->device, &alloc, NULL, &image->memory); + vulkan_debug_mark_memory(ctx->device, image->memory); + + vkBindImageMemory(ctx->device, image->image, image->memory, 0); + + /* Create an image view which we can render into. */ + view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view.pNext = NULL; + view.flags = 0; + view.image = image->image; + view.viewType = VK_IMAGE_VIEW_TYPE_2D; + view.format = format; + view.components.r = VK_COMPONENT_SWIZZLE_R; + view.components.g = VK_COMPONENT_SWIZZLE_G; + view.components.b = VK_COMPONENT_SWIZZLE_B; + view.components.a = VK_COMPONENT_SWIZZLE_A; + view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + view.subresourceRange.baseMipLevel = 0; + view.subresourceRange.levelCount = 1; + view.subresourceRange.baseArrayLayer = 0; + view.subresourceRange.layerCount = 1; + + vkCreateImageView(ctx->device, &view, NULL, &image->view); + + /* Create the framebuffer */ + info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + info.pNext = NULL; + info.flags = 0; + info.renderPass = render_pass; + info.attachmentCount = 1; + info.pAttachments = &image->view; + info.width = ctx->swapchain_width; + info.height = ctx->swapchain_height; + info.layers = 1; + + vkCreateFramebuffer(ctx->device, &info, NULL, &image->framebuffer); +} + +static void vulkan_run_hdr_pipeline(VkPipeline pipeline, VkRenderPass render_pass, const struct vk_image* source_image, struct vk_image* render_target, vk_t* vk) +{ + vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; + VkRenderPassBeginInfo rp_info; + VkClearValue clear_color; + + mapped_ubo->mvp = vk->mvp_no_rot; + + rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + rp_info.pNext = NULL; + rp_info.renderPass = render_pass; + rp_info.framebuffer = render_target->framebuffer; + rp_info.renderArea.offset.x = 0; + rp_info.renderArea.offset.y = 0; + rp_info.renderArea.extent.width = vk->context->swapchain_width; + rp_info.renderArea.extent.height = vk->context->swapchain_height; + rp_info.clearValueCount = 1; + rp_info.pClearValues = &clear_color; + + clear_color.color.float32[0] = 0.0f; + clear_color.color.float32[1] = 0.0f; + clear_color.color.float32[2] = 0.0f; + clear_color.color.float32[3] = 0.0f; + + /* Begin render pass and set up viewport */ + vkCmdBeginRenderPass(vk->cmd, &rp_info, VK_SUBPASS_CONTENTS_INLINE); + + { + if (pipeline != vk->tracker.pipeline) + { + vkCmdBindPipeline(vk->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + + vk->tracker.pipeline = pipeline; + /* Changing pipeline invalidates dynamic state. */ + vk->tracker.dirty |= VULKAN_DIRTY_DYNAMIC_BIT; + } + } + + { + VkWriteDescriptorSet write; + VkDescriptorImageInfo image_info; + VkDescriptorSet set = vulkan_descriptor_manager_alloc( + vk->context->device, + &vk->chain->descriptor_manager); + + VULKAN_SET_UNIFORM_BUFFER(vk->context->device, + set, + 0, + vk->hdr.ubo.buffer, + 0, + vk->hdr.ubo.size); + + image_info.sampler = vk->samplers.nearest; + image_info.imageView = source_image->view; + image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.pNext = NULL; + write.dstSet = set; + write.dstBinding = 2; + write.dstArrayElement = 0; + write.descriptorCount = 1; + write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write.pImageInfo = &image_info; + write.pBufferInfo = NULL; + write.pTexelBufferView = NULL; + + vkUpdateDescriptorSets(vk->context->device, 1, &write, 0, NULL); + + vkCmdBindDescriptorSets(vk->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + vk->pipelines.layout, 0, + 1, &set, 0, NULL); + + vk->tracker.view = source_image->view; + vk->tracker.sampler = vk->samplers.nearest; + } + + { + VkViewport viewport; + VkRect2D sci; + + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = vk->context->swapchain_width; + viewport.height = vk->context->swapchain_height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + sci.offset.x = (int32_t)viewport.x; + sci.offset.y = (int32_t)viewport.y; + sci.extent.width = (uint32_t)viewport.width; + sci.extent.height = (uint32_t)viewport.height; + vkCmdSetViewport(vk->cmd, 0, 1, &viewport); + vkCmdSetScissor(vk->cmd, 0, 1, &sci); + } + + /* Upload VBO */ + { + struct vk_buffer_range range; + + vulkan_buffer_chain_alloc(vk->context, &vk->chain->vbo, 6 * sizeof(struct vk_vertex), &range); + + { + struct vk_vertex *pv = (struct vk_vertex*)range.data; + struct vk_color color; + + color.r = 1.0f; + color.g = 1.0f; + color.b = 1.0f; + color.a = 1.0f; + + VULKAN_WRITE_QUAD_VBO(pv, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, &color); + } + + vkCmdBindVertexBuffers(vk->cmd, 0, 1, + &range.buffer, &range.offset); + } + + vkCmdDraw(vk->cmd, 6, 1, 0, 0); + + vkCmdEndRenderPass(vk->cmd); +} + static bool vulkan_frame(void *data, const void *frame, unsigned frame_width, unsigned frame_height, uint64_t frame_count, @@ -4084,8 +4395,8 @@ static bool vulkan_frame(void *data, const void *frame, bool overlay_behind_menu = video_info->overlay_behind_menu; #ifdef VULKAN_HDR_SWAPCHAIN - bool use_main_buffer = (vk->context->flags & - VK_CTX_FLAG_HDR_ENABLE) + bool use_main_buffer = + ( vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) && (!vk->filter_chain || !vulkan_filter_chain_emits_hdr10(vk->filter_chain)); #endif /* VULKAN_HDR_SWAPCHAIN */ @@ -4386,13 +4697,6 @@ static bool vulkan_frame(void *data, const void *frame, clear_color.color.float32[2] = 0.0f; clear_color.color.float32[3] = 0.0f; - /* Prepare backbuffer for rendering. */ - VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, backbuffer->image, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - /* Begin render pass and set up viewport */ vkCmdBeginRenderPass(vk->cmd, &rp_info, VK_SUBPASS_CONTENTS_INLINE); @@ -4472,137 +4776,14 @@ static bool vulkan_frame(void *data, const void *frame, if (use_main_buffer) { backbuffer = &vk->backbuffers[swapchain_index]; - - vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; - - mapped_ubo->mvp = vk->mvp_no_rot; - - rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - rp_info.pNext = NULL; - rp_info.renderPass = vk->render_pass; - rp_info.framebuffer = backbuffer->framebuffer; - rp_info.renderArea.offset.x = 0; - rp_info.renderArea.offset.y = 0; - rp_info.renderArea.extent.width = vk->context->swapchain_width; - rp_info.renderArea.extent.height = vk->context->swapchain_height; - rp_info.clearValueCount = 1; - rp_info.pClearValues = &clear_color; - - clear_color.color.float32[0] = 0.0f; - clear_color.color.float32[1] = 0.0f; - clear_color.color.float32[2] = 0.0f; - clear_color.color.float32[3] = 0.0f; - - /* Prepare backbuffer for rendering. */ - VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, backbuffer->image, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - + /* Prepare source buffer for reading */ VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, vk->main_buffer.image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - /* Begin render pass and set up viewport */ - vkCmdBeginRenderPass(vk->cmd, &rp_info, VK_SUBPASS_CONTENTS_INLINE); - - { - if (vk->pipelines.hdr != vk->tracker.pipeline) - { - vkCmdBindPipeline(vk->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, vk->pipelines.hdr); - - vk->tracker.pipeline = vk->pipelines.hdr; - /* Changing pipeline invalidates dynamic state. */ - vk->tracker.dirty |= VULKAN_DIRTY_DYNAMIC_BIT; - } - } - - { - VkWriteDescriptorSet write; - VkDescriptorImageInfo image_info; - VkDescriptorSet set = vulkan_descriptor_manager_alloc( - vk->context->device, - &vk->chain->descriptor_manager); - - VULKAN_SET_UNIFORM_BUFFER(vk->context->device, - set, - 0, - vk->hdr.ubo.buffer, - 0, - vk->hdr.ubo.size); - - image_info.sampler = vk->samplers.nearest; - image_info.imageView = vk->main_buffer.view; - image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write.pNext = NULL; - write.dstSet = set; - write.dstBinding = 2; - write.dstArrayElement = 0; - write.descriptorCount = 1; - write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - write.pImageInfo = &image_info; - write.pBufferInfo = NULL; - write.pTexelBufferView = NULL; - - vkUpdateDescriptorSets(vk->context->device, 1, &write, 0, NULL); - - vkCmdBindDescriptorSets(vk->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - vk->pipelines.layout, 0, - 1, &set, 0, NULL); - - vk->tracker.view = vk->main_buffer.view; - vk->tracker.sampler = vk->samplers.nearest; - } - - { - VkViewport viewport; - VkRect2D sci; - - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = vk->context->swapchain_width; - viewport.height = vk->context->swapchain_height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - sci.offset.x = (int32_t)viewport.x; - sci.offset.y = (int32_t)viewport.y; - sci.extent.width = (uint32_t)viewport.width; - sci.extent.height = (uint32_t)viewport.height; - vkCmdSetViewport(vk->cmd, 0, 1, &viewport); - vkCmdSetScissor(vk->cmd, 0, 1, &sci); - } - - /* Upload VBO */ - { - struct vk_buffer_range range; - - vulkan_buffer_chain_alloc(vk->context, &vk->chain->vbo, 6 * sizeof(struct vk_vertex), &range); - - { - struct vk_vertex *pv = (struct vk_vertex*)range.data; - struct vk_color color; - - color.r = 1.0f; - color.g = 1.0f; - color.b = 1.0f; - color.a = 1.0f; - - VULKAN_WRITE_QUAD_VBO(pv, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, &color); - } - - vkCmdBindVertexBuffers(vk->cmd, 0, 1, - &range.buffer, &range.offset); - } - - vkCmdDraw(vk->cmd, 6, 1, 0, 0); - - vkCmdEndRenderPass(vk->cmd); + vulkan_run_hdr_pipeline(vk->pipelines.hdr, vk->render_pass, &vk->main_buffer, backbuffer, vk); } #endif /* VULKAN_HDR_SWAPCHAIN */ } @@ -4620,6 +4801,31 @@ static bool vulkan_frame(void *data, const void *frame, if ( (vk->flags & VK_FLAG_READBACK_PENDING) || (vk->flags & VK_FLAG_READBACK_STREAMED)) { + VkImageLayout backbuffer_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; +#ifdef VULKAN_HDR_SWAPCHAIN + struct vk_image* readback_source = backbuffer; + if (vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) + { + if (use_main_buffer) + { + /* Read directly from sdr main buffer instead of tonemapping */ + readback_source = &vk->main_buffer; + /* No need to transition layout, it's already read-only optimal */ + } + else + { + /* Prepare backbuffer for reading */ + backbuffer_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, backbuffer->image, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, backbuffer_layout, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + } + vulkan_run_hdr_pipeline(vk->pipelines.hdr_to_sdr, vk->readback_render_pass, readback_source, &vk->readback_image, vk); + readback_source = &vk->readback_image; + } +#endif /* VULKAN_HDR_SWAPCHAIN */ /* We cannot safely read back from an image which * has already been presented as we need to * maintain the PRESENT_SRC_KHR layout. @@ -4630,14 +4836,14 @@ static bool vulkan_frame(void *data, const void *frame, VULKAN_IMAGE_LAYOUT_TRANSITION( vk->cmd, backbuffer->image, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + backbuffer_layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - vulkan_readback(vk); + vulkan_readback(vk, readback_source); /* Prepare for presentation after transfers are complete. */ VULKAN_IMAGE_LAYOUT_TRANSITION( @@ -4781,7 +4987,7 @@ static bool vulkan_frame(void *data, const void *frame, /* Handle spurious swapchain invalidations as soon as we can, * i.e. right after swap buffers. */ #ifdef VULKAN_HDR_SWAPCHAIN - bool video_hdr_enable = video_info->hdr_enable; + bool video_hdr_enable = video_driver_supports_hdr() && video_info->hdr_enable; if ( (vk->flags & VK_FLAG_SHOULD_RESIZE) || (((vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) > 0) != video_hdr_enable)) @@ -4801,6 +5007,7 @@ static bool vulkan_frame(void *data, const void *frame, slock_unlock(vk->context->queue_lock); #endif vulkan_destroy_hdr_buffer(vk->context->device, &vk->main_buffer); + vulkan_destroy_hdr_buffer(vk->context->device, &vk->readback_image); } else vk->context->flags &= ~VK_CTX_FLAG_HDR_ENABLE; @@ -4815,94 +5022,14 @@ static bool vulkan_frame(void *data, const void *frame, vk->ctx_driver->set_resize(vk->ctx_data, mode.width, mode.height); #ifdef VULKAN_HDR_SWAPCHAIN - if ( (vk->context->swapchain_colour_space) - == VK_COLOR_SPACE_HDR10_ST2084_EXT) - vk->flags |= VK_FLAG_HDR_SUPPORT; - else - { - vk->flags &= ~VK_FLAG_HDR_SUPPORT; - vk->context->flags &= ~VK_CTX_FLAG_HDR_ENABLE; - } - if (vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) { - VkMemoryRequirements mem_reqs; - VkImageCreateInfo image_info; - VkMemoryAllocateInfo alloc; - VkImageViewCreateInfo view; - VkFramebufferCreateInfo info; - - memset(&vk->main_buffer, 0, sizeof(vk->main_buffer)); - - /* Create the image */ - image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_info.pNext = NULL; - image_info.flags = 0; - image_info.imageType = VK_IMAGE_TYPE_2D; - image_info.format = vk->context->swapchain_format; - image_info.extent.width = video_width; - image_info.extent.height = video_height; - image_info.extent.depth = 1; - image_info.mipLevels = 1; - image_info.arrayLayers = 1; - image_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_info.queueFamilyIndexCount= 0; - image_info.pQueueFamilyIndices = NULL; - image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - vkCreateImage(vk->context->device, &image_info, NULL, &vk->main_buffer.image); - vulkan_debug_mark_image(vk->context->device, vk->main_buffer.image); - vkGetImageMemoryRequirements(vk->context->device, vk->main_buffer.image, &mem_reqs); - alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - alloc.pNext = NULL; - alloc.allocationSize = mem_reqs.size; - alloc.memoryTypeIndex = vulkan_find_memory_type( - &vk->context->memory_properties, - mem_reqs.memoryTypeBits, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - vkAllocateMemory(vk->context->device, &alloc, NULL, &vk->main_buffer.memory); - vulkan_debug_mark_memory(vk->context->device, vk->main_buffer.memory); - - vkBindImageMemory(vk->context->device, vk->main_buffer.image, vk->main_buffer.memory, 0); - - /* Create an image view which we can render into. */ - view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - view.pNext = NULL; - view.flags = 0; - view.image = vk->main_buffer.image; - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - view.format = image_info.format; - view.components.r = VK_COMPONENT_SWIZZLE_R; - view.components.g = VK_COMPONENT_SWIZZLE_G; - view.components.b = VK_COMPONENT_SWIZZLE_B; - view.components.a = VK_COMPONENT_SWIZZLE_A; - view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view.subresourceRange.baseMipLevel = 0; - view.subresourceRange.levelCount = 1; - view.subresourceRange.baseArrayLayer = 0; - view.subresourceRange.layerCount = 1; - - vkCreateImageView(vk->context->device, &view, NULL, &vk->main_buffer.view); - - /* Create the framebuffer */ - info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - info.pNext = NULL; - info.flags = 0; - info.renderPass = vk->render_pass; - info.attachmentCount = 1; - info.pAttachments = &vk->main_buffer.view; - info.width = vk->context->swapchain_width; - info.height = vk->context->swapchain_height; - info.layers = 1; - - vkCreateFramebuffer(vk->context->device, &info, NULL, &vk->main_buffer.framebuffer); + /* Create intermediary buffer to render filter chain output to */ + vulkan_init_render_target(&vk->main_buffer, video_width, video_height, + vk->context->swapchain_format, vk->render_pass, vk->context); + /* Create image for readback target in bgra8 format */ + vulkan_init_render_target(&vk->readback_image, video_width, video_height, + VK_FORMAT_B8G8R8A8_UNORM, vk->readback_render_pass, vk->context); } #endif /* VULKAN_HDR_SWAPCHAIN */ vk->flags &= ~VK_FLAG_SHOULD_RESIZE; @@ -5426,12 +5553,20 @@ static bool vulkan_read_viewport(void *data, uint8_t *buffer, bool is_idle) staging = &vk->readback.staging[vk->context->current_frame_index]; + VkFormat format = vk->context->swapchain_format; +#ifdef VULKAN_HDR_SWAPCHAIN + if (vk->context->flags & VK_CTX_FLAG_HDR_ENABLE) + { + /* Hdr readback is implemented through format conversion on the GPU */ + format = VK_FORMAT_B8G8R8A8_UNORM; + } +#endif /* VULKAN_HDR_SWAPCHAIN */ if (vk->flags & VK_FLAG_READBACK_STREAMED) { const uint8_t *src = NULL; struct scaler_ctx *ctx = NULL; - switch (vk->context->swapchain_format) + switch (format) { case VK_FORMAT_R8G8B8A8_UNORM: case VK_FORMAT_A8B8G8R8_UNORM_PACK32: @@ -5506,7 +5641,7 @@ static bool vulkan_read_viewport(void *data, uint8_t *buffer, bool is_idle) const uint8_t *src = (const uint8_t*)staging->mapped; buffer += 3 * (vk->vp.height - 1) * vk->vp.width; - switch (vk->context->swapchain_format) + switch (format) { case VK_FORMAT_B8G8R8A8_UNORM: for (y = 0; y < (int) vk->vp.height; y++, diff --git a/gfx/drivers/vulkan_shaders/hdr.frag b/gfx/drivers/vulkan_shaders/hdr.frag index 72df88b89f..e677634ca4 100644 --- a/gfx/drivers/vulkan_shaders/hdr.frag +++ b/gfx/drivers/vulkan_shaders/hdr.frag @@ -1,108 +1,24 @@ #version 310 es + precision highp float; layout(location = 0) in vec2 vTexCoord; layout(location = 0) out vec4 FragColor; layout(set = 0, binding = 2) uniform highp sampler2D Source; -layout(std140, set = 0, binding = 0) uniform UBO -{ - mat4 MVP; - float contrast; /* 2.0f; */ - float paper_white_nits; /* 200.0f; */ - float max_nits; /* 1000.0f; */ - float expand_gamut; /* 1.0f; */ - float inverse_tonemap; - float hdr10; -} global; - -/* Inverse Tonemap section */ -#define kMaxNitsFor2084 10000.0f -#define kEpsilon 0.0001f -#define kLumaChannelRatio 0.25f - -vec3 InverseTonemap(vec3 sdr) -{ - vec3 hdr; - - if (global.inverse_tonemap > 0.0f) - { - sdr = pow(abs(sdr), vec3(global.contrast / 2.2f)); /* Display Gamma - needs to be determined by calibration screen */ - - float luma = dot(sdr, vec3(0.2126, 0.7152, 0.0722)); /* Rec BT.709 luma coefficients - https://en.wikipedia.org/wiki/Luma_(video) */ - - /* Inverse reinhard tonemap */ - float maxValue = (global.max_nits / global.paper_white_nits) + kEpsilon; - float elbow = maxValue / (maxValue - 1.0f); - float offset = 1.0f - ((0.5f * elbow) / (elbow - 0.5f)); - - float hdrLumaInvTonemap = offset + ((luma * elbow) / (elbow - luma)); - float sdrLumaInvTonemap = luma / ((1.0f + kEpsilon) - luma); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */ - - float lumaInvTonemap = (luma > 0.5f) ? hdrLumaInvTonemap : sdrLumaInvTonemap; - vec3 perLuma = sdr / (luma + kEpsilon) * lumaInvTonemap; - - vec3 hdrInvTonemap = offset + ((sdr * elbow) / (elbow - sdr)); - vec3 sdrInvTonemap = sdr / ((1.0f + kEpsilon) - sdr); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */ - - vec3 perChannel = vec3(sdr.x > 0.5f ? hdrInvTonemap.x : sdrInvTonemap.x, - sdr.y > 0.5f ? hdrInvTonemap.y : sdrInvTonemap.y, - sdr.z > 0.5f ? hdrInvTonemap.z : sdrInvTonemap.z); - - hdr = mix(perLuma, perChannel, vec3(kLumaChannelRatio)); - } - else - { - hdr = sdr; - } - - return hdr; -} - -/* HDR10 section */ -#define kMaxNitsFor2084 10000.0f - -const mat3 k709to2020 = mat3 ( - 0.6274040f, 0.3292820f, 0.0433136f, - 0.0690970f, 0.9195400f, 0.0113612f, - 0.0163916f, 0.0880132f, 0.8955950f); - -/* START Converted from (Copyright (c) Microsoft Corporation - Licensed under the MIT License.) https://github.com/microsoft/Xbox-ATG-Samples/tree/master/Kits/ATGTK/HDR */ -const mat3 kExpanded709to2020 = mat3 ( - 0.6274040f, 0.3292820f, 0.0433136f, - 0.0457456, 0.941777, 0.0124772, - -0.00121055, 0.0176041, 0.983607); - -vec3 LinearToST2084(vec3 normalizedLinearValue) -{ - vec3 ST2084 = pow((0.8359375f + 18.8515625f * pow(abs(normalizedLinearValue), vec3(0.1593017578f))) / (1.0f + 18.6875f * pow(abs(normalizedLinearValue), vec3(0.1593017578f))), vec3(78.84375f)); - return ST2084; /* Don't clamp between [0..1], so we can still perform operations on scene values higher than 10,000 nits */ -} -/* END Converted from (Copyright (c) Microsoft Corporation - Licensed under the MIT License.) https://github.com/microsoft/Xbox-ATG-Samples/tree/master/Kits/ATGTK/HDR */ - -vec3 Hdr10(vec3 hdr) -{ - vec3 hdr10; - - if (global.hdr10 > 0.0f) - { - /* Now convert into HDR10 */ - vec3 rec2020 = hdr * k709to2020; - - if (global.expand_gamut > 0.0f) - rec2020 = hdr * kExpanded709to2020; - - vec3 linearColour = rec2020 * (global.paper_white_nits / kMaxNitsFor2084); - hdr10 = LinearToST2084(linearColour); - } - else - hdr10 = hdr; - - return hdr10; -} +#include "hdr_common.glsl" void main() { - vec4 sdr = texture(Source, vTexCoord); - vec4 hdr = vec4(InverseTonemap(sdr.rgb), sdr.a); - FragColor = vec4(Hdr10(hdr.rgb), hdr.a); + vec4 source = texture(Source, vTexCoord); + vec3 sdr = source.rgb; + vec3 hdr = sdr; + if (settings.inverse_tonemap > 0.0f) + { + hdr = InverseTonemap(sdr); + } + if (settings.hdr10 > 0.0f) + { + hdr = ConvertLinearToHDR10(hdr); + } + FragColor = vec4(hdr, source.a); } diff --git a/gfx/drivers/vulkan_shaders/hdr.frag.inc b/gfx/drivers/vulkan_shaders/hdr.frag.inc index c3f6f2d695..42df0e9ca9 100644 --- a/gfx/drivers/vulkan_shaders/hdr.frag.inc +++ b/gfx/drivers/vulkan_shaders/hdr.frag.inc @@ -1,9 +1,9 @@ -{0x07230203,0x00010000,0x000d000a,0x00000125, +{0x07230203,0x00010000,0x000d000b,0x00000141, 0x00000000,0x00020011,0x00000001,0x0006000b, 0x00000001,0x4c534c47,0x6474732e,0x3035342e, 0x00000000,0x0003000e,0x00000000,0x00000001, 0x0007000f,0x00000004,0x00000004,0x6e69616d, -0x00000000,0x0000010a,0x0000011a,0x00030010, +0x00000000,0x000000ff,0x0000011a,0x00030010, 0x00000004,0x00000007,0x00030003,0x00000001, 0x00000136,0x000a0004,0x475f4c47,0x4c474f4f, 0x70635f45,0x74735f70,0x5f656c79,0x656e696c, @@ -17,418 +17,452 @@ 0x6f547261,0x30325453,0x76283438,0x003b3366, 0x00080005,0x0000000d,0x6d726f6e,0x7a696c61, 0x694c6465,0x7261656e,0x756c6156,0x00000065, -0x00050005,0x00000011,0x31726448,0x66762830, -0x00003b33,0x00030005,0x00000010,0x00726468, -0x00030005,0x00000015,0x004f4255,0x00040006, -0x00000015,0x00000000,0x0050564d,0x00060006, -0x00000015,0x00000001,0x746e6f63,0x74736172, -0x00000000,0x00080006,0x00000015,0x00000002, -0x65706170,0x68775f72,0x5f657469,0x7374696e, -0x00000000,0x00060006,0x00000015,0x00000003, -0x5f78616d,0x7374696e,0x00000000,0x00070006, -0x00000015,0x00000004,0x61707865,0x675f646e, -0x74756d61,0x00000000,0x00070006,0x00000015, -0x00000005,0x65766e69,0x5f657372,0x656e6f74, -0x0070616d,0x00050006,0x00000015,0x00000006, -0x31726468,0x00000030,0x00040005,0x00000017, -0x626f6c67,0x00006c61,0x00040005,0x0000002c, -0x616d756c,0x00000000,0x00050005,0x00000033, +0x00090005,0x00000011,0x6d726f4e,0x7a696c61, +0x52444865,0x6e656353,0x6c615665,0x76286575, +0x003b3366,0x00060005,0x00000010,0x53726468, +0x656e6563,0x756c6156,0x00000065,0x00090005, +0x00000014,0x766e6f43,0x4c747265,0x61656e69, +0x486f5472,0x30315244,0x33667628,0x0000003b, +0x00030005,0x00000013,0x00726468,0x00030005, +0x0000001a,0x004f4255,0x00040006,0x0000001a, +0x00000000,0x0050564d,0x00060006,0x0000001a, +0x00000001,0x746e6f63,0x74736172,0x00000000, +0x00080006,0x0000001a,0x00000002,0x65706170, +0x68775f72,0x5f657469,0x7374696e,0x00000000, +0x00060006,0x0000001a,0x00000003,0x5f78616d, +0x7374696e,0x00000000,0x00070006,0x0000001a, +0x00000004,0x61707865,0x675f646e,0x74756d61, +0x00000000,0x00070006,0x0000001a,0x00000005, +0x65766e69,0x5f657372,0x656e6f74,0x0070616d, +0x00050006,0x0000001a,0x00000006,0x31726468, +0x00000030,0x00050005,0x0000001c,0x74746573, +0x73676e69,0x00000000,0x00040005,0x00000027, +0x616d756c,0x00000000,0x00050005,0x0000002e, 0x5678616d,0x65756c61,0x00000000,0x00040005, -0x0000003d,0x6f626c65,0x00000077,0x00040005, -0x00000043,0x7366666f,0x00007465,0x00070005, -0x0000004b,0x4c726468,0x49616d75,0x6f54766e, -0x616d656e,0x00000070,0x00070005,0x00000055, +0x00000038,0x6f626c65,0x00000077,0x00040005, +0x0000003e,0x7366666f,0x00007465,0x00070005, +0x00000046,0x4c726468,0x49616d75,0x6f54766e, +0x616d656e,0x00000070,0x00070005,0x00000050, 0x4c726473,0x49616d75,0x6f54766e,0x616d656e, -0x00000070,0x00060005,0x0000005b,0x616d756c, +0x00000070,0x00060005,0x00000056,0x616d756c, 0x54766e49,0x6d656e6f,0x00007061,0x00040005, -0x00000061,0x4c726570,0x00616d75,0x00060005, -0x00000069,0x49726468,0x6f54766e,0x616d656e, -0x00000070,0x00060005,0x00000075,0x49726473, +0x0000005d,0x4c726570,0x00616d75,0x00060005, +0x00000065,0x49726468,0x6f54766e,0x616d656e, +0x00000070,0x00060005,0x00000071,0x49726473, 0x6f54766e,0x616d656e,0x00000070,0x00050005, -0x0000007b,0x43726570,0x6e6e6168,0x00006c65, -0x00030005,0x000000a5,0x00726468,0x00040005, -0x000000b0,0x30325453,0x00003438,0x00040005, -0x000000cf,0x32636572,0x00303230,0x00060005, -0x000000f1,0x656e696c,0x6f437261,0x72756f6c, -0x00000000,0x00040005,0x000000f8,0x31726468, -0x00000030,0x00040005,0x000000f9,0x61726170, -0x0000006d,0x00030005,0x00000102,0x00726473, -0x00040005,0x00000106,0x72756f53,0x00006563, -0x00050005,0x0000010a,0x78655476,0x726f6f43, -0x00000064,0x00030005,0x0000010d,0x00726468, -0x00040005,0x0000010e,0x61726170,0x0000006d, -0x00050005,0x0000011a,0x67617246,0x6f6c6f43, -0x00000072,0x00040005,0x0000011b,0x61726170, -0x0000006d,0x00040048,0x00000015,0x00000000, -0x00000005,0x00050048,0x00000015,0x00000000, -0x00000023,0x00000000,0x00050048,0x00000015, -0x00000000,0x00000007,0x00000010,0x00050048, -0x00000015,0x00000001,0x00000023,0x00000040, -0x00050048,0x00000015,0x00000002,0x00000023, -0x00000044,0x00050048,0x00000015,0x00000003, -0x00000023,0x00000048,0x00050048,0x00000015, -0x00000004,0x00000023,0x0000004c,0x00050048, -0x00000015,0x00000005,0x00000023,0x00000050, -0x00050048,0x00000015,0x00000006,0x00000023, -0x00000054,0x00030047,0x00000015,0x00000002, -0x00040047,0x00000017,0x00000022,0x00000000, -0x00040047,0x00000017,0x00000021,0x00000000, -0x00040047,0x00000106,0x00000022,0x00000000, -0x00040047,0x00000106,0x00000021,0x00000002, -0x00040047,0x0000010a,0x0000001e,0x00000000, -0x00040047,0x0000011a,0x0000001e,0x00000000, -0x00020013,0x00000002,0x00030021,0x00000003, -0x00000002,0x00030016,0x00000006,0x00000020, -0x00040017,0x00000007,0x00000006,0x00000003, -0x00040020,0x00000008,0x00000007,0x00000007, -0x00040021,0x00000009,0x00000007,0x00000008, -0x00040017,0x00000013,0x00000006,0x00000004, -0x00040018,0x00000014,0x00000013,0x00000004, -0x0009001e,0x00000015,0x00000014,0x00000006, +0x00000077,0x43726570,0x6e6e6168,0x00006c65, +0x00040005,0x000000a8,0x30325453,0x00003438, +0x00040005,0x000000ca,0x32636572,0x00303230, +0x00060005,0x000000ed,0x656e696c,0x6f437261, +0x72756f6c,0x00000000,0x00040005,0x000000ee, +0x61726170,0x0000006d,0x00040005,0x000000f1, +0x61726170,0x0000006d,0x00040005,0x000000f7, +0x72756f73,0x00006563,0x00040005,0x000000fb, +0x72756f53,0x00006563,0x00050005,0x000000ff, +0x78655476,0x726f6f43,0x00000064,0x00030005, +0x00000102,0x00726473,0x00030005,0x00000105, +0x00726468,0x00040005,0x0000010d,0x61726170, +0x0000006d,0x00040005,0x00000116,0x61726170, +0x0000006d,0x00050005,0x0000011a,0x67617246, +0x6f6c6f43,0x00000072,0x00040048,0x0000001a, +0x00000000,0x00000005,0x00050048,0x0000001a, +0x00000000,0x00000023,0x00000000,0x00050048, +0x0000001a,0x00000000,0x00000007,0x00000010, +0x00050048,0x0000001a,0x00000001,0x00000023, +0x00000040,0x00050048,0x0000001a,0x00000002, +0x00000023,0x00000044,0x00050048,0x0000001a, +0x00000003,0x00000023,0x00000048,0x00050048, +0x0000001a,0x00000004,0x00000023,0x0000004c, +0x00050048,0x0000001a,0x00000005,0x00000023, +0x00000050,0x00050048,0x0000001a,0x00000006, +0x00000023,0x00000054,0x00030047,0x0000001a, +0x00000002,0x00040047,0x0000001c,0x00000022, +0x00000000,0x00040047,0x0000001c,0x00000021, +0x00000000,0x00040047,0x000000fb,0x00000022, +0x00000000,0x00040047,0x000000fb,0x00000021, +0x00000002,0x00040047,0x000000ff,0x0000001e, +0x00000000,0x00040047,0x0000011a,0x0000001e, +0x00000000,0x00020013,0x00000002,0x00030021, +0x00000003,0x00000002,0x00030016,0x00000006, +0x00000020,0x00040017,0x00000007,0x00000006, +0x00000003,0x00040020,0x00000008,0x00000007, +0x00000007,0x00040021,0x00000009,0x00000007, +0x00000008,0x00040017,0x00000018,0x00000006, +0x00000004,0x00040018,0x00000019,0x00000018, +0x00000004,0x0009001e,0x0000001a,0x00000019, 0x00000006,0x00000006,0x00000006,0x00000006, -0x00000006,0x00040020,0x00000016,0x00000002, -0x00000015,0x0004003b,0x00000016,0x00000017, -0x00000002,0x00040015,0x00000018,0x00000020, -0x00000001,0x0004002b,0x00000018,0x00000019, -0x00000005,0x00040020,0x0000001a,0x00000002, -0x00000006,0x0004002b,0x00000006,0x0000001d, -0x00000000,0x00020014,0x0000001e,0x0004002b, -0x00000018,0x00000024,0x00000001,0x0004002b, -0x00000006,0x00000027,0x400ccccd,0x00040020, -0x0000002b,0x00000007,0x00000006,0x0004002b, -0x00000006,0x0000002e,0x3e59b3d0,0x0004002b, -0x00000006,0x0000002f,0x3f371759,0x0004002b, -0x00000006,0x00000030,0x3d93dd98,0x0006002c, -0x00000007,0x00000031,0x0000002e,0x0000002f, -0x00000030,0x0004002b,0x00000018,0x00000034, -0x00000003,0x0004002b,0x00000018,0x00000037, -0x00000002,0x0004002b,0x00000006,0x0000003b, -0x38d1b717,0x0004002b,0x00000006,0x00000040, -0x3f800000,0x0004002b,0x00000006,0x00000044, -0x3f000000,0x0004002b,0x00000006,0x00000057, -0x3f800347,0x00040015,0x0000007c,0x00000020, -0x00000000,0x0004002b,0x0000007c,0x0000007d, -0x00000000,0x0004002b,0x0000007c,0x0000008a, -0x00000001,0x0004002b,0x0000007c,0x00000097, -0x00000002,0x0004002b,0x00000006,0x000000a8, -0x3e800000,0x0006002c,0x00000007,0x000000a9, -0x000000a8,0x000000a8,0x000000a8,0x0004002b, -0x00000006,0x000000b1,0x3f560000,0x0004002b, -0x00000006,0x000000b2,0x4196d000,0x0004002b, -0x00000006,0x000000b5,0x3e232000,0x0006002c, -0x00000007,0x000000b6,0x000000b5,0x000000b5, -0x000000b5,0x0004002b,0x00000006,0x000000bb, -0x41958000,0x0004002b,0x00000006,0x000000c3, -0x429db000,0x0006002c,0x00000007,0x000000c4, -0x000000c3,0x000000c3,0x000000c3,0x0004002b, -0x00000018,0x000000c9,0x00000006,0x00040018, -0x000000d1,0x00000007,0x00000003,0x0004002b, -0x00000006,0x000000d2,0x3f209d8c,0x0004002b, -0x00000006,0x000000d3,0x3ea897a6,0x0004002b, -0x00000006,0x000000d4,0x3d31699a,0x0006002c, -0x00000007,0x000000d5,0x000000d2,0x000000d3, -0x000000d4,0x0004002b,0x00000006,0x000000d6, -0x3d8d82ba,0x0004002b,0x00000006,0x000000d7, -0x3f6b66f9,0x0004002b,0x00000006,0x000000d8, -0x3c3a2454,0x0006002c,0x00000007,0x000000d9, -0x000000d6,0x000000d7,0x000000d8,0x0004002b, -0x00000006,0x000000da,0x3c8647ad,0x0004002b, -0x00000006,0x000000db,0x3db44044,0x0004002b, -0x00000006,0x000000dc,0x3f6545b7,0x0006002c, -0x00000007,0x000000dd,0x000000da,0x000000db, -0x000000dc,0x0006002c,0x000000d1,0x000000de, -0x000000d5,0x000000d9,0x000000dd,0x0004002b, -0x00000018,0x000000e0,0x00000004,0x0004002b, -0x00000006,0x000000e7,0x3d3b5fbd,0x0004002b, -0x00000006,0x000000e8,0x3f71184c,0x0004002b, -0x00000006,0x000000e9,0x3c4c6d2b,0x0006002c, -0x00000007,0x000000ea,0x000000e7,0x000000e8, -0x000000e9,0x0004002b,0x00000006,0x000000eb, -0xba9eab51,0x0004002b,0x00000006,0x000000ec, -0x3c903679,0x0004002b,0x00000006,0x000000ed, -0x3f7bcdab,0x0006002c,0x00000007,0x000000ee, -0x000000eb,0x000000ec,0x000000ed,0x0006002c, -0x000000d1,0x000000ef,0x000000d5,0x000000ea, -0x000000ee,0x0004002b,0x00000006,0x000000f5, -0x461c4000,0x00040020,0x00000101,0x00000007, -0x00000013,0x00090019,0x00000103,0x00000006, -0x00000001,0x00000000,0x00000000,0x00000000, -0x00000001,0x00000000,0x0003001b,0x00000104, -0x00000103,0x00040020,0x00000105,0x00000000, -0x00000104,0x0004003b,0x00000105,0x00000106, -0x00000000,0x00040017,0x00000108,0x00000006, -0x00000002,0x00040020,0x00000109,0x00000001, -0x00000108,0x0004003b,0x00000109,0x0000010a, -0x00000001,0x0004002b,0x0000007c,0x00000112, -0x00000003,0x00040020,0x00000119,0x00000003, -0x00000013,0x0004003b,0x00000119,0x0000011a, -0x00000003,0x00050036,0x00000002,0x00000004, -0x00000000,0x00000003,0x000200f8,0x00000005, -0x0004003b,0x00000101,0x00000102,0x00000007, -0x0004003b,0x00000101,0x0000010d,0x00000007, -0x0004003b,0x00000008,0x0000010e,0x00000007, -0x0004003b,0x00000008,0x0000011b,0x00000007, -0x0004003d,0x00000104,0x00000107,0x00000106, -0x0004003d,0x00000108,0x0000010b,0x0000010a, -0x00050057,0x00000013,0x0000010c,0x00000107, -0x0000010b,0x0003003e,0x00000102,0x0000010c, -0x0004003d,0x00000013,0x0000010f,0x00000102, -0x0008004f,0x00000007,0x00000110,0x0000010f, -0x0000010f,0x00000000,0x00000001,0x00000002, -0x0003003e,0x0000010e,0x00000110,0x00050039, -0x00000007,0x00000111,0x0000000b,0x0000010e, -0x00050041,0x0000002b,0x00000113,0x00000102, -0x00000112,0x0004003d,0x00000006,0x00000114, -0x00000113,0x00050051,0x00000006,0x00000115, -0x00000111,0x00000000,0x00050051,0x00000006, -0x00000116,0x00000111,0x00000001,0x00050051, -0x00000006,0x00000117,0x00000111,0x00000002, -0x00070050,0x00000013,0x00000118,0x00000115, -0x00000116,0x00000117,0x00000114,0x0003003e, -0x0000010d,0x00000118,0x0004003d,0x00000013, -0x0000011c,0x0000010d,0x0008004f,0x00000007, -0x0000011d,0x0000011c,0x0000011c,0x00000000, -0x00000001,0x00000002,0x0003003e,0x0000011b, -0x0000011d,0x00050039,0x00000007,0x0000011e, -0x00000011,0x0000011b,0x00050041,0x0000002b, -0x0000011f,0x0000010d,0x00000112,0x0004003d, -0x00000006,0x00000120,0x0000011f,0x00050051, -0x00000006,0x00000121,0x0000011e,0x00000000, -0x00050051,0x00000006,0x00000122,0x0000011e, -0x00000001,0x00050051,0x00000006,0x00000123, -0x0000011e,0x00000002,0x00070050,0x00000013, -0x00000124,0x00000121,0x00000122,0x00000123, -0x00000120,0x0003003e,0x0000011a,0x00000124, -0x000100fd,0x00010038,0x00050036,0x00000007, -0x0000000b,0x00000000,0x00000009,0x00030037, -0x00000008,0x0000000a,0x000200f8,0x0000000c, -0x0004003b,0x0000002b,0x0000002c,0x00000007, -0x0004003b,0x0000002b,0x00000033,0x00000007, -0x0004003b,0x0000002b,0x0000003d,0x00000007, -0x0004003b,0x0000002b,0x00000043,0x00000007, -0x0004003b,0x0000002b,0x0000004b,0x00000007, -0x0004003b,0x0000002b,0x00000055,0x00000007, -0x0004003b,0x0000002b,0x0000005b,0x00000007, -0x0004003b,0x00000008,0x00000061,0x00000007, -0x0004003b,0x00000008,0x00000069,0x00000007, -0x0004003b,0x00000008,0x00000075,0x00000007, -0x0004003b,0x00000008,0x0000007b,0x00000007, -0x0004003b,0x0000002b,0x00000081,0x00000007, -0x0004003b,0x0000002b,0x0000008e,0x00000007, -0x0004003b,0x0000002b,0x0000009b,0x00000007, -0x0004003b,0x00000008,0x000000a5,0x00000007, -0x00050041,0x0000001a,0x0000001b,0x00000017, -0x00000019,0x0004003d,0x00000006,0x0000001c, -0x0000001b,0x000500ba,0x0000001e,0x0000001f, -0x0000001c,0x0000001d,0x000300f7,0x00000021, -0x00000000,0x000400fa,0x0000001f,0x00000020, -0x000000ab,0x000200f8,0x00000020,0x0004003d, -0x00000007,0x00000022,0x0000000a,0x0006000c, -0x00000007,0x00000023,0x00000001,0x00000004, -0x00000022,0x00050041,0x0000001a,0x00000025, -0x00000017,0x00000024,0x0004003d,0x00000006, -0x00000026,0x00000025,0x00050088,0x00000006, -0x00000028,0x00000026,0x00000027,0x00060050, -0x00000007,0x00000029,0x00000028,0x00000028, -0x00000028,0x0007000c,0x00000007,0x0000002a, -0x00000001,0x0000001a,0x00000023,0x00000029, -0x0003003e,0x0000000a,0x0000002a,0x0004003d, -0x00000007,0x0000002d,0x0000000a,0x00050094, -0x00000006,0x00000032,0x0000002d,0x00000031, -0x0003003e,0x0000002c,0x00000032,0x00050041, -0x0000001a,0x00000035,0x00000017,0x00000034, -0x0004003d,0x00000006,0x00000036,0x00000035, -0x00050041,0x0000001a,0x00000038,0x00000017, -0x00000037,0x0004003d,0x00000006,0x00000039, -0x00000038,0x00050088,0x00000006,0x0000003a, -0x00000036,0x00000039,0x00050081,0x00000006, -0x0000003c,0x0000003a,0x0000003b,0x0003003e, -0x00000033,0x0000003c,0x0004003d,0x00000006, -0x0000003e,0x00000033,0x0004003d,0x00000006, -0x0000003f,0x00000033,0x00050083,0x00000006, -0x00000041,0x0000003f,0x00000040,0x00050088, -0x00000006,0x00000042,0x0000003e,0x00000041, -0x0003003e,0x0000003d,0x00000042,0x0004003d, -0x00000006,0x00000045,0x0000003d,0x00050085, -0x00000006,0x00000046,0x00000044,0x00000045, -0x0004003d,0x00000006,0x00000047,0x0000003d, -0x00050083,0x00000006,0x00000048,0x00000047, -0x00000044,0x00050088,0x00000006,0x00000049, -0x00000046,0x00000048,0x00050083,0x00000006, -0x0000004a,0x00000040,0x00000049,0x0003003e, -0x00000043,0x0000004a,0x0004003d,0x00000006, -0x0000004c,0x00000043,0x0004003d,0x00000006, -0x0000004d,0x0000002c,0x0004003d,0x00000006, -0x0000004e,0x0000003d,0x00050085,0x00000006, -0x0000004f,0x0000004d,0x0000004e,0x0004003d, -0x00000006,0x00000050,0x0000003d,0x0004003d, -0x00000006,0x00000051,0x0000002c,0x00050083, -0x00000006,0x00000052,0x00000050,0x00000051, -0x00050088,0x00000006,0x00000053,0x0000004f, -0x00000052,0x00050081,0x00000006,0x00000054, -0x0000004c,0x00000053,0x0003003e,0x0000004b, -0x00000054,0x0004003d,0x00000006,0x00000056, -0x0000002c,0x0004003d,0x00000006,0x00000058, -0x0000002c,0x00050083,0x00000006,0x00000059, -0x00000057,0x00000058,0x00050088,0x00000006, -0x0000005a,0x00000056,0x00000059,0x0003003e, -0x00000055,0x0000005a,0x0004003d,0x00000006, -0x0000005c,0x0000002c,0x000500ba,0x0000001e, -0x0000005d,0x0000005c,0x00000044,0x0004003d, -0x00000006,0x0000005e,0x0000004b,0x0004003d, -0x00000006,0x0000005f,0x00000055,0x000600a9, -0x00000006,0x00000060,0x0000005d,0x0000005e, -0x0000005f,0x0003003e,0x0000005b,0x00000060, -0x0004003d,0x00000007,0x00000062,0x0000000a, -0x0004003d,0x00000006,0x00000063,0x0000002c, -0x00050081,0x00000006,0x00000064,0x00000063, -0x0000003b,0x00060050,0x00000007,0x00000065, -0x00000064,0x00000064,0x00000064,0x00050088, -0x00000007,0x00000066,0x00000062,0x00000065, -0x0004003d,0x00000006,0x00000067,0x0000005b, -0x0005008e,0x00000007,0x00000068,0x00000066, -0x00000067,0x0003003e,0x00000061,0x00000068, -0x0004003d,0x00000006,0x0000006a,0x00000043, -0x0004003d,0x00000007,0x0000006b,0x0000000a, -0x0004003d,0x00000006,0x0000006c,0x0000003d, -0x0005008e,0x00000007,0x0000006d,0x0000006b, -0x0000006c,0x0004003d,0x00000006,0x0000006e, -0x0000003d,0x0004003d,0x00000007,0x0000006f, -0x0000000a,0x00060050,0x00000007,0x00000070, -0x0000006e,0x0000006e,0x0000006e,0x00050083, -0x00000007,0x00000071,0x00000070,0x0000006f, -0x00050088,0x00000007,0x00000072,0x0000006d, -0x00000071,0x00060050,0x00000007,0x00000073, -0x0000006a,0x0000006a,0x0000006a,0x00050081, -0x00000007,0x00000074,0x00000073,0x00000072, -0x0003003e,0x00000069,0x00000074,0x0004003d, -0x00000007,0x00000076,0x0000000a,0x0004003d, -0x00000007,0x00000077,0x0000000a,0x00060050, -0x00000007,0x00000078,0x00000057,0x00000057, -0x00000057,0x00050083,0x00000007,0x00000079, -0x00000078,0x00000077,0x00050088,0x00000007, -0x0000007a,0x00000076,0x00000079,0x0003003e, -0x00000075,0x0000007a,0x00050041,0x0000002b, -0x0000007e,0x0000000a,0x0000007d,0x0004003d, -0x00000006,0x0000007f,0x0000007e,0x000500ba, -0x0000001e,0x00000080,0x0000007f,0x00000044, -0x000300f7,0x00000083,0x00000000,0x000400fa, -0x00000080,0x00000082,0x00000086,0x000200f8, -0x00000082,0x00050041,0x0000002b,0x00000084, -0x00000069,0x0000007d,0x0004003d,0x00000006, -0x00000085,0x00000084,0x0003003e,0x00000081, -0x00000085,0x000200f9,0x00000083,0x000200f8, -0x00000086,0x00050041,0x0000002b,0x00000087, -0x00000075,0x0000007d,0x0004003d,0x00000006, -0x00000088,0x00000087,0x0003003e,0x00000081, -0x00000088,0x000200f9,0x00000083,0x000200f8, -0x00000083,0x0004003d,0x00000006,0x00000089, -0x00000081,0x00050041,0x0000002b,0x0000008b, -0x0000000a,0x0000008a,0x0004003d,0x00000006, -0x0000008c,0x0000008b,0x000500ba,0x0000001e, -0x0000008d,0x0000008c,0x00000044,0x000300f7, -0x00000090,0x00000000,0x000400fa,0x0000008d, -0x0000008f,0x00000093,0x000200f8,0x0000008f, -0x00050041,0x0000002b,0x00000091,0x00000069, -0x0000008a,0x0004003d,0x00000006,0x00000092, -0x00000091,0x0003003e,0x0000008e,0x00000092, -0x000200f9,0x00000090,0x000200f8,0x00000093, -0x00050041,0x0000002b,0x00000094,0x00000075, -0x0000008a,0x0004003d,0x00000006,0x00000095, -0x00000094,0x0003003e,0x0000008e,0x00000095, -0x000200f9,0x00000090,0x000200f8,0x00000090, -0x0004003d,0x00000006,0x00000096,0x0000008e, -0x00050041,0x0000002b,0x00000098,0x0000000a, -0x00000097,0x0004003d,0x00000006,0x00000099, -0x00000098,0x000500ba,0x0000001e,0x0000009a, -0x00000099,0x00000044,0x000300f7,0x0000009d, -0x00000000,0x000400fa,0x0000009a,0x0000009c, -0x000000a0,0x000200f8,0x0000009c,0x00050041, -0x0000002b,0x0000009e,0x00000069,0x00000097, -0x0004003d,0x00000006,0x0000009f,0x0000009e, -0x0003003e,0x0000009b,0x0000009f,0x000200f9, -0x0000009d,0x000200f8,0x000000a0,0x00050041, -0x0000002b,0x000000a1,0x00000075,0x00000097, -0x0004003d,0x00000006,0x000000a2,0x000000a1, -0x0003003e,0x0000009b,0x000000a2,0x000200f9, -0x0000009d,0x000200f8,0x0000009d,0x0004003d, -0x00000006,0x000000a3,0x0000009b,0x00060050, -0x00000007,0x000000a4,0x00000089,0x00000096, -0x000000a3,0x0003003e,0x0000007b,0x000000a4, -0x0004003d,0x00000007,0x000000a6,0x00000061, -0x0004003d,0x00000007,0x000000a7,0x0000007b, -0x0008000c,0x00000007,0x000000aa,0x00000001, -0x0000002e,0x000000a6,0x000000a7,0x000000a9, -0x0003003e,0x000000a5,0x000000aa,0x000200f9, -0x00000021,0x000200f8,0x000000ab,0x0004003d, -0x00000007,0x000000ac,0x0000000a,0x0003003e, -0x000000a5,0x000000ac,0x000200f9,0x00000021, -0x000200f8,0x00000021,0x0004003d,0x00000007, -0x000000ad,0x000000a5,0x000200fe,0x000000ad, -0x00010038,0x00050036,0x00000007,0x0000000e, +0x00000006,0x00000006,0x00040020,0x0000001b, +0x00000002,0x0000001a,0x0004003b,0x0000001b, +0x0000001c,0x00000002,0x00040015,0x0000001d, +0x00000020,0x00000001,0x0004002b,0x0000001d, +0x0000001e,0x00000001,0x00040020,0x0000001f, +0x00000002,0x00000006,0x0004002b,0x00000006, +0x00000022,0x400ccccd,0x00040020,0x00000026, +0x00000007,0x00000006,0x0004002b,0x00000006, +0x00000029,0x3e59b3d0,0x0004002b,0x00000006, +0x0000002a,0x3f371759,0x0004002b,0x00000006, +0x0000002b,0x3d93dd98,0x0006002c,0x00000007, +0x0000002c,0x00000029,0x0000002a,0x0000002b, +0x0004002b,0x0000001d,0x0000002f,0x00000003, +0x0004002b,0x0000001d,0x00000032,0x00000002, +0x0004002b,0x00000006,0x00000036,0x38d1b717, +0x0004002b,0x00000006,0x0000003b,0x3f800000, +0x0004002b,0x00000006,0x0000003f,0x3f000000, +0x0004002b,0x00000006,0x00000052,0x3f800347, +0x00020014,0x00000058,0x00040015,0x00000078, +0x00000020,0x00000000,0x0004002b,0x00000078, +0x00000079,0x00000000,0x0004002b,0x00000078, +0x00000086,0x00000001,0x0004002b,0x00000078, +0x00000093,0x00000002,0x0004002b,0x00000006, +0x000000a3,0x3e800000,0x0006002c,0x00000007, +0x000000a4,0x000000a3,0x000000a3,0x000000a3, +0x0004002b,0x00000006,0x000000a9,0x3f560000, +0x0004002b,0x00000006,0x000000aa,0x4196d000, +0x0004002b,0x00000006,0x000000ad,0x3e232000, +0x0006002c,0x00000007,0x000000ae,0x000000ad, +0x000000ad,0x000000ad,0x0004002b,0x00000006, +0x000000b3,0x41958000,0x0004002b,0x00000006, +0x000000bb,0x429db000,0x0006002c,0x00000007, +0x000000bc,0x000000bb,0x000000bb,0x000000bb, +0x0004002b,0x00000006,0x000000c5,0x461c4000, +0x00040018,0x000000cc,0x00000007,0x00000003, +0x0004002b,0x00000006,0x000000cd,0x3f209d8c, +0x0004002b,0x00000006,0x000000ce,0x3ea897a6, +0x0004002b,0x00000006,0x000000cf,0x3d31699a, +0x0006002c,0x00000007,0x000000d0,0x000000cd, +0x000000ce,0x000000cf,0x0004002b,0x00000006, +0x000000d1,0x3d8d82ba,0x0004002b,0x00000006, +0x000000d2,0x3f6b66f9,0x0004002b,0x00000006, +0x000000d3,0x3c3a2454,0x0006002c,0x00000007, +0x000000d4,0x000000d1,0x000000d2,0x000000d3, +0x0004002b,0x00000006,0x000000d5,0x3c8647ad, +0x0004002b,0x00000006,0x000000d6,0x3db44044, +0x0004002b,0x00000006,0x000000d7,0x3f6545b7, +0x0006002c,0x00000007,0x000000d8,0x000000d5, +0x000000d6,0x000000d7,0x0006002c,0x000000cc, +0x000000d9,0x000000d0,0x000000d4,0x000000d8, +0x0004002b,0x0000001d,0x000000db,0x00000004, +0x0004002b,0x00000006,0x000000de,0x00000000, +0x0004002b,0x00000006,0x000000e3,0x3d3b5fbd, +0x0004002b,0x00000006,0x000000e4,0x3f71184c, +0x0004002b,0x00000006,0x000000e5,0x3c4c6d2b, +0x0006002c,0x00000007,0x000000e6,0x000000e3, +0x000000e4,0x000000e5,0x0004002b,0x00000006, +0x000000e7,0xba9eab51,0x0004002b,0x00000006, +0x000000e8,0x3c903679,0x0004002b,0x00000006, +0x000000e9,0x3f7bcdab,0x0006002c,0x00000007, +0x000000ea,0x000000e7,0x000000e8,0x000000e9, +0x0006002c,0x000000cc,0x000000eb,0x000000d0, +0x000000e6,0x000000ea,0x00040020,0x000000f6, +0x00000007,0x00000018,0x00090019,0x000000f8, +0x00000006,0x00000001,0x00000000,0x00000000, +0x00000000,0x00000001,0x00000000,0x0003001b, +0x000000f9,0x000000f8,0x00040020,0x000000fa, +0x00000000,0x000000f9,0x0004003b,0x000000fa, +0x000000fb,0x00000000,0x00040017,0x000000fd, +0x00000006,0x00000002,0x00040020,0x000000fe, +0x00000001,0x000000fd,0x0004003b,0x000000fe, +0x000000ff,0x00000001,0x0004002b,0x0000001d, +0x00000107,0x00000005,0x0004002b,0x0000001d, +0x00000110,0x00000006,0x00040020,0x00000119, +0x00000003,0x00000018,0x0004003b,0x00000119, +0x0000011a,0x00000003,0x0004002b,0x00000078, +0x0000011c,0x00000003,0x0004002b,0x00000006, +0x00000123,0x3e5cf9a0,0x0004002b,0x00000006, +0x00000124,0x3f33e3c1,0x0004002b,0x00000006, +0x00000125,0x3df7be12,0x0006002c,0x00000007, +0x00000126,0x00000123,0x00000124,0x00000125, +0x0004002b,0x00000006,0x00000127,0x3fd48af8, +0x0004002b,0x00000006,0x00000128,0xbf166fa6, +0x0004002b,0x00000006,0x00000129,0xbd953254, +0x0006002c,0x00000007,0x0000012a,0x00000127, +0x00000128,0x00000129,0x0004002b,0x00000006, +0x0000012b,0xbdff1455,0x0004002b,0x00000006, +0x0000012c,0x3f9102dd,0x0004002b,0x00000006, +0x0000012d,0xbc08cbec,0x0006002c,0x00000007, +0x0000012e,0x0000012b,0x0000012c,0x0000012d, +0x0004002b,0x00000006,0x0000012f,0xbc94b0fd, +0x0004002b,0x00000006,0x00000130,0xbdcdfc4f, +0x0004002b,0x00000006,0x00000131,0x3f8f3289, +0x0006002c,0x00000007,0x00000132,0x0000012f, +0x00000130,0x00000131,0x0006002c,0x000000cc, +0x00000133,0x0000012a,0x0000012e,0x00000132, +0x0004002b,0x00000006,0x00000134,0x3fd15326, +0x0004002b,0x00000006,0x00000135,0xbf1210e0, +0x0004002b,0x00000006,0x00000136,0xbd84a904, +0x0006002c,0x00000007,0x00000137,0x00000134, +0x00000135,0x00000136,0x0004002b,0x00000006, +0x00000138,0xbda2c691,0x0004002b,0x00000006, +0x00000139,0x3f8b7e91,0x0004002b,0x00000006, +0x0000013a,0xbc2927ac,0x0006002c,0x00000007, +0x0000013b,0x00000138,0x00000139,0x0000013a, +0x0004002b,0x00000006,0x0000013c,0x3b61206c, +0x0004002b,0x00000006,0x0000013d,0xbca58927, +0x0004002b,0x00000006,0x0000013e,0x3f822585, +0x0006002c,0x00000007,0x0000013f,0x0000013c, +0x0000013d,0x0000013e,0x0006002c,0x000000cc, +0x00000140,0x00000137,0x0000013b,0x0000013f, +0x00050036,0x00000002,0x00000004,0x00000000, +0x00000003,0x000200f8,0x00000005,0x0004003b, +0x000000f6,0x000000f7,0x00000007,0x0004003b, +0x00000008,0x00000102,0x00000007,0x0004003b, +0x00000008,0x00000105,0x00000007,0x0004003b, +0x00000008,0x0000010d,0x00000007,0x0004003b, +0x00000008,0x00000116,0x00000007,0x0004003d, +0x000000f9,0x000000fc,0x000000fb,0x0004003d, +0x000000fd,0x00000100,0x000000ff,0x00050057, +0x00000018,0x00000101,0x000000fc,0x00000100, +0x0003003e,0x000000f7,0x00000101,0x0004003d, +0x00000018,0x00000103,0x000000f7,0x0008004f, +0x00000007,0x00000104,0x00000103,0x00000103, +0x00000000,0x00000001,0x00000002,0x0003003e, +0x00000102,0x00000104,0x0004003d,0x00000007, +0x00000106,0x00000102,0x0003003e,0x00000105, +0x00000106,0x00050041,0x0000001f,0x00000108, +0x0000001c,0x00000107,0x0004003d,0x00000006, +0x00000109,0x00000108,0x000500ba,0x00000058, +0x0000010a,0x00000109,0x000000de,0x000300f7, +0x0000010c,0x00000000,0x000400fa,0x0000010a, +0x0000010b,0x0000010c,0x000200f8,0x0000010b, +0x0004003d,0x00000007,0x0000010e,0x00000102, +0x0003003e,0x0000010d,0x0000010e,0x00050039, +0x00000007,0x0000010f,0x0000000b,0x0000010d, +0x0003003e,0x00000105,0x0000010f,0x000200f9, +0x0000010c,0x000200f8,0x0000010c,0x00050041, +0x0000001f,0x00000111,0x0000001c,0x00000110, +0x0004003d,0x00000006,0x00000112,0x00000111, +0x000500ba,0x00000058,0x00000113,0x00000112, +0x000000de,0x000300f7,0x00000115,0x00000000, +0x000400fa,0x00000113,0x00000114,0x00000115, +0x000200f8,0x00000114,0x0004003d,0x00000007, +0x00000117,0x00000105,0x0003003e,0x00000116, +0x00000117,0x00050039,0x00000007,0x00000118, +0x00000014,0x00000116,0x0003003e,0x00000105, +0x00000118,0x000200f9,0x00000115,0x000200f8, +0x00000115,0x0004003d,0x00000007,0x0000011b, +0x00000105,0x00050041,0x00000026,0x0000011d, +0x000000f7,0x0000011c,0x0004003d,0x00000006, +0x0000011e,0x0000011d,0x00050051,0x00000006, +0x0000011f,0x0000011b,0x00000000,0x00050051, +0x00000006,0x00000120,0x0000011b,0x00000001, +0x00050051,0x00000006,0x00000121,0x0000011b, +0x00000002,0x00070050,0x00000018,0x00000122, +0x0000011f,0x00000120,0x00000121,0x0000011e, +0x0003003e,0x0000011a,0x00000122,0x000100fd, +0x00010038,0x00050036,0x00000007,0x0000000b, 0x00000000,0x00000009,0x00030037,0x00000008, -0x0000000d,0x000200f8,0x0000000f,0x0004003b, -0x00000008,0x000000b0,0x00000007,0x0004003d, -0x00000007,0x000000b3,0x0000000d,0x0006000c, -0x00000007,0x000000b4,0x00000001,0x00000004, -0x000000b3,0x0007000c,0x00000007,0x000000b7, -0x00000001,0x0000001a,0x000000b4,0x000000b6, -0x0005008e,0x00000007,0x000000b8,0x000000b7, -0x000000b2,0x00060050,0x00000007,0x000000b9, -0x000000b1,0x000000b1,0x000000b1,0x00050081, -0x00000007,0x000000ba,0x000000b9,0x000000b8, -0x0004003d,0x00000007,0x000000bc,0x0000000d, -0x0006000c,0x00000007,0x000000bd,0x00000001, -0x00000004,0x000000bc,0x0007000c,0x00000007, -0x000000be,0x00000001,0x0000001a,0x000000bd, -0x000000b6,0x0005008e,0x00000007,0x000000bf, -0x000000be,0x000000bb,0x00060050,0x00000007, -0x000000c0,0x00000040,0x00000040,0x00000040, -0x00050081,0x00000007,0x000000c1,0x000000c0, -0x000000bf,0x00050088,0x00000007,0x000000c2, -0x000000ba,0x000000c1,0x0007000c,0x00000007, -0x000000c5,0x00000001,0x0000001a,0x000000c2, -0x000000c4,0x0003003e,0x000000b0,0x000000c5, -0x0004003d,0x00000007,0x000000c6,0x000000b0, -0x000200fe,0x000000c6,0x00010038,0x00050036, -0x00000007,0x00000011,0x00000000,0x00000009, -0x00030037,0x00000008,0x00000010,0x000200f8, -0x00000012,0x0004003b,0x00000008,0x000000cf, +0x0000000a,0x000200f8,0x0000000c,0x0004003b, +0x00000026,0x00000027,0x00000007,0x0004003b, +0x00000026,0x0000002e,0x00000007,0x0004003b, +0x00000026,0x00000038,0x00000007,0x0004003b, +0x00000026,0x0000003e,0x00000007,0x0004003b, +0x00000026,0x00000046,0x00000007,0x0004003b, +0x00000026,0x00000050,0x00000007,0x0004003b, +0x00000026,0x00000056,0x00000007,0x0004003b, +0x00000008,0x0000005d,0x00000007,0x0004003b, +0x00000008,0x00000065,0x00000007,0x0004003b, +0x00000008,0x00000071,0x00000007,0x0004003b, +0x00000008,0x00000077,0x00000007,0x0004003b, +0x00000026,0x0000007d,0x00000007,0x0004003b, +0x00000026,0x0000008a,0x00000007,0x0004003b, +0x00000026,0x00000097,0x00000007,0x0004003d, +0x00000007,0x00000016,0x0000000a,0x0006000c, +0x00000007,0x00000017,0x00000001,0x00000004, +0x00000016,0x00050041,0x0000001f,0x00000020, +0x0000001c,0x0000001e,0x0004003d,0x00000006, +0x00000021,0x00000020,0x00050088,0x00000006, +0x00000023,0x00000021,0x00000022,0x00060050, +0x00000007,0x00000024,0x00000023,0x00000023, +0x00000023,0x0007000c,0x00000007,0x00000025, +0x00000001,0x0000001a,0x00000017,0x00000024, +0x0003003e,0x0000000a,0x00000025,0x0004003d, +0x00000007,0x00000028,0x0000000a,0x00050094, +0x00000006,0x0000002d,0x00000028,0x0000002c, +0x0003003e,0x00000027,0x0000002d,0x00050041, +0x0000001f,0x00000030,0x0000001c,0x0000002f, +0x0004003d,0x00000006,0x00000031,0x00000030, +0x00050041,0x0000001f,0x00000033,0x0000001c, +0x00000032,0x0004003d,0x00000006,0x00000034, +0x00000033,0x00050088,0x00000006,0x00000035, +0x00000031,0x00000034,0x00050081,0x00000006, +0x00000037,0x00000035,0x00000036,0x0003003e, +0x0000002e,0x00000037,0x0004003d,0x00000006, +0x00000039,0x0000002e,0x0004003d,0x00000006, +0x0000003a,0x0000002e,0x00050083,0x00000006, +0x0000003c,0x0000003a,0x0000003b,0x00050088, +0x00000006,0x0000003d,0x00000039,0x0000003c, +0x0003003e,0x00000038,0x0000003d,0x0004003d, +0x00000006,0x00000040,0x00000038,0x00050085, +0x00000006,0x00000041,0x0000003f,0x00000040, +0x0004003d,0x00000006,0x00000042,0x00000038, +0x00050083,0x00000006,0x00000043,0x00000042, +0x0000003f,0x00050088,0x00000006,0x00000044, +0x00000041,0x00000043,0x00050083,0x00000006, +0x00000045,0x0000003b,0x00000044,0x0003003e, +0x0000003e,0x00000045,0x0004003d,0x00000006, +0x00000047,0x0000003e,0x0004003d,0x00000006, +0x00000048,0x00000027,0x0004003d,0x00000006, +0x00000049,0x00000038,0x00050085,0x00000006, +0x0000004a,0x00000048,0x00000049,0x0004003d, +0x00000006,0x0000004b,0x00000038,0x0004003d, +0x00000006,0x0000004c,0x00000027,0x00050083, +0x00000006,0x0000004d,0x0000004b,0x0000004c, +0x00050088,0x00000006,0x0000004e,0x0000004a, +0x0000004d,0x00050081,0x00000006,0x0000004f, +0x00000047,0x0000004e,0x0003003e,0x00000046, +0x0000004f,0x0004003d,0x00000006,0x00000051, +0x00000027,0x0004003d,0x00000006,0x00000053, +0x00000027,0x00050083,0x00000006,0x00000054, +0x00000052,0x00000053,0x00050088,0x00000006, +0x00000055,0x00000051,0x00000054,0x0003003e, +0x00000050,0x00000055,0x0004003d,0x00000006, +0x00000057,0x00000027,0x000500ba,0x00000058, +0x00000059,0x00000057,0x0000003f,0x0004003d, +0x00000006,0x0000005a,0x00000046,0x0004003d, +0x00000006,0x0000005b,0x00000050,0x000600a9, +0x00000006,0x0000005c,0x00000059,0x0000005a, +0x0000005b,0x0003003e,0x00000056,0x0000005c, +0x0004003d,0x00000007,0x0000005e,0x0000000a, +0x0004003d,0x00000006,0x0000005f,0x00000027, +0x00050081,0x00000006,0x00000060,0x0000005f, +0x00000036,0x00060050,0x00000007,0x00000061, +0x00000060,0x00000060,0x00000060,0x00050088, +0x00000007,0x00000062,0x0000005e,0x00000061, +0x0004003d,0x00000006,0x00000063,0x00000056, +0x0005008e,0x00000007,0x00000064,0x00000062, +0x00000063,0x0003003e,0x0000005d,0x00000064, +0x0004003d,0x00000006,0x00000066,0x0000003e, +0x0004003d,0x00000007,0x00000067,0x0000000a, +0x0004003d,0x00000006,0x00000068,0x00000038, +0x0005008e,0x00000007,0x00000069,0x00000067, +0x00000068,0x0004003d,0x00000006,0x0000006a, +0x00000038,0x0004003d,0x00000007,0x0000006b, +0x0000000a,0x00060050,0x00000007,0x0000006c, +0x0000006a,0x0000006a,0x0000006a,0x00050083, +0x00000007,0x0000006d,0x0000006c,0x0000006b, +0x00050088,0x00000007,0x0000006e,0x00000069, +0x0000006d,0x00060050,0x00000007,0x0000006f, +0x00000066,0x00000066,0x00000066,0x00050081, +0x00000007,0x00000070,0x0000006f,0x0000006e, +0x0003003e,0x00000065,0x00000070,0x0004003d, +0x00000007,0x00000072,0x0000000a,0x0004003d, +0x00000007,0x00000073,0x0000000a,0x00060050, +0x00000007,0x00000074,0x00000052,0x00000052, +0x00000052,0x00050083,0x00000007,0x00000075, +0x00000074,0x00000073,0x00050088,0x00000007, +0x00000076,0x00000072,0x00000075,0x0003003e, +0x00000071,0x00000076,0x00050041,0x00000026, +0x0000007a,0x0000000a,0x00000079,0x0004003d, +0x00000006,0x0000007b,0x0000007a,0x000500ba, +0x00000058,0x0000007c,0x0000007b,0x0000003f, +0x000300f7,0x0000007f,0x00000000,0x000400fa, +0x0000007c,0x0000007e,0x00000082,0x000200f8, +0x0000007e,0x00050041,0x00000026,0x00000080, +0x00000065,0x00000079,0x0004003d,0x00000006, +0x00000081,0x00000080,0x0003003e,0x0000007d, +0x00000081,0x000200f9,0x0000007f,0x000200f8, +0x00000082,0x00050041,0x00000026,0x00000083, +0x00000071,0x00000079,0x0004003d,0x00000006, +0x00000084,0x00000083,0x0003003e,0x0000007d, +0x00000084,0x000200f9,0x0000007f,0x000200f8, +0x0000007f,0x0004003d,0x00000006,0x00000085, +0x0000007d,0x00050041,0x00000026,0x00000087, +0x0000000a,0x00000086,0x0004003d,0x00000006, +0x00000088,0x00000087,0x000500ba,0x00000058, +0x00000089,0x00000088,0x0000003f,0x000300f7, +0x0000008c,0x00000000,0x000400fa,0x00000089, +0x0000008b,0x0000008f,0x000200f8,0x0000008b, +0x00050041,0x00000026,0x0000008d,0x00000065, +0x00000086,0x0004003d,0x00000006,0x0000008e, +0x0000008d,0x0003003e,0x0000008a,0x0000008e, +0x000200f9,0x0000008c,0x000200f8,0x0000008f, +0x00050041,0x00000026,0x00000090,0x00000071, +0x00000086,0x0004003d,0x00000006,0x00000091, +0x00000090,0x0003003e,0x0000008a,0x00000091, +0x000200f9,0x0000008c,0x000200f8,0x0000008c, +0x0004003d,0x00000006,0x00000092,0x0000008a, +0x00050041,0x00000026,0x00000094,0x0000000a, +0x00000093,0x0004003d,0x00000006,0x00000095, +0x00000094,0x000500ba,0x00000058,0x00000096, +0x00000095,0x0000003f,0x000300f7,0x00000099, +0x00000000,0x000400fa,0x00000096,0x00000098, +0x0000009c,0x000200f8,0x00000098,0x00050041, +0x00000026,0x0000009a,0x00000065,0x00000093, +0x0004003d,0x00000006,0x0000009b,0x0000009a, +0x0003003e,0x00000097,0x0000009b,0x000200f9, +0x00000099,0x000200f8,0x0000009c,0x00050041, +0x00000026,0x0000009d,0x00000071,0x00000093, +0x0004003d,0x00000006,0x0000009e,0x0000009d, +0x0003003e,0x00000097,0x0000009e,0x000200f9, +0x00000099,0x000200f8,0x00000099,0x0004003d, +0x00000006,0x0000009f,0x00000097,0x00060050, +0x00000007,0x000000a0,0x00000085,0x00000092, +0x0000009f,0x0003003e,0x00000077,0x000000a0, +0x0004003d,0x00000007,0x000000a1,0x0000005d, +0x0004003d,0x00000007,0x000000a2,0x00000077, +0x0008000c,0x00000007,0x000000a5,0x00000001, +0x0000002e,0x000000a1,0x000000a2,0x000000a4, +0x000200fe,0x000000a5,0x00010038,0x00050036, +0x00000007,0x0000000e,0x00000000,0x00000009, +0x00030037,0x00000008,0x0000000d,0x000200f8, +0x0000000f,0x0004003b,0x00000008,0x000000a8, +0x00000007,0x0004003d,0x00000007,0x000000ab, +0x0000000d,0x0006000c,0x00000007,0x000000ac, +0x00000001,0x00000004,0x000000ab,0x0007000c, +0x00000007,0x000000af,0x00000001,0x0000001a, +0x000000ac,0x000000ae,0x0005008e,0x00000007, +0x000000b0,0x000000af,0x000000aa,0x00060050, +0x00000007,0x000000b1,0x000000a9,0x000000a9, +0x000000a9,0x00050081,0x00000007,0x000000b2, +0x000000b1,0x000000b0,0x0004003d,0x00000007, +0x000000b4,0x0000000d,0x0006000c,0x00000007, +0x000000b5,0x00000001,0x00000004,0x000000b4, +0x0007000c,0x00000007,0x000000b6,0x00000001, +0x0000001a,0x000000b5,0x000000ae,0x0005008e, +0x00000007,0x000000b7,0x000000b6,0x000000b3, +0x00060050,0x00000007,0x000000b8,0x0000003b, +0x0000003b,0x0000003b,0x00050081,0x00000007, +0x000000b9,0x000000b8,0x000000b7,0x00050088, +0x00000007,0x000000ba,0x000000b2,0x000000b9, +0x0007000c,0x00000007,0x000000bd,0x00000001, +0x0000001a,0x000000ba,0x000000bc,0x0003003e, +0x000000a8,0x000000bd,0x0004003d,0x00000007, +0x000000be,0x000000a8,0x000200fe,0x000000be, +0x00010038,0x00050036,0x00000007,0x00000011, +0x00000000,0x00000009,0x00030037,0x00000008, +0x00000010,0x000200f8,0x00000012,0x0004003d, +0x00000007,0x000000c1,0x00000010,0x00050041, +0x0000001f,0x000000c2,0x0000001c,0x00000032, +0x0004003d,0x00000006,0x000000c3,0x000000c2, +0x0005008e,0x00000007,0x000000c4,0x000000c1, +0x000000c3,0x00060050,0x00000007,0x000000c6, +0x000000c5,0x000000c5,0x000000c5,0x00050088, +0x00000007,0x000000c7,0x000000c4,0x000000c6, +0x000200fe,0x000000c7,0x00010038,0x00050036, +0x00000007,0x00000014,0x00000000,0x00000009, +0x00030037,0x00000008,0x00000013,0x000200f8, +0x00000015,0x0004003b,0x00000008,0x000000ca, +0x00000007,0x0004003b,0x00000008,0x000000ed, +0x00000007,0x0004003b,0x00000008,0x000000ee, 0x00000007,0x0004003b,0x00000008,0x000000f1, -0x00000007,0x0004003b,0x00000008,0x000000f8, -0x00000007,0x0004003b,0x00000008,0x000000f9, -0x00000007,0x00050041,0x0000001a,0x000000ca, -0x00000017,0x000000c9,0x0004003d,0x00000006, -0x000000cb,0x000000ca,0x000500ba,0x0000001e, -0x000000cc,0x000000cb,0x0000001d,0x000300f7, -0x000000ce,0x00000000,0x000400fa,0x000000cc, -0x000000cd,0x000000fc,0x000200f8,0x000000cd, -0x0004003d,0x00000007,0x000000d0,0x00000010, -0x00050090,0x00000007,0x000000df,0x000000d0, -0x000000de,0x0003003e,0x000000cf,0x000000df, -0x00050041,0x0000001a,0x000000e1,0x00000017, -0x000000e0,0x0004003d,0x00000006,0x000000e2, -0x000000e1,0x000500ba,0x0000001e,0x000000e3, -0x000000e2,0x0000001d,0x000300f7,0x000000e5, -0x00000000,0x000400fa,0x000000e3,0x000000e4, -0x000000e5,0x000200f8,0x000000e4,0x0004003d, -0x00000007,0x000000e6,0x00000010,0x00050090, -0x00000007,0x000000f0,0x000000e6,0x000000ef, -0x0003003e,0x000000cf,0x000000f0,0x000200f9, -0x000000e5,0x000200f8,0x000000e5,0x0004003d, -0x00000007,0x000000f2,0x000000cf,0x00050041, -0x0000001a,0x000000f3,0x00000017,0x00000037, -0x0004003d,0x00000006,0x000000f4,0x000000f3, -0x00050088,0x00000006,0x000000f6,0x000000f4, -0x000000f5,0x0005008e,0x00000007,0x000000f7, -0x000000f2,0x000000f6,0x0003003e,0x000000f1, -0x000000f7,0x0004003d,0x00000007,0x000000fa, -0x000000f1,0x0003003e,0x000000f9,0x000000fa, -0x00050039,0x00000007,0x000000fb,0x0000000e, -0x000000f9,0x0003003e,0x000000f8,0x000000fb, -0x000200f9,0x000000ce,0x000200f8,0x000000fc, -0x0004003d,0x00000007,0x000000fd,0x00000010, -0x0003003e,0x000000f8,0x000000fd,0x000200f9, -0x000000ce,0x000200f8,0x000000ce,0x0004003d, -0x00000007,0x000000fe,0x000000f8,0x000200fe, -0x000000fe,0x00010038} +0x00000007,0x0004003d,0x00000007,0x000000cb, +0x00000013,0x00050090,0x00000007,0x000000da, +0x000000cb,0x000000d9,0x0003003e,0x000000ca, +0x000000da,0x00050041,0x0000001f,0x000000dc, +0x0000001c,0x000000db,0x0004003d,0x00000006, +0x000000dd,0x000000dc,0x000500ba,0x00000058, +0x000000df,0x000000dd,0x000000de,0x000300f7, +0x000000e1,0x00000000,0x000400fa,0x000000df, +0x000000e0,0x000000e1,0x000200f8,0x000000e0, +0x0004003d,0x00000007,0x000000e2,0x00000013, +0x00050090,0x00000007,0x000000ec,0x000000e2, +0x000000eb,0x0003003e,0x000000ca,0x000000ec, +0x000200f9,0x000000e1,0x000200f8,0x000000e1, +0x0004003d,0x00000007,0x000000ef,0x000000ca, +0x0003003e,0x000000ee,0x000000ef,0x00050039, +0x00000007,0x000000f0,0x00000011,0x000000ee, +0x0003003e,0x000000ed,0x000000f0,0x0004003d, +0x00000007,0x000000f2,0x000000ed,0x0003003e, +0x000000f1,0x000000f2,0x00050039,0x00000007, +0x000000f3,0x0000000e,0x000000f1,0x000200fe, +0x000000f3,0x00010038} diff --git a/gfx/drivers/vulkan_shaders/hdr_common.glsl b/gfx/drivers/vulkan_shaders/hdr_common.glsl new file mode 100644 index 0000000000..b97f36d83e --- /dev/null +++ b/gfx/drivers/vulkan_shaders/hdr_common.glsl @@ -0,0 +1,163 @@ +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; + float contrast; /* 2.0f; */ + float paper_white_nits; /* 200.0f; */ + float max_nits; /* 1000.0f; */ + float expand_gamut; /* 1.0f; */ + float inverse_tonemap; + float hdr10; +} settings; + +/* Tonemapping: conversion from HDR to SDR (and vice-versa) */ +const float kMaxNitsFor2084 = 10000.0f; +const float kEpsilon = 0.0001f; +const float kLumaChannelRatio = 0.25f; + +/* Rec BT.709 luma coefficients - https://en.wikipedia.org/wiki/Luma_(video) */ +const vec3 k709LumaCoeff = vec3(0.2126f, 0.7152f, 0.0722f); +/* Expanded Rec BT.709 luma coefficients - obtained by linear transformation + normalization */ +const vec3 kExpanded709LumaCoeff = vec3(0.215796f, 0.702694f, 0.120968f); + +vec3 InverseTonemap(vec3 sdr) +{ + /* Display Gamma - needs to be determined by calibration screen */ + sdr = pow(abs(sdr), vec3(settings.contrast / 2.2f)); + float luma = dot(sdr, k709LumaCoeff); + + /* Apply inverse tonemap to luma and color channels separately. + * SDR values in the range 0..0.5 are mapped to the range 0..1 with a simple inverse reinhard tonemap. + * SDR values higher than 0.5 are mapped to the range 1..infinity with an inverse reinhard scaled according to settings. + */ + float maxValue = (settings.max_nits / settings.paper_white_nits) + kEpsilon; + float elbow = maxValue / (maxValue - 1.0f); + float offset = 1.0f - ((0.5f * elbow) / (elbow - 0.5f)); + + float hdrLumaInvTonemap = offset + ((luma * elbow) / (elbow - luma)); + float sdrLumaInvTonemap = luma / (1.0f + kEpsilon - luma); + + float lumaInvTonemap = (luma > 0.5f) ? hdrLumaInvTonemap : sdrLumaInvTonemap; + vec3 perLuma = sdr / (luma + kEpsilon) * lumaInvTonemap; + + vec3 hdrInvTonemap = offset + ((sdr * elbow) / (elbow - sdr)); + vec3 sdrInvTonemap = sdr / ((1.0f + kEpsilon) - sdr); + + vec3 perChannel = vec3(sdr.x > 0.5f ? hdrInvTonemap.x : sdrInvTonemap.x, + sdr.y > 0.5f ? hdrInvTonemap.y : sdrInvTonemap.y, + sdr.z > 0.5f ? hdrInvTonemap.z : sdrInvTonemap.z); + + return mix(perLuma, perChannel, vec3(kLumaChannelRatio)); +} + +vec3 Tonemap(vec3 hdr) +{ + float luma = dot(hdr, k709LumaCoeff); + if (settings.expand_gamut > 0.0f) + luma = dot(hdr, kExpanded709LumaCoeff); + + float maxValue = (settings.max_nits / settings.paper_white_nits) + kEpsilon; + float elbow = maxValue / (maxValue - 1.0f); + float offset = 1.0f - ((0.5f * elbow) / (elbow - 0.5f)); + + /* Tonemap luma and individual channels separately, and combine them afterwards*/ + float hdrLumaTonemap = elbow * (offset - luma) / (offset - luma - elbow + kEpsilon); + float sdrLumaTonemap = luma / (luma + 1.0f); + float lumaTonemap = luma >= 1.0f ? hdrLumaTonemap : sdrLumaTonemap; + vec3 perLuma = hdr / (luma + kEpsilon) * lumaTonemap; + + vec3 hdrTonemap = elbow * (offset - hdr) / (offset - hdr - elbow + kEpsilon); + vec3 sdrTonemap = hdr / (hdr + 1.0f); + vec3 perChannel = vec3(hdr.x > 1.0f ? hdrTonemap.x : sdrTonemap.x, + hdr.y > 1.0f ? hdrTonemap.y : sdrTonemap.y, + hdr.z > 1.0f ? hdrTonemap.z : sdrTonemap.z); + + vec3 tonemap = clamp(mix(perLuma, perChannel, vec3(kLumaChannelRatio)), 0.0f, 1.0f); + /* Display Gamma - needs to be determined by calibration screen */ + return pow(tonemap, vec3(2.2f / settings.contrast)); +} + +/* Colorspace conversions */ +/* START Converted from (Copyright (c) Microsoft Corporation - Licensed under the MIT License.) https://github.com/microsoft/Xbox-ATG-Samples/tree/master/Kits/ATGTK/HDR */ + +vec3 LinearToST2084(vec3 normalizedLinearValue) +{ + vec3 ST2084 = pow((0.8359375f + 18.8515625f * pow(abs(normalizedLinearValue), vec3(0.1593017578f))) / (1.0f + 18.6875f * pow(abs(normalizedLinearValue), vec3(0.1593017578f))), vec3(78.84375f)); + return ST2084; /* Don't clamp between [0..1], so we can still perform operations on scene values higher than 10,000 nits */ +} + +vec3 ST2084ToLinear(vec3 ST2084) +{ + vec3 normalizedLinear = pow(abs(max(pow(abs(ST2084), vec3(1.0f / 78.84375f)) - 0.8359375f, 0.0f) / (18.8515625f - 18.6875f * pow(abs(ST2084), vec3(1.0f / 78.84375f)))), vec3(1.0f / 0.1593017578f)); + return normalizedLinear; +} + +/* Color rotation matrix to rotate Rec.709 color primaries into Rec.2020 */ +const mat3 k709to2020 = mat3 ( + 0.6274040f, 0.3292820f, 0.0433136f, + 0.0690970f, 0.9195400f, 0.0113612f, + 0.0163916f, 0.0880132f, 0.8955950f); + +/* Color rotation matrix to rotate Rec.2020 color primaries into Rec.709 */ +const mat3 k2020to709 = mat3 ( + 1.6604910f, -0.5876411f, -0.0728499f, + -0.1245505f, 1.1328999f, -0.0083494f, + -0.0181508f, -0.1005789f, 1.1187297f); + +/* Rotation matrix describing a custom color space which is bigger than Rec.709, but a little smaller than P3-D65. + * This enhances colors, especially in the SDR range, by being a little more saturated. This can be used instead + * of from709to2020. + */ +const mat3 kExpanded709to2020 = mat3 ( + 0.6274040f, 0.3292820f, 0.0433136f, + 0.0457456f, 0.941777f, 0.0124772f, + -0.00121055f, 0.0176041f, 0.983607f); + +/* Rotation matrix from Rec. 2020 color primaries into the custom expanded Rec.709 colorspace described above. */ +const mat3 k2020toExpanded709 = mat3 ( + 1.63535f, -0.57057f, -0.0647755f, + -0.0794803f, 1.0898f, -0.0103244f, + 0.00343516f, -0.020207f, 1.01677f); + +/* Per spec, the max nits for ST.2084 is 10,000 nits. We need to establish what the value of 1.0f means + * by normalizing the values using the defined nits for paper white. According to SDR specs, paper white + * is 80 nits, but that is paper white in a cinema with a dark environment, and is perceived as grey on + * a display in office and living room environments. This value should be tuned according to the nits + * that the consumer perceives as white in his living room, e.g. 200 nits. As refernce, PC monitors is + * normally in the range 200-300 nits, SDR TVs 150-250 nits. + */ +vec3 NormalizeHDRSceneValue(vec3 hdrSceneValue) +{ + return hdrSceneValue * settings.paper_white_nits / kMaxNitsFor2084; +} + +/* Calc the value that the HDR scene has to use to output a certain brightness */ +vec3 CalcHDRSceneValue(vec3 nits) +{ + return nits * kMaxNitsFor2084 / settings.paper_white_nits; +} + +/* Converts a linear HDR value in the Rec.709 colorspace to a non-linear HDR10 value in the BT. 2020 colorspace */ +vec3 ConvertLinearToHDR10(vec3 hdr) +{ + vec3 rec2020 = hdr * k709to2020; + if (settings.expand_gamut > 0.0f) + rec2020 = hdr * kExpanded709to2020; + + vec3 linearColour = NormalizeHDRSceneValue(rec2020); + return LinearToST2084(linearColour); +} + +/* END Converted from (Copyright (c) Microsoft Corporation - Licensed under the MIT License.) https://github.com/microsoft/Xbox-ATG-Samples/tree/master/Kits/ATGTK/HDR */ + +/* Converts a non-linear HDR10 value in the BT. 2020 colorspace to a linear HDR value in the Rec. 709 colorspace */ +vec3 ConvertHDR10ToLinear(vec3 hdr10) +{ + vec3 normalizedLinear = ST2084ToLinear(hdr10); + vec3 rec2020 = CalcHDRSceneValue(normalizedLinear); + + vec3 hdr = rec2020 * k2020to709; + if (settings.expand_gamut > 0.0f) + hdr = rec2020 * k2020toExpanded709; + + return hdr; +} diff --git a/gfx/drivers/vulkan_shaders/hdr_tonemap.frag b/gfx/drivers/vulkan_shaders/hdr_tonemap.frag new file mode 100644 index 0000000000..9ba324bdda --- /dev/null +++ b/gfx/drivers/vulkan_shaders/hdr_tonemap.frag @@ -0,0 +1,27 @@ +#version 310 es + +precision highp float; +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform highp sampler2D Source; + +#include "hdr_common.glsl" + +void main() +{ + vec4 source = texture(Source, vTexCoord); + vec3 hdr = source.rgb; + vec3 linear = hdr; + if (settings.hdr10 == 0.0f) + { + /* Backbuffer is in HDR10, need to convert to linear */ + linear = ConvertHDR10ToLinear(hdr); + } + vec3 sdr = hdr; + if (settings.inverse_tonemap == 0.0f) + { + /* Backbuffer is inverse tonemapped, need to tonemap back */ + sdr = Tonemap(linear); + } + FragColor = vec4(sdr, source.a); +} diff --git a/gfx/drivers/vulkan_shaders/hdr_tonemap.frag.inc b/gfx/drivers/vulkan_shaders/hdr_tonemap.frag.inc new file mode 100644 index 0000000000..31744df449 --- /dev/null +++ b/gfx/drivers/vulkan_shaders/hdr_tonemap.frag.inc @@ -0,0 +1,501 @@ +{0x07230203,0x00010000,0x000d000b,0x00000158, +0x00000000,0x00020011,0x00000001,0x0006000b, +0x00000001,0x4c534c47,0x6474732e,0x3035342e, +0x00000000,0x0003000e,0x00000000,0x00000001, +0x0007000f,0x00000004,0x00000004,0x6e69616d, +0x00000000,0x0000011c,0x00000139,0x00030010, +0x00000004,0x00000007,0x00030003,0x00000001, +0x00000136,0x000a0004,0x475f4c47,0x4c474f4f, +0x70635f45,0x74735f70,0x5f656c79,0x656e696c, +0x7269645f,0x69746365,0x00006576,0x00080004, +0x475f4c47,0x4c474f4f,0x6e695f45,0x64756c63, +0x69645f65,0x74636572,0x00657669,0x00040005, +0x00000004,0x6e69616d,0x00000000,0x00060005, +0x0000000b,0x656e6f54,0x2870616d,0x3b336676, +0x00000000,0x00030005,0x0000000a,0x00726468, +0x00070005,0x0000000e,0x30325453,0x6f543438, +0x656e694c,0x76287261,0x003b3366,0x00040005, +0x0000000d,0x30325453,0x00003438,0x00080005, +0x00000011,0x636c6143,0x53524448,0x656e6563, +0x756c6156,0x66762865,0x00003b33,0x00040005, +0x00000010,0x7374696e,0x00000000,0x00090005, +0x00000014,0x766e6f43,0x48747265,0x30315244, +0x694c6f54,0x7261656e,0x33667628,0x0000003b, +0x00040005,0x00000013,0x31726468,0x00000030, +0x00040005,0x00000017,0x616d756c,0x00000000, +0x00030005,0x00000020,0x004f4255,0x00040006, +0x00000020,0x00000000,0x0050564d,0x00060006, +0x00000020,0x00000001,0x746e6f63,0x74736172, +0x00000000,0x00080006,0x00000020,0x00000002, +0x65706170,0x68775f72,0x5f657469,0x7374696e, +0x00000000,0x00060006,0x00000020,0x00000003, +0x5f78616d,0x7374696e,0x00000000,0x00070006, +0x00000020,0x00000004,0x61707865,0x675f646e, +0x74756d61,0x00000000,0x00070006,0x00000020, +0x00000005,0x65766e69,0x5f657372,0x656e6f74, +0x0070616d,0x00050006,0x00000020,0x00000006, +0x31726468,0x00000030,0x00050005,0x00000022, +0x74746573,0x73676e69,0x00000000,0x00050005, +0x00000033,0x5678616d,0x65756c61,0x00000000, +0x00040005,0x0000003d,0x6f626c65,0x00000077, +0x00040005,0x00000043,0x7366666f,0x00007465, +0x00060005,0x0000004b,0x4c726468,0x54616d75, +0x6d656e6f,0x00007061,0x00060005,0x00000058, +0x4c726473,0x54616d75,0x6d656e6f,0x00007061, +0x00050005,0x0000005d,0x616d756c,0x656e6f54, +0x0070616d,0x00040005,0x00000063,0x4c726570, +0x00616d75,0x00050005,0x0000006b,0x54726468, +0x6d656e6f,0x00007061,0x00050005,0x0000007c, +0x54726473,0x6d656e6f,0x00007061,0x00050005, +0x00000082,0x43726570,0x6e6e6168,0x00006c65, +0x00040005,0x000000ac,0x656e6f74,0x0070616d, +0x00070005,0x000000bf,0x6d726f6e,0x7a696c61, +0x694c6465,0x7261656e,0x00000000,0x00070005, +0x000000e3,0x6d726f6e,0x7a696c61,0x694c6465, +0x7261656e,0x00000000,0x00040005,0x000000e4, +0x61726170,0x0000006d,0x00040005,0x000000e7, +0x32636572,0x00303230,0x00040005,0x000000e8, +0x61726170,0x0000006d,0x00030005,0x000000eb, +0x00726468,0x00040005,0x00000114,0x72756f73, +0x00006563,0x00040005,0x00000118,0x72756f53, +0x00006563,0x00050005,0x0000011c,0x78655476, +0x726f6f43,0x00000064,0x00030005,0x0000011f, +0x00726468,0x00040005,0x00000122,0x656e696c, +0x00007261,0x00040005,0x0000012a,0x61726170, +0x0000006d,0x00030005,0x0000012d,0x00726473, +0x00040005,0x00000135,0x61726170,0x0000006d, +0x00050005,0x00000139,0x67617246,0x6f6c6f43, +0x00000072,0x00040048,0x00000020,0x00000000, +0x00000005,0x00050048,0x00000020,0x00000000, +0x00000023,0x00000000,0x00050048,0x00000020, +0x00000000,0x00000007,0x00000010,0x00050048, +0x00000020,0x00000001,0x00000023,0x00000040, +0x00050048,0x00000020,0x00000002,0x00000023, +0x00000044,0x00050048,0x00000020,0x00000003, +0x00000023,0x00000048,0x00050048,0x00000020, +0x00000004,0x00000023,0x0000004c,0x00050048, +0x00000020,0x00000005,0x00000023,0x00000050, +0x00050048,0x00000020,0x00000006,0x00000023, +0x00000054,0x00030047,0x00000020,0x00000002, +0x00040047,0x00000022,0x00000022,0x00000000, +0x00040047,0x00000022,0x00000021,0x00000000, +0x00040047,0x00000118,0x00000022,0x00000000, +0x00040047,0x00000118,0x00000021,0x00000002, +0x00040047,0x0000011c,0x0000001e,0x00000000, +0x00040047,0x00000139,0x0000001e,0x00000000, +0x00020013,0x00000002,0x00030021,0x00000003, +0x00000002,0x00030016,0x00000006,0x00000020, +0x00040017,0x00000007,0x00000006,0x00000003, +0x00040020,0x00000008,0x00000007,0x00000007, +0x00040021,0x00000009,0x00000007,0x00000008, +0x00040020,0x00000016,0x00000007,0x00000006, +0x0004002b,0x00000006,0x00000019,0x3e59b3d0, +0x0004002b,0x00000006,0x0000001a,0x3f371759, +0x0004002b,0x00000006,0x0000001b,0x3d93dd98, +0x0006002c,0x00000007,0x0000001c,0x00000019, +0x0000001a,0x0000001b,0x00040017,0x0000001e, +0x00000006,0x00000004,0x00040018,0x0000001f, +0x0000001e,0x00000004,0x0009001e,0x00000020, +0x0000001f,0x00000006,0x00000006,0x00000006, +0x00000006,0x00000006,0x00000006,0x00040020, +0x00000021,0x00000002,0x00000020,0x0004003b, +0x00000021,0x00000022,0x00000002,0x00040015, +0x00000023,0x00000020,0x00000001,0x0004002b, +0x00000023,0x00000024,0x00000004,0x00040020, +0x00000025,0x00000002,0x00000006,0x0004002b, +0x00000006,0x00000028,0x00000000,0x00020014, +0x00000029,0x0004002b,0x00000006,0x0000002e, +0x3e5cf9a0,0x0004002b,0x00000006,0x0000002f, +0x3f33e3c1,0x0004002b,0x00000006,0x00000030, +0x3df7be12,0x0006002c,0x00000007,0x00000031, +0x0000002e,0x0000002f,0x00000030,0x0004002b, +0x00000023,0x00000034,0x00000003,0x0004002b, +0x00000023,0x00000037,0x00000002,0x0004002b, +0x00000006,0x0000003b,0x38d1b717,0x0004002b, +0x00000006,0x00000040,0x3f800000,0x0004002b, +0x00000006,0x00000044,0x3f000000,0x00040015, +0x00000083,0x00000020,0x00000000,0x0004002b, +0x00000083,0x00000084,0x00000000,0x0004002b, +0x00000083,0x00000091,0x00000001,0x0004002b, +0x00000083,0x0000009e,0x00000002,0x0004002b, +0x00000006,0x000000af,0x3e800000,0x0006002c, +0x00000007,0x000000b0,0x000000af,0x000000af, +0x000000af,0x0004002b,0x00000006,0x000000b6, +0x400ccccd,0x0004002b,0x00000023,0x000000b7, +0x00000001,0x0004002b,0x00000006,0x000000c2, +0x3c4fcdac,0x0006002c,0x00000007,0x000000c3, +0x000000c2,0x000000c2,0x000000c2,0x0004002b, +0x00000006,0x000000c5,0x3f560000,0x0004002b, +0x00000006,0x000000ca,0x4196d000,0x0004002b, +0x00000006,0x000000cb,0x41958000,0x0004002b, +0x00000006,0x000000d4,0x40c8e06b,0x0006002c, +0x00000007,0x000000d5,0x000000d4,0x000000d4, +0x000000d4,0x0004002b,0x00000006,0x000000db, +0x461c4000,0x00040018,0x000000ed,0x00000007, +0x00000003,0x0004002b,0x00000006,0x000000ee, +0x3fd48af8,0x0004002b,0x00000006,0x000000ef, +0xbf166fa6,0x0004002b,0x00000006,0x000000f0, +0xbd953254,0x0006002c,0x00000007,0x000000f1, +0x000000ee,0x000000ef,0x000000f0,0x0004002b, +0x00000006,0x000000f2,0xbdff1455,0x0004002b, +0x00000006,0x000000f3,0x3f9102dd,0x0004002b, +0x00000006,0x000000f4,0xbc08cbec,0x0006002c, +0x00000007,0x000000f5,0x000000f2,0x000000f3, +0x000000f4,0x0004002b,0x00000006,0x000000f6, +0xbc94b0fd,0x0004002b,0x00000006,0x000000f7, +0xbdcdfc4f,0x0004002b,0x00000006,0x000000f8, +0x3f8f3289,0x0006002c,0x00000007,0x000000f9, +0x000000f6,0x000000f7,0x000000f8,0x0006002c, +0x000000ed,0x000000fa,0x000000f1,0x000000f5, +0x000000f9,0x0004002b,0x00000006,0x00000102, +0x3fd15326,0x0004002b,0x00000006,0x00000103, +0xbf1210e0,0x0004002b,0x00000006,0x00000104, +0xbd84a904,0x0006002c,0x00000007,0x00000105, +0x00000102,0x00000103,0x00000104,0x0004002b, +0x00000006,0x00000106,0xbda2c691,0x0004002b, +0x00000006,0x00000107,0x3f8b7e91,0x0004002b, +0x00000006,0x00000108,0xbc2927ac,0x0006002c, +0x00000007,0x00000109,0x00000106,0x00000107, +0x00000108,0x0004002b,0x00000006,0x0000010a, +0x3b61206c,0x0004002b,0x00000006,0x0000010b, +0xbca58927,0x0004002b,0x00000006,0x0000010c, +0x3f822585,0x0006002c,0x00000007,0x0000010d, +0x0000010a,0x0000010b,0x0000010c,0x0006002c, +0x000000ed,0x0000010e,0x00000105,0x00000109, +0x0000010d,0x00040020,0x00000113,0x00000007, +0x0000001e,0x00090019,0x00000115,0x00000006, +0x00000001,0x00000000,0x00000000,0x00000000, +0x00000001,0x00000000,0x0003001b,0x00000116, +0x00000115,0x00040020,0x00000117,0x00000000, +0x00000116,0x0004003b,0x00000117,0x00000118, +0x00000000,0x00040017,0x0000011a,0x00000006, +0x00000002,0x00040020,0x0000011b,0x00000001, +0x0000011a,0x0004003b,0x0000011b,0x0000011c, +0x00000001,0x0004002b,0x00000023,0x00000124, +0x00000006,0x0004002b,0x00000023,0x0000012f, +0x00000005,0x00040020,0x00000138,0x00000003, +0x0000001e,0x0004003b,0x00000138,0x00000139, +0x00000003,0x0004002b,0x00000083,0x0000013b, +0x00000003,0x0004002b,0x00000006,0x00000142, +0x3f209d8c,0x0004002b,0x00000006,0x00000143, +0x3ea897a6,0x0004002b,0x00000006,0x00000144, +0x3d31699a,0x0006002c,0x00000007,0x00000145, +0x00000142,0x00000143,0x00000144,0x0004002b, +0x00000006,0x00000146,0x3d8d82ba,0x0004002b, +0x00000006,0x00000147,0x3f6b66f9,0x0004002b, +0x00000006,0x00000148,0x3c3a2454,0x0006002c, +0x00000007,0x00000149,0x00000146,0x00000147, +0x00000148,0x0004002b,0x00000006,0x0000014a, +0x3c8647ad,0x0004002b,0x00000006,0x0000014b, +0x3db44044,0x0004002b,0x00000006,0x0000014c, +0x3f6545b7,0x0006002c,0x00000007,0x0000014d, +0x0000014a,0x0000014b,0x0000014c,0x0006002c, +0x000000ed,0x0000014e,0x00000145,0x00000149, +0x0000014d,0x0004002b,0x00000006,0x0000014f, +0x3d3b5fbd,0x0004002b,0x00000006,0x00000150, +0x3f71184c,0x0004002b,0x00000006,0x00000151, +0x3c4c6d2b,0x0006002c,0x00000007,0x00000152, +0x0000014f,0x00000150,0x00000151,0x0004002b, +0x00000006,0x00000153,0xba9eab51,0x0004002b, +0x00000006,0x00000154,0x3c903679,0x0004002b, +0x00000006,0x00000155,0x3f7bcdab,0x0006002c, +0x00000007,0x00000156,0x00000153,0x00000154, +0x00000155,0x0006002c,0x000000ed,0x00000157, +0x00000145,0x00000152,0x00000156,0x00050036, +0x00000002,0x00000004,0x00000000,0x00000003, +0x000200f8,0x00000005,0x0004003b,0x00000113, +0x00000114,0x00000007,0x0004003b,0x00000008, +0x0000011f,0x00000007,0x0004003b,0x00000008, +0x00000122,0x00000007,0x0004003b,0x00000008, +0x0000012a,0x00000007,0x0004003b,0x00000008, +0x0000012d,0x00000007,0x0004003b,0x00000008, +0x00000135,0x00000007,0x0004003d,0x00000116, +0x00000119,0x00000118,0x0004003d,0x0000011a, +0x0000011d,0x0000011c,0x00050057,0x0000001e, +0x0000011e,0x00000119,0x0000011d,0x0003003e, +0x00000114,0x0000011e,0x0004003d,0x0000001e, +0x00000120,0x00000114,0x0008004f,0x00000007, +0x00000121,0x00000120,0x00000120,0x00000000, +0x00000001,0x00000002,0x0003003e,0x0000011f, +0x00000121,0x0004003d,0x00000007,0x00000123, +0x0000011f,0x0003003e,0x00000122,0x00000123, +0x00050041,0x00000025,0x00000125,0x00000022, +0x00000124,0x0004003d,0x00000006,0x00000126, +0x00000125,0x000500b4,0x00000029,0x00000127, +0x00000126,0x00000028,0x000300f7,0x00000129, +0x00000000,0x000400fa,0x00000127,0x00000128, +0x00000129,0x000200f8,0x00000128,0x0004003d, +0x00000007,0x0000012b,0x0000011f,0x0003003e, +0x0000012a,0x0000012b,0x00050039,0x00000007, +0x0000012c,0x00000014,0x0000012a,0x0003003e, +0x00000122,0x0000012c,0x000200f9,0x00000129, +0x000200f8,0x00000129,0x0004003d,0x00000007, +0x0000012e,0x0000011f,0x0003003e,0x0000012d, +0x0000012e,0x00050041,0x00000025,0x00000130, +0x00000022,0x0000012f,0x0004003d,0x00000006, +0x00000131,0x00000130,0x000500b4,0x00000029, +0x00000132,0x00000131,0x00000028,0x000300f7, +0x00000134,0x00000000,0x000400fa,0x00000132, +0x00000133,0x00000134,0x000200f8,0x00000133, +0x0004003d,0x00000007,0x00000136,0x00000122, +0x0003003e,0x00000135,0x00000136,0x00050039, +0x00000007,0x00000137,0x0000000b,0x00000135, +0x0003003e,0x0000012d,0x00000137,0x000200f9, +0x00000134,0x000200f8,0x00000134,0x0004003d, +0x00000007,0x0000013a,0x0000012d,0x00050041, +0x00000016,0x0000013c,0x00000114,0x0000013b, +0x0004003d,0x00000006,0x0000013d,0x0000013c, +0x00050051,0x00000006,0x0000013e,0x0000013a, +0x00000000,0x00050051,0x00000006,0x0000013f, +0x0000013a,0x00000001,0x00050051,0x00000006, +0x00000140,0x0000013a,0x00000002,0x00070050, +0x0000001e,0x00000141,0x0000013e,0x0000013f, +0x00000140,0x0000013d,0x0003003e,0x00000139, +0x00000141,0x000100fd,0x00010038,0x00050036, +0x00000007,0x0000000b,0x00000000,0x00000009, +0x00030037,0x00000008,0x0000000a,0x000200f8, +0x0000000c,0x0004003b,0x00000016,0x00000017, +0x00000007,0x0004003b,0x00000016,0x00000033, +0x00000007,0x0004003b,0x00000016,0x0000003d, +0x00000007,0x0004003b,0x00000016,0x00000043, +0x00000007,0x0004003b,0x00000016,0x0000004b, +0x00000007,0x0004003b,0x00000016,0x00000058, +0x00000007,0x0004003b,0x00000016,0x0000005d, +0x00000007,0x0004003b,0x00000008,0x00000063, +0x00000007,0x0004003b,0x00000008,0x0000006b, +0x00000007,0x0004003b,0x00000008,0x0000007c, +0x00000007,0x0004003b,0x00000008,0x00000082, +0x00000007,0x0004003b,0x00000016,0x00000088, +0x00000007,0x0004003b,0x00000016,0x00000095, +0x00000007,0x0004003b,0x00000016,0x000000a2, +0x00000007,0x0004003b,0x00000008,0x000000ac, +0x00000007,0x0004003d,0x00000007,0x00000018, +0x0000000a,0x00050094,0x00000006,0x0000001d, +0x00000018,0x0000001c,0x0003003e,0x00000017, +0x0000001d,0x00050041,0x00000025,0x00000026, +0x00000022,0x00000024,0x0004003d,0x00000006, +0x00000027,0x00000026,0x000500ba,0x00000029, +0x0000002a,0x00000027,0x00000028,0x000300f7, +0x0000002c,0x00000000,0x000400fa,0x0000002a, +0x0000002b,0x0000002c,0x000200f8,0x0000002b, +0x0004003d,0x00000007,0x0000002d,0x0000000a, +0x00050094,0x00000006,0x00000032,0x0000002d, +0x00000031,0x0003003e,0x00000017,0x00000032, +0x000200f9,0x0000002c,0x000200f8,0x0000002c, +0x00050041,0x00000025,0x00000035,0x00000022, +0x00000034,0x0004003d,0x00000006,0x00000036, +0x00000035,0x00050041,0x00000025,0x00000038, +0x00000022,0x00000037,0x0004003d,0x00000006, +0x00000039,0x00000038,0x00050088,0x00000006, +0x0000003a,0x00000036,0x00000039,0x00050081, +0x00000006,0x0000003c,0x0000003a,0x0000003b, +0x0003003e,0x00000033,0x0000003c,0x0004003d, +0x00000006,0x0000003e,0x00000033,0x0004003d, +0x00000006,0x0000003f,0x00000033,0x00050083, +0x00000006,0x00000041,0x0000003f,0x00000040, +0x00050088,0x00000006,0x00000042,0x0000003e, +0x00000041,0x0003003e,0x0000003d,0x00000042, +0x0004003d,0x00000006,0x00000045,0x0000003d, +0x00050085,0x00000006,0x00000046,0x00000044, +0x00000045,0x0004003d,0x00000006,0x00000047, +0x0000003d,0x00050083,0x00000006,0x00000048, +0x00000047,0x00000044,0x00050088,0x00000006, +0x00000049,0x00000046,0x00000048,0x00050083, +0x00000006,0x0000004a,0x00000040,0x00000049, +0x0003003e,0x00000043,0x0000004a,0x0004003d, +0x00000006,0x0000004c,0x0000003d,0x0004003d, +0x00000006,0x0000004d,0x00000043,0x0004003d, +0x00000006,0x0000004e,0x00000017,0x00050083, +0x00000006,0x0000004f,0x0000004d,0x0000004e, +0x00050085,0x00000006,0x00000050,0x0000004c, +0x0000004f,0x0004003d,0x00000006,0x00000051, +0x00000043,0x0004003d,0x00000006,0x00000052, +0x00000017,0x00050083,0x00000006,0x00000053, +0x00000051,0x00000052,0x0004003d,0x00000006, +0x00000054,0x0000003d,0x00050083,0x00000006, +0x00000055,0x00000053,0x00000054,0x00050081, +0x00000006,0x00000056,0x00000055,0x0000003b, +0x00050088,0x00000006,0x00000057,0x00000050, +0x00000056,0x0003003e,0x0000004b,0x00000057, +0x0004003d,0x00000006,0x00000059,0x00000017, +0x0004003d,0x00000006,0x0000005a,0x00000017, +0x00050081,0x00000006,0x0000005b,0x0000005a, +0x00000040,0x00050088,0x00000006,0x0000005c, +0x00000059,0x0000005b,0x0003003e,0x00000058, +0x0000005c,0x0004003d,0x00000006,0x0000005e, +0x00000017,0x000500be,0x00000029,0x0000005f, +0x0000005e,0x00000040,0x0004003d,0x00000006, +0x00000060,0x0000004b,0x0004003d,0x00000006, +0x00000061,0x00000058,0x000600a9,0x00000006, +0x00000062,0x0000005f,0x00000060,0x00000061, +0x0003003e,0x0000005d,0x00000062,0x0004003d, +0x00000007,0x00000064,0x0000000a,0x0004003d, +0x00000006,0x00000065,0x00000017,0x00050081, +0x00000006,0x00000066,0x00000065,0x0000003b, +0x00060050,0x00000007,0x00000067,0x00000066, +0x00000066,0x00000066,0x00050088,0x00000007, +0x00000068,0x00000064,0x00000067,0x0004003d, +0x00000006,0x00000069,0x0000005d,0x0005008e, +0x00000007,0x0000006a,0x00000068,0x00000069, +0x0003003e,0x00000063,0x0000006a,0x0004003d, +0x00000006,0x0000006c,0x0000003d,0x0004003d, +0x00000006,0x0000006d,0x00000043,0x0004003d, +0x00000007,0x0000006e,0x0000000a,0x00060050, +0x00000007,0x0000006f,0x0000006d,0x0000006d, +0x0000006d,0x00050083,0x00000007,0x00000070, +0x0000006f,0x0000006e,0x0005008e,0x00000007, +0x00000071,0x00000070,0x0000006c,0x0004003d, +0x00000006,0x00000072,0x00000043,0x0004003d, +0x00000007,0x00000073,0x0000000a,0x00060050, +0x00000007,0x00000074,0x00000072,0x00000072, +0x00000072,0x00050083,0x00000007,0x00000075, +0x00000074,0x00000073,0x0004003d,0x00000006, +0x00000076,0x0000003d,0x00060050,0x00000007, +0x00000077,0x00000076,0x00000076,0x00000076, +0x00050083,0x00000007,0x00000078,0x00000075, +0x00000077,0x00060050,0x00000007,0x00000079, +0x0000003b,0x0000003b,0x0000003b,0x00050081, +0x00000007,0x0000007a,0x00000078,0x00000079, +0x00050088,0x00000007,0x0000007b,0x00000071, +0x0000007a,0x0003003e,0x0000006b,0x0000007b, +0x0004003d,0x00000007,0x0000007d,0x0000000a, +0x0004003d,0x00000007,0x0000007e,0x0000000a, +0x00060050,0x00000007,0x0000007f,0x00000040, +0x00000040,0x00000040,0x00050081,0x00000007, +0x00000080,0x0000007e,0x0000007f,0x00050088, +0x00000007,0x00000081,0x0000007d,0x00000080, +0x0003003e,0x0000007c,0x00000081,0x00050041, +0x00000016,0x00000085,0x0000000a,0x00000084, +0x0004003d,0x00000006,0x00000086,0x00000085, +0x000500ba,0x00000029,0x00000087,0x00000086, +0x00000040,0x000300f7,0x0000008a,0x00000000, +0x000400fa,0x00000087,0x00000089,0x0000008d, +0x000200f8,0x00000089,0x00050041,0x00000016, +0x0000008b,0x0000006b,0x00000084,0x0004003d, +0x00000006,0x0000008c,0x0000008b,0x0003003e, +0x00000088,0x0000008c,0x000200f9,0x0000008a, +0x000200f8,0x0000008d,0x00050041,0x00000016, +0x0000008e,0x0000007c,0x00000084,0x0004003d, +0x00000006,0x0000008f,0x0000008e,0x0003003e, +0x00000088,0x0000008f,0x000200f9,0x0000008a, +0x000200f8,0x0000008a,0x0004003d,0x00000006, +0x00000090,0x00000088,0x00050041,0x00000016, +0x00000092,0x0000000a,0x00000091,0x0004003d, +0x00000006,0x00000093,0x00000092,0x000500ba, +0x00000029,0x00000094,0x00000093,0x00000040, +0x000300f7,0x00000097,0x00000000,0x000400fa, +0x00000094,0x00000096,0x0000009a,0x000200f8, +0x00000096,0x00050041,0x00000016,0x00000098, +0x0000006b,0x00000091,0x0004003d,0x00000006, +0x00000099,0x00000098,0x0003003e,0x00000095, +0x00000099,0x000200f9,0x00000097,0x000200f8, +0x0000009a,0x00050041,0x00000016,0x0000009b, +0x0000007c,0x00000091,0x0004003d,0x00000006, +0x0000009c,0x0000009b,0x0003003e,0x00000095, +0x0000009c,0x000200f9,0x00000097,0x000200f8, +0x00000097,0x0004003d,0x00000006,0x0000009d, +0x00000095,0x00050041,0x00000016,0x0000009f, +0x0000000a,0x0000009e,0x0004003d,0x00000006, +0x000000a0,0x0000009f,0x000500ba,0x00000029, +0x000000a1,0x000000a0,0x00000040,0x000300f7, +0x000000a4,0x00000000,0x000400fa,0x000000a1, +0x000000a3,0x000000a7,0x000200f8,0x000000a3, +0x00050041,0x00000016,0x000000a5,0x0000006b, +0x0000009e,0x0004003d,0x00000006,0x000000a6, +0x000000a5,0x0003003e,0x000000a2,0x000000a6, +0x000200f9,0x000000a4,0x000200f8,0x000000a7, +0x00050041,0x00000016,0x000000a8,0x0000007c, +0x0000009e,0x0004003d,0x00000006,0x000000a9, +0x000000a8,0x0003003e,0x000000a2,0x000000a9, +0x000200f9,0x000000a4,0x000200f8,0x000000a4, +0x0004003d,0x00000006,0x000000aa,0x000000a2, +0x00060050,0x00000007,0x000000ab,0x00000090, +0x0000009d,0x000000aa,0x0003003e,0x00000082, +0x000000ab,0x0004003d,0x00000007,0x000000ad, +0x00000063,0x0004003d,0x00000007,0x000000ae, +0x00000082,0x0008000c,0x00000007,0x000000b1, +0x00000001,0x0000002e,0x000000ad,0x000000ae, +0x000000b0,0x00060050,0x00000007,0x000000b2, +0x00000028,0x00000028,0x00000028,0x00060050, +0x00000007,0x000000b3,0x00000040,0x00000040, +0x00000040,0x0008000c,0x00000007,0x000000b4, +0x00000001,0x0000002b,0x000000b1,0x000000b2, +0x000000b3,0x0003003e,0x000000ac,0x000000b4, +0x0004003d,0x00000007,0x000000b5,0x000000ac, +0x00050041,0x00000025,0x000000b8,0x00000022, +0x000000b7,0x0004003d,0x00000006,0x000000b9, +0x000000b8,0x00050088,0x00000006,0x000000ba, +0x000000b6,0x000000b9,0x00060050,0x00000007, +0x000000bb,0x000000ba,0x000000ba,0x000000ba, +0x0007000c,0x00000007,0x000000bc,0x00000001, +0x0000001a,0x000000b5,0x000000bb,0x000200fe, +0x000000bc,0x00010038,0x00050036,0x00000007, +0x0000000e,0x00000000,0x00000009,0x00030037, +0x00000008,0x0000000d,0x000200f8,0x0000000f, +0x0004003b,0x00000008,0x000000bf,0x00000007, +0x0004003d,0x00000007,0x000000c0,0x0000000d, +0x0006000c,0x00000007,0x000000c1,0x00000001, +0x00000004,0x000000c0,0x0007000c,0x00000007, +0x000000c4,0x00000001,0x0000001a,0x000000c1, +0x000000c3,0x00060050,0x00000007,0x000000c6, +0x000000c5,0x000000c5,0x000000c5,0x00050083, +0x00000007,0x000000c7,0x000000c4,0x000000c6, +0x00060050,0x00000007,0x000000c8,0x00000028, +0x00000028,0x00000028,0x0007000c,0x00000007, +0x000000c9,0x00000001,0x00000028,0x000000c7, +0x000000c8,0x0004003d,0x00000007,0x000000cc, +0x0000000d,0x0006000c,0x00000007,0x000000cd, +0x00000001,0x00000004,0x000000cc,0x0007000c, +0x00000007,0x000000ce,0x00000001,0x0000001a, +0x000000cd,0x000000c3,0x0005008e,0x00000007, +0x000000cf,0x000000ce,0x000000cb,0x00060050, +0x00000007,0x000000d0,0x000000ca,0x000000ca, +0x000000ca,0x00050083,0x00000007,0x000000d1, +0x000000d0,0x000000cf,0x00050088,0x00000007, +0x000000d2,0x000000c9,0x000000d1,0x0006000c, +0x00000007,0x000000d3,0x00000001,0x00000004, +0x000000d2,0x0007000c,0x00000007,0x000000d6, +0x00000001,0x0000001a,0x000000d3,0x000000d5, +0x0003003e,0x000000bf,0x000000d6,0x0004003d, +0x00000007,0x000000d7,0x000000bf,0x000200fe, +0x000000d7,0x00010038,0x00050036,0x00000007, +0x00000011,0x00000000,0x00000009,0x00030037, +0x00000008,0x00000010,0x000200f8,0x00000012, +0x0004003d,0x00000007,0x000000da,0x00000010, +0x0005008e,0x00000007,0x000000dc,0x000000da, +0x000000db,0x00050041,0x00000025,0x000000dd, +0x00000022,0x00000037,0x0004003d,0x00000006, +0x000000de,0x000000dd,0x00060050,0x00000007, +0x000000df,0x000000de,0x000000de,0x000000de, +0x00050088,0x00000007,0x000000e0,0x000000dc, +0x000000df,0x000200fe,0x000000e0,0x00010038, +0x00050036,0x00000007,0x00000014,0x00000000, +0x00000009,0x00030037,0x00000008,0x00000013, +0x000200f8,0x00000015,0x0004003b,0x00000008, +0x000000e3,0x00000007,0x0004003b,0x00000008, +0x000000e4,0x00000007,0x0004003b,0x00000008, +0x000000e7,0x00000007,0x0004003b,0x00000008, +0x000000e8,0x00000007,0x0004003b,0x00000008, +0x000000eb,0x00000007,0x0004003d,0x00000007, +0x000000e5,0x00000013,0x0003003e,0x000000e4, +0x000000e5,0x00050039,0x00000007,0x000000e6, +0x0000000e,0x000000e4,0x0003003e,0x000000e3, +0x000000e6,0x0004003d,0x00000007,0x000000e9, +0x000000e3,0x0003003e,0x000000e8,0x000000e9, +0x00050039,0x00000007,0x000000ea,0x00000011, +0x000000e8,0x0003003e,0x000000e7,0x000000ea, +0x0004003d,0x00000007,0x000000ec,0x000000e7, +0x00050090,0x00000007,0x000000fb,0x000000ec, +0x000000fa,0x0003003e,0x000000eb,0x000000fb, +0x00050041,0x00000025,0x000000fc,0x00000022, +0x00000024,0x0004003d,0x00000006,0x000000fd, +0x000000fc,0x000500ba,0x00000029,0x000000fe, +0x000000fd,0x00000028,0x000300f7,0x00000100, +0x00000000,0x000400fa,0x000000fe,0x000000ff, +0x00000100,0x000200f8,0x000000ff,0x0004003d, +0x00000007,0x00000101,0x000000e7,0x00050090, +0x00000007,0x0000010f,0x00000101,0x0000010e, +0x0003003e,0x000000eb,0x0000010f,0x000200f9, +0x00000100,0x000200f8,0x00000100,0x0004003d, +0x00000007,0x00000110,0x000000eb,0x000200fe, +0x00000110,0x00010038}