Failed
Vulkan spec for external formats를 정확히 따랐습니다: 1. format = VK_FORMAT_UNDEFINED 2. VkExternalFormatANDROID chain (externalFormat = 0x7FA30C04) 3. usage = VK_IMAGE_USAGE_SAMPLED_BIT ONLY (TRANSFER_DST 제거) 4. flags = 0 5. mipLevels = 1 6. arrayLayers = 1 7. samples = VK_SAMPLE_COUNT_1_BIT
This commit is contained in:
@@ -13,6 +13,30 @@ void main() {
|
||||
// and the YCbCr conversion parameters from AHardwareBuffer format properties
|
||||
vec4 rgba = texture(ycbcrTexture, fragTexCoord);
|
||||
|
||||
// Output RGB color with full alpha
|
||||
// DEBUG: Test if YCbCr conversion is actually happening
|
||||
// If conversion works: rgba should be RGB (red sky = high R, low G, low B)
|
||||
// If conversion FAILS: rgba will be YUV (Y in .r, U in .g, V in .b)
|
||||
// - For red pixels: Y=high, U=low, V=high -> would show as purple/magenta!
|
||||
|
||||
// DEBUG TEST 1: Show Y channel only (should show grayscale brightness)
|
||||
// If this shows correct brightness, Y is in the right place
|
||||
// outColor = vec4(rgba.r, rgba.r, rgba.r, 1.0);
|
||||
|
||||
// DEBUG TEST 2: Show U channel only (should show blue-yellow gradient)
|
||||
// outColor = vec4(rgba.g, rgba.g, rgba.g, 1.0);
|
||||
|
||||
// DEBUG TEST 3: Show V channel only (should show red-green gradient)
|
||||
// outColor = vec4(rgba.b, rgba.b, rgba.b, 1.0);
|
||||
|
||||
// DEBUG TEST 4: Try swapped UV (maybe U and V are reversed in NV12?)
|
||||
// float Y = rgba.r - 0.0625;
|
||||
// float V = rgba.g - 0.5; // SWAPPED: V from .g
|
||||
// float U = rgba.b - 0.5; // SWAPPED: U from .b
|
||||
// float R = Y + 1.5748 * V;
|
||||
// float G = Y - 0.1873 * U - 0.4681 * V;
|
||||
// float B = Y + 1.8556 * U;
|
||||
// outColor = vec4(R, G, B, 1.0);
|
||||
|
||||
// DEBUG TEST 5: Raw passthrough (see what hardware gives us)
|
||||
outColor = vec4(rgba.rgb, 1.0);
|
||||
}
|
||||
@@ -365,25 +365,45 @@ bool MediaCodecSurfaceManager::CreateVulkanImage(void* vk_device, void* vk_insta
|
||||
LogInfo(" is_qualcomm_gpu (Adreno): " + std::string(is_qualcomm_gpu ? "true" : "false"));
|
||||
LogInfo(" is_samsung: " + std::string(is_samsung ? "true" : "false"));
|
||||
|
||||
// CRITICAL: For external formats (Qualcomm vendor formats), we MUST attach VkExternalFormatANDROID
|
||||
VkExternalFormatANDROID externalFormat = {};
|
||||
externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
|
||||
externalFormat.pNext = nullptr;
|
||||
externalFormat.externalFormat = 0; // Will be set if using external format
|
||||
|
||||
VkSamplerYcbcrConversionCreateInfo ycbcrConversionCreateInfo = {};
|
||||
ycbcrConversionCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
|
||||
ycbcrConversionCreateInfo.pNext = nullptr;
|
||||
ycbcrConversionCreateInfo.pNext = nullptr; // Will chain externalFormat if needed
|
||||
|
||||
// Use format properties from AHardwareBuffer
|
||||
// CRITICAL FIX: Use AHardwareBuffer's actual format, NOT Vulkan's suggested format!
|
||||
// Qualcomm returns VK_FORMAT_UNDEFINED (0) in ahb_format_props.format
|
||||
// But the REAL format is in ahb_desc.format (Qualcomm vendor format 0x7FA30C04)
|
||||
//
|
||||
// We need to use the AHardwareBuffer format directly as a Vulkan "external format"
|
||||
VkFormat vulkan_format = ahb_format_props.format;
|
||||
|
||||
// Log both formats to debug
|
||||
LogInfo("Format detection:");
|
||||
LogInfo(" AHardwareBuffer format (ahb_desc.format): 0x" + std::to_string(ahb_desc.format));
|
||||
LogInfo(" Vulkan suggested format (ahb_format_props.format): " + std::to_string(ahb_format_props.format));
|
||||
|
||||
if (vulkan_format == VK_FORMAT_UNDEFINED || vulkan_format == 0) {
|
||||
// WORKAROUND: GPU-specific format detection
|
||||
// Qualcomm Adreno GPU → NV21 (CrCb) requires component swizzle
|
||||
// Other GPUs → NV12 (CbCr) standard format
|
||||
if (is_qualcomm_gpu || is_nv21_device) {
|
||||
vulkan_format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR; // NV12 format (will use BT.601)
|
||||
is_nv21_device = true;
|
||||
LogInfo("Qualcomm Adreno GPU detected → Using NV12 format with BT.601 + component swizzle");
|
||||
} else {
|
||||
vulkan_format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR; // NV12 format
|
||||
is_nv21_device = false;
|
||||
LogInfo("Non-Qualcomm GPU → Using NV12 format with MediaCodec settings");
|
||||
}
|
||||
// CRITICAL: Qualcomm GPU returns UNDEFINED format
|
||||
// We MUST use external format instead of hardcoding NV12!
|
||||
LogInfo("Vulkan driver returned VK_FORMAT_UNDEFINED - using external format path");
|
||||
LogInfo(" This is EXPECTED on Qualcomm Adreno GPUs with vendor-specific formats");
|
||||
|
||||
// Use the AHardwareBuffer's native format as external format
|
||||
externalFormat.externalFormat = ahb_desc.format; // 0x7FA30C04 for Qualcomm
|
||||
ycbcrConversionCreateInfo.pNext = &externalFormat; // Chain external format
|
||||
vulkan_format = VK_FORMAT_UNDEFINED; // MUST be UNDEFINED when using external format
|
||||
|
||||
LogInfo("Using external format:");
|
||||
LogInfo(" externalFormat = 0x" + std::to_string(externalFormat.externalFormat));
|
||||
LogInfo(" Vulkan format = VK_FORMAT_UNDEFINED (required for external formats)");
|
||||
} else {
|
||||
LogInfo("Vulkan driver provided explicit format: " + std::to_string(vulkan_format));
|
||||
LogInfo(" NOT using external format path");
|
||||
}
|
||||
|
||||
ycbcrConversionCreateInfo.format = vulkan_format;
|
||||
@@ -447,20 +467,40 @@ bool MediaCodecSurfaceManager::CreateVulkanImage(void* vk_device, void* vk_insta
|
||||
external_mem_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
|
||||
external_mem_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
|
||||
|
||||
// CRITICAL: For external formats, chain VkExternalFormatANDROID to VkImageCreateInfo
|
||||
if (vulkan_format == VK_FORMAT_UNDEFINED) {
|
||||
external_mem_info.pNext = &externalFormat; // Chain external format
|
||||
LogInfo("VkImage: Chaining VkExternalFormatANDROID (format=0x" + std::to_string(externalFormat.externalFormat) + ")");
|
||||
} else {
|
||||
external_mem_info.pNext = nullptr;
|
||||
LogInfo("VkImage: Using explicit Vulkan format (no external format)");
|
||||
}
|
||||
|
||||
VkImageCreateInfo image_info = {};
|
||||
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
image_info.pNext = &external_mem_info;
|
||||
image_info.flags = 0; // CRITICAL: Must be 0 for external formats
|
||||
image_info.imageType = VK_IMAGE_TYPE_2D;
|
||||
// Use the same format as YCbCr conversion (already validated above)
|
||||
image_info.format = vulkan_format;
|
||||
image_info.extent.width = ahb_desc.width;
|
||||
image_info.extent.height = ahb_desc.height;
|
||||
image_info.extent.depth = 1;
|
||||
image_info.mipLevels = 1;
|
||||
image_info.arrayLayers = 1;
|
||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
image_info.mipLevels = 1; // CRITICAL: Must be 1 for external formats
|
||||
image_info.arrayLayers = 1; // CRITICAL: Must be 1 for external formats
|
||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT; // CRITICAL: Must be 1 for external formats
|
||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
|
||||
// CRITICAL: External formats ONLY support VK_IMAGE_USAGE_SAMPLED_BIT
|
||||
// Adding TRANSFER_DST causes crash on Qualcomm GPUs
|
||||
if (vulkan_format == VK_FORMAT_UNDEFINED) {
|
||||
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; // ONLY sampled for external formats
|
||||
LogInfo("VkImage: usage = SAMPLED_BIT only (external format restriction)");
|
||||
} else {
|
||||
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
LogInfo("VkImage: usage = SAMPLED_BIT | TRANSFER_DST_BIT");
|
||||
}
|
||||
|
||||
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user