mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 21:28:32 +09:00
[Fix] (DirectVulkan): bound image mutability so Adreno keeps UBWC compression
- Every storage-capable colour texture was created MUTABLE_FORMAT, and Adreno gives up bandwidth compression on an image that may be viewed as any format in its compatibility class. MC's main render target therefore ran uncompressed; in a fill-bound scene that is the whole frame budget. Measured on Adreno 650, MC 26.2, same scene and camera, device cooled to 38-40C before each run: 65.3 -> 80.9 fps (+23.9%), GPU busy ~93% in both. - VK_KHR_image_format_list (enabled when present) fixes it without giving up mutability: VkImageFormatListCreateInfo names the exact formats a view may use, so the driver can keep the image compressed. The set must be exhaustive or the result is undefined - for sampled views it is exactly what ResolveSampledImageViewFormat can return over the three numeric domains. - glBindImageTexture may name any compatible format, which cannot be enumerated ahead of time, so a texture bound to an image unit gets no format list. That is what VK_IMAGE_USAGE_STORAGE_BIT becoming on-demand is for: it makes "unmarked" mean "will never receive an arbitrary-format storage view", which is what makes the list sound. Removing STORAGE is worth nothing on its own (65.4 fps, measured) - only the mutability bound pays. - MarkStorageImageTexture runs over every collected image-unit texture before the probe loop in PrepareStorageImageTextures, because that loop stops at the first texture needing work and would leave the rest unmarked. The mark makes NeedsStorageImagePreparation report true, which is what ends the render pass, so the recreate lands outside it. - storageUsageResolved separates "not upgraded yet" from "this format can never carry STORAGE", so a format whose optimalTilingFeatures lack STORAGE_IMAGE cannot ask for a recreate that will never happen. SyncTexture's cross-draw early-out also has to break on a pending upgrade or the recreate never runs. - An upgrade recreates the image and carries its contents forward through PreserveTextureContentsOnRecreate, which submits its own command buffer and waits. Whatever the frame already recorded into the old image is still unsubmitted, so that copy would read pre-frame content and this frame's rendering into the texture would be lost - exactly the render-target-then- image-unit case. PrepareStorageImageTextures now flushes first; it takes the FrameData rather than a command buffer because the flush retires the current one, and drops the sampled-descriptor-set memo that described it.
This commit is contained in:
@@ -576,8 +576,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const RenderPassEntry& renderPassEntry);
|
||||
VkPipeline GetOrCreateComputePipeline(const ProgramFactory::VkProgramObject& programObj);
|
||||
void DestroyComputePipelines();
|
||||
// Takes the frame rather than a command buffer: a first-time storage-usage upgrade has to
|
||||
// flush the pending recording (see the body), which retires the current command buffer.
|
||||
Bool PrepareStorageImageTextures(
|
||||
VkCommandBuffer commandBuffer,
|
||||
FrameContext::FrameData& frame,
|
||||
const MG_State::GLState::ProgramObject& program,
|
||||
const ProgramFactory::VkProgramObject& programObj);
|
||||
|
||||
@@ -639,6 +641,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const PhysicalDevice& compareWithDevice,
|
||||
PhysicalDevice& outBetterDevice);
|
||||
static constexpr const char* s_validationLayerNames[] = {"VK_LAYER_KHRONOS_validation"};
|
||||
// VK_KHR_image_format_list: lets MUTABLE_FORMAT images declare their exact view-format
|
||||
// set so the driver can keep bandwidth compression (see CreateLogicalDeviceAndQueues).
|
||||
Bool m_imageFormatListExtensionEnabled = false;
|
||||
|
||||
static constexpr const char* s_deviceExtensionNames[] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
|
||||
static Bool CheckValidationLayerSupport();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user