Формат поверхности - B8G8R8A8_UNORM, но vkCmdClearColorImage принимает float?

Я использую vkGetPhysicalDeviceSurfaceFormatsKHR, чтобы получить поддерживаемые форматы изображений для цепочки подкачки, и (в Linux + Nvidia, используя SDL) я получаю VK_FORMAT_B8G8R8A8_UNORM в качестве первого варианта, и я иду дальше и создаю цепочку подкачки с этим форматом:

VkSwapchainCreateInfoKHR swapchain_info = {
    ...
    .imageFormat = format, /* taken from vkGetPhysicalDeviceSurfaceFormatsKHR */
    ...
};

Пока все имеет смысл. Формат изображения, используемый для рисования на экране, - это обычный 8-битный-канальный BGRA.

В рамках моего процесса обучения я до сих пор настраивал множество вещей, но еще не создал графический конвейер 1. Итак, я пытаюсь использовать единственную команду, для которой не нужен конвейер: vkCmdClearColorImage 2.

VkClearColorValue, используемый для определения прозрачного цвета, может принимать цвет как float, uint32_t или int32_t, в зависимости от формата изображения. Я ожидал, исходя из формата изображения, предоставленного цепочке подкачки, что я должен дать ему uint32_t значений, но это не кажется правильным. Знаю, потому что цвет экрана не изменился. Я попробовал дать ему floats, и он работает.

У меня вопрос: почему чистый цвет нужно указывать в floats, когда формат изображения - VK_FORMAT_B8G8R8A8_UNORM?


1 На самом деле у меня есть, но я подумал, что сначала попробую более простой случай отсутствия конвейера. Я пытаюсь постепенно использовать Vulkan (учитывая его многословность), особенно потому, что я также пишу по нему учебные пособия как я узнал.

2 На самом деле, технически не требуется проход рендеринга, но я подумал, эй, я не использую здесь какие-либо конвейеры, поэтому давайте попробуем это без конвейера, и это сработало. < / sub>


Мой цикл рендеринга по сути следующий:

  • получить изображение из свопчейна
  • create a command buffer with the following:
    • transition from VK_IMAGE_LAYOUT_UNDEFINED to VK_IMAGE_LAYOUT_GENERAL (because I'm clearing the image outside a render pass)
    • очистить изображение
    • переход с VK_IMAGE_LAYOUT_GENERAL на VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
  • отправить буфер команд в очередь (заботясь о синхронизации с swapchain с семафорами)
  • представить для презентации

person Shahbaz    schedule 06.05.2016    source источник


Ответы (1)


У меня вопрос: почему четкий цвет нужно указывать в числах с плавающей запятой, если формат изображения - VK_FORMAT_B8G8R8A8_UNORM?

Поскольку форматы изображений нормализованные, масштабированные или sRGB на самом деле являются всего лишь различными формами сжатия с плавающей запятой. Нормализованное целое число - это способ хранения значений с плавающей запятой в диапазоне [0, 1] или [-1, 1], но с использованием гораздо меньшего объема данных, чем даже 16-битное число с плавающей запятой. Масштабируемое целое число - это способ хранения значений с плавающей запятой в диапазоне [0, MAX] или [-MIN, MAX]. И sRGB - это просто сжатый способ хранения линейных значений цвета в диапазоне [0, 1], но в цветовом пространстве с гамма-коррекцией, которое обеспечивает точность в разных местах, чем предполагают линейные значения цвета.

То же самое и с входными данными вершинного шейдера. Тип ввода vec4 может подаваться как в нормализованных форматах, так и в форматах с плавающей запятой.

person Nicol Bolas    schedule 06.05.2016
comment
Скажем, компонент цвета - это 8-битовое целое число без знака, поэтому он имеет диапазон [0, 255]. Как вы сказали, это представитель диапазона [0, 1]. Это прекрасно. Однако, когда вы предоставляете значение в этом формате, вы должны указать его, например, как (127, 63, 127), а не (0,5, 0,25, 0,5), хотя на самом деле они представляют одно и то же. Я думал, что B8G8R8A8 означает, что цвета хранятся как 4 8-битных целых числа, но вы говорите, что это не так? Какой тогда смысл называть его B8G8R8A8? - person Shahbaz; 06.05.2016
comment
Собственно я только что заметил, что есть еще форматы типа B8G8R8A8_UINT. Я предполагаю, что UNORM тогда сообщает вам, что формат находится в float. - person Shahbaz; 06.05.2016
comment
Я нашел объяснение нормализованных целых чисел. Не стесняйтесь игнорировать предыдущие комментарии. - person Shahbaz; 06.05.2016
comment
@Shahbaz: К вашему сведению: вы можете удалить свои комментарии с помощью кнопки X, которая появляется рядом с ними, когда вы наводите на них указатель мыши. - person Nicol Bolas; 06.05.2016
comment
Я знаю. Я оставил их там на случай, если вы хотите что-то интересное о них сказать. В любом случае мне кажется странным, что на самом деле существует различие между UNORM и UINT, учитывая, что они представляют собой один и тот же битовый шаблон. - person Shahbaz; 06.05.2016
comment
unorm a = 1.0 (255); unorm b = a * a (255); uint c = 255; uint d = c * c / 256 (254). По сути, это пытается сказать, что реализация умножения для unorm должна немного отличаться от простого целочисленного умножения с фиксированной запятой. - person Pauli Nieminen; 22.10.2016
comment
@PauliNieminen, два года спустя, программист графики, так что теперь я определенно знаю разницу. Однако ваш пример действительно бесполезен, так как в uint d = c * c / ... вам действительно нужно разделить на 255, то есть результат двух операций одинаков (хотя версия unorm имеет неявное деление, что является допустимой точкой) - person Shahbaz; 06.03.2018