*/
#include "vk_format_info.h"
+#include "genX_multisample.h"
static uint32_t
vertex_element_comp_control(enum isl_format format, unsigned comp)
if (input_index < 0)
continue;
+ if (attr == VARYING_SLOT_PNTC) {
+ sbe.PointSpriteTextureCoordinateEnable = 1 << input_index;
+ continue;
+ }
+
const int slot = fs_input_map->varying_to_slot[attr];
if (input_index >= 16)
[VK_FRONT_FACE_CLOCKWISE] = 0
};
+static void
+emit_rs_state(struct anv_pipeline *pipeline,
+ const VkPipelineRasterizationStateCreateInfo *rs_info,
+ const VkPipelineMultisampleStateCreateInfo *ms_info,
+ const struct anv_render_pass *pass,
+ const struct anv_subpass *subpass,
+ const struct anv_graphics_pipeline_create_info *extra)
+{
+ struct GENX(3DSTATE_SF) sf = {
+ GENX(3DSTATE_SF_header),
+ };
+
+ sf.ViewportTransformEnable = !(extra && extra->use_rectlist);
+ sf.StatisticsEnable = true;
+ sf.TriangleStripListProvokingVertexSelect = 0;
+ sf.LineStripListProvokingVertexSelect = 0;
+ sf.TriangleFanProvokingVertexSelect = 1;
+ sf.PointWidthSource = Vertex;
+ sf.PointWidth = 1.0;
+
+#if GEN_GEN >= 8
+ struct GENX(3DSTATE_RASTER) raster = {
+ GENX(3DSTATE_RASTER_header),
+ };
+#else
+# define raster sf
+#endif
+
+ /* For details on 3DSTATE_RASTER multisample state, see the BSpec table
+ * "Multisample Modes State".
+ */
+#if GEN_GEN >= 8
+ raster.DXMultisampleRasterizationEnable = true;
+ raster.ForcedSampleCount = FSC_NUMRASTSAMPLES_0;
+ raster.ForceMultisampling = false;
+#else
+ raster.MultisampleRasterizationMode =
+ (ms_info && ms_info->rasterizationSamples > 1) ?
+ MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL;
+#endif
+
+ raster.FrontWinding = vk_to_gen_front_face[rs_info->frontFace];
+ raster.CullMode = vk_to_gen_cullmode[rs_info->cullMode];
+ raster.FrontFaceFillMode = vk_to_gen_fillmode[rs_info->polygonMode];
+ raster.BackFaceFillMode = vk_to_gen_fillmode[rs_info->polygonMode];
+ raster.ScissorRectangleEnable = !(extra && extra->use_rectlist);
+
+#if GEN_GEN >= 9
+ /* GEN9+ splits ViewportZClipTestEnable into near and far enable bits */
+ raster.ViewportZFarClipTestEnable = !pipeline->depth_clamp_enable;
+ raster.ViewportZNearClipTestEnable = !pipeline->depth_clamp_enable;
+#elif GEN_GEN >= 8
+ raster.ViewportZClipTestEnable = !pipeline->depth_clamp_enable;
+#endif
+
+ raster.GlobalDepthOffsetEnableSolid = rs_info->depthBiasEnable;
+ raster.GlobalDepthOffsetEnableWireframe = rs_info->depthBiasEnable;
+ raster.GlobalDepthOffsetEnablePoint = rs_info->depthBiasEnable;
+
+#if GEN_GEN == 7
+ /* Gen7 requires that we provide the depth format in 3DSTATE_SF so that it
+ * can get the depth offsets correct.
+ */
+ if (subpass->depth_stencil_attachment < pass->attachment_count) {
+ VkFormat vk_format =
+ pass->attachments[subpass->depth_stencil_attachment].format;
+ assert(vk_format_is_depth_or_stencil(vk_format));
+ if (vk_format_aspects(vk_format) & VK_IMAGE_ASPECT_DEPTH_BIT) {
+ enum isl_format isl_format =
+ anv_get_isl_format(&pipeline->device->info, vk_format,
+ VK_IMAGE_ASPECT_DEPTH_BIT,
+ VK_IMAGE_TILING_OPTIMAL);
+ sf.DepthBufferSurfaceFormat =
+ isl_format_get_depth_format(isl_format, false);
+ }
+ }
+#endif
+
+#if GEN_GEN >= 8
+ GENX(3DSTATE_SF_pack)(NULL, pipeline->gen8.sf, &sf);
+ GENX(3DSTATE_RASTER_pack)(NULL, pipeline->gen8.raster, &raster);
+#else
+# undef raster
+ GENX(3DSTATE_SF_pack)(NULL, &pipeline->gen7.sf, &sf);
+#endif
+}
+
+static void
+emit_ms_state(struct anv_pipeline *pipeline,
+ const VkPipelineMultisampleStateCreateInfo *info)
+{
+ uint32_t samples = 1;
+ uint32_t log2_samples = 0;
+
+ /* From the Vulkan 1.0 spec:
+ * If pSampleMask is NULL, it is treated as if the mask has all bits
+ * enabled, i.e. no coverage is removed from fragments.
+ *
+ * 3DSTATE_SAMPLE_MASK.SampleMask is 16 bits.
+ */
+#if GEN_GEN >= 8
+ uint32_t sample_mask = 0xffff;
+#else
+ uint32_t sample_mask = 0xff;
+#endif
+
+ if (info) {
+ samples = info->rasterizationSamples;
+ log2_samples = __builtin_ffs(samples) - 1;
+ }
+
+ if (info && info->pSampleMask)
+ sample_mask &= info->pSampleMask[0];
+
+ anv_batch_emit(&pipeline->batch, GENX(3DSTATE_MULTISAMPLE), ms) {
+ ms.NumberofMultisamples = log2_samples;
+
+#if GEN_GEN >= 8
+ /* The PRM says that this bit is valid only for DX9:
+ *
+ * SW can choose to set this bit only for DX9 API. DX10/OGL API's
+ * should not have any effect by setting or not setting this bit.
+ */
+ ms.PixelPositionOffsetEnable = false;
+ ms.PixelLocation = CENTER;
+#else
+ ms.PixelLocation = PIXLOC_CENTER;
+
+ switch (samples) {
+ case 1:
+ SAMPLE_POS_1X(ms.Sample);
+ break;
+ case 2:
+ SAMPLE_POS_2X(ms.Sample);
+ break;
+ case 4:
+ SAMPLE_POS_4X(ms.Sample);
+ break;
+ case 8:
+ SAMPLE_POS_8X(ms.Sample);
+ break;
+ default:
+ break;
+ }
+#endif
+ }
+
+ anv_batch_emit(&pipeline->batch, GENX(3DSTATE_SAMPLE_MASK), sm) {
+ sm.SampleMask = sample_mask;
+ }
+}
+
static const uint32_t vk_to_gen_logic_op[] = {
[VK_LOGIC_OP_COPY] = LOGICOP_COPY,
[VK_LOGIC_OP_CLEAR] = LOGICOP_CLEAR,
GENX(3DSTATE_WM_DEPTH_STENCIL_pack)(NULL, depth_stencil_dw, &depth_stencil);
#endif
}
+
+static void
+emit_cb_state(struct anv_pipeline *pipeline,
+ const VkPipelineColorBlendStateCreateInfo *info,
+ const VkPipelineMultisampleStateCreateInfo *ms_info)
+{
+ struct anv_device *device = pipeline->device;
+
+ const uint32_t num_dwords = GENX(BLEND_STATE_length);
+ pipeline->blend_state =
+ anv_state_pool_alloc(&device->dynamic_state_pool, num_dwords * 4, 64);
+
+ struct GENX(BLEND_STATE) blend_state = {
+#if GEN_GEN >= 8
+ .AlphaToCoverageEnable = ms_info && ms_info->alphaToCoverageEnable,
+ .AlphaToOneEnable = ms_info && ms_info->alphaToOneEnable,
+#else
+ /* Make sure it gets zeroed */
+ .Entry = { { 0, }, },
+#endif
+ };
+
+ /* Default everything to disabled */
+ for (uint32_t i = 0; i < 8; i++) {
+ blend_state.Entry[i].WriteDisableAlpha = true;
+ blend_state.Entry[i].WriteDisableRed = true;
+ blend_state.Entry[i].WriteDisableGreen = true;
+ blend_state.Entry[i].WriteDisableBlue = true;
+ }
+
+ struct anv_pipeline_bind_map *map =
+ &pipeline->bindings[MESA_SHADER_FRAGMENT];
+
+ bool has_writeable_rt = false;
+ for (unsigned i = 0; i < map->surface_count; i++) {
+ struct anv_pipeline_binding *binding = &map->surface_to_descriptor[i];
+
+ /* All color attachments are at the beginning of the binding table */
+ if (binding->set != ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS)
+ break;
+
+ /* We can have at most 8 attachments */
+ assert(i < 8);
+
+ if (binding->index >= info->attachmentCount)
+ continue;
+
+ assert(binding->binding == 0);
+ const VkPipelineColorBlendAttachmentState *a =
+ &info->pAttachments[binding->index];
+
+ blend_state.Entry[i] = (struct GENX(BLEND_STATE_ENTRY)) {
+#if GEN_GEN < 8
+ .AlphaToCoverageEnable = ms_info && ms_info->alphaToCoverageEnable,
+ .AlphaToOneEnable = ms_info && ms_info->alphaToOneEnable,
+#endif
+ .LogicOpEnable = info->logicOpEnable,
+ .LogicOpFunction = vk_to_gen_logic_op[info->logicOp],
+ .ColorBufferBlendEnable = a->blendEnable,
+ .ColorClampRange = COLORCLAMP_RTFORMAT,
+ .PreBlendColorClampEnable = true,
+ .PostBlendColorClampEnable = true,
+ .SourceBlendFactor = vk_to_gen_blend[a->srcColorBlendFactor],
+ .DestinationBlendFactor = vk_to_gen_blend[a->dstColorBlendFactor],
+ .ColorBlendFunction = vk_to_gen_blend_op[a->colorBlendOp],
+ .SourceAlphaBlendFactor = vk_to_gen_blend[a->srcAlphaBlendFactor],
+ .DestinationAlphaBlendFactor = vk_to_gen_blend[a->dstAlphaBlendFactor],
+ .AlphaBlendFunction = vk_to_gen_blend_op[a->alphaBlendOp],
+ .WriteDisableAlpha = !(a->colorWriteMask & VK_COLOR_COMPONENT_A_BIT),
+ .WriteDisableRed = !(a->colorWriteMask & VK_COLOR_COMPONENT_R_BIT),
+ .WriteDisableGreen = !(a->colorWriteMask & VK_COLOR_COMPONENT_G_BIT),
+ .WriteDisableBlue = !(a->colorWriteMask & VK_COLOR_COMPONENT_B_BIT),
+ };
+
+ if (a->srcColorBlendFactor != a->srcAlphaBlendFactor ||
+ a->dstColorBlendFactor != a->dstAlphaBlendFactor ||
+ a->colorBlendOp != a->alphaBlendOp) {
+#if GEN_GEN >= 8
+ blend_state.IndependentAlphaBlendEnable = true;
+#else
+ blend_state.Entry[i].IndependentAlphaBlendEnable = true;
+#endif
+ }
+
+ if (a->colorWriteMask != 0)
+ has_writeable_rt = true;
+
+ /* Our hardware applies the blend factor prior to the blend function
+ * regardless of what function is used. Technically, this means the
+ * hardware can do MORE than GL or Vulkan specify. However, it also
+ * means that, for MIN and MAX, we have to stomp the blend factor to
+ * ONE to make it a no-op.
+ */
+ if (a->colorBlendOp == VK_BLEND_OP_MIN ||
+ a->colorBlendOp == VK_BLEND_OP_MAX) {
+ blend_state.Entry[i].SourceBlendFactor = BLENDFACTOR_ONE;
+ blend_state.Entry[i].DestinationBlendFactor = BLENDFACTOR_ONE;
+ }
+ if (a->alphaBlendOp == VK_BLEND_OP_MIN ||
+ a->alphaBlendOp == VK_BLEND_OP_MAX) {
+ blend_state.Entry[i].SourceAlphaBlendFactor = BLENDFACTOR_ONE;
+ blend_state.Entry[i].DestinationAlphaBlendFactor = BLENDFACTOR_ONE;
+ }
+ }
+
+#if GEN_GEN >= 8
+ struct GENX(BLEND_STATE_ENTRY) *bs0 = &blend_state.Entry[0];
+ anv_batch_emit(&pipeline->batch, GENX(3DSTATE_PS_BLEND), blend) {
+ blend.AlphaToCoverageEnable = blend_state.AlphaToCoverageEnable;
+ blend.HasWriteableRT = has_writeable_rt;
+ blend.ColorBufferBlendEnable = bs0->ColorBufferBlendEnable;
+ blend.SourceAlphaBlendFactor = bs0->SourceAlphaBlendFactor;
+ blend.DestinationAlphaBlendFactor = bs0->DestinationAlphaBlendFactor;
+ blend.SourceBlendFactor = bs0->SourceBlendFactor;
+ blend.DestinationBlendFactor = bs0->DestinationBlendFactor;
+ blend.AlphaTestEnable = false;
+ blend.IndependentAlphaBlendEnable =
+ blend_state.IndependentAlphaBlendEnable;
+ }
+#else
+ (void)has_writeable_rt;
+#endif
+
+ GENX(BLEND_STATE_pack)(NULL, pipeline->blend_state.map, &blend_state);
+ if (!device->info.has_llc)
+ anv_state_clflush(pipeline->blend_state);
+
+ anv_batch_emit(&pipeline->batch, GENX(3DSTATE_BLEND_STATE_POINTERS), bsp) {
+ bsp.BlendStatePointer = pipeline->blend_state.offset;
+#if GEN_GEN >= 8
+ bsp.BlendStatePointerValid = true;
+#endif
+ }
+}
+
+static void
+emit_3dstate_clip(struct anv_pipeline *pipeline,
+ const VkPipelineViewportStateCreateInfo *vp_info,
+ const VkPipelineRasterizationStateCreateInfo *rs_info,
+ const struct anv_graphics_pipeline_create_info *extra)
+{
+ const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline);
+ (void) wm_prog_data;
+ anv_batch_emit(&pipeline->batch, GENX(3DSTATE_CLIP), clip) {
+ clip.ClipEnable = !(extra && extra->use_rectlist);
+ clip.EarlyCullEnable = true;
+ clip.APIMode = APIMODE_D3D,
+ clip.ViewportXYClipTestEnable = true;
+
+ clip.ClipMode = CLIPMODE_NORMAL;
+
+ clip.TriangleStripListProvokingVertexSelect = 0;
+ clip.LineStripListProvokingVertexSelect = 0;
+ clip.TriangleFanProvokingVertexSelect = 1;
+
+ clip.MinimumPointWidth = 0.125;
+ clip.MaximumPointWidth = 255.875;
+ clip.MaximumVPIndex = vp_info->viewportCount - 1;
+
+#if GEN_GEN == 7
+ clip.FrontWinding = vk_to_gen_front_face[rs_info->frontFace];
+ clip.CullMode = vk_to_gen_cullmode[rs_info->cullMode];
+ clip.ViewportZClipTestEnable = !pipeline->depth_clamp_enable;
+#else
+ clip.NonPerspectiveBarycentricEnable = wm_prog_data ?
+ (wm_prog_data->barycentric_interp_modes & 0x38) != 0 : 0;
+#endif
+ }
+}
+
+static void
+emit_3dstate_streamout(struct anv_pipeline *pipeline,
+ const VkPipelineRasterizationStateCreateInfo *rs_info)
+{
+ anv_batch_emit(&pipeline->batch, GENX(3DSTATE_STREAMOUT), so) {
+ so.RenderingDisable = rs_info->rasterizerDiscardEnable;
+ }
+}