Vulkan filled pit learn Day11- inherent function

Vulkan inherent function

Vulkan inherent function, early graphics API provides a default state in many stages of the graphics rendering pipeline. In Vulkan, the size of the viewport to a mixing function, a hands need to do everything. In this chapter we will fill all the structures related to the intrinsic function operation.

A vertex input

VkPipelineVertexInputStateCreateInfo structure describes the format of the vertex data, the data transfer of the structure into the vertex shader. It is described in two ways:

1.Bindings:根据数据的间隙,确定数据是每个顶点或者是每个instance(instancing)
2.Attribute 描述:描述将要进行绑定及加载属性的顶点着色器中的相关属性类型。

Since we will be hard-coded into the vertex data in the vertex shader, so we will not be filled vertex data structure to load. We will be back in operation vertex buffer section.

VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 0;
vertexInputInfo.pVertexBindingDescriptions = nullptr; // Optional
vertexInputInfo.vertexAttributeDescriptionCount = 0;
vertexInputInfo.pVertexAttributeDescriptions = nullptr; // Optional

pVertexBindingDescriptions pVertexAttributeDescriptions member points and an array of structures, described further information for the vertex data is loaded. This structure shaderStages createGraphicsPipeline function was added in the array.

Second, the input component

VkPipelineInputAssemblyStateCreateInfo structure described two things: primitive vertex data to what type of topology and geometry is enabled draw cord restart primitive vertices. Primitive type topology topology enumeration values ​​as follows:

VK_PRIMITIVE_TOPOLOGY_POINT_LIST: 顶点到点
VK_PRIMITIVE_TOPOLOGY_LINE_LIST: 两点成线,顶点不共用
VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: 两点成线,每个线段的结束顶点作为下一个线段的开始顶点
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 三点成面,顶点不共用
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: 每个但教训的第二个、第三个顶点都作为下一个三角形的前两个顶点

Under normal circumstances, the vertex data buffer according to the sequence as an index, but the index may be specified by the vertex data itself buffer element buffer. Vertex data by multiplexing improve performance. If primitiveRestartEnable members VK_TRUE, can be decomposed as a special index line and triangle primitives in _STRIP mode topology by 0xFFFF or 0xFFFFFFFF.

Drawing a triangle by this tutorial, we adhere to the following format in accordance with the padding data structure:

VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;

Third, windows and cutting

Viewport framebuffer used to describe the target area as a result of an output rendering. Its value is always in the tutorial is provided at (0, 0) and (width, height).

VkViewport viewport = {};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float) swapChainExtent.width;
viewport.height = (float) swapChainExtent.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;

Remember swap chain and its image size images and HEIGHT WIDTH may vary depending on the form. The image will swap chain in the frame buffer framebuffers use, so we should stick to their size.

minDepth the specified value range and maxDepth framebuffer in depth. These values ​​must converge in [0.0f, 1.0f] punch section, but may be greater than minDepth maxDepth. If you do not specify any recommended standard values ​​0.0f and 1.0f.

viewports to define the image image conversion relation framebuffer frame buffer, which pixel cropping rectangle defines the region are stored. Any pixels outside the crop will be discarded at the grating massive stage. They function more like a filter instead of defining the conversion relationship. This distinction is shown below. Note that, for larger image than the viewport size case, cropping rectangle on the left side just one of many possible manifestations.
Here Insert Picture Description
In this tutorial we will need to draw a complete picture of the frame buffer in the framebuffer, so we define the cropping rectangle to cover the entire image:

VkRect2D scissor = {};
scissor.offset = {0, 0};
scissor.extent = swapChainExtent;

and a rectangular viewport clipping means VkPipelineViewportStateCreateInfo structure need be used in combination. You can use multiple viewports and clipping rectangle in some graphics cards through an array reference. Using this feature requires GPU support this feature, specifically to see the creation of logical devices.

VkPipelineViewportStateCreateInfo viewportState = {};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.pViewports = &viewport;
viewportState.scissorCount = 1;
viewportState.pScissors = &scissor;

Fourth, the rasterization

The shaping of the grating vertex by vertex shader and the specific geometry algorithm, and transferred to the graphics fragment shader colored work. It also performs a depth test depth testing, and cutting surface of the cutting face culling test, it can be configured to output the fragment to decide whether to output the entire frame or primitive topology (wireframe rendering). VkPipelineRasterizationStateCreateInfo all configuration defined by the structure.

VkPipelineRasterizationStateCreateInfo rasterizer = {};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;

It depthClampEnable set VK_TRUE, trimmed surface of the sheet over the distance element will converge rather than discarding them. It is useful in special cases, such as shadow maps. Using this feature requires the support of the GPU.

rasterizer.rasterizerDiscardEnable = VK_FALSE;

If rasterizerDiscardEnable set VK_TRUE, then the geometry is never transmitted to the rasterization stage. This is the basic method for inhibiting framebuffer frame buffer to any output.

rasterizer.polygonMode = VK_POLYGON_MODE_FILL;

polygonMode decided to produce content for the image geometry. Effective following modes:

VK_POLYGON_MODE_FILL: 多边形区域填充
VK_POLYGON_MODE_LINE: 多边形边缘线框绘制
VK_POLYGON_MODE_POINT: 多边形顶点作为描点绘制

Any padding needed to open GPU capabilities.

rasterizer.lineWidth = 1.0f;

lineWidth member is directly filled, the line width described according to the number of fragments. Maximum width depends on hardware support, no need to open the line width greater than 1.0 wideLines feature support GPU.

rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;

cullMode variable for determining the type of surface cut manner. You can disable culling, clipping front faces, cull back faces or all of them. frontFace order of the vertices for front-facing surface as described, may be clockwise counterclockwise.

rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f; // Optional
rasterizer.depthBiasClamp = 0.0f; // Optional
rasterizer.depthBiasSlopeFactor = 0.0f; // Optional

Rasterization depth can be changed by adding a constant value based on the slope or the fragment. Some time for shadow maps are useful, but we will not use in sections, set depthBiasEnable to VK_FALSE.

Fifth, resampling

VkPipelineMultisampleStateCreateInfo structure configured for multiple samples. The so-called multi-sampling anti-aliasing is an implementation of anti-aliasing. It results through a combination of a plurality of fragment shader polygons, the rasterization of the same pixel. This occurs mainly at the edges, where it is the most compelling appear jagged. If only one pixel mapped to the polygon is not required to run multiple sampling fragment shader, high resolution compared to, it takes a lower cost. Turning on this feature requires GPU support.

VkPipelineMultisampleStateCreateInfo multisampling = {};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisampling.minSampleShading = 1.0f; // Optional
multisampling.pSampleMask = nullptr; // Optional
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
multisampling.alphaToOneEnable = VK_FALSE; // Optional

In this tutorial we will not use multi-sampling, but you can try casual, specific parameters, please refer to the specifications.

Sixth, depth and stencil test

If you use the depth or stencil buffer is required VkPipelineDepthStencilStateCreateInfo configuration. We do not need to use, so simple pass nullptr, devoted on this branch of the depth buffer section.

Seven color mixing

Fragment shader output specific color, it needs to be mixed with the already present in the frame buffer color framebuffer. This conversion process to be mixing it in two ways:

1.将old和new颜色进行混合产出一个最终的颜色
2.使用按位操作混合old和new颜色的值

There are two structures arranged for color mixing. VkPipelineColorBlendAttachmentState comprises a first structure attached to the frame buffer for each configuration. The second structure body includes VkPipelineColorBlendStateCreateInfo global set color mixing. In our example, we use only the first way:

VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE;
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; // Optional
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; // Optional

Such mixing for each frame buffer is configured manner, will be described using the following pseudo-code:

if (blendEnable) {
    finalColor.rgb = (srcColorBlendFactor * newColor.rgb) <colorBlendOp> (dstColorBlendFactor * oldColor.rgb);
    finalColor.a = (srcAlphaBlendFactor * newColor.a) <alphaBlendOp> (dstAlphaBlendFactor * oldColor.a);
} else {
    finalColor = newColor;
}

finalColor = finalColor & colorWriteMask;

If blendEnable set VK_FALSE, then the new color output from the fragment shader does not change, blending two or operation calculates a new color. The results obtained with colorWriteMask AND operation to determine the actual transmission channel.

Most cases used for achieving mixing alpha blending, mixing new colors based on their opacity will clear the old color channel. finalColor as the final output:

finalColor.rgb = newAlpha * newColor + (1 - newAlpha) * oldColor;
finalColor.a = newAlpha.a;

Can be completed by the following parameters:

colorBlendAttachment.blendEnable = VK_TRUE;
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;

You can find all enumeration values ​​related VkBlendFactor and VkBlendOp in the specification.

The second structure holds a reference to all of the frame buffer, which allows mixing operation set constant, the constant can be calculated as a blending factor follow:

VkPipelineColorBlendStateCreateInfo colorBlending = {};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;
colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f; // Optional
colorBlending.blendConstants[1] = 0.0f; // Optional
colorBlending.blendConstants[2] = 0.0f; // Optional
colorBlending.blendConstants[3] = 0.0f; // Optional

If you need to use the second mixing operation provided (bitwise combination), to be set logicOpEnable VK_TURE. LogicOp bit operation specified in the field. Automatically blocks in a first embodiment, each equivalent to one additional frame buffer framebuffer closed mixing operation, blendEnable is VK_FALSE. colorWriteMask the mask is determined by the specific color frame buffer which channel is affected. It may also be disabled in two ways, so far, does not make any change in the buffer segment to the color frame buffer output.

Eight, dynamic modification

Some state structure created earlier can be modified dynamically at run time without having to re-create. For example, viewport size, line width and blend constants. If such an operation is required, it is necessary to fill VkPipelineDynamicStateCreateInfo structure:

VkDynamicState dynamicStates[] = {
    VK_DYNAMIC_STATE_VIEWPORT,
    VK_DYNAMIC_STATE_LINE_WIDTH
};

VkPipelineDynamicStateCreateInfo dynamicState = {};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = 2;
dynamicState.pDynamicStates = dynamicStates;

These data specified in the drawing process, which will lead to the relevant value before ignored. We'll come back to in later chapters. If there is no clear need to dynamically modify the value set to nullptr.

Nine, piping layout

You can use uniform in the shader, which is similar to global variables can be modified with the dynamic state variables at the time of the painting, you can change the behavior of the shader without having to recreate them. They are typically used to pass a transformation matrix to create a vertex shader or a punch in the texture sampler fragment shader.

These values ​​needed in the pipeline to create a uniform process, designated by VkPipelineLayout object. Even in subsequent content use, we still need to create an empty pipeline layout.

Create a class member variable to hold the object, as we refer to it in the following sections of the function:

VkPipelineLayout pipelineLayout;

Create objects in createGraphicsPipeline function:

VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 0; // Optional
pipelineLayoutInfo.pSetLayouts = nullptr; // Optional
pipelineLayoutInfo.pushConstantRangeCount = 0; // Optional
pipelineLayoutInfo.pPushConstantRanges = 0; // Optional

if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
    throw std::runtime_error("failed to create pipeline layout!");
}

The structure further specifies the constant push, which is passed to the dynamic values ​​shader carry one embodiment. pipeline layout can be referenced within the entire program life cycle, so it be destroyed when the program exits.

void cleanup() {
    vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
    ...
}

in conclusion

That's all related to fixed-function, it seems there is a lot of work to do, it is fortunate that we understand almost all the content related to the rendering pipeline. This process reduces the likelihood of default due to ignorance of some components, and runtime behavior encountered an unknown cause.

However, before we can ultimately create graphics pipeline, there is a need to create an object, it is a render pass.

Published 13 original articles · won praise 0 · Views 193

Guess you like

Origin blog.csdn.net/qq_35312463/article/details/103955952