| // Copyright (c) 2015-2018 Khronos Group. This work is licensed under a |
| // Creative Commons Attribution 4.0 International License; see |
| // http://creativecommons.org/licenses/by/4.0/ |
| |
| [[primsrast]] |
| = Rasterization |
| |
| Rasterization is the process by which a primitive is converted to a |
| two-dimensional image. |
| Each point of this image contains associated data such as depth, color, or |
| other attributes. |
| |
| Rasterizing a primitive begins by determining which squares of an integer |
| grid in framebuffer coordinates are occupied by the primitive, and assigning |
| one or more depth values to each such square. |
| This process is described below for points, lines, and polygons. |
| |
| A grid square, including its [eq]#(x,y)# framebuffer coordinates, [eq]#z# |
| (depth), and associated data added by fragment shaders, is called a |
| fragment. |
| A fragment is located by its upper left corner, which lies on integer grid |
| coordinates. |
| |
| Rasterization operations also refer to a fragment's sample locations, which |
| are offset by subpixel fractional values from its upper left corner. |
| The rasterization rules for points, lines, and triangles involve testing |
| whether each sample location is inside the primitive. |
| Fragments need not actually be square, and rasterization rules are not |
| affected by the aspect ratio of fragments. |
| Display of non-square grids, however, will cause rasterized points and line |
| segments to appear fatter in one direction than the other. |
| |
| We assume that fragments are square, since it simplifies antialiasing and |
| texturing. |
| After rasterization, fragments are processed by the <<fragops-early,early |
| per-fragment tests>>, if enabled. |
| |
| Several factors affect rasterization, including the members of |
| sname:VkPipelineRasterizationStateCreateInfo and |
| sname:VkPipelineMultisampleStateCreateInfo. |
| |
| [open,refpage='VkPipelineRasterizationStateCreateInfo',desc='Structure specifying parameters of a newly created pipeline rasterization state',type='structs'] |
| -- |
| |
| The sname:VkPipelineRasterizationStateCreateInfo structure is defined as: |
| |
| include::../api/structs/VkPipelineRasterizationStateCreateInfo.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:flags is reserved for future use. |
| * pname:depthClampEnable controls whether to clamp the fragment's depth |
| values instead of clipping primitives to the z planes of the frustum, as |
| described in <<vertexpostproc-clipping,Primitive Clipping>>. |
| * pname:rasterizerDiscardEnable controls whether primitives are discarded |
| immediately before the rasterization stage. |
| * pname:polygonMode is the triangle rendering mode. |
| See elink:VkPolygonMode. |
| * pname:cullMode is the triangle facing direction used for primitive |
| culling. |
| See elink:VkCullModeFlagBits. |
| * pname:frontFace is a elink:VkFrontFace value specifying the front-facing |
| triangle orientation to be used for culling. |
| * pname:depthBiasEnable controls whether to bias fragment depth values. |
| * pname:depthBiasConstantFactor is a scalar factor controlling the |
| constant depth value added to each fragment. |
| * pname:depthBiasClamp is the maximum (or minimum) depth bias of a |
| fragment. |
| * pname:depthBiasSlopeFactor is a scalar factor applied to a fragment's |
| slope in depth bias calculations. |
| * pname:lineWidth is the width of rasterized line segments. |
| |
| ifdef::VK_AMD_rasterization_order[] |
| The application can: also add a |
| sname:VkPipelineRasterizationStateRasterizationOrderAMD structure to the |
| pname:pNext chain of a sname:VkPipelineRasterizationStateCreateInfo |
| structure. |
| This structure enables selecting the rasterization order to use when |
| rendering with the corresponding graphics pipeline as described in |
| <<primrast-order, Rasterization Order>>. |
| endif::VK_AMD_rasterization_order[] |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkPipelineRasterizationStateCreateInfo-depthClampEnable-00782]] |
| If the <<features-features-depthClamp,depth clamping>> feature is not |
| enabled, pname:depthClampEnable must: be ename:VK_FALSE |
| ifndef::VK_NV_fill_rectangle[] |
| * [[VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01413]] |
| If the <<features-features-fillModeNonSolid,non-solid fill modes>> |
| feature is not enabled, pname:polygonMode must: be |
| ename:VK_POLYGON_MODE_FILL |
| endif::VK_NV_fill_rectangle[] |
| ifdef::VK_NV_fill_rectangle[] |
| * [[VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01507]] |
| If the <<features-features-fillModeNonSolid,non-solid fill modes>> |
| feature is not enabled, pname:polygonMode must: be |
| ename:VK_POLYGON_MODE_FILL or ename:VK_POLYGON_MODE_FILL_RECTANGLE_NV |
| * [[VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01414]] |
| If the `<<VK_NV_fill_rectangle>>` extension is not enabled, |
| pname:polygonMode must: not be ename:VK_POLYGON_MODE_FILL_RECTANGLE_NV |
| endif::VK_NV_fill_rectangle[] |
| **** |
| |
| include::../validity/structs/VkPipelineRasterizationStateCreateInfo.txt[] |
| -- |
| |
| [open,refpage='VkPipelineRasterizationStateCreateFlags',desc='Reserved for future use',type='enums'] |
| -- |
| include::../api/flags/VkPipelineRasterizationStateCreateFlags.txt[] |
| |
| sname:VkPipelineRasterizationStateCreateFlags is a bitmask type for setting |
| a mask, but is currently reserved for future use. |
| -- |
| |
| [open,refpage='VkPipelineMultisampleStateCreateInfo',desc='Structure specifying parameters of a newly created pipeline multisample state',type='structs'] |
| -- |
| |
| The sname:VkPipelineMultisampleStateCreateInfo structure is defined as: |
| |
| include::../api/structs/VkPipelineMultisampleStateCreateInfo.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:flags is reserved for future use. |
| * pname:rasterizationSamples is a elink:VkSampleCountFlagBits specifying |
| the number of samples per pixel used in rasterization. |
| * pname:sampleShadingEnable can: be used to enable |
| <<primsrast-sampleshading,Sample Shading>>. |
| * pname:minSampleShading specifies a minimum fraction of sample shading if |
| pname:sampleShadingEnable is set to ename:VK_TRUE. |
| * pname:pSampleMask is a bitmask of static coverage information that is |
| ANDed with the coverage information generated during rasterization, as |
| described in <<fragops-samplemask,Sample Mask>>. |
| * pname: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 <<fragops-covg,Multisample Coverage>> |
| section. |
| * pname:alphaToOneEnable controls whether the alpha component of the |
| fragment's first color output is replaced with one as described in |
| <<fragops-covg,Multisample Coverage>>. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkPipelineMultisampleStateCreateInfo-sampleShadingEnable-00784]] |
| If the <<features-features-sampleRateShading,sample rate shading>> |
| feature is not enabled, pname:sampleShadingEnable must: be |
| ename:VK_FALSE |
| * [[VUID-VkPipelineMultisampleStateCreateInfo-alphaToOneEnable-00785]] |
| If the <<features-features-alphaToOne,alpha to one>> feature is not |
| enabled, pname:alphaToOneEnable must: be ename:VK_FALSE |
| * [[VUID-VkPipelineMultisampleStateCreateInfo-minSampleShading-00786]] |
| pname:minSampleShading must: be in the range [eq]#[0,1]# |
| ifdef::VK_NV_framebuffer_mixed_samples[] |
| * [[VUID-VkPipelineMultisampleStateCreateInfo-rasterizationSamples-01415]] |
| If the subpass has any color attachments and pname:rasterizationSamples |
| is greater than the number of color samples, then |
| pname:sampleShadingEnable must: be ename:VK_FALSE |
| endif::VK_NV_framebuffer_mixed_samples[] |
| |
| **** |
| |
| include::../validity/structs/VkPipelineMultisampleStateCreateInfo.txt[] |
| -- |
| |
| [open,refpage='VkPipelineMultisampleStateCreateFlags',desc='Reserved for future use',type='enums'] |
| -- |
| include::../api/flags/VkPipelineMultisampleStateCreateFlags.txt[] |
| |
| sname:VkPipelineMultisampleStateCreateFlags is a bitmask type for setting a |
| mask, but is currently reserved for future use. |
| -- |
| |
| Rasterization only produces fragments corresponding to pixels in the |
| framebuffer. |
| Fragments which would be produced by application of any of the primitive |
| rasterization rules described below but which lie outside the framebuffer |
| are not produced, nor are they processed by any later stage of the pipeline, |
| including any of the early per-fragment tests described in |
| <<fragops-early,Early Per-Fragment Tests>>. |
| |
| Surviving fragments are processed by fragment shaders. |
| Fragment shaders determine associated data for fragments, and can: also |
| modify or replace their assigned depth values. |
| |
| ifndef::VK_AMD_mixed_attachment_samples[] |
| ifndef::VK_NV_framebuffer_mixed_samples[] |
| |
| If the subpass for which this pipeline is being created uses color and/or |
| depth/stencil attachments, then pname:rasterizationSamples must: be the same |
| as the sample count for those subpass attachments. |
| |
| endif::VK_NV_framebuffer_mixed_samples[] |
| endif::VK_AMD_mixed_attachment_samples[] |
| |
| ifdef::VK_AMD_mixed_attachment_samples[] |
| |
| If the subpass for which this pipeline is being created uses color and/or |
| depth/stencil attachments, then pname:rasterizationSamples must: be the same |
| as the maximum of the sample counts of those subpass attachments. |
| |
| endif::VK_AMD_mixed_attachment_samples[] |
| |
| If the subpass for which this pipeline is being created does not use color |
| or depth/stencil attachments, pname:rasterizationSamples must: follow the |
| rules for a <<renderpass-noattachments, zero-attachment subpass>>. |
| |
| |
| [[primsrast-discard]] |
| == Discarding Primitives Before Rasterization |
| |
| Primitives are discarded before rasterization if the |
| pname:rasterizerDiscardEnable member of |
| slink:VkPipelineRasterizationStateCreateInfo is enabled. |
| When enabled, primitives are discarded after they are processed by the last |
| active shader stage in the pipeline before rasterization. |
| |
| |
| [[primrast-order]] |
| == Rasterization Order |
| |
| Within a subpass of a <<renderpass,render pass instance>>, for a given |
| (x,y,layer,sample) sample location, the following operations are guaranteed |
| to execute in _rasterization order_, for each separate primitive that |
| includes that sample location: |
| |
| . <<fragops-scissor,Scissor test>> |
| . <<fragops-samplemask,Sample mask generation>> |
| . <<fragops-dbt,Depth bounds test>> |
| . <<fragops-stencil, Stencil test, stencil op and stencil write>> |
| . <<fragops-depth, Depth test and depth write>> |
| . <<fragops-samplecount,Sample counting>> for |
| <<queries-occlusion,occlusion queries>> |
| ifdef::VK_NV_fragment_coverage_to_color[] |
| . <<fragops-coverage-to-color,Fragment Coverage To Color>> |
| endif::VK_NV_fragment_coverage_to_color[] |
| . <<fragops-coverage-reduction,coverage reduction>> |
| . <<framebuffer-blending, Blending>>, <<framebuffer-logicop, logic |
| operations>>, and color writes |
| |
| Each of these operations is atomically executed for each primitive and |
| sample location. |
| |
| Execution of these operations for each primitive in a subpass occurs in |
| ifndef::VK_AMD_rasterization_order[] |
| <<drawing-primitive-order, primitive order>>. |
| endif::VK_AMD_rasterization_order[] |
| ifdef::VK_AMD_rasterization_order[] |
| an order determined by the application. |
| |
| [open,refpage='VkPipelineRasterizationStateRasterizationOrderAMD',desc='Structure defining rasterization order for a graphics pipeline',type='structs'] |
| -- |
| |
| The rasterization order to use for a graphics pipeline is specified by |
| adding a sname:VkPipelineRasterizationStateRasterizationOrderAMD structure |
| to the pname:pNext chain of a slink:VkPipelineRasterizationStateCreateInfo |
| structure. |
| |
| The sname:VkPipelineRasterizationStateRasterizationOrderAMD structure is |
| defined as: |
| |
| include::../api/structs/VkPipelineRasterizationStateRasterizationOrderAMD.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:rasterizationOrder is a elink:VkRasterizationOrderAMD value |
| specifying the primitive rasterization order to use. |
| |
| include::../validity/structs/VkPipelineRasterizationStateRasterizationOrderAMD.txt[] |
| |
| If the `<<VK_AMD_rasterization_order>>` device extension is not enabled or |
| the application does not request a particular rasterization order through |
| specifying a sname:VkPipelineRasterizationStateRasterizationOrderAMD |
| structure then the rasterization order used by the graphics pipeline |
| defaults to ename:VK_RASTERIZATION_ORDER_STRICT_AMD. |
| |
| -- |
| |
| [open,refpage='VkRasterizationOrderAMD',desc='Specify rasterization order for a graphics pipeline',type='enums'] |
| -- |
| |
| Possible values of |
| slink:VkPipelineRasterizationStateRasterizationOrderAMD::pname:rasterizationOrder, |
| specifying the primitive rasterization order, are: |
| |
| include::../api/enums/VkRasterizationOrderAMD.txt[] |
| |
| * ename:VK_RASTERIZATION_ORDER_STRICT_AMD specifies that operations for |
| each primitive in a subpass must: occur in <<drawing-primitive-order, |
| primitive order>>. |
| * ename:VK_RASTERIZATION_ORDER_RELAXED_AMD specifies that operations for |
| each primitive in a subpass may: not occur in <<drawing-primitive-order, |
| primitive order>>. |
| |
| -- |
| |
| endif::VK_AMD_rasterization_order[] |
| |
| |
| [[primsrast-multisampling]] |
| == Multisampling |
| |
| Multisampling is a mechanism to antialias all Vulkan primitives: points, |
| lines, and polygons. |
| The technique is to sample all primitives multiple times at each pixel. |
| Each sample in each framebuffer attachment has storage for a color, depth, |
| and/or stencil value, such that per-fragment operations apply to each sample |
| independently. |
| The color sample values can: be later _resolved_ to a single color (see |
| <<copies-resolve,Resolving Multisample Images>> and the <<renderpass,Render |
| Pass>> chapter for more details on how to resolve multisample images to |
| non-multisample images). |
| |
| Vulkan defines rasterization rules for single-sample modes in a way that is |
| equivalent to a multisample mode with a single sample in the center of each |
| pixel. |
| |
| Each fragment includes a coverage value with pname:rasterizationSamples bits |
| (see <<fragops-samplemask,Sample Mask>>). |
| Each fragment includes pname:rasterizationSamples depth values and sets of |
| associated data. |
| An implementation may: choose to assign the same associated data to more |
| than one sample. |
| The location for evaluating such associated data may: be anywhere within the |
| pixel including the pixel center or any of the sample locations. |
| When pname:rasterizationSamples is ename:VK_SAMPLE_COUNT_1_BIT, the pixel |
| center must: be used. |
| The different associated data values need not all be evaluated at the same |
| location. |
| Each pixel fragment thus consists of integer x and y grid coordinates, |
| pname:rasterizationSamples depth values and sets of associated data, and a |
| coverage value with pname:rasterizationSamples bits. |
| |
| It is understood that each pixel has pname:rasterizationSamples locations |
| associated with it. |
| These locations are exact positions, rather than regions or areas, and each |
| is referred to as a sample point. |
| The sample points associated with a pixel must: be located inside or on the |
| boundary of the unit square that is considered to bound the pixel. |
| Furthermore, the relative locations of sample points may: be identical for |
| each pixel in the framebuffer, or they may: differ. |
| If the current pipeline includes a fragment shader with one or more |
| variables in its interface decorated with code:Sample and code:Input, the |
| data associated with those variables will be assigned independently for each |
| sample. |
| The values for each sample must: be evaluated at the location of the sample. |
| The data associated with any other variables not decorated with code:Sample |
| and code:Input need not be evaluated independently for each sample. |
| |
| If the pname:standardSampleLocations member of slink:VkPhysicalDeviceLimits |
| is ename:VK_TRUE, then the sample counts ename:VK_SAMPLE_COUNT_1_BIT, |
| ename:VK_SAMPLE_COUNT_2_BIT, ename:VK_SAMPLE_COUNT_4_BIT, |
| ename:VK_SAMPLE_COUNT_8_BIT, and ename:VK_SAMPLE_COUNT_16_BIT have sample |
| locations as listed in the following table, with the [eq]##i##th entry in |
| the table corresponding to bit [eq]#i# in the sample masks. |
| ename:VK_SAMPLE_COUNT_32_BIT and ename:VK_SAMPLE_COUNT_64_BIT do not have |
| standard sample locations. |
| Locations are defined relative to an origin in the upper left corner of the |
| pixel. |
| |
| <<< |
| |
| .Standard sample locations |
| [align="center"] |
| |==== |
| |ename:VK_SAMPLE_COUNT_1_BIT|ename:VK_SAMPLE_COUNT_2_BIT|ename:VK_SAMPLE_COUNT_4_BIT|ename:VK_SAMPLE_COUNT_8_BIT|ename:VK_SAMPLE_COUNT_16_BIT |
| | |
| [eq]#(0.5,0.5)# |
| | |
| [eq]#(0.75,0.75)# + |
| [eq]#(0.25,0.25)# |
| | |
| [eq]#(0.375, 0.125)# + |
| [eq]#(0.875, 0.375)# + |
| [eq]#(0.125, 0.625)# + |
| [eq]#(0.625, 0.875)# |
| | |
| [eq]#(0.5625, 0.3125)# + |
| [eq]#(0.4375, 0.6875)# + |
| [eq]#(0.8125, 0.5625)# + |
| [eq]#(0.3125, 0.1875)# + |
| [eq]#(0.1875, 0.8125)# + |
| [eq]#(0.0625, 0.4375)# + |
| [eq]#(0.6875, 0.9375)# + |
| [eq]#(0.9375, 0.0625)# |
| | |
| [eq]#(0.5625, 0.5625)# + |
| [eq]#(0.4375, 0.3125)# + |
| [eq]#(0.3125, 0.625)# + |
| [eq]#(0.75, 0.4375)# + |
| [eq]#(0.1875, 0.375)# + |
| [eq]#(0.625, 0.8125)# + |
| [eq]#(0.8125, 0.6875)# + |
| [eq]#(0.6875, 0.1875)# + |
| [eq]#(0.375, 0.875)# + |
| [eq]#(0.5, 0.0625)# + |
| [eq]#(0.25, 0.125)# + |
| [eq]#(0.125, 0.75)# + |
| [eq]#(0.0, 0.5)# + |
| [eq]#(0.9375, 0.25)# + |
| [eq]#(0.875, 0.9375)# + |
| [eq]#(0.0625, 0.0)# |
| |image:images/sample_count_1.svg[align="center"] |
| |image:images/sample_count_2.svg[align="center"] |
| |image:images/sample_count_4.svg[align="center"] |
| |image:images/sample_count_8.svg[align="center"] |
| |image:images/sample_count_16.svg[align="center"] |
| |==== |
| |
| ifdef::VK_AMD_shader_fragment_mask[] |
| Color images created with multiple samples per pixel use a compression |
| technique where there are two arrays of data associated with each pixel. |
| The first array contains one element per sample where each element stores an |
| index to the second array defining the _fragment mask_ of the pixel. |
| The second array contains one element per _color fragment_ and each element |
| stores a unique color value in the format of the image. |
| With this compression technique it's not always necessary to actually use |
| unique storage locations for each color sample: when multiple samples share |
| the same color value the fragment mask may: have two samples referring to |
| the same color fragment. |
| The number of color fragments is determined by the pname:samples member of |
| the slink:VkImageCreateInfo structure used to create the image. |
| The `<<VK_AMD_shader_fragment_mask>>` device extension provides shader |
| instructions enabling the application to get direct access to the fragment |
| mask and the individual color fragment values. |
| |
| [[vk-amd-shader-fragment-mask-diagram]] |
| [%inline] |
| image::images/fragment_mask.svg[align="center",title="Fragment Mask",align="center"] |
| |
| endif::VK_AMD_shader_fragment_mask[] |
| |
| ifdef::VK_EXT_sample_locations[] |
| |
| [[primrast-samplelocations]] |
| == Custom Sample Locations |
| |
| [open,refpage='VkPipelineSampleLocationsStateCreateInfoEXT',desc='Structure specifying sample locations for a pipeline',type='structs'] |
| -- |
| |
| Applications can: also control the sample locations used for rasterization. |
| |
| If the pname:pNext chain of the slink:VkPipelineMultisampleStateCreateInfo |
| structure specified at pipeline creation time includes an instance of the |
| sname:VkPipelineSampleLocationsStateCreateInfoEXT structure, then that |
| structure controls the sample locations used when rasterizing primitives |
| with the pipeline. |
| |
| The sname:VkPipelineSampleLocationsStateCreateInfoEXT structure is defined |
| as: |
| |
| include::../api/structs/VkPipelineSampleLocationsStateCreateInfoEXT.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:sampleLocationsEnable controls whether custom sample locations are |
| used. |
| If pname:sampleLocationsEnable is ename:VK_FALSE, the default sample |
| locations are used and the values specified in pname:sampleLocationsInfo |
| are ignored. |
| * pname:sampleLocationsInfo is the sample locations to use during |
| rasterization if pname:sampleLocationsEnable is ename:VK_TRUE and the |
| graphics pipeline is not created with |
| ename:VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT. |
| |
| include::../validity/structs/VkPipelineSampleLocationsStateCreateInfoEXT.txt[] |
| -- |
| |
| [open,refpage='VkSampleLocationsInfoEXT',desc='Structure specifying a set of sample locations',type='structs'] |
| -- |
| |
| The sname:VkSampleLocationsInfoEXT structure is defined as: |
| |
| include::../api/structs/VkSampleLocationsInfoEXT.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:sampleLocationsPerPixel is a elink:VkSampleCountFlagBits |
| specifying the number of sample locations per pixel. |
| * pname:sampleLocationGridSize is the size of the sample location grid to |
| select custom sample locations for. |
| * pname:sampleLocationsCount is the number of sample locations in |
| pname:pSampleLocations. |
| * pname:pSampleLocations is an array of pname:sampleLocationsCount |
| slink:VkSampleLocationEXT structures. |
| |
| This structure can: be used either to specify the sample locations to be |
| used for rendering or to specify the set of sample locations an image |
| subresource has been last rendered with for the purposes of layout |
| transitions of depth/stencil images created with |
| ename:VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT. |
| |
| The sample locations in pname:pSampleLocations specify |
| pname:sampleLocationsPerPixel number of sample locations for each pixel in |
| the grid of the size specified in pname:sampleLocationGridSize. |
| The sample location for sample [eq]#i# at the pixel grid location |
| [eq]#(x,y)# is taken from [eq]#pname:pSampleLocations[(x + y * |
| pname:sampleLocationGridSize.width) |
| * pname:sampleLocationsPerPixel + i]#. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkSampleLocationsInfoEXT-sampleLocationsPerPixel-01526]] |
| pname:sampleLocationsPerPixel must: be a bit value that is set in |
| slink:VkPhysicalDeviceSampleLocationsPropertiesEXT::pname:sampleLocationSampleCounts |
| * [[VUID-VkSampleLocationsInfoEXT-sampleLocationsCount-01527]] |
| pname:sampleLocationsCount must: equal |
| [eq]#pname:sampleLocationsPerPixel {times} |
| pname:sampleLocationGridSize.width {times} |
| pname:sampleLocationGridSize.height# |
| **** |
| |
| include::../validity/structs/VkSampleLocationsInfoEXT.txt[] |
| -- |
| |
| [open,refpage='VkSampleLocationEXT',desc='Structure specifying the coordinates of a sample location',type='structs'] |
| -- |
| |
| The sname:VkSampleLocationEXT structure is defined as: |
| |
| include::../api/structs/VkSampleLocationEXT.txt[] |
| |
| * pname:x is the horizontal coordinate of the sample's location. |
| * pname:y is the vertical coordinate of the sample's location. |
| |
| The domain space of the sample location coordinates has an upper-left origin |
| within the pixel in framebuffer space. |
| |
| The values specified in a sname:VkSampleLocationEXT structure are always |
| clamped to the implementation-dependent sample location coordinate range |
| [eq]#[pname:sampleLocationCoordinateRange[0],pname:sampleLocationCoordinateRange[1]]# |
| that can: be queried by chaining the |
| slink:VkPhysicalDeviceSampleLocationsPropertiesEXT structure to the |
| pname:pNext chain of slink:VkPhysicalDeviceProperties2. |
| |
| include::../validity/structs/VkSampleLocationEXT.txt[] |
| -- |
| |
| [open,refpage='vkCmdSetSampleLocationsEXT',desc='Set the dynamic sample locations state',type='protos'] |
| -- |
| The custom sample locations used for rasterization when |
| sname:VkPipelineSampleLocationsStateCreateInfoEXT::pname:sampleLocationsEnable |
| is ename:VK_TRUE are specified by the |
| sname:VkPipelineSampleLocationsStateCreateInfoEXT::pname:sampleLocationsInfo |
| property of the bound graphics pipeline, if the pipeline was not created |
| with ename:VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT enabled. |
| |
| Otherwise, the sample locations used for rasterization are set by calling |
| fname:vkCmdSetSampleLocationsEXT: |
| |
| include::../api/protos/vkCmdSetSampleLocationsEXT.txt[] |
| |
| * pname:commandBuffer is the command buffer into which the command will be |
| recorded. |
| * pname:pSampleLocationsInfo is the sample locations state to set. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkCmdSetSampleLocationsEXT-None-01528]] |
| The bound graphics pipeline must: have been created with the |
| ename:VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT dynamic state enabled |
| * [[VUID-vkCmdSetSampleLocationsEXT-sampleLocationsPerPixel-01529]] |
| The pname:sampleLocationsPerPixel member of pname:pSampleLocationsInfo |
| must: equal the pname:rasterizationSamples member of the |
| slink:VkPipelineMultisampleStateCreateInfo structure the bound graphics |
| pipeline has been created with |
| * [[VUID-vkCmdSetSampleLocationsEXT-variableSampleLocations-01530]] |
| If |
| slink:VkPhysicalDeviceSampleLocationsPropertiesEXT::pname:variableSampleLocations |
| is ename:VK_FALSE then the current render pass must: have been begun by |
| specifying a slink:VkRenderPassSampleLocationsBeginInfoEXT structure |
| whose pname:pPostSubpassSampleLocations member contains an element with |
| a pname:subpassIndex matching the current subpass index and the |
| pname:sampleLocationsInfo member of that element must: match the sample |
| locations state pointed to by pname:pSampleLocationsInfo |
| **** |
| |
| include::../validity/protos/vkCmdSetSampleLocationsEXT.txt[] |
| -- |
| |
| endif::VK_EXT_sample_locations[] |
| |
| |
| [[primsrast-sampleshading]] |
| == Sample Shading |
| |
| Sample shading can: be used to specify a minimum number of unique samples to |
| process for each fragment. |
| If sample shading is enabled an implementation must: provide a minimum of |
| [eq]#max({lceil} pname:minSampleShadingFactor {times} pname:totalSamples |
| {rceil}, 1)# unique associated data for each fragment, where |
| pname:minSampleShadingFactor is the minimum fraction of sample shading and |
| pname:totalSamples is |
| ifdef::VK_AMD_mixed_attachment_samples[] |
| the number of samples of the color attachments used in the subpass or, if |
| the subpass does not use any color attachments, |
| endif::VK_AMD_mixed_attachment_samples[] |
| the value of |
| slink:VkPipelineMultisampleStateCreateInfo::pname:rasterizationSamples |
| specified at pipeline creation time. |
| These are associated with the samples in an implementation-dependent manner. |
| When pname:minSampleShadingFactor is `1.0`, a separate set of associated |
| data are evaluated for each sample, and each set of values is evaluated at |
| the sample location. |
| |
| Sample shading is enabled for a graphics pipeline: |
| |
| * If the interface of the fragment shader entry point of the graphics |
| pipeline includes an input variable decorated with code:SampleId or |
| code:SamplePosition. |
| In this case pname:minSampleShadingFactor takes the value `1.0`. |
| * Else if the pname:sampleShadingEnable member of the |
| slink:VkPipelineMultisampleStateCreateInfo structure specified when |
| creating the graphics pipeline is set to ename:VK_TRUE. |
| In this case pname:minSampleShadingFactor takes the value of |
| slink:VkPipelineMultisampleStateCreateInfo::pname:minSampleShading. |
| |
| Otherwise, sample shading is considered disabled. |
| |
| |
| [[primsrast-points]] |
| == Points |
| |
| A point is drawn by generating a set of fragments in the shape of a square |
| centered around the vertex of the point. |
| Each vertex has an associated point size that controls the width/height of |
| that square. |
| The point size is taken from the (potentially clipped) shader built-in |
| code:PointSize written by: |
| |
| * the geometry shader, if active; |
| * the tessellation evaluation shader, if active and no geometry shader is |
| active; |
| * the vertex shader, otherwise |
| |
| and clamped to the implementation-dependent point size range |
| [eq]#[pname:pointSizeRange[0],pname:pointSizeRange[1]]#. |
| If the value written to code:PointSize is less than or equal to zero, or if |
| no value was written to code:PointSize, results are undefined. |
| |
| Not all point sizes need be supported, but the size 1.0 must: be supported. |
| The range of supported sizes and the size of evenly-spaced gradations within |
| that range are implementation-dependent. |
| The range and gradations are obtained from the pname:pointSizeRange and |
| pname:pointSizeGranularity members of slink:VkPhysicalDeviceLimits. |
| If, for instance, the size range is from 0.1 to 2.0 and the gradation size |
| is 0.1, then the size 0.1, 0.2, ..., 1.9, 2.0 are supported. |
| Additional point sizes may: also be supported. |
| There is no requirement that these sizes be equally spaced. |
| If an unsupported size is requested, the nearest supported size is used |
| instead. |
| |
| |
| [[primsrast-points-basic]] |
| === Basic Point Rasterization |
| |
| Point rasterization produces a fragment for each framebuffer pixel with one |
| or more sample points that intersect a region centered at the point's |
| [eq]#(x~f~,y~f~)#. |
| This region is a square with side equal to the current point size. |
| Coverage bits that correspond to sample points that intersect the region are |
| 1, other coverage bits are 0. |
| |
| All fragments produced in rasterizing a point are assigned the same |
| associated data, which are those of the vertex corresponding to the point. |
| However, the fragment shader built-in code:PointCoord contains point sprite |
| texture coordinates. |
| The [eq]#s# and [eq]#t# point sprite texture coordinates vary from zero to |
| one across the point horizontally left-to-right and top-to-bottom, |
| respectively. |
| The following formulas are used to evaluate [eq]#s# and [eq]#t#: |
| |
| [latexmath] |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| s = {1 \over 2} + { \left( x_p - x_f \right) \over \text{size} } |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| [latexmath] |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| t = {1 \over 2} + { \left( y_p - y_f \right) \over \text{size} } |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| where size is the point's size, [eq]#(x~p~,y~p~)# is the location at which |
| the point sprite coordinates are evaluated - this may: be the framebuffer |
| coordinates of the pixel center (i.e. at the half-integer) or the location |
| of a sample, and [eq]#(x~f~,y~f~)# is the exact, unrounded framebuffer |
| coordinate of the vertex for the point. |
| When pname:rasterizationSamples is ename:VK_SAMPLE_COUNT_1_BIT, the pixel |
| center must: be used. |
| |
| |
| [[primsrast-lines]] |
| == Line Segments |
| |
| A line is drawn by generating a set of fragments overlapping a rectangle |
| centered on the line segment. |
| Each line segment has an associated width that controls the width of that |
| rectangle. |
| |
| [open,refpage='vkCmdSetLineWidth',desc='Set the dynamic line width state',type='protos'] |
| -- |
| |
| The line width is specified by the |
| slink:VkPipelineRasterizationStateCreateInfo::pname:lineWidth property of |
| the currently active pipeline, if the pipeline was not created with |
| ename:VK_DYNAMIC_STATE_LINE_WIDTH enabled. |
| |
| Otherwise, the line width is set by calling fname:vkCmdSetLineWidth: |
| |
| include::../api/protos/vkCmdSetLineWidth.txt[] |
| |
| * pname:commandBuffer is the command buffer into which the command will be |
| recorded. |
| * pname:lineWidth is the width of rasterized line segments. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkCmdSetLineWidth-None-00787]] |
| The bound graphics pipeline must: have been created with the |
| ename:VK_DYNAMIC_STATE_LINE_WIDTH dynamic state enabled |
| * [[VUID-vkCmdSetLineWidth-lineWidth-00788]] |
| If the <<features-features-wideLines,wide lines>> feature is not |
| enabled, pname:lineWidth must: be `1.0` |
| **** |
| |
| include::../validity/protos/vkCmdSetLineWidth.txt[] |
| -- |
| |
| Not all line widths need be supported for line segment rasterization, but |
| width 1.0 antialiased segments must: be provided. |
| The range and gradations are obtained from the pname:lineWidthRange and |
| pname:lineWidthGranularity members of slink:VkPhysicalDeviceLimits. |
| If, for instance, the size range is from 0.1 to 2.0 and the gradation size |
| is 0.1, then the size 0.1, 0.2, ..., 1.9, 2.0 are supported. |
| Additional line widths may: also be supported. |
| There is no requirement that these widths be equally spaced. |
| If an unsupported width is requested, the nearest supported width is used |
| instead. |
| |
| |
| [[primsrast-lines-basic]] |
| === Basic Line Segment Rasterization |
| |
| Rasterized line segments produce fragments which intersect a rectangle |
| centered on the line segment. |
| Two of the edges are parallel to the specified line segment; each is at a |
| distance of one-half the current width from that segment in directions |
| perpendicular to the direction of the line. |
| The other two edges pass through the line endpoints and are perpendicular to |
| the direction of the specified line segment. |
| Coverage bits that correspond to sample points that intersect the rectangle |
| are 1, other coverage bits are 0. |
| |
| Next we specify how the data associated with each rasterized fragment are |
| obtained. |
| Let [eq]#**p**~r~ = (x~d~, y~d~)# be the framebuffer coordinates at which |
| associated data are evaluated. |
| This may: be the pixel center of a fragment or the location of a sample |
| within the fragment. |
| When pname:rasterizationSamples is ename:VK_SAMPLE_COUNT_1_BIT, the pixel |
| center must: be used. |
| Let [eq]#**p**~a~ = (x~a~, y~a~)# and [eq]#**p**~b~ = (x~b~,y~b~)# be |
| initial and final endpoints of the line segment, respectively. |
| Set |
| |
| // Equation {linet:eq} |
| [latexmath] |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| t = {{( \mathbf{p}_r - \mathbf{p}_a ) \cdot ( \mathbf{p}_b - \mathbf{p}_a )} |
| \over {\| \mathbf{p}_b - \mathbf{p}_a \|^2 }} |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| (Note that [eq]#t = 0# at [eq]#**p**_a# and [eq]#t = 1# at [eq]#**p**~b~#. |
| Also note that this calculation projects the vector from [eq]#**p**~a~# to |
| [eq]#**p**~r~# onto the line, and thus computes the normalized distance of |
| the fragment along the line.) |
| |
| [[line_perspective_interpolation]] |
| The value of an associated datum [eq]#f# for the fragment, whether it be a |
| shader output or the clip [eq]#w# coordinate, must: be determined using |
| _perspective interpolation_: |
| |
| [latexmath] |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| f = {{ (1-t) {f_a / w_a} + t { f_b / w_b} } \over |
| {(1-t) / w_a + t / w_b }} |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| where [eq]#f~a~# and [eq]#f~b~# are the data associated with the starting |
| and ending endpoints of the segment, respectively; [eq]#w~a~# and [eq]#w~b~# |
| are the clip [eq]#w# coordinates of the starting and ending endpoints of the |
| segments, respectively. |
| |
| [[line_linear_interpolation]] |
| Depth values for lines must: be determined using _linear interpolation_: |
| |
| :: [eq]#z = (1 - t) z~a~ {plus} t z~b~# |
| |
| where [eq]#z~a~# and [eq]#z~b~# are the depth values of the starting and |
| ending endpoints of the segment, respectively. |
| |
| The code:NoPerspective and code:Flat |
| <<shaders-interpolation-decorations,interpolation decorations>> can: be used |
| with fragment shader inputs to declare how they are interpolated. |
| When neither decoration is applied, <<line_perspective_interpolation, |
| perspective interpolation>> is performed as described above. |
| When the code:NoPerspective decoration is used, <<line_linear_interpolation, |
| linear interpolation>> is performed in the same fashion as for depth values, |
| as described above. |
| When the code:Flat decoration is used, no interpolation is performed, and |
| outputs are taken from the corresponding input value of the |
| <<vertexpostproc-flatshading,provoking vertex>> corresponding to that |
| primitive. |
| |
| The above description documents the preferred method of line rasterization, |
| and must: be used when the implementation advertises the pname:strictLines |
| limit in slink:VkPhysicalDeviceLimits as ename:VK_TRUE. |
| |
| When pname:strictLines is ename:VK_FALSE, the edges of the lines are |
| generated as a parallelogram surrounding the original line. |
| The major axis is chosen by noting the axis in which there is the greatest |
| distance between the line start and end points. |
| If the difference is equal in both directions then the X axis is chosen as |
| the major axis. |
| Edges 2 and 3 are aligned to the minor axis and are centered on the |
| endpoints of the line as in <<fig-non-strict-lines>>, and each is |
| pname:lineWidth long. |
| Edges 0 and 1 are parallel to the line and connect the endpoints of edges 2 |
| and 3. |
| Coverage bits that correspond to sample points that intersect the |
| parallelogram are 1, other coverage bits are 0. |
| |
| Samples that fall exactly on the edge of the parallelogram follow the |
| polygon rasterization rules. |
| |
| Interpolation occurs as if the parallelogram was decomposed into two |
| triangles where each pair of vertices at each end of the line has identical |
| attributes. |
| |
| [[fig-non-strict-lines]] |
| [%inline] |
| image::images/non_strict_lines.svg[align="center",title="Non strict lines"] |
| |
| |
| [[primsrast-polygons]] |
| == Polygons |
| |
| A polygon results from the decomposition of a triangle strip, triangle fan |
| or a series of independent triangles. |
| Like points and line segments, polygon rasterization is controlled by |
| several variables in the slink:VkPipelineRasterizationStateCreateInfo |
| structure. |
| |
| |
| [[primsrast-polygons-basic]] |
| === Basic Polygon Rasterization |
| |
| [open,refpage='VkFrontFace',desc='Interpret polygon front-facing orientation',type='enums'] |
| -- |
| |
| The first step of polygon rasterization is to determine whether the triangle |
| is _back-facing_ or _front-facing_. |
| This determination is made based on the sign of the (clipped or unclipped) |
| polygon's area computed in framebuffer coordinates. |
| One way to compute this area is: |
| |
| [latexmath] |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| a = -{1 \over 2}\sum_{i=0}^{n-1} |
| x_f^i y_f^{i \oplus 1} - |
| x_f^{i \oplus 1} y_f^i |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| where latexmath:[x_f^i] and latexmath:[y_f^i] are the [eq]#x# and [eq]#y# |
| framebuffer coordinates of the [eq]##i##th vertex of the [eq]#n#-vertex |
| polygon (vertices are numbered starting at zero for the purposes of this |
| computation) and [eq]#i {oplus} 1# is [eq]#(i {plus} 1) mod n#. |
| |
| The interpretation of the sign of [eq]#a# is determined by the |
| slink:VkPipelineRasterizationStateCreateInfo::pname:frontFace property of |
| the currently active pipeline. |
| Possible values are: |
| |
| include::../api/enums/VkFrontFace.txt[] |
| |
| * ename:VK_FRONT_FACE_COUNTER_CLOCKWISE specifies that a triangle with |
| positive area is considered front-facing. |
| * ename:VK_FRONT_FACE_CLOCKWISE specifies that a triangle with negative |
| area is considered front-facing. |
| |
| Any triangle which is not front-facing is back-facing, including zero-area |
| triangles. |
| |
| -- |
| |
| [open,refpage='VkCullModeFlagBits',desc='Bitmask controlling triangle culling',type='enums'] |
| -- |
| |
| Once the orientation of triangles is determined, they are culled according |
| to the slink:VkPipelineRasterizationStateCreateInfo::pname:cullMode property |
| of the currently active pipeline. |
| Possible values are: |
| |
| include::../api/enums/VkCullModeFlagBits.txt[] |
| |
| * ename:VK_CULL_MODE_NONE specifies that no triangles are discarded |
| * ename:VK_CULL_MODE_FRONT_BIT specifies that front-facing triangles are |
| discarded |
| * ename:VK_CULL_MODE_BACK_BIT specifies that back-facing triangles are |
| discarded |
| * ename: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. |
| |
| -- |
| |
| [open,refpage='VkCullModeFlags',desc='Bitmask of VkCullModeFlagBits',type='enums'] |
| -- |
| include::../api/flags/VkCullModeFlags.txt[] |
| |
| sname:VkCullModeFlags is a bitmask type for setting a mask of zero or more |
| slink:VkCullModeFlagBits. |
| -- |
| |
| The rule for determining which fragments are produced by polygon |
| rasterization is called _point sampling_. |
| The two-dimensional projection obtained by taking the x and y framebuffer |
| coordinates of the polygon's vertices is formed. |
| Fragments are produced for any pixels for which any sample points lie inside |
| of this polygon. |
| Coverage bits that correspond to sample points that satisfy the point |
| sampling criteria are 1, other coverage bits are 0. |
| Special treatment is given to a sample whose sample location lies on a |
| polygon edge. |
| In such a case, if two polygons lie on either side of a common edge (with |
| identical endpoints) on which a sample point lies, then exactly one of the |
| polygons must: result in a covered sample for that fragment during |
| rasterization. |
| As for the data associated with each fragment produced by rasterizing a |
| polygon, we begin by specifying how these values are produced for fragments |
| in a triangle. |
| Define _barycentric coordinates_ for a triangle. |
| Barycentric coordinates are a set of three numbers, [eq]#a#, [eq]#b#, and |
| [eq]#c#, each in the range [eq]#[0,1]#, with [eq]#a {plus} b {plus} c = 1#. |
| These coordinates uniquely specify any point [eq]#p# within the triangle or |
| on the triangle's boundary as |
| |
| :: [eq]#p = a p~a~ {plus} b p~b~ {plus} c p~c~# |
| |
| where [eq]#p~a~#, [eq]#p~b~#, and [eq]#p~c~# are the vertices of the |
| triangle. |
| [eq]#a#, [eq]#b#, and [eq]#c# are determined by: |
| |
| [latexmath] |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| a = {{\mathrm{A}(p p_b p_c)} \over {\mathrm{A}(p_a p_b p_c)}}, \quad |
| b = {{\mathrm{A}(p p_a p_c)} \over {\mathrm{A}(p_a p_b p_c)}}, \quad |
| c = {{\mathrm{A}(p p_a p_b)} \over {\mathrm{A}(p_a p_b p_c)}}, |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| where [eq]#A(lmn)# denotes the area in framebuffer coordinates of the |
| triangle with vertices [eq]#l#, [eq]#m#, and [eq]#n#. |
| |
| Denote an associated datum at [eq]#p~a~#, [eq]#p~b~#, or [eq]#p~c~# as |
| [eq]#f~a~#, [eq]#f~b~#, or [eq]#f~c~#, respectively. |
| |
| [[triangle_perspective_interpolation]] |
| The value of an associated datum [eq]#f# for a fragment produced by |
| rasterizing a triangle, whether it be a shader output or the clip [eq]#w# |
| coordinate, must: be determined using perspective interpolation: |
| |
| [latexmath] |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| f = { a {f_a / w_a} + b {f_b / w_b} + c {f_c / w_c} } \over |
| { {a / w_a} + {b / w_b} + {c / w_c} } |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| where [eq]#w~a~#, [eq]#w~b~#, and [eq]#w~c~# are the clip [eq]#w# |
| coordinates of [eq]#p~a~#, [eq]#p~b~#, and [eq]#p~c~#, respectively. |
| [eq]#a#, [eq]#b#, and [eq]#c# are the barycentric coordinates of the |
| location at which the data are produced - this must: be a pixel center or |
| the location of a sample. |
| When pname:rasterizationSamples is ename:VK_SAMPLE_COUNT_1_BIT, the pixel |
| center must: be used. |
| |
| [[triangle_linear_interpolation]] |
| Depth values for triangles must: be determined using linear interpolation: |
| |
| :: [eq]#z = a z~a~ {plus} b z~b~ {plus} c z~c~# |
| |
| where [eq]#z~a~#, [eq]#z~b~#, and [eq]#z~c~# are the depth values of |
| [eq]#p~a~#, [eq]#p~b~#, and [eq]#p~c~#, respectively. |
| |
| The code:NoPerspective and code:Flat |
| <<shaders-interpolation-decorations,interpolation decorations>> can: be used |
| with fragment shader inputs to declare how they are interpolated. |
| When neither decoration is applied, <<triangle_perspective_interpolation, |
| perspective interpolation>> is performed as described above. |
| When the code:NoPerspective decoration is used, |
| <<triangle_linear_interpolation, linear interpolation>> is performed in the |
| same fashion as for depth values, as described above. |
| When the code:Flat decoration is used, no interpolation is performed, and |
| outputs are taken from the corresponding input value of the |
| <<vertexpostproc-flatshading,provoking vertex>> corresponding to that |
| primitive. |
| |
| ifdef::VK_AMD_shader_explicit_vertex_parameter[] |
| When the `<<VK_AMD_shader_explicit_vertex_parameter>>` device extension is |
| enabled the code:CustomInterpAMD <<shaders-interpolation-decorations, |
| interpolation decoration>> can: also be used with fragment shader inputs |
| which indicate that the decorated inputs can: only be accessed by the |
| extended instruction code:InterpolateAtVertexAMD and allows accessing the |
| value of the inputs for individual vertices of the primitive. |
| endif::VK_AMD_shader_explicit_vertex_parameter[] |
| |
| For a polygon with more than three edges, such as are produced by clipping a |
| triangle, a convex combination of the values of the datum at the polygon's |
| vertices must: be used to obtain the value assigned to each fragment |
| produced by the rasterization algorithm. |
| That is, it must: be the case that at every fragment |
| |
| [latexmath] |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| f = \sum_{i=1}^{n} a_i f_i |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| where [eq]#n# is the number of vertices in the polygon and [eq]#f~i~# is the |
| value of [eq]#f# at vertex [eq]#i#. |
| For each [eq]#i#, [eq]#0 {leq} a~i~ {leq} 1# and |
| latexmath:[\sum_{i=1}^{n}a_i = 1]. |
| The values of [eq]#a~i~# may: differ from fragment to fragment, but at |
| vertex [eq]#i#, [eq]#a~i~ = 1# and [eq]#a~j~ = 0# for [eq]#j {neq} i#. |
| |
| [NOTE] |
| .Note |
| ==== |
| One algorithm that achieves the required behavior is to triangulate a |
| polygon (without adding any vertices) and then treat each triangle |
| individually as already discussed. |
| A scan-line rasterizer that linearly interpolates data along each edge and |
| then linearly interpolates data across each horizontal span from edge to |
| edge also satisfies the restrictions (in this case, the numerator and |
| denominator of equation <<triangle_perspective_interpolation>> are iterated |
| independently and a division performed for each fragment). |
| ==== |
| |
| |
| [[primsrast-polygonmode]] |
| === Polygon Mode |
| |
| [open,refpage='VkPolygonMode',desc='Control polygon rasterization mode',type='enums'] |
| -- |
| |
| Possible values of the |
| slink:VkPipelineRasterizationStateCreateInfo::pname:polygonMode property of |
| the currently active pipeline, specifying the method of rasterization for |
| polygons, are: |
| |
| include::../api/enums/VkPolygonMode.txt[] |
| |
| * ename:VK_POLYGON_MODE_POINT specifies that polygon vertices are drawn as |
| points. |
| * ename:VK_POLYGON_MODE_LINE specifies that polygon edges are drawn as |
| line segments. |
| * ename:VK_POLYGON_MODE_FILL specifies that polygons are rendered using |
| the polygon rasterization rules in this section. |
| ifdef::VK_NV_fill_rectangle[] |
| * ename:VK_POLYGON_MODE_FILL_RECTANGLE_NV specifies that polygons are |
| rendered using polygon rasterization rules, modified to consider a |
| sample within the primitive if the sample location is inside the |
| axis-aligned bounding box of the triangle after projection. |
| Note that the barycentric weights used in attribute interpolation can: |
| extend outside the range [eq]#[0,1]# when these primitives are shaded. |
| Special treatment is given to a sample position on the boundary edge of |
| the bounding box. |
| In such a case, if two rectangles lie on either side of a common edge |
| (with identical endpoints) on which a sample position lies, then exactly |
| one of the triangles must: produce a fragment that covers that sample |
| during rasterization. |
| + |
| Polygons rendered in ename:VK_POLYGON_MODE_FILL_RECTANGLE_NV mode may: be |
| clipped by the frustum or by user clip planes. |
| If clipping is applied, the triangle is culled rather than clipped. |
| + |
| Area calculation and facingness are determined for |
| ename:VK_POLYGON_MODE_FILL_RECTANGLE_NV mode using the triangle's |
| vertices. |
| endif::VK_NV_fill_rectangle[] |
| |
| These modes affect only the final rasterization of polygons: in particular, |
| a polygon's vertices are shaded and the polygon is clipped and possibly |
| culled before these modes are applied. |
| |
| -- |
| |
| |
| [[primsrast-depthbias]] |
| === Depth Bias |
| |
| [open,refpage='vkCmdSetDepthBias',desc='Set the depth bias dynamic state',type='protos'] |
| -- |
| |
| The depth values of all fragments generated by the rasterization of a |
| polygon can: be offset by a single value that is computed for that polygon. |
| This behavior is controlled by the pname:depthBiasEnable, |
| pname:depthBiasConstantFactor, pname:depthBiasClamp, and |
| pname:depthBiasSlopeFactor members of |
| slink:VkPipelineRasterizationStateCreateInfo, or by the corresponding |
| parameters to the fname:vkCmdSetDepthBias command if depth bias state is |
| dynamic. |
| |
| include::../api/protos/vkCmdSetDepthBias.txt[] |
| |
| * pname:commandBuffer is the command buffer into which the command will be |
| recorded. |
| * pname:depthBiasConstantFactor is a scalar factor controlling the |
| constant depth value added to each fragment. |
| * pname:depthBiasClamp is the maximum (or minimum) depth bias of a |
| fragment. |
| * pname:depthBiasSlopeFactor is a scalar factor applied to a fragment's |
| slope in depth bias calculations. |
| |
| If pname:depthBiasEnable is ename:VK_FALSE, no depth bias is applied and the |
| fragment's depth values are unchanged. |
| |
| pname:depthBiasSlopeFactor scales the maximum depth slope of the polygon, |
| and pname:depthBiasConstantFactor scales an implementation-dependent |
| constant that relates to the usable resolution of the depth buffer. |
| The resulting values are summed to produce the depth bias value which is |
| then clamped to a minimum or maximum value specified by |
| pname:depthBiasClamp. |
| pname:depthBiasSlopeFactor, pname:depthBiasConstantFactor, and |
| pname:depthBiasClamp can: each be positive, negative, or zero. |
| |
| The maximum depth slope [eq]#m# of a triangle is |
| |
| [latexmath] |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| m = \sqrt{ \left({{\partial z_f} \over {\partial x_f}}\right)^2 |
| + \left({{\partial z_f} \over {\partial y_f}}\right)^2} |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| where [eq]#(x~f~, y~f~, z~f~)# is a point on the triangle. |
| [eq]#m# may: be approximated as |
| |
| [latexmath] |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| m = \max\left( \left| { {\partial z_f} \over {\partial x_f} } \right|, |
| \left| { {\partial z_f} \over {\partial y_f} } \right| |
| \right). |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| The minimum resolvable difference [eq]#r# is an implementation-dependent |
| parameter that depends on the depth buffer representation. |
| It is the smallest difference in framebuffer coordinate [eq]#z# values that |
| is guaranteed to remain distinct throughout polygon rasterization and in the |
| depth buffer. |
| All pairs of fragments generated by the rasterization of two polygons with |
| otherwise identical vertices, but [eq]#pname:z~f~# values that differ by |
| [eq]#r#, will have distinct depth values. |
| |
| For fixed-point depth buffer representations, [eq]#r# is constant throughout |
| the range of the entire depth buffer. |
| For floating-point depth buffers, there is no single minimum resolvable |
| difference. |
| In this case, the minimum resolvable difference for a given polygon is |
| dependent on the maximum exponent, [eq]#e#, in the range of [eq]#z# values |
| spanned by the primitive. |
| If [eq]#n# is the number of bits in the floating-point mantissa, the minimum |
| resolvable difference, [eq]#r#, for the given primitive is defined as |
| |
| :: [eq]#r = 2^e-n^# |
| |
| ifdef::VK_NV_fill_rectangle[] |
| If a triangle is rasterized using the |
| ename:VK_POLYGON_MODE_FILL_RECTANGLE_NV polygon mode, then this minimum |
| resolvable difference may: not be resolvable for samples outside of the |
| triangle, where the depth is extrapolated. |
| endif::VK_NV_fill_rectangle[] |
| |
| |
| If no depth buffer is present, [eq]#r# is undefined. |
| |
| The bias value [eq]#o# for a polygon is |
| |
| [latexmath] |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| o = |
| \begin{cases} |
| m \times depthBiasSlopeFactor + |
| r \times depthBiasConstantFactor & depthBiasClamp = 0\ or\ NaN \\ |
| \min(m \times depthBiasSlopeFactor + |
| r \times depthBiasConstantFactor, |
| depthBiasClamp) & depthBiasClamp > 0 \\ |
| \max(m \times depthBiasSlopeFactor + |
| r \times depthBiasConstantFactor, |
| depthBiasClamp) & depthBiasClamp < 0 \\ |
| \end{cases} |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| [eq]#m# is computed as described above. |
| If the depth buffer uses a fixed-point representation, [eq]#m# is a function |
| of depth values in the range [eq]#[0,1]#, and [eq]#o# is applied to depth |
| values in the same range. |
| |
| For fixed-point depth buffers, fragment depth values are always limited to |
| the range [eq]#[0,1]# by clamping after depth bias addition is performed. |
| ifdef::VK_EXT_depth_range_unrestricted[] |
| Unless the `<<VK_EXT_depth_range_unrestricted>>` extension is enabled, |
| fragment depth values are clamped even when the depth buffer uses a |
| floating-point representation. |
| endif::VK_EXT_depth_range_unrestricted[] |
| ifndef::VK_EXT_depth_range_unrestricted[] |
| Fragment depth values are clamped even when the depth buffer uses a |
| floating-point representation. |
| endif::VK_EXT_depth_range_unrestricted[] |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkCmdSetDepthBias-None-00789]] |
| The bound graphics pipeline must: have been created with the |
| ename:VK_DYNAMIC_STATE_DEPTH_BIAS dynamic state enabled |
| * [[VUID-vkCmdSetDepthBias-depthBiasClamp-00790]] |
| If the <<features-features-depthBiasClamp,depth bias clamping>> feature |
| is not enabled, pname:depthBiasClamp must: be `0.0` |
| **** |
| |
| include::../validity/protos/vkCmdSetDepthBias.txt[] |
| -- |
| |
| ifdef::VK_EXT_conservative_rasterization[] |
| [[primsrast-conservativeraster]] |
| === Conservative Rasterization |
| |
| [open,refpage='VkPipelineRasterizationConservativeStateCreateInfoEXT',desc='Structure specifying conservative raster state',type='structs'] |
| -- |
| |
| Polygon rasterization can: be made conservative by setting |
| pname:conservativeRasterizationMode to |
| ename:VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT or |
| ename:VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT in |
| sname:VkPipelineRasterizationConservativeStateCreateInfoEXT. |
| The sname:VkPipelineRasterizationConservativeStateCreateInfoEXT state is set |
| by adding an instance of this structure to the pname:pNext chain of an |
| instance of the sname:VkPipelineRasterizationStateCreateInfo structure when |
| creating the graphics pipeline. |
| Enabling these modes also affects line and point rasterization if the |
| implementation sets |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:conservativePointAndLineRasterization |
| to pname:VK_TRUE. |
| |
| sname:VkPipelineRasterizationConservativeStateCreateInfoEXT is defined as: |
| |
| include::../api/structs/VkPipelineRasterizationConservativeStateCreateInfoEXT.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:flags is reserved for future use. |
| * pname:conservativeRasterizationMode is the conservative rasterization |
| mode to use. |
| * pname:extraPrimitiveOverestimationSize is the extra size in pixels to |
| increase the generating primitive during conservative rasterization at |
| each of its edges in `X` and `Y` equally in screen space beyond the base |
| overestimation specified in |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:primitiveOverestimationSize. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkPipelineRasterizationConservativeStateCreateInfoEXT-extraPrimitiveOverestimationSize-01769]] |
| pname:extraPrimitiveOverestimationSize must: be in the range of `0.0` to |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:maxExtraPrimitiveOverestimationSize |
| inclusive |
| **** |
| |
| include::../validity/structs/VkPipelineRasterizationConservativeStateCreateInfoEXT.txt[] |
| -- |
| |
| [open,refpage='VkPipelineRasterizationConservativeStateCreateFlagsEXT',desc='Reserved for future use',type='enums'] |
| -- |
| include::../api/flags/VkPipelineRasterizationConservativeStateCreateFlagsEXT.txt[] |
| |
| sname:VkPipelineRasterizationConservativeStateCreateFlagsEXT is a bitmask |
| type for setting a mask, but is currently reserved for future use. |
| -- |
| |
| [open,refpage='VkConservativeRasterizationModeEXT',desc='Specify the conservative rasterization mode',type='enums'] |
| -- |
| |
| Possible values of |
| slink:VkPipelineRasterizationConservativeStateCreateInfoEXT::pname:conservativeRasterizationMode, |
| specifying the conservative rasterization mode are: |
| |
| include::../api/enums/VkConservativeRasterizationModeEXT.txt[] |
| |
| * ename:VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT specifies that |
| conservative rasterization is disabled and rasterization proceeds as |
| normal. |
| * ename:VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT specifies that |
| conservative rasterization is enabled in overestimation mode. |
| * ename:VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT specifies |
| that conservative rasterization is enabled in underestimation mode. |
| |
| -- |
| |
| When overestimate conservative rasterization is enabled, rather than |
| evaluating coverage at individual sample locations, a determination is made |
| of whether any portion of the pixel (including its edges and corners) is |
| covered by the primitive. |
| If any portion of the pixel is covered, then all bits of the coverage sample |
| mask for the fragment are enabled. |
| ifdef::VK_EXT_post_depth_coverage[] |
| If the implementation supports |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:conservativeRasterizationPostDepthCoverage |
| and the |
| <<shaders-fragment-earlytest-postdepthcoverage,code:PostDepthCoverage>> |
| execution mode is specified the code:SampleMask built-in input variable will |
| reflect the coverage after the early per-fragment depth and stencil tests |
| are applied. |
| endif::VK_EXT_post_depth_coverage[] |
| |
| For the purposes of evaluating which pixels are covered by the primitive, |
| implementations can: increase the size of the primitive by up to |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:primitiveOverestimationSize |
| pixels at each of the primitive edges. |
| This may: increase the number of fragments generated by this primitive and |
| represents an overestimation of the pixel coverage. |
| |
| This overestimation size can be increased further by setting the |
| pname:extraPrimitiveOverestimationSize value above `0.0` in steps of |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:extraPrimitiveOverestimationSizeGranularity |
| up to and including |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:extraPrimitiveOverestimationSize. |
| This will: further increase the number of fragments generated by this |
| primitive. |
| |
| The actual precision of the overestimation size used for conservative |
| rasterization may: vary between implementations and produce results that |
| only approximate the pname:primitiveOverestimationSize and |
| pname:extraPrimitiveOverestimationSizeGranularity properties. |
| |
| For triangles if ename:VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT |
| is enabled, fragments will be generated if the primitive area covers any |
| portion of the pixel, including its edges or corners. |
| The tie-breaking rule described in <<primsrast-polygons-basic, Basic Polygon |
| Rasterization>> does not apply during conservative rasterization and |
| coverage is set for all fragments generated from shared edges of polygons. |
| Degenerate triangles that evaluate to zero area after rasterization, even |
| for pixels that contain a vertex or edge of the zero-area polygon, will be |
| culled if |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:degenerateTrianglesRasterized |
| is ename:VK_FALSE or will generate fragments if |
| pname:degenerateTrianglesRasterized is ename:VK_TRUE. |
| The fragment input values for these degenerate triangles take their |
| attribute and depth values from the provoking vertex. |
| Degenerate triangles are considered backfacing and the application can: |
| enable backface culling if desired. |
| Triangles that are zero area before rasterization may: be culled regardless. |
| |
| For lines if ename:VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT is |
| enabled, and the implementation sets |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:conservativePointAndLineRasterization |
| to ename:VK_TRUE, fragments will be generated if the line covers any portion |
| of the pixel, including its edges or corners. |
| Degenerate lines that evaluate to zero length after rasterization will be |
| culled if |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:degenerateLinesRasterized |
| is ename:VK_FALSE or will generate fragments if |
| pname:degenerateLinesRasterized is ename:VK_TRUE. |
| The fragments input values for these degenerate lines take their attribute |
| and depth values from the provoking vertex. |
| Lines that are zero length before rasterization may: be culled regardless. |
| |
| For points if ename:VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT is |
| enabled, and the implementation sets |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:conservativePointAndLineRasterization |
| to ename:VK_TRUE, fragments will be generated if the point square covers any |
| portion of the pixel square, including its edges or corners. |
| |
| When underestimate conservative rasterization is enabled, rather than |
| evaluating coverage at individual sample locations, a determination is made |
| of whether all of the pixel (including its edges and corners) is covered by |
| the primitive. |
| If the entire pixel is covered, then a fragment is generated with all bits |
| of its coverage sample mask enabled, otherwise the fragment is discarded |
| even if some portion of the pixel is covered. |
| ifdef::VK_EXT_post_depth_coverage[] |
| If the implementation supports |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:conservativeRasterizationPostDepthCoverage |
| and the |
| <<shaders-fragment-earlytest-postdepthcoverage,code:PostDepthCoverage>> |
| execution mode is specified the code:SampleMask built-in input variable will |
| reflect the coverage after the early per-fragment depth and stencil tests |
| are applied. |
| endif::VK_EXT_post_depth_coverage[] |
| |
| For triangles, if ename:VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT |
| is enabled, fragments will only be generated if they are fully covered by |
| the generating primitive, including its edges and corners. |
| |
| For lines, if ename:VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT is |
| enabled, fragments will be generated if the entire pixel, including its |
| edges and corners is covered by the line. |
| |
| For points, if ename:VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT is |
| enabled, fragments will only be generated for pixel squares that are fully |
| covered by the point square. |
| |
| For both overestimate and underestimate conservative rasterization modes a |
| pixel square that is fully covered by the generating primitive must: set |
| code:FullyCoveredEXT to pname:VK_TRUE if the implementation enables the |
| sname:VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pname:fullyCoveredFragmentShaderInputVariable |
| feature. |
| |
| endif::VK_EXT_conservative_rasterization[] |