使用VK_IMAGE_TILING_LINEAR表示srgb格式?

时间:2018-04-13 17:06:16

标签: vulkan

所以我仍然试图找出渲染纹理的颜色空间,以及如何创建没有颜色条带的图像。在我的gbuffer中,我将VK_FORMAT_R8G8B8A8_UNORM与VK_IMAGE_TILING用于我的反照率纹理和VK_FORMAT_A2B10G10R10_UNORM_PACK32与VK_IMAGE_TILING_OPTIMAL用于我的法线和发射渲染纹理。对于我的亮度纹理(其中包含场景中被视为“明亮”的像素值)和发光渲染纹理(将在以后添加到最终场景中的布隆效果的最终纹理),我使用VK_FORMAT_R8G8B8A8_SRGB和VK_IMAGE_TILING_OPTIMAL(尽管看这个,我应该让我的明亮和最终纹理R16G16B16A16浮动格式代替)。我得到的绝对不是我的想法: enter image description here

将我的普通,发光,发光和亮度纹理的平铺更改为VK_IMAGE_TILING_LINEAR,但是,我得到了不错的结果,但代价是: enter image description here

关于它的好处(对于左上角的怪异边框,在MS画面上裁剪而感到遗憾......),是图像不会受到色带的影响,例如在使用时不使用我的纹理的这些格式,我使用VK_FORMAT_R8G8B8A8_UNORM与VK_IMAGE_TILING_OPTIMAL: enter image description here

您是否可以看到头盔左上方以及下方(黑色管子所在的位置)出现条带。当然,我听说过从post

中避免使用VK_IMAGE_TILING_LINEAR

一般来说,我在查找使用srgb纹理时避免使用VK_IMAGE_TILING_LINEAR的最佳方法时遇到问题?我仍然想保留srgb给我的漂亮清晰的图像,但我不确定如何解决这个问题。该链接实际上可能有解决方案,但我不太确定是否有办法将其应用于我的gbuffer。

我还想澄清一点,VK_IMAGE_TILING_OPTIMAL适用于基于Nvidia的GPU(好吧,在GTX 870M上测试过)但是抱怨使用VK_IMAGE_TILING_LINEAR用于srgb格式,但是,基于intel的gpus可以正常使用VK_IMAGE_TILING_LINEAR并且有点像废话一样使用VK_IMAGE_TILING_OPTIMAL时,第一张图片在这篇文章的顶部。

引擎是定制的,请随时查看link

如果你想要一些代码,我在Engine / Renderer / Private / Renderer.cpp文件中使用一个名为SetUpRenderTextures()的函数,在1396行下:

      VkImageCreateInfo cImageInfo = { };
  VkImageViewCreateInfo cViewInfo = { };

  // TODO(): Need to make this more adaptable, as intel chips have trouble with srgb optimal tiling.
  cImageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  cImageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
  cImageInfo.imageType = VK_IMAGE_TYPE_2D;
  cImageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
  cImageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  cImageInfo.mipLevels = 1;
  cImageInfo.extent.depth = 1;
  cImageInfo.arrayLayers = 1;
  cImageInfo.extent.width = m_pWindow->Width();
  cImageInfo.extent.height = m_pWindow->Height();
  cImageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
  cImageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  cImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;

  cViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 
  cViewInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
  cViewInfo.image = nullptr; // No need to set the image, texture->Initialize() handles this for us.
  cViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  cViewInfo.subresourceRange = { };
  cViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  cViewInfo.subresourceRange.baseArrayLayer = 0;
  cViewInfo.subresourceRange.baseMipLevel = 0;
  cViewInfo.subresourceRange.layerCount = 1;
  cViewInfo.subresourceRange.levelCount = 1;

  gbuffer_Albedo->Initialize(cImageInfo, cViewInfo);
  gbuffer_Emission->Initialize(cImageInfo, cViewInfo);

  cImageInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
  cViewInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
  cImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
  GlowTarget->Initialize(cImageInfo, cViewInfo);
  // It's probably best that these be 64bit float formats as well...
  pbr_Bright->Initialize(cImageInfo, cViewInfo);
  pbr_Final->Initialize(cImageInfo, cViewInfo);

  cImageInfo.format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
  cImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
  cViewInfo.format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;

  gbuffer_Normal->Initialize(cImageInfo, cViewInfo);
  gbuffer_Position->Initialize(cImageInfo, cViewInfo);

所以,是的,破败。如何避免使用线性图像平铺srgb纹理?这是硬件特定的东西,是强制性的吗?另外,我为这个问题上的任何形式的无知道歉。

谢谢:3

1 个答案:

答案 0 :(得分:2)

必须支持此组合,因此第一张图片中的损坏是应用程序或驱动程序错误。

因此VK_FORMAT_R8G8B8A8_SRGB正在您的Nvidia GPU上使用VK_IMAGE_TILING_OPTIMAL,但在您的英特尔GPU上却没有?但是VK_FORMAT_R8G8B8A8_SRGB是否适用于英特尔GPU上的VK_IMAGE_TILING_LINEAR

如果是这样,听起来你的图像布局过渡有些缺失或不正确。英特尔比Nvidia更加敏感。验证层是否会抱怨什么?您需要确保图片在呈现时为VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,并在从中进行采样时VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL