Aqoole_Hateenaの技術日記

vulkan+raytraceで色々描いてます

サポートされているsample count取得方法

multisamplingの機能を利用する場合の、supported sample count取得具体例(Android)

VkImageFormatProperties imageFormatProp = {};
vkGetPhysicalDeviceImageFormatProperties(physicalDevice, VK_FORMAT_R8G8B8A8_UNORM,
    VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
    VK_NULL_HANDLE, &imageFormatProp);
__android_log_print(ANDROID_LOG_INFO, "limits sample count", "%s", std::to_string(imageFormatProp.sampleCounts).c_str());

pipelineでのmultisamplingの指定方法については以下記事参照。
aqoole-hateena.hatenablog.com

VkImageFormatProperties

// Provided by VK_VERSION_1_0
typedef struct VkImageFormatProperties {
    VkExtent3D            maxExtent;
    uint32_t              maxMipLevels;
    uint32_t              maxArrayLayers;
    VkSampleCountFlags    sampleCounts;
    VkDeviceSize          maxResourceSize;
} VkImageFormatProperties;

sampleCounts is a bitmask of VkSampleCountFlagBits specifying all the supported sample counts for this image as described below.
VkImageFormatProperties(3)

sampleCountsにサポートされるsample countが格納されるのだが、bitmaskの形で情報が取得される。

VkSampleCountFlagBits

// Provided by VK_VERSION_1_0
typedef enum VkSampleCountFlagBits {
    VK_SAMPLE_COUNT_1_BIT = 0x00000001,
    VK_SAMPLE_COUNT_2_BIT = 0x00000002,
    VK_SAMPLE_COUNT_4_BIT = 0x00000004,
    VK_SAMPLE_COUNT_8_BIT = 0x00000008,
    VK_SAMPLE_COUNT_16_BIT = 0x00000010,
    VK_SAMPLE_COUNT_32_BIT = 0x00000020,
    VK_SAMPLE_COUNT_64_BIT = 0x00000040,
} VkSampleCountFlagBits;

VkSampleCountFlagBits(3)

vkGetPhysicalDeviceImageFormatProperties()

vkGetPhysicalDeviceImageFormatProperties - Lists physical device's image format capabilities
To query additional capabilities specific to image types, call:

// Provided by VK_VERSION_1_0
VkResult vkGetPhysicalDeviceImageFormatProperties(
    VkPhysicalDevice                            physicalDevice,
    VkFormat                                    format,
    VkImageType                                 type,
    VkImageTiling                               tiling,
    VkImageUsageFlags                           usage,
    VkImageCreateFlags                          flags,
    VkImageFormatProperties*                    pImageFormatProperties);

pImageFormatProperties is a pointer to a VkImageFormatProperties structure in which capabilities are returned.
vkGetPhysicalDeviceImageFormatProperties(3)

サポートされている情報の取得はvkGetPhysicalDeviceImageFormatProperties()関数で行う。

Rasterization Stageの指定

Rasterization Stageでの処理

rasterization stageではrasterizationとmultisamplingの処理が行われる。
それぞれVkPipelineRasterizationStateCreateInfoとVkPipelineMultisampleStateCreateInfoにパラメータを記述する。

VkPipelineRasterizationStateCreateInfo

// Provided by VK_VERSION_1_0
typedef struct VkPipelineRasterizationStateCreateInfo {
    VkStructureType                            sType;
    const void*                                pNext;
    VkPipelineRasterizationStateCreateFlags    flags;
    VkBool32                                   depthClampEnable;
    VkBool32                                   rasterizerDiscardEnable;
    VkPolygonMode                              polygonMode;
    VkCullModeFlags                            cullMode;
    VkFrontFace                                frontFace;
    VkBool32                                   depthBiasEnable;
    float                                      depthBiasConstantFactor;
    float                                      depthBiasClamp;
    float                                      depthBiasSlopeFactor;
    float                                      lineWidth;
} VkPipelineRasterizationStateCreateInfo;

  • depthClampEnable controls whether to clamp the fragment’s depth values as described in Depth Test. If the pipeline is not created with VkPipelineRasterizationDepthClipStateCreateInfoEXT present then enabling depth clamp will also disable clipping primitives to the z planes of the frustrum as described in Primitive Clipping. Otherwise depth clipping is controlled by the state set in VkPipelineRasterizationDepthClipStateCreateInfoEXT.
  • rasterizerDiscardEnable controls whether primitives are discarded immediately before the rasterization stage.
  • polygonMode is the triangle rendering mode. See VkPolygonMode.
  • cullMode is the triangle facing direction used for primitive culling. See VkCullModeFlagBits.
  • frontFace is a VkFrontFace value specifying the front-facing triangle orientation to be used for culling.
  • depthBiasEnable controls whether to bias fragment depth values.

VkPipelineRasterizationStateCreateInfo(3)

depthClampEnable

depth testとは、あるdepth valueがpositionに対応するdepth bufferの値と比較し、よりfrontであれば表示し、behindであれば表示しない、というもの。depth test自体はrenderingでは一般的な用語なので、OpenGLでの説明を引用。

When depth testing is enabled, OpenGL tests the depth value of a fragment against the content of the depth buffer. OpenGL performs a depth test and if this test passes, the fragment is rendered and the depth buffer is updated with the new depth value. If the depth test fails, the fragment is discarded.
LearnOpenGL - Depth testing

depthClampEnableはdepthの値をdepth testの値にclampするかどうかを決める。

cullMode

破棄する三角形の向きを決める。
cullは「淘汰、間引き」の意味。
cullingの意味・使い方・読み方 | Weblio英和辞書

VkCullModeFlagBits

VkCullModeFlagBits - Bitmask controlling triangle culling

// Provided by VK_VERSION_1_0
typedef enum VkCullModeFlagBits {
    VK_CULL_MODE_NONE = 0,
    VK_CULL_MODE_FRONT_BIT = 0x00000001,
    VK_CULL_MODE_BACK_BIT = 0x00000002,
    VK_CULL_MODE_FRONT_AND_BACK = 0x00000003,
} VkCullModeFlagBits;

  • VK_CULL_MODE_NONE specifies that no triangles are discarded
  • VK_CULL_MODE_FRONT_BIT specifies that front-facing triangles are discarded
  • VK_CULL_MODE_BACK_BIT specifies that back-facing triangles are discarded
  • VK_CULL_MODE_FRONT_AND_BACK specifies that all triangles are discarded.

Following culling, fragments are produced for any triangles which have not been discarded.
VkCullModeFlagBits(3)

frontFace

どの回り方(反時計回りor時計回り)が表面かを指定する。

// Provided by VK_VERSION_1_0
typedef enum VkFrontFace {
    VK_FRONT_FACE_COUNTER_CLOCKWISE = 0,
    VK_FRONT_FACE_CLOCKWISE = 1,
} VkFrontFace;

VkFrontFace(3)

depthBiasEnable

depth biasとは

The depth values of all fragments generated by the rasterization of a polygon can be biased (offset) by a single depth bias value o that is computed for that polygon.
Vulkan® 1.2.203 - A Specification (with all registered Vulkan extensions)

すべてのdepth valueはひとつのdepth bias valueでbias可能とある。
biasは「偏り」の意味。
biasの意味・使い方・読み方 | Weblio英和辞書
これだけだと意味が分からないのでもう少し調べてみると、Nvidiaのdeveloper zoneにはこのようにある。

Specify the constant offset used to compute a depth offset for polygons. See the units parameter description on the OpenGL glPolygonOffset manual page for details. See the D3DRS_DEPTHBIAS render state description for DirectX 9.
DepthBias

depth offsetを計算するための定数のoffsetとある。
詳細を知りたければOpenGL glPolygonOffset manual pageを見ろとあるので、見てみた。

glPolygonOffset
void glPolygonOffset(GLfloat factor,
 	GLfloat units);

glPolygonOffset is useful for rendering hidden-line images, for applying decals to surfaces, and for rendering solids with highlighted edges.
Description
When GL_POLYGON_OFFSET_FILL, GL_POLYGON_OFFSET_LINE, or GL_POLYGON_OFFSET_POINT is enabled, each fragment's depth value will be offset after it is interpolated from the depth values of the appropriate vertices. The value of the offset is factor × DZ + r × units , where DZ is a measurement of the change in depth relative to the screen area of the polygon, and r is the smallest value that is guaranteed to produce a resolvable offset for a given implementation. The offset is added before the depth test is performed and before the value is written into the depth buffer.
glPolygonOffset - OpenGL 4 Reference Pages

「depth bias(glPolygonOffset)は隠れたラインやimagesをsurface上に転写するときに使える」とある。壁の奥にオブジェクトがある場合に、そのedge部分だけを壁の表面に描きたい場合などに、depthにoffsetを与えて補正することにより描けるよう。

VkPipelineMultisampleStateCreateInfo

// Provided by VK_VERSION_1_0
typedef struct VkPipelineMultisampleStateCreateInfo {
    VkStructureType                          sType;
    const void*                              pNext;
    VkPipelineMultisampleStateCreateFlags    flags;
    VkSampleCountFlagBits                    rasterizationSamples;
    VkBool32                                 sampleShadingEnable;
    float                                    minSampleShading;
    const VkSampleMask*                      pSampleMask;
    VkBool32                                 alphaToCoverageEnable;
    VkBool32                                 alphaToOneEnable;
} VkPipelineMultisampleStateCreateInfo;

  • rasterizationSamples is a VkSampleCountFlagBits value specifying the number of samples used in rasterization.
  • sampleShadingEnable can be used to enable Sample Shading.
  • minSampleShading specifies a minimum fraction of sample shading if sampleShadingEnable is set to VK_TRUE.
  • pSampleMask is a pointer to an array of VkSampleMask values used in the sample mask test.
  • alphaToCoverageEnable controls whether a temporary coverage value is generated based on the alpha component of the fragment’s first color output as specified in the Multisample Coverage section.
  • alphaToOneEnable controls whether the alpha component of the fragment’s first color output is replaced with one as described in Multisample Coverage.

rasterizationSamplesではsampleのカウントを指定する。
VkPhysicalDeviceLimitsのstandardSampleLocationsがVK_TRUEの場合、下tableのようなsample locationsになる。

f:id:Aqoole_Hateena:20220116123241p:plain
Table36 Standard sample locations

出典:Vulkan® 1.2.203 - A Specification (with all registered Vulkan extensions)

sampleShadingEnableはsample rate shadingの機能のon/offを設定する。
sample rate shadingとは、fragment shaderがpixelごとではなく、sampleごとに動作することである。
multisamplingにより図形のedgeはよりきれいに表現されるが、samplingした結果をfragment shaderに送るため、multisamplingはfragment shaderが高空間周波数の結果を出力した場合に対しては無力である。空間周波数とは、空間内の位置全体で周期的な構造の特性である。
Spatial frequency - Wikipedia
sampleShadingEnableをonにするとfragment shaderがsample rateで動くため、このような場合にも対応できる。

minSampleShadingはsampleShadingEnableが有効な場合のパラメータで、0.0f - 1.0fの値を入力する。
minSampleShadingはfragment shaderの動作頻度を管理する。
値が1.0の場合、pixel内のすべてのsampleにおいてfragment shaderが実行され、その結果を別のsampleにも送る。
値が0.0から1.0の間の場合、fragment shaderを実行するsample数の割合はdevice依存で計算される。

pSampleMaskは32bitのbit maskである。sample indexとbit位置が対応しており、bitが1であれば、fragment shaderが実行される。

If sample shading is enabled, fragment shaders will only see values of 1 for samples being shaded - other bits will be 0.
Vulkan® 1.2.203 - A Specification (with all registered Vulkan extensions)

alphaToCoverageEnableは対応する位置のfragment shaderの出力のalpha値に基づいて、一時的なcoverage maskを決めるかどうかを定める。
coverage maskとはmultisamplingにおいて、実際に有効となるfragment shaderをもつsampleのindexに対応したbit maskである。

If alphaToCoverageEnable is enabled, a temporary coverage mask is generated where each bit is determined by the fragment’s alpha value, which is ANDed with the fragment coverage mask.
Vulkan® 1.2.203 - A Specification (with all registered Vulkan extensions)

alphaToOneEnableはalpha値を1.0fなどの最大値に書き換えるかどうかを決める。

Finally, if alphaToOneEnable is enabled, each alpha value is replaced by the maximum representable alpha value for fixed-point color attachments, or by 1.0 for floating-point attachments. Otherwise, the alpha values are not changed.
Vulkan® 1.2.203 - A Specification (with all registered Vulkan extensions)

サポートされているsample count取得方法

aqoole-hateena.hatenablog.com

更新履歴

2022/1/17 サポートされているsample count取得方法を追記

Vertex Post-processing Stageの指定

Vertex Post-processing Stage

記事にあるGraphics pipeline diagramのVertex Post-processing stageでは、いわゆるClip and Cullの処理が行われる。
aqoole-hateena.hatenablog.com
Clip and Cullとはworld座標から画面に表示される範囲を抽出することである。

座標変換

Vertex Post-processing StageではClip SpaceからScreen Spaceへの変換を行う。Clip SpaceはNormal Device Coordinatesともよばれ、Screen SpaceはWindow Coordinatesともよばれる。

f:id:Aqoole_Hateena:20220111205527p:plain
The global picture

出典:LearnOpenGL - Coordinate Systems
※図はOpenGLのもののため、y軸の向きが逆向きになっている。

Vertex Post-processingの処理はVkPipelineViewportStateCreateInfoに記述する。

VkPipelineViewportStateCreateInfo

VkPipelineViewportStateCreateInfo - Structure specifying parameters of a newly created pipeline viewport state

// Provided by VK_VERSION_1_0
typedef struct VkPipelineViewportStateCreateInfo {
    VkStructureType                       sType;
    const void*                           pNext;
    VkPipelineViewportStateCreateFlags    flags;
    uint32_t                              viewportCount;
    const VkViewport*                     pViewports;
    uint32_t                              scissorCount;
    const VkRect2D*                       pScissors;
} VkPipelineViewportStateCreateInfo;

  • pViewports is a pointer to an array of VkViewport structures, defining the viewport transforms. If the viewport state is dynamic, this member is ignored.
  • pScissors is a pointer to an array of VkRect2D structures defining the rectangular bounds of the scissor for the corresponding viewport. If the scissor state is dynamic, this member is ignored.

VkPipelineViewportStateCreateInfo(3)

VkViewportとVkRect2Dの情報が必要。VkViewportは座標変換の内のviewport transformsに必要で、VkRect2Dはviewportの領域の境界を指定するのに必要。

VkViewport

VkViewport - Structure specifying a viewport

// Provided by VK_VERSION_1_0
typedef struct VkViewport {
    float    x;
    float    y;
    float    width;
    float    height;
    float    minDepth;
    float    maxDepth;
} VkViewport;

  • x and y are the viewport’s upper left corner (x,y).
  • width and height are the viewport’s width and height, respectively.
  • minDepth and maxDepth are the depth range for the viewport.

VkViewport(3)

window coordinatesは通常、左上を(0, 0)とし、pixelの数だけwidthとheightをもつ座標系である。
swapchainで作成しているwindow全体をviewportとする場合の具体例

  VkViewport viewports{
      .x = 0,
      .y = 0,
      .width = (float)displaySize.width,
      .height = (float)displaySize.height,
      .minDepth = 0.0f,
      .maxDepth = 1.0f,
  };

VkRect2D

VkRect2D - Structure specifying a two-dimensional subregion.
Rectangles are used to describe a specified rectangular region of pixels within an image or framebuffer.

// Provided by VK_VERSION_1_0
typedef struct VkRect2D {
    VkOffset2D    offset;
    VkExtent2D    extent;
} VkRect2D;

  • offset is a VkOffset2D specifying the rectangle offset.
  • extent is a VkExtent2D specifying the rectangle extent.

offsetとextentをそれぞれ構造体で定義する。

VkOffset2D
// Provided by VK_VERSION_1_0
typedef struct VkOffset2D {
    int32_t    x;
    int32_t    y;
} VkOffset2D;

  • x is the x offset.
  • y is the y offset.

VkOffset2D(3)

VkExtent2D
// Provided by VK_VERSION_1_0
typedef struct VkExtent2D {
    uint32_t    width;
    uint32_t    height;
} VkExtent2D;

  • width is the width of the extent.
  • height is the height of the extent.

VkExtent2D(3)

extentとは「広さ、範囲」の意味。
extentの意味・使い方・読み方 | Weblio英和辞書

Shader Stageの指定

Shader Stageの指定

pipeline diagramにあるように、pipelineにはshaderを使用することにより処理を行うpipeline shader stageがある。
aqoole-hateena.hatenablog.com
pipeline shader stageを指定するには、VkPipelineShaderStageCreateInfoを実装するshader stageの数だけ記述する。
最終的にVkGraphicsPipelineCreateInfoに情報を記述することで、pipelineを作成することができる。

VkPipelineShaderStageCreateInfo

VkPipelineShaderStageCreateInfo - Structure specifying parameters of a newly created pipeline shader stage

// Provided by VK_VERSION_1_0
typedef struct VkPipelineShaderStageCreateInfo {
    VkStructureType                     sType;
    const void*                         pNext;
    VkPipelineShaderStageCreateFlags    flags;
    VkShaderStageFlagBits               stage;
    VkShaderModule                      module;
    const char*                         pName;
    const VkSpecializationInfo*         pSpecializationInfo;
} VkPipelineShaderStageCreateInfo;

  • sType is the type of this structure.
  • pNext is NULL or a pointer to a structure extending this structure.
  • flags is a bitmask of VkPipelineShaderStageCreateFlagBits specifying how the pipeline shader stage will be generated.
  • stage is a VkShaderStageFlagBits value specifying a single pipeline stage.
  • module is a VkShaderModule object containing the shader for this stage.
  • pName is a pointer to a null-terminated UTF-8 string specifying the entry point name of the shader for this stage.
  • pSpecializationInfo is a pointer to a VkSpecializationInfo structure, as described in Specialization Constants, or NULL.

VkPipelineShaderStageCreateInfo(3)

VkShaderStageFlagBits

VkShaderStageFlagBits - Bitmask specifying a pipeline stage

// Provided by VK_VERSION_1_0
typedef enum VkShaderStageFlagBits {
    VK_SHADER_STAGE_VERTEX_BIT = 0x00000001,
    VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002,
    VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004,
    VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008,
    VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010,
    VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020,
    VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F,
    VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
:
}VkShaderStageFlagBits;

  • VK_SHADER_STAGE_VERTEX_BIT specifies the vertex stage.
  • VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT specifies the tessellation control stage.
  • VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT specifies the tessellation evaluation stage.
  • VK_SHADER_STAGE_GEOMETRY_BIT specifies the geometry stage.
  • VK_SHADER_STAGE_FRAGMENT_BIT specifies the fragment stage.
  • VK_SHADER_STAGE_COMPUTE_BIT specifies the compute stage.
  • VK_SHADER_STAGE_ALL_GRAPHICS is a combination of bits used as shorthand to specify all graphics stages defined above (excluding the compute stage).
  • VK_SHADER_STAGE_ALL is a combination of bits used as shorthand to specify all shader stages supported by the device, including all additional stages which are introduced by extensions.

VkShaderStageFlagBits(3)

Ray tracingやVK_NV_などの拡張期機能は割愛している。
Rasterizationのpipelineで指定できるshader stageの種類は、基本的にはここに定義されている5種類しかない。(COMPUTE_BITを除く)

Graphics Pipeline基礎知識

Graphics pipelineとは

コマンドの入力によって、データが各ステージで処理される生産ラインのこと。
各ステージは実装によってon/offが可能だが、vertex shaderのステージだけは例外なく実装する必要がある。

Block diagram of the Vulkan pipeline

f:id:Aqoole_Hateena:20220110184943p:plain
Block diagram of the Vulkan pipeline

出典:Vulkan® 1.2.203 - A Specification
Figure 2. Block diagram of the Vulkan pipeline

左がpipelineのフローである。
調べた用語をまとめる。

Tessellation Control Shader

tessellation要素のためのプログラム可能なshader stage.
tessellationとは3頂点などで表されるポリゴンをさらに細かく分割して、より詳細かつ滑らかに表現する技法である。
テッセレーション - Wikipedia
tessellationはVulkanではオプションの操作で、tessellation control shaderとtessellation evaluation shaderの両方がpipelineに含まれる場合に行うことができる。
Vulkan® 1.2.203 - A Specification

Geometry Shader

wikipediaには以下のように説明されている。


ジオメトリシェーダーにより、実行時に頂点数を増減させたり、プリミティブの種類を変更したりすることが可能となる。OpenGLではプリミティブシェーダーとも呼ばれる。

シェーダー - Wikipedia
例えば三角形のメッシュをワイヤーフレームの三角形に変形させることなどが行える。

Vertex Post-Processing

Clip and cullの操作などがここに含まれる。Clip and cullとは描画される範囲を決めることである。
描画されない範囲は捨てて、描画される範囲をrasterizeするために次のステージに送る。

Rasterization

頂点の羅列で表されている図形を将来的にpixelで表現するために、fragment shaderに渡せるようなfragmentsに変換する。
fragmentsとは、図形が載っているpixelのことである。
Vulkanの仕様書には、以下のように説明されている。

Rasterization is the process by which a primitive is converted to a two-dimensional image. Each discrete location of this image contains associated data such as depth, color, or other attributes.
Vulkan® 1.2.203 - A Specification

「Rasterizationとは図形を2次元のimageに変換することで、imageにはdepthやcolorなどの情報が含まれる。」とある。

各pipeline stageの記述方法について

別記事にまとめていく。

Vertex Post-processing

aqoole-hateena.hatenablog.com

更新履歴

2022/1/22 Rasterization 表現を微修正

Bufferの作成とメモリ割り当てについて

vkCreateBuffer()

vkCreateBuffer - Create a new buffer object

// Provided by VK_VERSION_1_0
VkResult vkCreateBuffer(
    VkDevice                                    device,
    const VkBufferCreateInfo*                   pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkBuffer*                                   pBuffer);

vkCreateBuffer(3)
Bufferの作成にはvkCreateBuffer()を使用する。
作成に当たり、VkBufferCreateInfoを埋める必要がある。

VkBufferCreateInfo

VkBufferCreateInfo - Structure specifying the parameters of a newly created buffer object

// Provided by VK_VERSION_1_0
typedef struct VkBufferCreateInfo {
    VkStructureType        sType;
    const void*            pNext;
    VkBufferCreateFlags    flags;
    VkDeviceSize           size;
    VkBufferUsageFlags     usage;
    VkSharingMode          sharingMode;
    uint32_t               queueFamilyIndexCount;
    const uint32_t*        pQueueFamilyIndices;
} VkBufferCreateInfo;

  • sType is the type of this structure.
  • pNext is NULL or a pointer to a structure extending this structure.
  • flags is a bitmask of VkBufferCreateFlagBits specifying additional parameters of the buffer.
  • size is the size in bytes of the buffer to be created.
  • usage is a bitmask of VkBufferUsageFlagBits specifying allowed usages of the buffer.
  • sharingMode is a VkSharingMode value specifying the sharing mode of the buffer when it will be accessed by multiple queue families.
  • queueFamilyIndexCount is the number of entries in the pQueueFamilyIndices array.
  • pQueueFamilyIndices is a pointer to an array of queue families that will access this buffer. It is ignored if sharingMode is not VK_SHARING_MODE_CONCURRENT.

VkBufferCreateInfo(3)

VkSharingMode

VkSharingMode - Buffer and image sharing modes.
Buffer and image objects are created with a sharing mode controlling how they can be accessed from queues.

Sharing ModeとはQueueからのaccess modeのこと。

// Provided by VK_VERSION_1_0
typedef enum VkSharingMode {
    VK_SHARING_MODE_EXCLUSIVE = 0,
    VK_SHARING_MODE_CONCURRENT = 1,
} VkSharingMode;

メンバはEXCLUSIVEとCONCURRENTの2つのみ。

  • VK_SHARING_MODE_EXCLUSIVE specifies that access to any range or image subresource of the object will be exclusive to a single queue family at a time.
  • VK_SHARING_MODE_CONCURRENT specifies that concurrent access to any range or image subresource of the object from multiple queue families is supported.

VkSharingMode(3)

exclusiveは「排他的な、他を入れない」という意味で、concurrentは「同時」という意味。
exclusive とは 意味・読み方・表現 | Weblio英和辞書
concurrent とは 意味・読み方・表現 | Weblio英和辞書
VK_SHARING_MODE_EXCLUSIVE を指定すると、一度にひとつのqueue familyからしかアクセスできず、VK_SHARING_MODE_CONCURRENT を指定すると一度に複数のqueue familyからアクセスできる。

vkAllocateMemory()

vkAllocateMemory - Allocate device memory

作成したBufferをデバイスメモリに割り当てるには、vkAllocateMemory()を使用する。

// Provided by VK_VERSION_1_0
VkResult vkAllocateMemory(
    VkDevice                                    device,
    const VkMemoryAllocateInfo*                 pAllocateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkDeviceMemory*                             pMemory);

  • device is the logical device that owns the memory.
  • pAllocateInfo is a pointer to a VkMemoryAllocateInfo structure describing parameters of the allocation. A successfully returned allocation must use the requested parameters — no substitution is permitted by the implementation.
  • pAllocator controls host memory allocation as described in the Memory Allocation chapter.
  • pMemory is a pointer to a VkDeviceMemory handle in which information about the allocated memory is returned.

vkAllocateMemory(3)

VkMemoryAllocateInfoによる具体的なパラメータの指定が必要。

VkMemoryAllocateInfo

VkMemoryAllocateInfo - Structure containing parameters of a memory allocation

// Provided by VK_VERSION_1_0
typedef struct VkMemoryAllocateInfo {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceSize       allocationSize;
    uint32_t           memoryTypeIndex;
} VkMemoryAllocateInfo;

  • sType is the type of this structure.
  • pNext is NULL or a pointer to a structure extending this structure.
  • allocationSize is the size of the allocation in bytes.
  • memoryTypeIndex is an index identifying a memory type from the memoryTypes array of the VkPhysicalDeviceMemoryProperties structure.

VkMemoryAllocateInfo(3)

使用したいmemory typeを、VkPhysicalDeviceMemoryPropertiesのmemoryTypes[]のindexで指定する必要がある。

VkPhysicalDeviceMemoryProperties

VkPhysicalDeviceMemoryProperties - Structure specifying physical device memory properties

// Provided by VK_VERSION_1_0
typedef struct VkPhysicalDeviceMemoryProperties {
    uint32_t        memoryTypeCount;
    VkMemoryType    memoryTypes[VK_MAX_MEMORY_TYPES];
    uint32_t        memoryHeapCount;
    VkMemoryHeap    memoryHeaps[VK_MAX_MEMORY_HEAPS];
} VkPhysicalDeviceMemoryProperties;

VkPhysicalDeviceMemoryProperties(3)
vkGetBufferMemoryRequirements()でphysical deviceでサポートされているVkPhysicalDeviceMemoryPropertiesが取得できるので、そこから使用するmemory typesのindexを指定してVkMemoryAllocateInfoに記述する。

vkAllocateMemory()の具体例

サンプルコードでよく見かける具体例。

VkMemoryRequirements memReq;
vkGetBufferMemoryRequirements(device, buffer, &memReq);
VkMemoryAllocateInfo allocInfo{
    .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
    .pNext = nullptr,
    .allocationSize = memReq.size,
    .memoryTypeIndex = 0,  // Memory type assigned in the next step
};

vkGetBufferMemoryRequirements()でbuffer objectのmemory requiementを取得する。
vkGetBufferMemoryRequirements(3)
このrequirementでallocInfo.allocationSizeの値を埋める。

VkMemoryRequirements

VkMemoryRequirements - Structure specifying memory requirements

// Provided by VK_VERSION_1_0
typedef struct VkMemoryRequirements {
    VkDeviceSize    size;
    VkDeviceSize    alignment;
    uint32_t        memoryTypeBits;
} VkMemoryRequirements;

  • size is the size, in bytes, of the memory allocation required for the resource.
  • alignment is the alignment, in bytes, of the offset within the allocation required for the resource.
  • memoryTypeBits is a bitmask and contains one bit set for every supported memory type for the resource. Bit i is set if and only if the memory type i in the VkPhysicalDeviceMemoryProperties structure for the physical device is supported for the resource.

VkMemoryRequirements(3)

memoryTypeBitsはphysical deviceでサポートされているビットセットを表す。bitのi番目はVkPhysicalDeviceMemoryProperties.memoryTypesのi番目に対応する。
この事実をもとに、割り当てるメモリで使いたいmemory propertyをもつmemoryTypesは何番目かを調べる。

uint32_t SearchIndex(typeBits, requirements_mask){
  for (uint32_t i = 0; i < memReq.memoryTypeCount; i++) {
    if ((typeBits & 1) == 1) {
      // Type is available, does it match user properties?
      if ((memoryProperties.memoryTypes[i].propertyFlags & requirements_mask) ==
          requirements_mask) {
        return i;
      }
    }
    typeBits >>= 1;
  }
  throw std::runtime_error("failed to find suitable memory types for buffer");
}

typeBitsにはVkMemoryRequirements.memoryTypeBitsを入れ、requirements_maskには指定したいVkFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BITなど)を入れる。
i番目のindexがi番目のtypeBitsのbitに対応しているので、bitが一致するかどうかを確かめる。一致していた場合、使用したいrequirements_maskがmemoryProperties.memoryTypesのi番目であるかどうかを確かめる。一致していた場合、このiが欲しいiなので、returnしてiを受け取る。一致しない場合、typeBitsを一つ右にシフトして、次のiに対応させてからsearchのループをやり直す。
以上の手順により、requirements_maskに対応するmemoryProperties.memoryTypesのindexを取得できる。
これでVkMemoryAllocateInfoが完成する。

ImageViewの作成について

vkCreateImageView

ImageViewはvkCreateImageView()で作成できるが、作成にはVkImageViewCreateInfo構造体に必要な情報をインプットする必要がある。
vkCreateImageView(3)

VkImageViewCreateInfo


VkImageViewCreateInfo - Structure specifying parameters of a newly created image view

// Provided by VK_VERSION_1_0
typedef struct VkImageViewCreateInfo {
    VkStructureType            sType;
    const void*                pNext;
    VkImageViewCreateFlags     flags;
    VkImage                    image;
    VkImageViewType            viewType;
    VkFormat                   format;
    VkComponentMapping         components;
    VkImageSubresourceRange    subresourceRange;
} VkImageViewCreateInfo;

  • components is a VkComponentMapping structure specifying a remapping of color components (or of depth or stencil components after they have been converted into color components).

VkImageViewCreateInfo(3)

componentsについて、説明文にremappingとあるのでimageのRGBAの並びを変更することができる。

VkComponentMapping


VkComponentMapping - Structure specifying a color component mapping

// Provided by VK_VERSION_1_0
typedef struct VkComponentMapping {
    VkComponentSwizzle    r;
    VkComponentSwizzle    g;
    VkComponentSwizzle    b;
    VkComponentSwizzle    a;
} VkComponentMapping;

VkComponentMapping(3)
構造体をたらい回しにされているが、VkComponentSwizzleのメンバにて要素を指定する。

VkComponentSwizzle


VkComponentSwizzle - Specify how a component is swizzled

// Provided by VK_VERSION_1_0
typedef enum VkComponentSwizzle {
    VK_COMPONENT_SWIZZLE_IDENTITY = 0,
    VK_COMPONENT_SWIZZLE_ZERO = 1,
    VK_COMPONENT_SWIZZLE_ONE = 2,
    VK_COMPONENT_SWIZZLE_R = 3,
    VK_COMPONENT_SWIZZLE_G = 4,
    VK_COMPONENT_SWIZZLE_B = 5,
    VK_COMPONENT_SWIZZLE_A = 6,
} VkComponentSwizzle;

VkComponentSwizzle(3)
swizzleについて、weblioで意味を調べると


To permute bits, or elements of a vector.
ビットまたはベクトルの要素を並べ替えます。

ということなので、RGBA要素の入れ替えについてのパラメータ。
また、VK_COMPONENT_SWIZZLE_IDENTITYは同じ位置のパラメータを指定する。つまり 各ComponentにVK_COMPONENT_SWIZZLE_IDENTITYを指定した場合、以下の値が指定される。

Component Identity Mapping
components.r VK_COMPONENT_SWIZZLE_R
components.g VK_COMPONENT_SWIZZLE_G
components.b VK_COMPONENT_SWIZZLE_B
components.a VK_COMPONENT_SWIZZLE_A