anv_query.c \
anv_util.c \
anv_x11.c \
- anv_gen8.c
+ gen8_state.c \
+ gen8_cmd_buffer.c \
+ gen8_pipeline.c
libvulkan_la_SOURCES = \
$(VULKAN_SOURCES) \
}
}
-static VkResult
-cmd_buffer_emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
- unsigned stage, struct anv_state *bt_state)
+VkResult
+anv_cmd_buffer_emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
+ unsigned stage, struct anv_state *bt_state)
{
struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
struct anv_subpass *subpass = cmd_buffer->state.subpass;
return VK_SUCCESS;
}
-static VkResult
-cmd_buffer_emit_samplers(struct anv_cmd_buffer *cmd_buffer,
- unsigned stage, struct anv_state *state)
+VkResult
+anv_cmd_buffer_emit_samplers(struct anv_cmd_buffer *cmd_buffer,
+ unsigned stage, struct anv_state *state)
{
struct anv_pipeline_layout *layout;
uint32_t sampler_count;
struct anv_state surfaces = { 0, }, samplers = { 0, };
VkResult result;
- result = cmd_buffer_emit_samplers(cmd_buffer, stage, &samplers);
+ result = anv_cmd_buffer_emit_samplers(cmd_buffer, stage, &samplers);
if (result != VK_SUCCESS)
return result;
- result = cmd_buffer_emit_binding_table(cmd_buffer, stage, &surfaces);
+ result = anv_cmd_buffer_emit_binding_table(cmd_buffer, stage, &surfaces);
if (result != VK_SUCCESS)
return result;
return VK_SUCCESS;
}
-static void
-flush_descriptor_sets(struct anv_cmd_buffer *cmd_buffer)
+void
+anv_flush_descriptor_sets(struct anv_cmd_buffer *cmd_buffer)
{
uint32_t s, dirty = cmd_buffer->state.descriptors_dirty &
cmd_buffer->state.pipeline->active_stages;
cmd_buffer->state.descriptors_dirty &= ~cmd_buffer->state.pipeline->active_stages;
}
-static struct anv_state
+struct anv_state
anv_cmd_buffer_emit_dynamic(struct anv_cmd_buffer *cmd_buffer,
uint32_t *a, uint32_t dwords, uint32_t alignment)
{
return state;
}
-static struct anv_state
+struct anv_state
anv_cmd_buffer_merge_dynamic(struct anv_cmd_buffer *cmd_buffer,
uint32_t *a, uint32_t *b,
uint32_t dwords, uint32_t alignment)
return state;
}
-static VkResult
-flush_compute_descriptor_set(struct anv_cmd_buffer *cmd_buffer)
-{
- struct anv_device *device = cmd_buffer->device;
- struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
- struct anv_state surfaces = { 0, }, samplers = { 0, };
- VkResult result;
-
- result = cmd_buffer_emit_samplers(cmd_buffer,
- VK_SHADER_STAGE_COMPUTE, &samplers);
- if (result != VK_SUCCESS)
- return result;
- result = cmd_buffer_emit_binding_table(cmd_buffer,
- VK_SHADER_STAGE_COMPUTE, &surfaces);
- if (result != VK_SUCCESS)
- return result;
-
- struct GEN8_INTERFACE_DESCRIPTOR_DATA desc = {
- .KernelStartPointer = pipeline->cs_simd,
- .KernelStartPointerHigh = 0,
- .BindingTablePointer = surfaces.offset,
- .BindingTableEntryCount = 0,
- .SamplerStatePointer = samplers.offset,
- .SamplerCount = 0,
- .NumberofThreadsinGPGPUThreadGroup = 0 /* FIXME: Really? */
- };
-
- uint32_t size = GEN8_INTERFACE_DESCRIPTOR_DATA_length * sizeof(uint32_t);
- struct anv_state state =
- anv_state_pool_alloc(&device->dynamic_state_pool, size, 64);
-
- GEN8_INTERFACE_DESCRIPTOR_DATA_pack(NULL, state.map, &desc);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_MEDIA_INTERFACE_DESCRIPTOR_LOAD,
- .InterfaceDescriptorTotalLength = size,
- .InterfaceDescriptorDataStartAddress = state.offset);
-
- return VK_SUCCESS;
-}
-
-static void
-anv_cmd_buffer_flush_compute_state(struct anv_cmd_buffer *cmd_buffer)
-{
- struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
- VkResult result;
-
- assert(pipeline->active_stages == VK_SHADER_STAGE_COMPUTE_BIT);
-
- if (cmd_buffer->state.current_pipeline != GPGPU) {
- anv_batch_emit(&cmd_buffer->batch, GEN8_PIPELINE_SELECT,
- .PipelineSelection = GPGPU);
- cmd_buffer->state.current_pipeline = GPGPU;
- }
-
- if (cmd_buffer->state.compute_dirty & ANV_CMD_BUFFER_PIPELINE_DIRTY)
- anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->batch);
-
- if ((cmd_buffer->state.descriptors_dirty & VK_SHADER_STAGE_COMPUTE_BIT) ||
- (cmd_buffer->state.compute_dirty & ANV_CMD_BUFFER_PIPELINE_DIRTY)) {
- result = flush_compute_descriptor_set(cmd_buffer);
- assert(result == VK_SUCCESS);
- cmd_buffer->state.descriptors_dirty &= ~VK_SHADER_STAGE_COMPUTE;
- }
-
- cmd_buffer->state.compute_dirty = 0;
-}
-
-static void
-anv_cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer)
-{
- struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
- uint32_t *p;
-
- uint32_t vb_emit = cmd_buffer->state.vb_dirty & pipeline->vb_used;
-
- assert((pipeline->active_stages & VK_SHADER_STAGE_COMPUTE_BIT) == 0);
-
- if (cmd_buffer->state.current_pipeline != _3D) {
- anv_batch_emit(&cmd_buffer->batch, GEN8_PIPELINE_SELECT,
- .PipelineSelection = _3D);
- cmd_buffer->state.current_pipeline = _3D;
- }
-
- if (vb_emit) {
- const uint32_t num_buffers = __builtin_popcount(vb_emit);
- const uint32_t num_dwords = 1 + num_buffers * 4;
-
- p = anv_batch_emitn(&cmd_buffer->batch, num_dwords,
- GEN8_3DSTATE_VERTEX_BUFFERS);
- uint32_t vb, i = 0;
- for_each_bit(vb, vb_emit) {
- struct anv_buffer *buffer = cmd_buffer->state.vertex_bindings[vb].buffer;
- uint32_t offset = cmd_buffer->state.vertex_bindings[vb].offset;
-
- struct GEN8_VERTEX_BUFFER_STATE state = {
- .VertexBufferIndex = vb,
- .MemoryObjectControlState = GEN8_MOCS,
- .AddressModifyEnable = true,
- .BufferPitch = pipeline->binding_stride[vb],
- .BufferStartingAddress = { buffer->bo, buffer->offset + offset },
- .BufferSize = buffer->size - offset
- };
-
- GEN8_VERTEX_BUFFER_STATE_pack(&cmd_buffer->batch, &p[1 + i * 4], &state);
- i++;
- }
- }
-
- if (cmd_buffer->state.dirty & ANV_CMD_BUFFER_PIPELINE_DIRTY) {
- /* If somebody compiled a pipeline after starting a command buffer the
- * scratch bo may have grown since we started this cmd buffer (and
- * emitted STATE_BASE_ADDRESS). If we're binding that pipeline now,
- * reemit STATE_BASE_ADDRESS so that we use the bigger scratch bo. */
- if (cmd_buffer->state.scratch_size < pipeline->total_scratch)
- anv_cmd_buffer_emit_state_base_address(cmd_buffer);
-
- anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->batch);
- }
-
- if (cmd_buffer->state.descriptors_dirty)
- flush_descriptor_sets(cmd_buffer);
-
- if (cmd_buffer->state.dirty & ANV_CMD_BUFFER_VP_DIRTY) {
- struct anv_dynamic_vp_state *vp_state = cmd_buffer->state.vp_state;
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_SCISSOR_STATE_POINTERS,
- .ScissorRectPointer = vp_state->scissor.offset);
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_VIEWPORT_STATE_POINTERS_CC,
- .CCViewportPointer = vp_state->cc_vp.offset);
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP,
- .SFClipViewportPointer = vp_state->sf_clip_vp.offset);
- }
-
- if (cmd_buffer->state.dirty & (ANV_CMD_BUFFER_PIPELINE_DIRTY |
- ANV_CMD_BUFFER_RS_DIRTY)) {
- anv_batch_emit_merge(&cmd_buffer->batch,
- cmd_buffer->state.rs_state->state_sf,
- pipeline->state_sf);
- anv_batch_emit_merge(&cmd_buffer->batch,
- cmd_buffer->state.rs_state->state_raster,
- pipeline->state_raster);
- }
-
- if (cmd_buffer->state.ds_state &&
- (cmd_buffer->state.dirty & (ANV_CMD_BUFFER_PIPELINE_DIRTY |
- ANV_CMD_BUFFER_DS_DIRTY))) {
- anv_batch_emit_merge(&cmd_buffer->batch,
- cmd_buffer->state.ds_state->state_wm_depth_stencil,
- pipeline->state_wm_depth_stencil);
- }
-
- if (cmd_buffer->state.dirty & (ANV_CMD_BUFFER_CB_DIRTY |
- ANV_CMD_BUFFER_DS_DIRTY)) {
- struct anv_state state;
- if (cmd_buffer->state.ds_state == NULL)
- state = anv_cmd_buffer_emit_dynamic(cmd_buffer,
- cmd_buffer->state.cb_state->state_color_calc,
- GEN8_COLOR_CALC_STATE_length, 64);
- else if (cmd_buffer->state.cb_state == NULL)
- state = anv_cmd_buffer_emit_dynamic(cmd_buffer,
- cmd_buffer->state.ds_state->state_color_calc,
- GEN8_COLOR_CALC_STATE_length, 64);
- else
- state = anv_cmd_buffer_merge_dynamic(cmd_buffer,
- cmd_buffer->state.ds_state->state_color_calc,
- cmd_buffer->state.cb_state->state_color_calc,
- GEN8_COLOR_CALC_STATE_length, 64);
-
- anv_batch_emit(&cmd_buffer->batch,
- GEN8_3DSTATE_CC_STATE_POINTERS,
- .ColorCalcStatePointer = state.offset,
- .ColorCalcStatePointerValid = true);
- }
-
- if (cmd_buffer->state.dirty & (ANV_CMD_BUFFER_PIPELINE_DIRTY |
- ANV_CMD_BUFFER_INDEX_BUFFER_DIRTY)) {
- anv_batch_emit_merge(&cmd_buffer->batch,
- cmd_buffer->state.state_vf, pipeline->state_vf);
- }
-
- cmd_buffer->state.vb_dirty &= ~vb_emit;
- cmd_buffer->state.dirty = 0;
-}
-
-void anv_CmdDraw(
- VkCmdBuffer cmdBuffer,
- uint32_t firstVertex,
- uint32_t vertexCount,
- uint32_t firstInstance,
- uint32_t instanceCount)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
-
- anv_cmd_buffer_flush_state(cmd_buffer);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DPRIMITIVE,
- .VertexAccessType = SEQUENTIAL,
- .VertexCountPerInstance = vertexCount,
- .StartVertexLocation = firstVertex,
- .InstanceCount = instanceCount,
- .StartInstanceLocation = firstInstance,
- .BaseVertexLocation = 0);
-}
-
-void anv_CmdDrawIndexed(
- VkCmdBuffer cmdBuffer,
- uint32_t firstIndex,
- uint32_t indexCount,
- int32_t vertexOffset,
- uint32_t firstInstance,
- uint32_t instanceCount)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
-
- anv_cmd_buffer_flush_state(cmd_buffer);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DPRIMITIVE,
- .VertexAccessType = RANDOM,
- .VertexCountPerInstance = indexCount,
- .StartVertexLocation = firstIndex,
- .InstanceCount = instanceCount,
- .StartInstanceLocation = firstInstance,
- .BaseVertexLocation = vertexOffset);
-}
-
-static void
-anv_batch_lrm(struct anv_batch *batch,
- uint32_t reg, struct anv_bo *bo, uint32_t offset)
-{
- anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
- .RegisterAddress = reg,
- .MemoryAddress = { bo, offset });
-}
-
-static void
-anv_batch_lri(struct anv_batch *batch, uint32_t reg, uint32_t imm)
-{
- anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_IMM,
- .RegisterOffset = reg,
- .DataDWord = imm);
-}
-
-/* Auto-Draw / Indirect Registers */
-#define GEN7_3DPRIM_END_OFFSET 0x2420
-#define GEN7_3DPRIM_START_VERTEX 0x2430
-#define GEN7_3DPRIM_VERTEX_COUNT 0x2434
-#define GEN7_3DPRIM_INSTANCE_COUNT 0x2438
-#define GEN7_3DPRIM_START_INSTANCE 0x243C
-#define GEN7_3DPRIM_BASE_VERTEX 0x2440
-
-void anv_CmdDrawIndirect(
- VkCmdBuffer cmdBuffer,
- VkBuffer _buffer,
- VkDeviceSize offset,
- uint32_t count,
- uint32_t stride)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
- struct anv_bo *bo = buffer->bo;
- uint32_t bo_offset = buffer->offset + offset;
-
- anv_cmd_buffer_flush_state(cmd_buffer);
-
- anv_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_VERTEX_COUNT, bo, bo_offset);
- anv_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_INSTANCE_COUNT, bo, bo_offset + 4);
- anv_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_VERTEX, bo, bo_offset + 8);
- anv_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 12);
- anv_batch_lri(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, 0);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DPRIMITIVE,
- .IndirectParameterEnable = true,
- .VertexAccessType = SEQUENTIAL);
-}
-
-void anv_CmdDrawIndexedIndirect(
- VkCmdBuffer cmdBuffer,
- VkBuffer _buffer,
- VkDeviceSize offset,
- uint32_t count,
- uint32_t stride)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
- struct anv_bo *bo = buffer->bo;
- uint32_t bo_offset = buffer->offset + offset;
-
- anv_cmd_buffer_flush_state(cmd_buffer);
-
- anv_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_VERTEX_COUNT, bo, bo_offset);
- anv_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_INSTANCE_COUNT, bo, bo_offset + 4);
- anv_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_VERTEX, bo, bo_offset + 8);
- anv_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, bo, bo_offset + 12);
- anv_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 16);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DPRIMITIVE,
- .IndirectParameterEnable = true,
- .VertexAccessType = RANDOM);
-}
-
-void anv_CmdDispatch(
- VkCmdBuffer cmdBuffer,
- uint32_t x,
- uint32_t y,
- uint32_t z)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
- struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
-
- anv_cmd_buffer_flush_compute_state(cmd_buffer);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_GPGPU_WALKER,
- .SIMDSize = prog_data->simd_size / 16,
- .ThreadDepthCounterMaximum = 0,
- .ThreadHeightCounterMaximum = 0,
- .ThreadWidthCounterMaximum = pipeline->cs_thread_width_max,
- .ThreadGroupIDXDimension = x,
- .ThreadGroupIDYDimension = y,
- .ThreadGroupIDZDimension = z,
- .RightExecutionMask = pipeline->cs_right_mask,
- .BottomExecutionMask = 0xffffffff);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_MEDIA_STATE_FLUSH);
-}
-
-#define GPGPU_DISPATCHDIMX 0x2500
-#define GPGPU_DISPATCHDIMY 0x2504
-#define GPGPU_DISPATCHDIMZ 0x2508
-
-void anv_CmdDispatchIndirect(
- VkCmdBuffer cmdBuffer,
- VkBuffer _buffer,
- VkDeviceSize offset)
+void
+anv_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_subpass *subpass)
{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
- struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
- struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
- struct anv_bo *bo = buffer->bo;
- uint32_t bo_offset = buffer->offset + offset;
-
- anv_cmd_buffer_flush_compute_state(cmd_buffer);
-
- anv_batch_lrm(&cmd_buffer->batch, GPGPU_DISPATCHDIMX, bo, bo_offset);
- anv_batch_lrm(&cmd_buffer->batch, GPGPU_DISPATCHDIMY, bo, bo_offset + 4);
- anv_batch_lrm(&cmd_buffer->batch, GPGPU_DISPATCHDIMZ, bo, bo_offset + 8);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_GPGPU_WALKER,
- .IndirectParameterEnable = true,
- .SIMDSize = prog_data->simd_size / 16,
- .ThreadDepthCounterMaximum = 0,
- .ThreadHeightCounterMaximum = 0,
- .ThreadWidthCounterMaximum = pipeline->cs_thread_width_max,
- .RightExecutionMask = pipeline->cs_right_mask,
- .BottomExecutionMask = 0xffffffff);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_MEDIA_STATE_FLUSH);
+ gen8_cmd_buffer_begin_subpass(cmd_buffer, subpass);
}
void anv_CmdSetEvent(
stub();
}
-static void
-anv_cmd_buffer_emit_depth_stencil(struct anv_cmd_buffer *cmd_buffer)
-{
- struct anv_subpass *subpass = cmd_buffer->state.subpass;
- struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
- const struct anv_depth_stencil_view *view;
-
- static const struct anv_depth_stencil_view null_view =
- { .depth_format = D16_UNORM, .depth_stride = 0, .stencil_stride = 0 };
-
- if (subpass->depth_stencil_attachment != VK_ATTACHMENT_UNUSED) {
- const struct anv_attachment_view *aview =
- fb->attachments[subpass->depth_stencil_attachment];
- assert(aview->attachment_type == ANV_ATTACHMENT_VIEW_TYPE_DEPTH_STENCIL);
- view = (const struct anv_depth_stencil_view *)aview;
- } else {
- view = &null_view;
- }
-
- /* FIXME: Implement the PMA stall W/A */
- /* FIXME: Width and Height are wrong */
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_DEPTH_BUFFER,
- .SurfaceType = SURFTYPE_2D,
- .DepthWriteEnable = view->depth_stride > 0,
- .StencilWriteEnable = view->stencil_stride > 0,
- .HierarchicalDepthBufferEnable = false,
- .SurfaceFormat = view->depth_format,
- .SurfacePitch = view->depth_stride > 0 ? view->depth_stride - 1 : 0,
- .SurfaceBaseAddress = { view->bo, view->depth_offset },
- .Height = cmd_buffer->state.framebuffer->height - 1,
- .Width = cmd_buffer->state.framebuffer->width - 1,
- .LOD = 0,
- .Depth = 1 - 1,
- .MinimumArrayElement = 0,
- .DepthBufferObjectControlState = GEN8_MOCS,
- .RenderTargetViewExtent = 1 - 1,
- .SurfaceQPitch = view->depth_qpitch >> 2);
-
- /* Disable hierarchial depth buffers. */
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_HIER_DEPTH_BUFFER);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_STENCIL_BUFFER,
- .StencilBufferEnable = view->stencil_stride > 0,
- .StencilBufferObjectControlState = GEN8_MOCS,
- .SurfacePitch = view->stencil_stride > 0 ? view->stencil_stride - 1 : 0,
- .SurfaceBaseAddress = { view->bo, view->stencil_offset },
- .SurfaceQPitch = view->stencil_qpitch >> 2);
-
- /* Clear the clear params. */
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_CLEAR_PARAMS);
-}
-
-void
-anv_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
- struct anv_subpass *subpass)
-{
- cmd_buffer->state.subpass = subpass;
-
- cmd_buffer->state.descriptors_dirty |= VK_SHADER_STAGE_FRAGMENT_BIT;
-
- anv_cmd_buffer_emit_depth_stencil(cmd_buffer);
-}
-
-void anv_CmdBeginRenderPass(
- VkCmdBuffer cmdBuffer,
- const VkRenderPassBeginInfo* pRenderPassBegin,
- VkRenderPassContents contents)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_render_pass, pass, pRenderPassBegin->renderPass);
- ANV_FROM_HANDLE(anv_framebuffer, framebuffer, pRenderPassBegin->framebuffer);
-
- cmd_buffer->state.framebuffer = framebuffer;
- cmd_buffer->state.pass = pass;
-
- const VkRect2D *render_area = &pRenderPassBegin->renderArea;
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_DRAWING_RECTANGLE,
- .ClippedDrawingRectangleYMin = render_area->offset.y,
- .ClippedDrawingRectangleXMin = render_area->offset.x,
- .ClippedDrawingRectangleYMax =
- render_area->offset.y + render_area->extent.height - 1,
- .ClippedDrawingRectangleXMax =
- render_area->offset.x + render_area->extent.width - 1,
- .DrawingRectangleOriginY = 0,
- .DrawingRectangleOriginX = 0);
-
- anv_cmd_buffer_clear_attachments(cmd_buffer, pass,
- pRenderPassBegin->pAttachmentClearValues);
-
- anv_cmd_buffer_begin_subpass(cmd_buffer, pass->subpasses);
-}
-
-void anv_CmdNextSubpass(
- VkCmdBuffer cmdBuffer,
- VkRenderPassContents contents)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
-
- assert(cmd_buffer->level == VK_CMD_BUFFER_LEVEL_PRIMARY);
-
- anv_cmd_buffer_begin_subpass(cmd_buffer, cmd_buffer->state.subpass + 1);
-}
-
-void anv_CmdEndRenderPass(
- VkCmdBuffer cmdBuffer)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
-
- /* Emit a flushing pipe control at the end of a pass. This is kind of a
- * hack but it ensures that render targets always actually get written.
- * Eventually, we should do flushing based on image format transitions
- * or something of that nature.
- */
- anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
- .PostSyncOperation = NoWrite,
- .RenderTargetCacheFlushEnable = true,
- .InstructionCacheInvalidateEnable = true,
- .DepthCacheFlushEnable = true,
- .VFCacheInvalidationEnable = true,
- .TextureCacheInvalidationEnable = true,
- .CommandStreamerStallEnable = true);
-}
-
void anv_CmdExecuteCommands(
VkCmdBuffer cmdBuffer,
uint32_t cmdBuffersCount,
+++ /dev/null
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "anv_private.h"
-
-VkResult gen8_CreateDynamicRasterState(
- VkDevice _device,
- const VkDynamicRasterStateCreateInfo* pCreateInfo,
- VkDynamicRasterState* pState)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_dynamic_rs_state *state;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_RASTER_STATE_CREATE_INFO);
-
- state = anv_device_alloc(device, sizeof(*state), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (state == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- struct GEN8_3DSTATE_SF sf = {
- GEN8_3DSTATE_SF_header,
- .LineWidth = pCreateInfo->lineWidth,
- };
-
- GEN8_3DSTATE_SF_pack(NULL, state->state_sf, &sf);
-
- bool enable_bias = pCreateInfo->depthBias != 0.0f ||
- pCreateInfo->slopeScaledDepthBias != 0.0f;
- struct GEN8_3DSTATE_RASTER raster = {
- .GlobalDepthOffsetEnableSolid = enable_bias,
- .GlobalDepthOffsetEnableWireframe = enable_bias,
- .GlobalDepthOffsetEnablePoint = enable_bias,
- .GlobalDepthOffsetConstant = pCreateInfo->depthBias,
- .GlobalDepthOffsetScale = pCreateInfo->slopeScaledDepthBias,
- .GlobalDepthOffsetClamp = pCreateInfo->depthBiasClamp
- };
-
- GEN8_3DSTATE_RASTER_pack(NULL, state->state_raster, &raster);
-
- *pState = anv_dynamic_rs_state_to_handle(state);
-
- return VK_SUCCESS;
-}
-
-void
-gen8_fill_buffer_surface_state(void *state, const struct anv_format *format,
- uint32_t offset, uint32_t range)
-{
- /* This assumes RGBA float format. */
- uint32_t stride = 4;
- uint32_t num_elements = range / stride;
-
- struct GEN8_RENDER_SURFACE_STATE surface_state = {
- .SurfaceType = SURFTYPE_BUFFER,
- .SurfaceArray = false,
- .SurfaceFormat = format->surface_format,
- .SurfaceVerticalAlignment = VALIGN4,
- .SurfaceHorizontalAlignment = HALIGN4,
- .TileMode = LINEAR,
- .VerticalLineStride = 0,
- .VerticalLineStrideOffset = 0,
- .SamplerL2BypassModeDisable = true,
- .RenderCacheReadWriteMode = WriteOnlyCache,
- .MemoryObjectControlState = GEN8_MOCS,
- .BaseMipLevel = 0.0,
- .SurfaceQPitch = 0,
- .Height = (num_elements >> 7) & 0x3fff,
- .Width = num_elements & 0x7f,
- .Depth = (num_elements >> 21) & 0x3f,
- .SurfacePitch = stride - 1,
- .MinimumArrayElement = 0,
- .NumberofMultisamples = MULTISAMPLECOUNT_1,
- .XOffset = 0,
- .YOffset = 0,
- .SurfaceMinLOD = 0,
- .MIPCountLOD = 0,
- .AuxiliarySurfaceMode = AUX_NONE,
- .RedClearColor = 0,
- .GreenClearColor = 0,
- .BlueClearColor = 0,
- .AlphaClearColor = 0,
- .ShaderChannelSelectRed = SCS_RED,
- .ShaderChannelSelectGreen = SCS_GREEN,
- .ShaderChannelSelectBlue = SCS_BLUE,
- .ShaderChannelSelectAlpha = SCS_ALPHA,
- .ResourceMinLOD = 0.0,
- /* FIXME: We assume that the image must be bound at this time. */
- .SurfaceBaseAddress = { NULL, offset },
- };
-
- GEN8_RENDER_SURFACE_STATE_pack(NULL, state, &surface_state);
-}
-
-VkResult gen8_CreateBufferView(
- VkDevice _device,
- const VkBufferViewCreateInfo* pCreateInfo,
- VkBufferView* pView)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_buffer_view *view;
- VkResult result;
-
- result = anv_buffer_view_create(device, pCreateInfo, &view);
- if (result != VK_SUCCESS)
- return result;
-
- const struct anv_format *format =
- anv_format_for_vk_format(pCreateInfo->format);
-
- gen8_fill_buffer_surface_state(view->view.surface_state.map, format,
- view->view.offset, pCreateInfo->range);
-
- *pView = anv_buffer_view_to_handle(view);
-
- return VK_SUCCESS;
-}
-
-VkResult gen8_CreateSampler(
- VkDevice _device,
- const VkSamplerCreateInfo* pCreateInfo,
- VkSampler* pSampler)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_sampler *sampler;
- uint32_t mag_filter, min_filter, max_anisotropy;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
-
- sampler = anv_device_alloc(device, sizeof(*sampler), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (!sampler)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- static const uint32_t vk_to_gen_tex_filter[] = {
- [VK_TEX_FILTER_NEAREST] = MAPFILTER_NEAREST,
- [VK_TEX_FILTER_LINEAR] = MAPFILTER_LINEAR
- };
-
- static const uint32_t vk_to_gen_mipmap_mode[] = {
- [VK_TEX_MIPMAP_MODE_BASE] = MIPFILTER_NONE,
- [VK_TEX_MIPMAP_MODE_NEAREST] = MIPFILTER_NEAREST,
- [VK_TEX_MIPMAP_MODE_LINEAR] = MIPFILTER_LINEAR
- };
-
- static const uint32_t vk_to_gen_tex_address[] = {
- [VK_TEX_ADDRESS_WRAP] = TCM_WRAP,
- [VK_TEX_ADDRESS_MIRROR] = TCM_MIRROR,
- [VK_TEX_ADDRESS_CLAMP] = TCM_CLAMP,
- [VK_TEX_ADDRESS_MIRROR_ONCE] = TCM_MIRROR_ONCE,
- [VK_TEX_ADDRESS_CLAMP_BORDER] = TCM_CLAMP_BORDER,
- };
-
- static const uint32_t vk_to_gen_compare_op[] = {
- [VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER,
- [VK_COMPARE_OP_LESS] = PREFILTEROPLESS,
- [VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL,
- [VK_COMPARE_OP_LESS_EQUAL] = PREFILTEROPLEQUAL,
- [VK_COMPARE_OP_GREATER] = PREFILTEROPGREATER,
- [VK_COMPARE_OP_NOT_EQUAL] = PREFILTEROPNOTEQUAL,
- [VK_COMPARE_OP_GREATER_EQUAL] = PREFILTEROPGEQUAL,
- [VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS,
- };
-
- if (pCreateInfo->maxAnisotropy > 1) {
- mag_filter = MAPFILTER_ANISOTROPIC;
- min_filter = MAPFILTER_ANISOTROPIC;
- max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
- } else {
- mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
- min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
- max_anisotropy = RATIO21;
- }
-
- struct GEN8_SAMPLER_STATE sampler_state = {
- .SamplerDisable = false,
- .TextureBorderColorMode = DX10OGL,
- .LODPreClampMode = 0,
- .BaseMipLevel = 0.0,
- .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipMode],
- .MagModeFilter = mag_filter,
- .MinModeFilter = min_filter,
- .TextureLODBias = pCreateInfo->mipLodBias * 256,
- .AnisotropicAlgorithm = EWAApproximation,
- .MinLOD = pCreateInfo->minLod,
- .MaxLOD = pCreateInfo->maxLod,
- .ChromaKeyEnable = 0,
- .ChromaKeyIndex = 0,
- .ChromaKeyMode = 0,
- .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
- .CubeSurfaceControlMode = 0,
-
- .IndirectStatePointer =
- device->border_colors.offset +
- pCreateInfo->borderColor * sizeof(float) * 4,
-
- .LODClampMagnificationMode = MIPNONE,
- .MaximumAnisotropy = max_anisotropy,
- .RAddressMinFilterRoundingEnable = 0,
- .RAddressMagFilterRoundingEnable = 0,
- .VAddressMinFilterRoundingEnable = 0,
- .VAddressMagFilterRoundingEnable = 0,
- .UAddressMinFilterRoundingEnable = 0,
- .UAddressMagFilterRoundingEnable = 0,
- .TrilinearFilterQuality = 0,
- .NonnormalizedCoordinateEnable = 0,
- .TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressU],
- .TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressV],
- .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressW],
- };
-
- GEN8_SAMPLER_STATE_pack(NULL, sampler->state, &sampler_state);
-
- *pSampler = anv_sampler_to_handle(sampler);
-
- return VK_SUCCESS;
-}
-
-static void
-emit_vertex_input(struct anv_pipeline *pipeline,
- const VkPipelineVertexInputStateCreateInfo *info)
-{
- const uint32_t num_dwords = 1 + info->attributeCount * 2;
- uint32_t *p;
- bool instancing_enable[32];
-
- pipeline->vb_used = 0;
- for (uint32_t i = 0; i < info->bindingCount; i++) {
- const VkVertexInputBindingDescription *desc =
- &info->pVertexBindingDescriptions[i];
-
- pipeline->vb_used |= 1 << desc->binding;
- pipeline->binding_stride[desc->binding] = desc->strideInBytes;
-
- /* Step rate is programmed per vertex element (attribute), not
- * binding. Set up a map of which bindings step per instance, for
- * reference by vertex element setup. */
- switch (desc->stepRate) {
- default:
- case VK_VERTEX_INPUT_STEP_RATE_VERTEX:
- instancing_enable[desc->binding] = false;
- break;
- case VK_VERTEX_INPUT_STEP_RATE_INSTANCE:
- instancing_enable[desc->binding] = true;
- break;
- }
- }
-
- p = anv_batch_emitn(&pipeline->batch, num_dwords,
- GEN8_3DSTATE_VERTEX_ELEMENTS);
-
- for (uint32_t i = 0; i < info->attributeCount; i++) {
- const VkVertexInputAttributeDescription *desc =
- &info->pVertexAttributeDescriptions[i];
- const struct anv_format *format = anv_format_for_vk_format(desc->format);
-
- struct GEN8_VERTEX_ELEMENT_STATE element = {
- .VertexBufferIndex = desc->binding,
- .Valid = true,
- .SourceElementFormat = format->surface_format,
- .EdgeFlagEnable = false,
- .SourceElementOffset = desc->offsetInBytes,
- .Component0Control = VFCOMP_STORE_SRC,
- .Component1Control = format->num_channels >= 2 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
- .Component2Control = format->num_channels >= 3 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
- .Component3Control = format->num_channels >= 4 ? VFCOMP_STORE_SRC : VFCOMP_STORE_1_FP
- };
- GEN8_VERTEX_ELEMENT_STATE_pack(NULL, &p[1 + i * 2], &element);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_INSTANCING,
- .InstancingEnable = instancing_enable[desc->binding],
- .VertexElementIndex = i,
- /* Vulkan so far doesn't have an instance divisor, so
- * this is always 1 (ignored if not instancing). */
- .InstanceDataStepRate = 1);
- }
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_SGVS,
- .VertexIDEnable = pipeline->vs_prog_data.uses_vertexid,
- .VertexIDComponentNumber = 2,
- .VertexIDElementOffset = info->bindingCount,
- .InstanceIDEnable = pipeline->vs_prog_data.uses_instanceid,
- .InstanceIDComponentNumber = 3,
- .InstanceIDElementOffset = info->bindingCount);
-}
-
-static void
-emit_ia_state(struct anv_pipeline *pipeline,
- const VkPipelineInputAssemblyStateCreateInfo *info,
- const struct anv_graphics_pipeline_create_info *extra)
-{
- static const uint32_t vk_to_gen_primitive_type[] = {
- [VK_PRIMITIVE_TOPOLOGY_POINT_LIST] = _3DPRIM_POINTLIST,
- [VK_PRIMITIVE_TOPOLOGY_LINE_LIST] = _3DPRIM_LINELIST,
- [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP] = _3DPRIM_LINESTRIP,
- [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = _3DPRIM_TRILIST,
- [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = _3DPRIM_TRISTRIP,
- [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN] = _3DPRIM_TRIFAN,
- [VK_PRIMITIVE_TOPOLOGY_LINE_LIST_ADJ] = _3DPRIM_LINELIST_ADJ,
- [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_ADJ] = _3DPRIM_LINESTRIP_ADJ,
- [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_ADJ] = _3DPRIM_TRILIST_ADJ,
- [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_ADJ] = _3DPRIM_TRISTRIP_ADJ,
- [VK_PRIMITIVE_TOPOLOGY_PATCH] = _3DPRIM_PATCHLIST_1
- };
- uint32_t topology = vk_to_gen_primitive_type[info->topology];
-
- if (extra && extra->use_rectlist)
- topology = _3DPRIM_RECTLIST;
-
- struct GEN8_3DSTATE_VF vf = {
- GEN8_3DSTATE_VF_header,
- .IndexedDrawCutIndexEnable = info->primitiveRestartEnable,
- };
- GEN8_3DSTATE_VF_pack(NULL, pipeline->state_vf, &vf);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_TOPOLOGY,
- .PrimitiveTopologyType = topology);
-}
-
-static void
-emit_rs_state(struct anv_pipeline *pipeline,
- const VkPipelineRasterStateCreateInfo *info,
- const struct anv_graphics_pipeline_create_info *extra)
-{
- static const uint32_t vk_to_gen_cullmode[] = {
- [VK_CULL_MODE_NONE] = CULLMODE_NONE,
- [VK_CULL_MODE_FRONT] = CULLMODE_FRONT,
- [VK_CULL_MODE_BACK] = CULLMODE_BACK,
- [VK_CULL_MODE_FRONT_AND_BACK] = CULLMODE_BOTH
- };
-
- static const uint32_t vk_to_gen_fillmode[] = {
- [VK_FILL_MODE_POINTS] = RASTER_POINT,
- [VK_FILL_MODE_WIREFRAME] = RASTER_WIREFRAME,
- [VK_FILL_MODE_SOLID] = RASTER_SOLID
- };
-
- static const uint32_t vk_to_gen_front_face[] = {
- [VK_FRONT_FACE_CCW] = CounterClockwise,
- [VK_FRONT_FACE_CW] = Clockwise
- };
-
- struct GEN8_3DSTATE_SF sf = {
- GEN8_3DSTATE_SF_header,
- .ViewportTransformEnable = !(extra && extra->disable_viewport),
- .TriangleStripListProvokingVertexSelect = 0,
- .LineStripListProvokingVertexSelect = 0,
- .TriangleFanProvokingVertexSelect = 0,
- .PointWidthSource = pipeline->writes_point_size ? Vertex : State,
- .PointWidth = 1.0,
- };
-
- /* FINISHME: VkBool32 rasterizerDiscardEnable; */
-
- GEN8_3DSTATE_SF_pack(NULL, pipeline->state_sf, &sf);
-
- struct GEN8_3DSTATE_RASTER raster = {
- GEN8_3DSTATE_RASTER_header,
- .FrontWinding = vk_to_gen_front_face[info->frontFace],
- .CullMode = vk_to_gen_cullmode[info->cullMode],
- .FrontFaceFillMode = vk_to_gen_fillmode[info->fillMode],
- .BackFaceFillMode = vk_to_gen_fillmode[info->fillMode],
- .ScissorRectangleEnable = !(extra && extra->disable_scissor),
- .ViewportZClipTestEnable = info->depthClipEnable
- };
-
- GEN8_3DSTATE_RASTER_pack(NULL, pipeline->state_raster, &raster);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE,
- .ForceVertexURBEntryReadLength = false,
- .ForceVertexURBEntryReadOffset = false,
- .PointSpriteTextureCoordinateOrigin = UPPERLEFT,
- .NumberofSFOutputAttributes =
- pipeline->wm_prog_data.num_varying_inputs);
-
-}
-
-static void
-emit_cb_state(struct anv_pipeline *pipeline,
- const VkPipelineColorBlendStateCreateInfo *info)
-{
- struct anv_device *device = pipeline->device;
-
- static const uint32_t vk_to_gen_logic_op[] = {
- [VK_LOGIC_OP_COPY] = LOGICOP_COPY,
- [VK_LOGIC_OP_CLEAR] = LOGICOP_CLEAR,
- [VK_LOGIC_OP_AND] = LOGICOP_AND,
- [VK_LOGIC_OP_AND_REVERSE] = LOGICOP_AND_REVERSE,
- [VK_LOGIC_OP_AND_INVERTED] = LOGICOP_AND_INVERTED,
- [VK_LOGIC_OP_NOOP] = LOGICOP_NOOP,
- [VK_LOGIC_OP_XOR] = LOGICOP_XOR,
- [VK_LOGIC_OP_OR] = LOGICOP_OR,
- [VK_LOGIC_OP_NOR] = LOGICOP_NOR,
- [VK_LOGIC_OP_EQUIV] = LOGICOP_EQUIV,
- [VK_LOGIC_OP_INVERT] = LOGICOP_INVERT,
- [VK_LOGIC_OP_OR_REVERSE] = LOGICOP_OR_REVERSE,
- [VK_LOGIC_OP_COPY_INVERTED] = LOGICOP_COPY_INVERTED,
- [VK_LOGIC_OP_OR_INVERTED] = LOGICOP_OR_INVERTED,
- [VK_LOGIC_OP_NAND] = LOGICOP_NAND,
- [VK_LOGIC_OP_SET] = LOGICOP_SET,
- };
-
- static const uint32_t vk_to_gen_blend[] = {
- [VK_BLEND_ZERO] = BLENDFACTOR_ZERO,
- [VK_BLEND_ONE] = BLENDFACTOR_ONE,
- [VK_BLEND_SRC_COLOR] = BLENDFACTOR_SRC_COLOR,
- [VK_BLEND_ONE_MINUS_SRC_COLOR] = BLENDFACTOR_INV_SRC_COLOR,
- [VK_BLEND_DEST_COLOR] = BLENDFACTOR_DST_COLOR,
- [VK_BLEND_ONE_MINUS_DEST_COLOR] = BLENDFACTOR_INV_DST_COLOR,
- [VK_BLEND_SRC_ALPHA] = BLENDFACTOR_SRC_ALPHA,
- [VK_BLEND_ONE_MINUS_SRC_ALPHA] = BLENDFACTOR_INV_SRC_ALPHA,
- [VK_BLEND_DEST_ALPHA] = BLENDFACTOR_DST_ALPHA,
- [VK_BLEND_ONE_MINUS_DEST_ALPHA] = BLENDFACTOR_INV_DST_ALPHA,
- [VK_BLEND_CONSTANT_COLOR] = BLENDFACTOR_CONST_COLOR,
- [VK_BLEND_ONE_MINUS_CONSTANT_COLOR] = BLENDFACTOR_INV_CONST_COLOR,
- [VK_BLEND_CONSTANT_ALPHA] = BLENDFACTOR_CONST_ALPHA,
- [VK_BLEND_ONE_MINUS_CONSTANT_ALPHA] = BLENDFACTOR_INV_CONST_ALPHA,
- [VK_BLEND_SRC_ALPHA_SATURATE] = BLENDFACTOR_SRC_ALPHA_SATURATE,
- [VK_BLEND_SRC1_COLOR] = BLENDFACTOR_SRC1_COLOR,
- [VK_BLEND_ONE_MINUS_SRC1_COLOR] = BLENDFACTOR_INV_SRC1_COLOR,
- [VK_BLEND_SRC1_ALPHA] = BLENDFACTOR_SRC1_ALPHA,
- [VK_BLEND_ONE_MINUS_SRC1_ALPHA] = BLENDFACTOR_INV_SRC1_ALPHA,
- };
-
- static const uint32_t vk_to_gen_blend_op[] = {
- [VK_BLEND_OP_ADD] = BLENDFUNCTION_ADD,
- [VK_BLEND_OP_SUBTRACT] = BLENDFUNCTION_SUBTRACT,
- [VK_BLEND_OP_REVERSE_SUBTRACT] = BLENDFUNCTION_REVERSE_SUBTRACT,
- [VK_BLEND_OP_MIN] = BLENDFUNCTION_MIN,
- [VK_BLEND_OP_MAX] = BLENDFUNCTION_MAX,
- };
-
- uint32_t num_dwords = GEN8_BLEND_STATE_length;
- pipeline->blend_state =
- anv_state_pool_alloc(&device->dynamic_state_pool, num_dwords * 4, 64);
-
- struct GEN8_BLEND_STATE blend_state = {
- .AlphaToCoverageEnable = info->alphaToCoverageEnable,
- };
-
- for (uint32_t i = 0; i < info->attachmentCount; i++) {
- const VkPipelineColorBlendAttachmentState *a = &info->pAttachments[i];
-
- blend_state.Entry[i] = (struct GEN8_BLEND_STATE_ENTRY) {
- .LogicOpEnable = info->logicOpEnable,
- .LogicOpFunction = vk_to_gen_logic_op[info->logicOp],
- .ColorBufferBlendEnable = a->blendEnable,
- .PreBlendSourceOnlyClampEnable = false,
- .PreBlendColorClampEnable = false,
- .PostBlendColorClampEnable = false,
- .SourceBlendFactor = vk_to_gen_blend[a->srcBlendColor],
- .DestinationBlendFactor = vk_to_gen_blend[a->destBlendColor],
- .ColorBlendFunction = vk_to_gen_blend_op[a->blendOpColor],
- .SourceAlphaBlendFactor = vk_to_gen_blend[a->srcBlendAlpha],
- .DestinationAlphaBlendFactor = vk_to_gen_blend[a->destBlendAlpha],
- .AlphaBlendFunction = vk_to_gen_blend_op[a->blendOpAlpha],
- .WriteDisableAlpha = !(a->channelWriteMask & VK_CHANNEL_A_BIT),
- .WriteDisableRed = !(a->channelWriteMask & VK_CHANNEL_R_BIT),
- .WriteDisableGreen = !(a->channelWriteMask & VK_CHANNEL_G_BIT),
- .WriteDisableBlue = !(a->channelWriteMask & VK_CHANNEL_B_BIT),
- };
- }
-
- GEN8_BLEND_STATE_pack(NULL, pipeline->blend_state.map, &blend_state);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_BLEND_STATE_POINTERS,
- .BlendStatePointer = pipeline->blend_state.offset,
- .BlendStatePointerValid = true);
-}
-
-static const uint32_t vk_to_gen_compare_op[] = {
- [VK_COMPARE_OP_NEVER] = COMPAREFUNCTION_NEVER,
- [VK_COMPARE_OP_LESS] = COMPAREFUNCTION_LESS,
- [VK_COMPARE_OP_EQUAL] = COMPAREFUNCTION_EQUAL,
- [VK_COMPARE_OP_LESS_EQUAL] = COMPAREFUNCTION_LEQUAL,
- [VK_COMPARE_OP_GREATER] = COMPAREFUNCTION_GREATER,
- [VK_COMPARE_OP_NOT_EQUAL] = COMPAREFUNCTION_NOTEQUAL,
- [VK_COMPARE_OP_GREATER_EQUAL] = COMPAREFUNCTION_GEQUAL,
- [VK_COMPARE_OP_ALWAYS] = COMPAREFUNCTION_ALWAYS,
-};
-
-static const uint32_t vk_to_gen_stencil_op[] = {
- [VK_STENCIL_OP_KEEP] = 0,
- [VK_STENCIL_OP_ZERO] = 0,
- [VK_STENCIL_OP_REPLACE] = 0,
- [VK_STENCIL_OP_INC_CLAMP] = 0,
- [VK_STENCIL_OP_DEC_CLAMP] = 0,
- [VK_STENCIL_OP_INVERT] = 0,
- [VK_STENCIL_OP_INC_WRAP] = 0,
- [VK_STENCIL_OP_DEC_WRAP] = 0
-};
-
-static void
-emit_ds_state(struct anv_pipeline *pipeline,
- const VkPipelineDepthStencilStateCreateInfo *info)
-{
- if (info == NULL) {
- /* We're going to OR this together with the dynamic state. We need
- * to make sure it's initialized to something useful.
- */
- memset(pipeline->state_wm_depth_stencil, 0,
- sizeof(pipeline->state_wm_depth_stencil));
- return;
- }
-
- /* VkBool32 depthBoundsEnable; // optional (depth_bounds_test) */
-
- struct GEN8_3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil = {
- .DepthTestEnable = info->depthTestEnable,
- .DepthBufferWriteEnable = info->depthWriteEnable,
- .DepthTestFunction = vk_to_gen_compare_op[info->depthCompareOp],
- .DoubleSidedStencilEnable = true,
-
- .StencilTestEnable = info->stencilTestEnable,
- .StencilFailOp = vk_to_gen_stencil_op[info->front.stencilFailOp],
- .StencilPassDepthPassOp = vk_to_gen_stencil_op[info->front.stencilPassOp],
- .StencilPassDepthFailOp = vk_to_gen_stencil_op[info->front.stencilDepthFailOp],
- .StencilTestFunction = vk_to_gen_compare_op[info->front.stencilCompareOp],
- .BackfaceStencilFailOp = vk_to_gen_stencil_op[info->back.stencilFailOp],
- .BackfaceStencilPassDepthPassOp = vk_to_gen_stencil_op[info->back.stencilPassOp],
- .BackfaceStencilPassDepthFailOp =vk_to_gen_stencil_op[info->back.stencilDepthFailOp],
- .BackfaceStencilTestFunction = vk_to_gen_compare_op[info->back.stencilCompareOp],
- };
-
- GEN8_3DSTATE_WM_DEPTH_STENCIL_pack(NULL, pipeline->state_wm_depth_stencil, &wm_depth_stencil);
-}
-
-VkResult
-gen8_graphics_pipeline_create(
- VkDevice _device,
- const VkGraphicsPipelineCreateInfo* pCreateInfo,
- const struct anv_graphics_pipeline_create_info *extra,
- VkPipeline* pPipeline)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_pipeline *pipeline;
- VkResult result;
- uint32_t offset, length;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
-
- pipeline = anv_device_alloc(device, sizeof(*pipeline), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (pipeline == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- pipeline->device = device;
- pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
- memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
-
- result = anv_reloc_list_init(&pipeline->batch_relocs, device);
- if (result != VK_SUCCESS) {
- anv_device_free(device, pipeline);
- return result;
- }
- pipeline->batch.next = pipeline->batch.start = pipeline->batch_data;
- pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data);
- pipeline->batch.relocs = &pipeline->batch_relocs;
-
- anv_state_stream_init(&pipeline->program_stream,
- &device->instruction_block_pool);
-
- for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
- pipeline->shaders[pCreateInfo->pStages[i].stage] =
- anv_shader_from_handle(pCreateInfo->pStages[i].shader);
- }
-
- if (pCreateInfo->pTessellationState)
- anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO");
- if (pCreateInfo->pViewportState)
- anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO");
- if (pCreateInfo->pMultisampleState)
- anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO");
-
- pipeline->use_repclear = extra && extra->use_repclear;
-
- anv_compiler_run(device->compiler, pipeline);
-
- /* FIXME: The compiler dead-codes FS inputs when we don't have a VS, so we
- * hard code this to num_attributes - 2. This is because the attributes
- * include VUE header and position, which aren't counted as varying
- * inputs. */
- if (pipeline->vs_simd8 == NO_KERNEL) {
- pipeline->wm_prog_data.num_varying_inputs =
- pCreateInfo->pVertexInputState->attributeCount - 2;
- }
-
- assert(pCreateInfo->pVertexInputState);
- emit_vertex_input(pipeline, pCreateInfo->pVertexInputState);
- assert(pCreateInfo->pInputAssemblyState);
- emit_ia_state(pipeline, pCreateInfo->pInputAssemblyState, extra);
- assert(pCreateInfo->pRasterState);
- emit_rs_state(pipeline, pCreateInfo->pRasterState, extra);
- emit_ds_state(pipeline, pCreateInfo->pDepthStencilState);
- emit_cb_state(pipeline, pCreateInfo->pColorBlendState);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_STATISTICS,
- .StatisticsEnable = true);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_HS, .Enable = false);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_TE, .TEEnable = false);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_DS, .FunctionEnable = false);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_STREAMOUT, .SOFunctionEnable = false);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_VS,
- .ConstantBufferOffset = 0,
- .ConstantBufferSize = 4);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_GS,
- .ConstantBufferOffset = 4,
- .ConstantBufferSize = 4);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_PS,
- .ConstantBufferOffset = 8,
- .ConstantBufferSize = 4);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM_CHROMAKEY,
- .ChromaKeyKillEnable = false);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE_SWIZ);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_AA_LINE_PARAMETERS);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_CLIP,
- .ClipEnable = true,
- .ViewportXYClipTestEnable = !(extra && extra->disable_viewport),
- .MinimumPointWidth = 0.125,
- .MaximumPointWidth = 255.875);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM,
- .StatisticsEnable = true,
- .LineEndCapAntialiasingRegionWidth = _05pixels,
- .LineAntialiasingRegionWidth = _10pixels,
- .EarlyDepthStencilControl = NORMAL,
- .ForceThreadDispatchEnable = NORMAL,
- .PointRasterizationRule = RASTRULE_UPPER_RIGHT,
- .BarycentricInterpolationMode =
- pipeline->wm_prog_data.barycentric_interp_modes);
-
- uint32_t samples = 1;
- uint32_t log2_samples = __builtin_ffs(samples) - 1;
- bool enable_sampling = samples > 1 ? true : false;
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_MULTISAMPLE,
- .PixelPositionOffsetEnable = enable_sampling,
- .PixelLocation = CENTER,
- .NumberofMultisamples = log2_samples);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SAMPLE_MASK,
- .SampleMask = 0xffff);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_VS,
- .VSURBStartingAddress = pipeline->urb.vs_start,
- .VSURBEntryAllocationSize = pipeline->urb.vs_size - 1,
- .VSNumberofURBEntries = pipeline->urb.nr_vs_entries);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_GS,
- .GSURBStartingAddress = pipeline->urb.gs_start,
- .GSURBEntryAllocationSize = pipeline->urb.gs_size - 1,
- .GSNumberofURBEntries = pipeline->urb.nr_gs_entries);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_HS,
- .HSURBStartingAddress = pipeline->urb.vs_start,
- .HSURBEntryAllocationSize = 0,
- .HSNumberofURBEntries = 0);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_DS,
- .DSURBStartingAddress = pipeline->urb.vs_start,
- .DSURBEntryAllocationSize = 0,
- .DSNumberofURBEntries = 0);
-
- const struct brw_gs_prog_data *gs_prog_data = &pipeline->gs_prog_data;
- offset = 1;
- length = (gs_prog_data->base.vue_map.num_slots + 1) / 2 - offset;
-
- if (pipeline->gs_vec4 == NO_KERNEL)
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS, .Enable = false);
- else
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS,
- .SingleProgramFlow = false,
- .KernelStartPointer = pipeline->gs_vec4,
- .VectorMaskEnable = Vmask,
- .SamplerCount = 0,
- .BindingTableEntryCount = 0,
- .ExpectedVertexCount = pipeline->gs_vertex_count,
-
- .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_GEOMETRY],
- .PerThreadScratchSpace = ffs(gs_prog_data->base.base.total_scratch / 2048),
-
- .OutputVertexSize = gs_prog_data->output_vertex_size_hwords * 2 - 1,
- .OutputTopology = gs_prog_data->output_topology,
- .VertexURBEntryReadLength = gs_prog_data->base.urb_read_length,
- .DispatchGRFStartRegisterForURBData =
- gs_prog_data->base.base.dispatch_grf_start_reg,
-
- .MaximumNumberofThreads = device->info.max_gs_threads,
- .ControlDataHeaderSize = gs_prog_data->control_data_header_size_hwords,
- //pipeline->gs_prog_data.dispatch_mode |
- .StatisticsEnable = true,
- .IncludePrimitiveID = gs_prog_data->include_primitive_id,
- .ReorderMode = TRAILING,
- .Enable = true,
-
- .ControlDataFormat = gs_prog_data->control_data_format,
-
- /* FIXME: mesa sets this based on ctx->Transform.ClipPlanesEnabled:
- * UserClipDistanceClipTestEnableBitmask_3DSTATE_GS(v)
- * UserClipDistanceCullTestEnableBitmask(v)
- */
-
- .VertexURBEntryOutputReadOffset = offset,
- .VertexURBEntryOutputLength = length);
-
- const struct brw_vue_prog_data *vue_prog_data = &pipeline->vs_prog_data.base;
- /* Skip the VUE header and position slots */
- offset = 1;
- length = (vue_prog_data->vue_map.num_slots + 1) / 2 - offset;
-
- if (pipeline->vs_simd8 == NO_KERNEL || (extra && extra->disable_vs))
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
- .FunctionEnable = false,
- .VertexURBEntryOutputReadOffset = 1,
- /* Even if VS is disabled, SBE still gets the amount of
- * vertex data to read from this field. We use attribute
- * count - 1, as we don't count the VUE header here. */
- .VertexURBEntryOutputLength =
- DIV_ROUND_UP(pCreateInfo->pVertexInputState->attributeCount - 1, 2));
- else
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
- .KernelStartPointer = pipeline->vs_simd8,
- .SingleVertexDispatch = Multiple,
- .VectorMaskEnable = Dmask,
- .SamplerCount = 0,
- .BindingTableEntryCount =
- vue_prog_data->base.binding_table.size_bytes / 4,
- .ThreadDispatchPriority = Normal,
- .FloatingPointMode = IEEE754,
- .IllegalOpcodeExceptionEnable = false,
- .AccessesUAV = false,
- .SoftwareExceptionEnable = false,
-
- .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_VERTEX],
- .PerThreadScratchSpace = ffs(vue_prog_data->base.total_scratch / 2048),
-
- .DispatchGRFStartRegisterForURBData =
- vue_prog_data->base.dispatch_grf_start_reg,
- .VertexURBEntryReadLength = vue_prog_data->urb_read_length,
- .VertexURBEntryReadOffset = 0,
-
- .MaximumNumberofThreads = device->info.max_vs_threads - 1,
- .StatisticsEnable = false,
- .SIMD8DispatchEnable = true,
- .VertexCacheDisable = false,
- .FunctionEnable = true,
-
- .VertexURBEntryOutputReadOffset = offset,
- .VertexURBEntryOutputLength = length,
- .UserClipDistanceClipTestEnableBitmask = 0,
- .UserClipDistanceCullTestEnableBitmask = 0);
-
- const struct brw_wm_prog_data *wm_prog_data = &pipeline->wm_prog_data;
- uint32_t ksp0, ksp2, grf_start0, grf_start2;
-
- ksp2 = 0;
- grf_start2 = 0;
- if (pipeline->ps_simd8 != NO_KERNEL) {
- ksp0 = pipeline->ps_simd8;
- grf_start0 = wm_prog_data->base.dispatch_grf_start_reg;
- if (pipeline->ps_simd16 != NO_KERNEL) {
- ksp2 = pipeline->ps_simd16;
- grf_start2 = wm_prog_data->dispatch_grf_start_reg_16;
- }
- } else if (pipeline->ps_simd16 != NO_KERNEL) {
- ksp0 = pipeline->ps_simd16;
- grf_start0 = wm_prog_data->dispatch_grf_start_reg_16;
- } else {
- unreachable("no ps shader");
- }
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS,
- .KernelStartPointer0 = ksp0,
-
- .SingleProgramFlow = false,
- .VectorMaskEnable = true,
- .SamplerCount = 1,
-
- .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
- .PerThreadScratchSpace = ffs(wm_prog_data->base.total_scratch / 2048),
-
- .MaximumNumberofThreadsPerPSD = 64 - 2,
- .PositionXYOffsetSelect = wm_prog_data->uses_pos_offset ?
- POSOFFSET_SAMPLE: POSOFFSET_NONE,
- .PushConstantEnable = wm_prog_data->base.nr_params > 0,
- ._8PixelDispatchEnable = pipeline->ps_simd8 != NO_KERNEL,
- ._16PixelDispatchEnable = pipeline->ps_simd16 != NO_KERNEL,
- ._32PixelDispatchEnable = false,
-
- .DispatchGRFStartRegisterForConstantSetupData0 = grf_start0,
- .DispatchGRFStartRegisterForConstantSetupData1 = 0,
- .DispatchGRFStartRegisterForConstantSetupData2 = grf_start2,
-
- .KernelStartPointer1 = 0,
- .KernelStartPointer2 = ksp2);
-
- bool per_sample_ps = false;
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS_EXTRA,
- .PixelShaderValid = true,
- .PixelShaderKillsPixel = wm_prog_data->uses_kill,
- .PixelShaderComputedDepthMode = wm_prog_data->computed_depth_mode,
- .AttributeEnable = wm_prog_data->num_varying_inputs > 0,
- .oMaskPresenttoRenderTarget = wm_prog_data->uses_omask,
- .PixelShaderIsPerSample = per_sample_ps);
-
- *pPipeline = anv_pipeline_to_handle(pipeline);
-
- return VK_SUCCESS;
-}
-
-VkResult gen8_compute_pipeline_create(
- VkDevice _device,
- const VkComputePipelineCreateInfo* pCreateInfo,
- VkPipeline* pPipeline)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_pipeline *pipeline;
- VkResult result;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
-
- pipeline = anv_device_alloc(device, sizeof(*pipeline), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (pipeline == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- pipeline->device = device;
- pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
-
- result = anv_reloc_list_init(&pipeline->batch_relocs, device);
- if (result != VK_SUCCESS) {
- anv_device_free(device, pipeline);
- return result;
- }
- pipeline->batch.next = pipeline->batch.start = pipeline->batch_data;
- pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data);
- pipeline->batch.relocs = &pipeline->batch_relocs;
-
- anv_state_stream_init(&pipeline->program_stream,
- &device->instruction_block_pool);
-
- memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
-
- pipeline->shaders[VK_SHADER_STAGE_COMPUTE] =
- anv_shader_from_handle(pCreateInfo->cs.shader);
-
- pipeline->use_repclear = false;
-
- anv_compiler_run(device->compiler, pipeline);
-
- const struct brw_cs_prog_data *cs_prog_data = &pipeline->cs_prog_data;
-
- anv_batch_emit(&pipeline->batch, GEN8_MEDIA_VFE_STATE,
- .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
- .PerThreadScratchSpace = ffs(cs_prog_data->base.total_scratch / 2048),
- .ScratchSpaceBasePointerHigh = 0,
- .StackSize = 0,
-
- .MaximumNumberofThreads = device->info.max_cs_threads - 1,
- .NumberofURBEntries = 2,
- .ResetGatewayTimer = true,
- .BypassGatewayControl = true,
- .URBEntryAllocationSize = 2,
- .CURBEAllocationSize = 0);
-
- struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
- uint32_t group_size = prog_data->local_size[0] *
- prog_data->local_size[1] * prog_data->local_size[2];
- pipeline->cs_thread_width_max = DIV_ROUND_UP(group_size, prog_data->simd_size);
- uint32_t remainder = group_size & (prog_data->simd_size - 1);
-
- if (remainder > 0)
- pipeline->cs_right_mask = ~0u >> (32 - remainder);
- else
- pipeline->cs_right_mask = ~0u >> (32 - prog_data->simd_size);
-
-
- *pPipeline = anv_pipeline_to_handle(pipeline);
-
- return VK_SUCCESS;
-}
-
-VkResult gen8_CreateDynamicDepthStencilState(
- VkDevice _device,
- const VkDynamicDepthStencilStateCreateInfo* pCreateInfo,
- VkDynamicDepthStencilState* pState)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_dynamic_ds_state *state;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_DEPTH_STENCIL_STATE_CREATE_INFO);
-
- state = anv_device_alloc(device, sizeof(*state), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (state == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- struct GEN8_3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil = {
- GEN8_3DSTATE_WM_DEPTH_STENCIL_header,
-
- /* Is this what we need to do? */
- .StencilBufferWriteEnable = pCreateInfo->stencilWriteMask != 0,
-
- .StencilTestMask = pCreateInfo->stencilReadMask & 0xff,
- .StencilWriteMask = pCreateInfo->stencilWriteMask & 0xff,
-
- .BackfaceStencilTestMask = pCreateInfo->stencilReadMask & 0xff,
- .BackfaceStencilWriteMask = pCreateInfo->stencilWriteMask & 0xff,
- };
-
- GEN8_3DSTATE_WM_DEPTH_STENCIL_pack(NULL, state->state_wm_depth_stencil,
- &wm_depth_stencil);
-
- struct GEN8_COLOR_CALC_STATE color_calc_state = {
- .StencilReferenceValue = pCreateInfo->stencilFrontRef,
- .BackFaceStencilReferenceValue = pCreateInfo->stencilBackRef
- };
-
- GEN8_COLOR_CALC_STATE_pack(NULL, state->state_color_calc, &color_calc_state);
-
- *pState = anv_dynamic_ds_state_to_handle(state);
-
- return VK_SUCCESS;
-}
-
-static void
-emit_ps_depth_count(struct anv_batch *batch,
- struct anv_bo *bo, uint32_t offset)
-{
- anv_batch_emit(batch, GEN8_PIPE_CONTROL,
- .DestinationAddressType = DAT_PPGTT,
- .PostSyncOperation = WritePSDepthCount,
- .Address = { bo, offset }); /* FIXME: This is only lower 32 bits */
-}
-
-void gen8_CmdBeginQuery(
- VkCmdBuffer cmdBuffer,
- VkQueryPool queryPool,
- uint32_t slot,
- VkQueryControlFlags flags)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
-
- switch (pool->type) {
- case VK_QUERY_TYPE_OCCLUSION:
- emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
- slot * sizeof(struct anv_query_pool_slot));
- break;
-
- case VK_QUERY_TYPE_PIPELINE_STATISTICS:
- default:
- unreachable("");
- }
-}
-
-void gen8_CmdEndQuery(
- VkCmdBuffer cmdBuffer,
- VkQueryPool queryPool,
- uint32_t slot)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
-
- switch (pool->type) {
- case VK_QUERY_TYPE_OCCLUSION:
- emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
- slot * sizeof(struct anv_query_pool_slot) + 8);
- break;
-
- case VK_QUERY_TYPE_PIPELINE_STATISTICS:
- default:
- unreachable("");
- }
-}
-
-#define TIMESTAMP 0x2358
-
-void gen8_CmdWriteTimestamp(
- VkCmdBuffer cmdBuffer,
- VkTimestampType timestampType,
- VkBuffer destBuffer,
- VkDeviceSize destOffset)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
- struct anv_bo *bo = buffer->bo;
-
- switch (timestampType) {
- case VK_TIMESTAMP_TYPE_TOP:
- anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
- .RegisterAddress = TIMESTAMP,
- .MemoryAddress = { bo, buffer->offset + destOffset });
- anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
- .RegisterAddress = TIMESTAMP + 4,
- .MemoryAddress = { bo, buffer->offset + destOffset + 4 });
- break;
-
- case VK_TIMESTAMP_TYPE_BOTTOM:
- anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
- .DestinationAddressType = DAT_PPGTT,
- .PostSyncOperation = WriteTimestamp,
- .Address = /* FIXME: This is only lower 32 bits */
- { bo, buffer->offset + destOffset });
- break;
-
- default:
- break;
- }
-}
-
-#define alu_opcode(v) __gen_field((v), 20, 31)
-#define alu_operand1(v) __gen_field((v), 10, 19)
-#define alu_operand2(v) __gen_field((v), 0, 9)
-#define alu(opcode, operand1, operand2) \
- alu_opcode(opcode) | alu_operand1(operand1) | alu_operand2(operand2)
-
-#define OPCODE_NOOP 0x000
-#define OPCODE_LOAD 0x080
-#define OPCODE_LOADINV 0x480
-#define OPCODE_LOAD0 0x081
-#define OPCODE_LOAD1 0x481
-#define OPCODE_ADD 0x100
-#define OPCODE_SUB 0x101
-#define OPCODE_AND 0x102
-#define OPCODE_OR 0x103
-#define OPCODE_XOR 0x104
-#define OPCODE_STORE 0x180
-#define OPCODE_STOREINV 0x580
-
-#define OPERAND_R0 0x00
-#define OPERAND_R1 0x01
-#define OPERAND_R2 0x02
-#define OPERAND_R3 0x03
-#define OPERAND_R4 0x04
-#define OPERAND_SRCA 0x20
-#define OPERAND_SRCB 0x21
-#define OPERAND_ACCU 0x31
-#define OPERAND_ZF 0x32
-#define OPERAND_CF 0x33
-
-#define CS_GPR(n) (0x2600 + (n) * 8)
-
-static void
-emit_load_alu_reg_u64(struct anv_batch *batch, uint32_t reg,
- struct anv_bo *bo, uint32_t offset)
-{
- anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
- .RegisterAddress = reg,
- .MemoryAddress = { bo, offset });
- anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
- .RegisterAddress = reg + 4,
- .MemoryAddress = { bo, offset + 4 });
-}
-
-void gen8_CmdCopyQueryPoolResults(
- VkCmdBuffer cmdBuffer,
- VkQueryPool queryPool,
- uint32_t startQuery,
- uint32_t queryCount,
- VkBuffer destBuffer,
- VkDeviceSize destOffset,
- VkDeviceSize destStride,
- VkQueryResultFlags flags)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
- ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
- uint32_t slot_offset, dst_offset;
-
- if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
- /* Where is the availabilty info supposed to go? */
- anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
- return;
- }
-
- assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
-
- /* FIXME: If we're not waiting, should we just do this on the CPU? */
- if (flags & VK_QUERY_RESULT_WAIT_BIT)
- anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
- .CommandStreamerStallEnable = true,
- .StallAtPixelScoreboard = true);
-
- dst_offset = buffer->offset + destOffset;
- for (uint32_t i = 0; i < queryCount; i++) {
-
- slot_offset = (startQuery + i) * sizeof(struct anv_query_pool_slot);
-
- emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(0), &pool->bo, slot_offset);
- emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(1), &pool->bo, slot_offset + 8);
-
- /* FIXME: We need to clamp the result for 32 bit. */
-
- uint32_t *dw = anv_batch_emitn(&cmd_buffer->batch, 5, GEN8_MI_MATH);
- dw[1] = alu(OPCODE_LOAD, OPERAND_SRCA, OPERAND_R1);
- dw[2] = alu(OPCODE_LOAD, OPERAND_SRCB, OPERAND_R0);
- dw[3] = alu(OPCODE_SUB, 0, 0);
- dw[4] = alu(OPCODE_STORE, OPERAND_R2, OPERAND_ACCU);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
- .RegisterAddress = CS_GPR(2),
- /* FIXME: This is only lower 32 bits */
- .MemoryAddress = { buffer->bo, dst_offset });
-
- if (flags & VK_QUERY_RESULT_64_BIT)
- anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
- .RegisterAddress = CS_GPR(2) + 4,
- /* FIXME: This is only lower 32 bits */
- .MemoryAddress = { buffer->bo, dst_offset + 4 });
-
- dst_offset += destStride;
- }
-}
-
-void
-gen8_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer)
-{
- struct anv_device *device = cmd_buffer->device;
- struct anv_bo *scratch_bo = NULL;
-
- cmd_buffer->state.scratch_size =
- anv_block_pool_size(&device->scratch_block_pool);
- if (cmd_buffer->state.scratch_size > 0)
- scratch_bo = &device->scratch_block_pool.bo;
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_STATE_BASE_ADDRESS,
- .GeneralStateBaseAddress = { scratch_bo, 0 },
- .GeneralStateMemoryObjectControlState = GEN8_MOCS,
- .GeneralStateBaseAddressModifyEnable = true,
- .GeneralStateBufferSize = 0xfffff,
- .GeneralStateBufferSizeModifyEnable = true,
-
- .SurfaceStateBaseAddress = { anv_cmd_buffer_current_surface_bo(cmd_buffer), 0 },
- .SurfaceStateMemoryObjectControlState = GEN8_MOCS,
- .SurfaceStateBaseAddressModifyEnable = true,
-
- .DynamicStateBaseAddress = { &device->dynamic_state_block_pool.bo, 0 },
- .DynamicStateMemoryObjectControlState = GEN8_MOCS,
- .DynamicStateBaseAddressModifyEnable = true,
- .DynamicStateBufferSize = 0xfffff,
- .DynamicStateBufferSizeModifyEnable = true,
-
- .IndirectObjectBaseAddress = { NULL, 0 },
- .IndirectObjectMemoryObjectControlState = GEN8_MOCS,
- .IndirectObjectBaseAddressModifyEnable = true,
- .IndirectObjectBufferSize = 0xfffff,
- .IndirectObjectBufferSizeModifyEnable = true,
-
- .InstructionBaseAddress = { &device->instruction_block_pool.bo, 0 },
- .InstructionMemoryObjectControlState = GEN8_MOCS,
- .InstructionBaseAddressModifyEnable = true,
- .InstructionBufferSize = 0xfffff,
- .InstructionBuffersizeModifyEnable = true);
-
- /* After re-setting the surface state base address, we have to do some
- * cache flusing so that the sampler engine will pick up the new
- * SURFACE_STATE objects and binding tables. From the Broadwell PRM,
- * Shared Function > 3D Sampler > State > State Caching (page 96):
- *
- * Coherency with system memory in the state cache, like the texture
- * cache is handled partially by software. It is expected that the
- * command stream or shader will issue Cache Flush operation or
- * Cache_Flush sampler message to ensure that the L1 cache remains
- * coherent with system memory.
- *
- * [...]
- *
- * Whenever the value of the Dynamic_State_Base_Addr,
- * Surface_State_Base_Addr are altered, the L1 state cache must be
- * invalidated to ensure the new surface or sampler state is fetched
- * from system memory.
- *
- * The PIPE_CONTROL command has a "State Cache Invalidation Enable" bit
- * which, according the PIPE_CONTROL instruction documentation in the
- * Broadwell PRM:
- *
- * Setting this bit is independent of any other bit in this packet.
- * This bit controls the invalidation of the L1 and L2 state caches
- * at the top of the pipe i.e. at the parsing time.
- *
- * Unfortunately, experimentation seems to indicate that state cache
- * invalidation through a PIPE_CONTROL does nothing whatsoever in
- * regards to surface state and binding tables. In stead, it seems that
- * invalidating the texture cache is what is actually needed.
- *
- * XXX: As far as we have been able to determine through
- * experimentation, shows that flush the texture cache appears to be
- * sufficient. The theory here is that all of the sampling/rendering
- * units cache the binding table in the texture cache. However, we have
- * yet to be able to actually confirm this.
- */
- anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
- .TextureCacheInvalidationEnable = true);
-}
-
-void gen8_CmdBindIndexBuffer(
- VkCmdBuffer cmdBuffer,
- VkBuffer _buffer,
- VkDeviceSize offset,
- VkIndexType indexType)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
-
- static const uint32_t vk_to_gen_index_type[] = {
- [VK_INDEX_TYPE_UINT16] = INDEX_WORD,
- [VK_INDEX_TYPE_UINT32] = INDEX_DWORD,
- };
-
- struct GEN8_3DSTATE_VF vf = {
- GEN8_3DSTATE_VF_header,
- .CutIndex = (indexType == VK_INDEX_TYPE_UINT16) ? UINT16_MAX : UINT32_MAX,
- };
- GEN8_3DSTATE_VF_pack(NULL, cmd_buffer->state.state_vf, &vf);
-
- cmd_buffer->state.dirty |= ANV_CMD_BUFFER_INDEX_BUFFER_DIRTY;
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_INDEX_BUFFER,
- .IndexFormat = vk_to_gen_index_type[indexType],
- .MemoryObjectControlState = GEN8_MOCS,
- .BufferStartingAddress = { buffer->bo, buffer->offset + offset },
- .BufferSize = buffer->size - offset);
-}
anv_CmdBindDynamicColorBlendState(anv_cmd_buffer_to_handle(cmd_buffer),
device->meta_state.shared.cb_state);
- anv_CmdDraw(anv_cmd_buffer_to_handle(cmd_buffer), 0, 3, 0, num_instances);
+ driver_layer->CmdDraw(anv_cmd_buffer_to_handle(cmd_buffer), 0, 3, 0, num_instances);
}
void
.dependencyCount = 0,
}, &pass);
- anv_CmdBeginRenderPass(anv_cmd_buffer_to_handle(cmd_buffer),
+ driver_layer->CmdBeginRenderPass(anv_cmd_buffer_to_handle(cmd_buffer),
&(VkRenderPassBeginInfo) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = pass,
device->meta_state.blit.pipeline_layout, 0, 1,
&set, 0, NULL);
- anv_CmdDraw(anv_cmd_buffer_to_handle(cmd_buffer), 0, 3, 0, 1);
+ driver_layer->CmdDraw(anv_cmd_buffer_to_handle(cmd_buffer), 0, 3, 0, 1);
- anv_CmdEndRenderPass(anv_cmd_buffer_to_handle(cmd_buffer));
+ driver_layer->CmdEndRenderPass(anv_cmd_buffer_to_handle(cmd_buffer));
/* At the point where we emit the draw call, all data from the
* descriptor sets, etc. has been used. We are free to delete it.
.dependencyCount = 0,
}, &pass);
- anv_CmdBeginRenderPass(anv_cmd_buffer_to_handle(cmd_buffer),
+ driver_layer->CmdBeginRenderPass(anv_cmd_buffer_to_handle(cmd_buffer),
&(VkRenderPassBeginInfo) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderArea = {
meta_emit_clear(cmd_buffer, 1, &instance_data,
(VkClearDepthStencilValue) {0});
- anv_CmdEndRenderPass(anv_cmd_buffer_to_handle(cmd_buffer));
+ driver_layer->CmdEndRenderPass(anv_cmd_buffer_to_handle(cmd_buffer));
}
}
}
struct anv_cmd_buffer *secondary);
void anv_cmd_buffer_prepare_execbuf(struct anv_cmd_buffer *cmd_buffer);
+VkResult anv_cmd_buffer_emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
+ unsigned stage, struct anv_state *bt_state);
+VkResult anv_cmd_buffer_emit_samplers(struct anv_cmd_buffer *cmd_buffer,
+ unsigned stage, struct anv_state *state);
+void anv_flush_descriptor_sets(struct anv_cmd_buffer *cmd_buffer);
+
+struct anv_state anv_cmd_buffer_emit_dynamic(struct anv_cmd_buffer *cmd_buffer,
+ uint32_t *a, uint32_t dwords,
+ uint32_t alignment);
+struct anv_state anv_cmd_buffer_merge_dynamic(struct anv_cmd_buffer *cmd_buffer,
+ uint32_t *a, uint32_t *b,
+ uint32_t dwords, uint32_t alignment);
+void anv_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_subpass *subpass);
+
struct anv_bo *
anv_cmd_buffer_current_surface_bo(struct anv_cmd_buffer *cmd_buffer);
struct anv_reloc_list *
VkResult anv_cmd_buffer_new_surface_state_bo(struct anv_cmd_buffer *cmd_buffer);
+void gen8_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer);
+
void anv_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer);
-void gen8_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer);
+void gen8_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_subpass *subpass);
void anv_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
struct anv_subpass *subpass);
--- /dev/null
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "anv_private.h"
+
+static void
+gen8_cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer)
+{
+ struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
+ uint32_t *p;
+
+ uint32_t vb_emit = cmd_buffer->state.vb_dirty & pipeline->vb_used;
+
+ assert((pipeline->active_stages & VK_SHADER_STAGE_COMPUTE_BIT) == 0);
+
+ if (cmd_buffer->state.current_pipeline != _3D) {
+ anv_batch_emit(&cmd_buffer->batch, GEN8_PIPELINE_SELECT,
+ .PipelineSelection = _3D);
+ cmd_buffer->state.current_pipeline = _3D;
+ }
+
+ if (vb_emit) {
+ const uint32_t num_buffers = __builtin_popcount(vb_emit);
+ const uint32_t num_dwords = 1 + num_buffers * 4;
+
+ p = anv_batch_emitn(&cmd_buffer->batch, num_dwords,
+ GEN8_3DSTATE_VERTEX_BUFFERS);
+ uint32_t vb, i = 0;
+ for_each_bit(vb, vb_emit) {
+ struct anv_buffer *buffer = cmd_buffer->state.vertex_bindings[vb].buffer;
+ uint32_t offset = cmd_buffer->state.vertex_bindings[vb].offset;
+
+ struct GEN8_VERTEX_BUFFER_STATE state = {
+ .VertexBufferIndex = vb,
+ .MemoryObjectControlState = GEN8_MOCS,
+ .AddressModifyEnable = true,
+ .BufferPitch = pipeline->binding_stride[vb],
+ .BufferStartingAddress = { buffer->bo, buffer->offset + offset },
+ .BufferSize = buffer->size - offset
+ };
+
+ GEN8_VERTEX_BUFFER_STATE_pack(&cmd_buffer->batch, &p[1 + i * 4], &state);
+ i++;
+ }
+ }
+
+ if (cmd_buffer->state.dirty & ANV_CMD_BUFFER_PIPELINE_DIRTY) {
+ /* If somebody compiled a pipeline after starting a command buffer the
+ * scratch bo may have grown since we started this cmd buffer (and
+ * emitted STATE_BASE_ADDRESS). If we're binding that pipeline now,
+ * reemit STATE_BASE_ADDRESS so that we use the bigger scratch bo. */
+ if (cmd_buffer->state.scratch_size < pipeline->total_scratch)
+ anv_cmd_buffer_emit_state_base_address(cmd_buffer);
+
+ anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->batch);
+ }
+
+ if (cmd_buffer->state.descriptors_dirty)
+ anv_flush_descriptor_sets(cmd_buffer);
+
+ if (cmd_buffer->state.dirty & ANV_CMD_BUFFER_VP_DIRTY) {
+ struct anv_dynamic_vp_state *vp_state = cmd_buffer->state.vp_state;
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_SCISSOR_STATE_POINTERS,
+ .ScissorRectPointer = vp_state->scissor.offset);
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_VIEWPORT_STATE_POINTERS_CC,
+ .CCViewportPointer = vp_state->cc_vp.offset);
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP,
+ .SFClipViewportPointer = vp_state->sf_clip_vp.offset);
+ }
+
+ if (cmd_buffer->state.dirty & (ANV_CMD_BUFFER_PIPELINE_DIRTY |
+ ANV_CMD_BUFFER_RS_DIRTY)) {
+ anv_batch_emit_merge(&cmd_buffer->batch,
+ cmd_buffer->state.rs_state->state_sf,
+ pipeline->state_sf);
+ anv_batch_emit_merge(&cmd_buffer->batch,
+ cmd_buffer->state.rs_state->state_raster,
+ pipeline->state_raster);
+ }
+
+ if (cmd_buffer->state.ds_state &&
+ (cmd_buffer->state.dirty & (ANV_CMD_BUFFER_PIPELINE_DIRTY |
+ ANV_CMD_BUFFER_DS_DIRTY))) {
+ anv_batch_emit_merge(&cmd_buffer->batch,
+ cmd_buffer->state.ds_state->state_wm_depth_stencil,
+ pipeline->state_wm_depth_stencil);
+ }
+
+ if (cmd_buffer->state.dirty & (ANV_CMD_BUFFER_CB_DIRTY |
+ ANV_CMD_BUFFER_DS_DIRTY)) {
+ struct anv_state state;
+ if (cmd_buffer->state.ds_state == NULL)
+ state = anv_cmd_buffer_emit_dynamic(cmd_buffer,
+ cmd_buffer->state.cb_state->state_color_calc,
+ GEN8_COLOR_CALC_STATE_length, 64);
+ else if (cmd_buffer->state.cb_state == NULL)
+ state = anv_cmd_buffer_emit_dynamic(cmd_buffer,
+ cmd_buffer->state.ds_state->state_color_calc,
+ GEN8_COLOR_CALC_STATE_length, 64);
+ else
+ state = anv_cmd_buffer_merge_dynamic(cmd_buffer,
+ cmd_buffer->state.ds_state->state_color_calc,
+ cmd_buffer->state.cb_state->state_color_calc,
+ GEN8_COLOR_CALC_STATE_length, 64);
+
+ anv_batch_emit(&cmd_buffer->batch,
+ GEN8_3DSTATE_CC_STATE_POINTERS,
+ .ColorCalcStatePointer = state.offset,
+ .ColorCalcStatePointerValid = true);
+ }
+
+ if (cmd_buffer->state.dirty & (ANV_CMD_BUFFER_PIPELINE_DIRTY |
+ ANV_CMD_BUFFER_INDEX_BUFFER_DIRTY)) {
+ anv_batch_emit_merge(&cmd_buffer->batch,
+ cmd_buffer->state.state_vf, pipeline->state_vf);
+ }
+
+ cmd_buffer->state.vb_dirty &= ~vb_emit;
+ cmd_buffer->state.dirty = 0;
+}
+
+void gen8_CmdDraw(
+ VkCmdBuffer cmdBuffer,
+ uint32_t firstVertex,
+ uint32_t vertexCount,
+ uint32_t firstInstance,
+ uint32_t instanceCount)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+
+ gen8_cmd_buffer_flush_state(cmd_buffer);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DPRIMITIVE,
+ .VertexAccessType = SEQUENTIAL,
+ .VertexCountPerInstance = vertexCount,
+ .StartVertexLocation = firstVertex,
+ .InstanceCount = instanceCount,
+ .StartInstanceLocation = firstInstance,
+ .BaseVertexLocation = 0);
+}
+
+void gen8_CmdDrawIndexed(
+ VkCmdBuffer cmdBuffer,
+ uint32_t firstIndex,
+ uint32_t indexCount,
+ int32_t vertexOffset,
+ uint32_t firstInstance,
+ uint32_t instanceCount)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+
+ gen8_cmd_buffer_flush_state(cmd_buffer);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DPRIMITIVE,
+ .VertexAccessType = RANDOM,
+ .VertexCountPerInstance = indexCount,
+ .StartVertexLocation = firstIndex,
+ .InstanceCount = instanceCount,
+ .StartInstanceLocation = firstInstance,
+ .BaseVertexLocation = vertexOffset);
+}
+
+static void
+emit_lrm(struct anv_batch *batch,
+ uint32_t reg, struct anv_bo *bo, uint32_t offset)
+{
+ anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
+ .RegisterAddress = reg,
+ .MemoryAddress = { bo, offset });
+}
+
+static void
+emit_lri(struct anv_batch *batch, uint32_t reg, uint32_t imm)
+{
+ anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_IMM,
+ .RegisterOffset = reg,
+ .DataDWord = imm);
+}
+
+/* Auto-Draw / Indirect Registers */
+#define GEN7_3DPRIM_END_OFFSET 0x2420
+#define GEN7_3DPRIM_START_VERTEX 0x2430
+#define GEN7_3DPRIM_VERTEX_COUNT 0x2434
+#define GEN7_3DPRIM_INSTANCE_COUNT 0x2438
+#define GEN7_3DPRIM_START_INSTANCE 0x243C
+#define GEN7_3DPRIM_BASE_VERTEX 0x2440
+
+void gen8_CmdDrawIndirect(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer _buffer,
+ VkDeviceSize offset,
+ uint32_t count,
+ uint32_t stride)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
+ struct anv_bo *bo = buffer->bo;
+ uint32_t bo_offset = buffer->offset + offset;
+
+ gen8_cmd_buffer_flush_state(cmd_buffer);
+
+ emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_VERTEX_COUNT, bo, bo_offset);
+ emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_INSTANCE_COUNT, bo, bo_offset + 4);
+ emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_VERTEX, bo, bo_offset + 8);
+ emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 12);
+ emit_lri(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, 0);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DPRIMITIVE,
+ .IndirectParameterEnable = true,
+ .VertexAccessType = SEQUENTIAL);
+}
+
+void gen8_CmdBindIndexBuffer(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer _buffer,
+ VkDeviceSize offset,
+ VkIndexType indexType)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
+
+ static const uint32_t vk_to_gen_index_type[] = {
+ [VK_INDEX_TYPE_UINT16] = INDEX_WORD,
+ [VK_INDEX_TYPE_UINT32] = INDEX_DWORD,
+ };
+
+ struct GEN8_3DSTATE_VF vf = {
+ GEN8_3DSTATE_VF_header,
+ .CutIndex = (indexType == VK_INDEX_TYPE_UINT16) ? UINT16_MAX : UINT32_MAX,
+ };
+ GEN8_3DSTATE_VF_pack(NULL, cmd_buffer->state.state_vf, &vf);
+
+ cmd_buffer->state.dirty |= ANV_CMD_BUFFER_INDEX_BUFFER_DIRTY;
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_INDEX_BUFFER,
+ .IndexFormat = vk_to_gen_index_type[indexType],
+ .MemoryObjectControlState = GEN8_MOCS,
+ .BufferStartingAddress = { buffer->bo, buffer->offset + offset },
+ .BufferSize = buffer->size - offset);
+}
+
+static VkResult
+gen8_flush_compute_descriptor_set(struct anv_cmd_buffer *cmd_buffer)
+{
+ struct anv_device *device = cmd_buffer->device;
+ struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
+ struct anv_state surfaces = { 0, }, samplers = { 0, };
+ VkResult result;
+
+ result = anv_cmd_buffer_emit_samplers(cmd_buffer,
+ VK_SHADER_STAGE_COMPUTE, &samplers);
+ if (result != VK_SUCCESS)
+ return result;
+ result = anv_cmd_buffer_emit_binding_table(cmd_buffer,
+ VK_SHADER_STAGE_COMPUTE, &surfaces);
+ if (result != VK_SUCCESS)
+ return result;
+
+ struct GEN8_INTERFACE_DESCRIPTOR_DATA desc = {
+ .KernelStartPointer = pipeline->cs_simd,
+ .KernelStartPointerHigh = 0,
+ .BindingTablePointer = surfaces.offset,
+ .BindingTableEntryCount = 0,
+ .SamplerStatePointer = samplers.offset,
+ .SamplerCount = 0,
+ .NumberofThreadsinGPGPUThreadGroup = 0 /* FIXME: Really? */
+ };
+
+ uint32_t size = GEN8_INTERFACE_DESCRIPTOR_DATA_length * sizeof(uint32_t);
+ struct anv_state state =
+ anv_state_pool_alloc(&device->dynamic_state_pool, size, 64);
+
+ GEN8_INTERFACE_DESCRIPTOR_DATA_pack(NULL, state.map, &desc);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MEDIA_INTERFACE_DESCRIPTOR_LOAD,
+ .InterfaceDescriptorTotalLength = size,
+ .InterfaceDescriptorDataStartAddress = state.offset);
+
+ return VK_SUCCESS;
+}
+
+static void
+gen8_cmd_buffer_flush_compute_state(struct anv_cmd_buffer *cmd_buffer)
+{
+ struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
+ VkResult result;
+
+ assert(pipeline->active_stages == VK_SHADER_STAGE_COMPUTE_BIT);
+
+ if (cmd_buffer->state.current_pipeline != GPGPU) {
+ anv_batch_emit(&cmd_buffer->batch, GEN8_PIPELINE_SELECT,
+ .PipelineSelection = GPGPU);
+ cmd_buffer->state.current_pipeline = GPGPU;
+ }
+
+ if (cmd_buffer->state.compute_dirty & ANV_CMD_BUFFER_PIPELINE_DIRTY)
+ anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->batch);
+
+ if ((cmd_buffer->state.descriptors_dirty & VK_SHADER_STAGE_COMPUTE_BIT) ||
+ (cmd_buffer->state.compute_dirty & ANV_CMD_BUFFER_PIPELINE_DIRTY)) {
+ result = gen8_flush_compute_descriptor_set(cmd_buffer);
+ assert(result == VK_SUCCESS);
+ cmd_buffer->state.descriptors_dirty &= ~VK_SHADER_STAGE_COMPUTE;
+ }
+
+ cmd_buffer->state.compute_dirty = 0;
+}
+
+void gen8_CmdDrawIndexedIndirect(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer _buffer,
+ VkDeviceSize offset,
+ uint32_t count,
+ uint32_t stride)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
+ struct anv_bo *bo = buffer->bo;
+ uint32_t bo_offset = buffer->offset + offset;
+
+ gen8_cmd_buffer_flush_state(cmd_buffer);
+
+ emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_VERTEX_COUNT, bo, bo_offset);
+ emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_INSTANCE_COUNT, bo, bo_offset + 4);
+ emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_VERTEX, bo, bo_offset + 8);
+ emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, bo, bo_offset + 12);
+ emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 16);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DPRIMITIVE,
+ .IndirectParameterEnable = true,
+ .VertexAccessType = RANDOM);
+}
+
+void gen8_CmdDispatch(
+ VkCmdBuffer cmdBuffer,
+ uint32_t x,
+ uint32_t y,
+ uint32_t z)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
+ struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
+
+ gen8_cmd_buffer_flush_compute_state(cmd_buffer);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_GPGPU_WALKER,
+ .SIMDSize = prog_data->simd_size / 16,
+ .ThreadDepthCounterMaximum = 0,
+ .ThreadHeightCounterMaximum = 0,
+ .ThreadWidthCounterMaximum = pipeline->cs_thread_width_max,
+ .ThreadGroupIDXDimension = x,
+ .ThreadGroupIDYDimension = y,
+ .ThreadGroupIDZDimension = z,
+ .RightExecutionMask = pipeline->cs_right_mask,
+ .BottomExecutionMask = 0xffffffff);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MEDIA_STATE_FLUSH);
+}
+
+#define GPGPU_DISPATCHDIMX 0x2500
+#define GPGPU_DISPATCHDIMY 0x2504
+#define GPGPU_DISPATCHDIMZ 0x2508
+
+void gen8_CmdDispatchIndirect(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer _buffer,
+ VkDeviceSize offset)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
+ struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
+ struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
+ struct anv_bo *bo = buffer->bo;
+ uint32_t bo_offset = buffer->offset + offset;
+
+ gen8_cmd_buffer_flush_compute_state(cmd_buffer);
+
+ emit_lrm(&cmd_buffer->batch, GPGPU_DISPATCHDIMX, bo, bo_offset);
+ emit_lrm(&cmd_buffer->batch, GPGPU_DISPATCHDIMY, bo, bo_offset + 4);
+ emit_lrm(&cmd_buffer->batch, GPGPU_DISPATCHDIMZ, bo, bo_offset + 8);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_GPGPU_WALKER,
+ .IndirectParameterEnable = true,
+ .SIMDSize = prog_data->simd_size / 16,
+ .ThreadDepthCounterMaximum = 0,
+ .ThreadHeightCounterMaximum = 0,
+ .ThreadWidthCounterMaximum = pipeline->cs_thread_width_max,
+ .RightExecutionMask = pipeline->cs_right_mask,
+ .BottomExecutionMask = 0xffffffff);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MEDIA_STATE_FLUSH);
+}
+
+static void
+gen8_cmd_buffer_emit_depth_stencil(struct anv_cmd_buffer *cmd_buffer)
+{
+ struct anv_subpass *subpass = cmd_buffer->state.subpass;
+ struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
+ const struct anv_depth_stencil_view *view;
+
+ static const struct anv_depth_stencil_view null_view =
+ { .depth_format = D16_UNORM, .depth_stride = 0, .stencil_stride = 0 };
+
+ if (subpass->depth_stencil_attachment != VK_ATTACHMENT_UNUSED) {
+ const struct anv_attachment_view *aview =
+ fb->attachments[subpass->depth_stencil_attachment];
+ assert(aview->attachment_type == ANV_ATTACHMENT_VIEW_TYPE_DEPTH_STENCIL);
+ view = (const struct anv_depth_stencil_view *)aview;
+ } else {
+ view = &null_view;
+ }
+
+ /* FIXME: Implement the PMA stall W/A */
+ /* FIXME: Width and Height are wrong */
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_DEPTH_BUFFER,
+ .SurfaceType = SURFTYPE_2D,
+ .DepthWriteEnable = view->depth_stride > 0,
+ .StencilWriteEnable = view->stencil_stride > 0,
+ .HierarchicalDepthBufferEnable = false,
+ .SurfaceFormat = view->depth_format,
+ .SurfacePitch = view->depth_stride > 0 ? view->depth_stride - 1 : 0,
+ .SurfaceBaseAddress = { view->bo, view->depth_offset },
+ .Height = cmd_buffer->state.framebuffer->height - 1,
+ .Width = cmd_buffer->state.framebuffer->width - 1,
+ .LOD = 0,
+ .Depth = 1 - 1,
+ .MinimumArrayElement = 0,
+ .DepthBufferObjectControlState = GEN8_MOCS,
+ .RenderTargetViewExtent = 1 - 1,
+ .SurfaceQPitch = view->depth_qpitch >> 2);
+
+ /* Disable hierarchial depth buffers. */
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_HIER_DEPTH_BUFFER);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_STENCIL_BUFFER,
+ .StencilBufferEnable = view->stencil_stride > 0,
+ .StencilBufferObjectControlState = GEN8_MOCS,
+ .SurfacePitch = view->stencil_stride > 0 ? view->stencil_stride - 1 : 0,
+ .SurfaceBaseAddress = { view->bo, view->stencil_offset },
+ .SurfaceQPitch = view->stencil_qpitch >> 2);
+
+ /* Clear the clear params. */
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_CLEAR_PARAMS);
+}
+
+void
+gen8_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_subpass *subpass)
+{
+ cmd_buffer->state.subpass = subpass;
+
+ cmd_buffer->state.descriptors_dirty |= VK_SHADER_STAGE_FRAGMENT_BIT;
+
+ gen8_cmd_buffer_emit_depth_stencil(cmd_buffer);
+}
+
+void gen8_CmdBeginRenderPass(
+ VkCmdBuffer cmdBuffer,
+ const VkRenderPassBeginInfo* pRenderPassBegin,
+ VkRenderPassContents contents)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_render_pass, pass, pRenderPassBegin->renderPass);
+ ANV_FROM_HANDLE(anv_framebuffer, framebuffer, pRenderPassBegin->framebuffer);
+
+ cmd_buffer->state.framebuffer = framebuffer;
+ cmd_buffer->state.pass = pass;
+
+ const VkRect2D *render_area = &pRenderPassBegin->renderArea;
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_DRAWING_RECTANGLE,
+ .ClippedDrawingRectangleYMin = render_area->offset.y,
+ .ClippedDrawingRectangleXMin = render_area->offset.x,
+ .ClippedDrawingRectangleYMax =
+ render_area->offset.y + render_area->extent.height - 1,
+ .ClippedDrawingRectangleXMax =
+ render_area->offset.x + render_area->extent.width - 1,
+ .DrawingRectangleOriginY = 0,
+ .DrawingRectangleOriginX = 0);
+
+ anv_cmd_buffer_clear_attachments(cmd_buffer, pass,
+ pRenderPassBegin->pAttachmentClearValues);
+
+ gen8_cmd_buffer_begin_subpass(cmd_buffer, pass->subpasses);
+}
+
+void gen8_CmdNextSubpass(
+ VkCmdBuffer cmdBuffer,
+ VkRenderPassContents contents)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+
+ assert(cmd_buffer->level == VK_CMD_BUFFER_LEVEL_PRIMARY);
+
+ gen8_cmd_buffer_begin_subpass(cmd_buffer, cmd_buffer->state.subpass + 1);
+}
+
+void gen8_CmdEndRenderPass(
+ VkCmdBuffer cmdBuffer)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+
+ /* Emit a flushing pipe control at the end of a pass. This is kind of a
+ * hack but it ensures that render targets always actually get written.
+ * Eventually, we should do flushing based on image format transitions
+ * or something of that nature.
+ */
+ anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
+ .PostSyncOperation = NoWrite,
+ .RenderTargetCacheFlushEnable = true,
+ .InstructionCacheInvalidateEnable = true,
+ .DepthCacheFlushEnable = true,
+ .VFCacheInvalidationEnable = true,
+ .TextureCacheInvalidationEnable = true,
+ .CommandStreamerStallEnable = true);
+}
+
+static void
+emit_ps_depth_count(struct anv_batch *batch,
+ struct anv_bo *bo, uint32_t offset)
+{
+ anv_batch_emit(batch, GEN8_PIPE_CONTROL,
+ .DestinationAddressType = DAT_PPGTT,
+ .PostSyncOperation = WritePSDepthCount,
+ .Address = { bo, offset }); /* FIXME: This is only lower 32 bits */
+}
+
+void gen8_CmdBeginQuery(
+ VkCmdBuffer cmdBuffer,
+ VkQueryPool queryPool,
+ uint32_t slot,
+ VkQueryControlFlags flags)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
+
+ switch (pool->type) {
+ case VK_QUERY_TYPE_OCCLUSION:
+ emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
+ slot * sizeof(struct anv_query_pool_slot));
+ break;
+
+ case VK_QUERY_TYPE_PIPELINE_STATISTICS:
+ default:
+ unreachable("");
+ }
+}
+
+void gen8_CmdEndQuery(
+ VkCmdBuffer cmdBuffer,
+ VkQueryPool queryPool,
+ uint32_t slot)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
+
+ switch (pool->type) {
+ case VK_QUERY_TYPE_OCCLUSION:
+ emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
+ slot * sizeof(struct anv_query_pool_slot) + 8);
+ break;
+
+ case VK_QUERY_TYPE_PIPELINE_STATISTICS:
+ default:
+ unreachable("");
+ }
+}
+
+#define TIMESTAMP 0x2358
+
+void gen8_CmdWriteTimestamp(
+ VkCmdBuffer cmdBuffer,
+ VkTimestampType timestampType,
+ VkBuffer destBuffer,
+ VkDeviceSize destOffset)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
+ struct anv_bo *bo = buffer->bo;
+
+ switch (timestampType) {
+ case VK_TIMESTAMP_TYPE_TOP:
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
+ .RegisterAddress = TIMESTAMP,
+ .MemoryAddress = { bo, buffer->offset + destOffset });
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
+ .RegisterAddress = TIMESTAMP + 4,
+ .MemoryAddress = { bo, buffer->offset + destOffset + 4 });
+ break;
+
+ case VK_TIMESTAMP_TYPE_BOTTOM:
+ anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
+ .DestinationAddressType = DAT_PPGTT,
+ .PostSyncOperation = WriteTimestamp,
+ .Address = /* FIXME: This is only lower 32 bits */
+ { bo, buffer->offset + destOffset });
+ break;
+
+ default:
+ break;
+ }
+}
+
+#define alu_opcode(v) __gen_field((v), 20, 31)
+#define alu_operand1(v) __gen_field((v), 10, 19)
+#define alu_operand2(v) __gen_field((v), 0, 9)
+#define alu(opcode, operand1, operand2) \
+ alu_opcode(opcode) | alu_operand1(operand1) | alu_operand2(operand2)
+
+#define OPCODE_NOOP 0x000
+#define OPCODE_LOAD 0x080
+#define OPCODE_LOADINV 0x480
+#define OPCODE_LOAD0 0x081
+#define OPCODE_LOAD1 0x481
+#define OPCODE_ADD 0x100
+#define OPCODE_SUB 0x101
+#define OPCODE_AND 0x102
+#define OPCODE_OR 0x103
+#define OPCODE_XOR 0x104
+#define OPCODE_STORE 0x180
+#define OPCODE_STOREINV 0x580
+
+#define OPERAND_R0 0x00
+#define OPERAND_R1 0x01
+#define OPERAND_R2 0x02
+#define OPERAND_R3 0x03
+#define OPERAND_R4 0x04
+#define OPERAND_SRCA 0x20
+#define OPERAND_SRCB 0x21
+#define OPERAND_ACCU 0x31
+#define OPERAND_ZF 0x32
+#define OPERAND_CF 0x33
+
+#define CS_GPR(n) (0x2600 + (n) * 8)
+
+static void
+emit_load_alu_reg_u64(struct anv_batch *batch, uint32_t reg,
+ struct anv_bo *bo, uint32_t offset)
+{
+ anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
+ .RegisterAddress = reg,
+ .MemoryAddress = { bo, offset });
+ anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
+ .RegisterAddress = reg + 4,
+ .MemoryAddress = { bo, offset + 4 });
+}
+
+void gen8_CmdCopyQueryPoolResults(
+ VkCmdBuffer cmdBuffer,
+ VkQueryPool queryPool,
+ uint32_t startQuery,
+ uint32_t queryCount,
+ VkBuffer destBuffer,
+ VkDeviceSize destOffset,
+ VkDeviceSize destStride,
+ VkQueryResultFlags flags)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
+ ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
+ uint32_t slot_offset, dst_offset;
+
+ if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
+ /* Where is the availabilty info supposed to go? */
+ anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
+ return;
+ }
+
+ assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
+
+ /* FIXME: If we're not waiting, should we just do this on the CPU? */
+ if (flags & VK_QUERY_RESULT_WAIT_BIT)
+ anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
+ .CommandStreamerStallEnable = true,
+ .StallAtPixelScoreboard = true);
+
+ dst_offset = buffer->offset + destOffset;
+ for (uint32_t i = 0; i < queryCount; i++) {
+
+ slot_offset = (startQuery + i) * sizeof(struct anv_query_pool_slot);
+
+ emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(0), &pool->bo, slot_offset);
+ emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(1), &pool->bo, slot_offset + 8);
+
+ /* FIXME: We need to clamp the result for 32 bit. */
+
+ uint32_t *dw = anv_batch_emitn(&cmd_buffer->batch, 5, GEN8_MI_MATH);
+ dw[1] = alu(OPCODE_LOAD, OPERAND_SRCA, OPERAND_R1);
+ dw[2] = alu(OPCODE_LOAD, OPERAND_SRCB, OPERAND_R0);
+ dw[3] = alu(OPCODE_SUB, 0, 0);
+ dw[4] = alu(OPCODE_STORE, OPERAND_R2, OPERAND_ACCU);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
+ .RegisterAddress = CS_GPR(2),
+ /* FIXME: This is only lower 32 bits */
+ .MemoryAddress = { buffer->bo, dst_offset });
+
+ if (flags & VK_QUERY_RESULT_64_BIT)
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
+ .RegisterAddress = CS_GPR(2) + 4,
+ /* FIXME: This is only lower 32 bits */
+ .MemoryAddress = { buffer->bo, dst_offset + 4 });
+
+ dst_offset += destStride;
+ }
+}
+
+void
+gen8_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer)
+{
+ struct anv_device *device = cmd_buffer->device;
+ struct anv_bo *scratch_bo = NULL;
+
+ cmd_buffer->state.scratch_size =
+ anv_block_pool_size(&device->scratch_block_pool);
+ if (cmd_buffer->state.scratch_size > 0)
+ scratch_bo = &device->scratch_block_pool.bo;
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_STATE_BASE_ADDRESS,
+ .GeneralStateBaseAddress = { scratch_bo, 0 },
+ .GeneralStateMemoryObjectControlState = GEN8_MOCS,
+ .GeneralStateBaseAddressModifyEnable = true,
+ .GeneralStateBufferSize = 0xfffff,
+ .GeneralStateBufferSizeModifyEnable = true,
+
+ .SurfaceStateBaseAddress = { anv_cmd_buffer_current_surface_bo(cmd_buffer), 0 },
+ .SurfaceStateMemoryObjectControlState = GEN8_MOCS,
+ .SurfaceStateBaseAddressModifyEnable = true,
+
+ .DynamicStateBaseAddress = { &device->dynamic_state_block_pool.bo, 0 },
+ .DynamicStateMemoryObjectControlState = GEN8_MOCS,
+ .DynamicStateBaseAddressModifyEnable = true,
+ .DynamicStateBufferSize = 0xfffff,
+ .DynamicStateBufferSizeModifyEnable = true,
+
+ .IndirectObjectBaseAddress = { NULL, 0 },
+ .IndirectObjectMemoryObjectControlState = GEN8_MOCS,
+ .IndirectObjectBaseAddressModifyEnable = true,
+ .IndirectObjectBufferSize = 0xfffff,
+ .IndirectObjectBufferSizeModifyEnable = true,
+
+ .InstructionBaseAddress = { &device->instruction_block_pool.bo, 0 },
+ .InstructionMemoryObjectControlState = GEN8_MOCS,
+ .InstructionBaseAddressModifyEnable = true,
+ .InstructionBufferSize = 0xfffff,
+ .InstructionBuffersizeModifyEnable = true);
+
+ /* After re-setting the surface state base address, we have to do some
+ * cache flusing so that the sampler engine will pick up the new
+ * SURFACE_STATE objects and binding tables. From the Broadwell PRM,
+ * Shared Function > 3D Sampler > State > State Caching (page 96):
+ *
+ * Coherency with system memory in the state cache, like the texture
+ * cache is handled partially by software. It is expected that the
+ * command stream or shader will issue Cache Flush operation or
+ * Cache_Flush sampler message to ensure that the L1 cache remains
+ * coherent with system memory.
+ *
+ * [...]
+ *
+ * Whenever the value of the Dynamic_State_Base_Addr,
+ * Surface_State_Base_Addr are altered, the L1 state cache must be
+ * invalidated to ensure the new surface or sampler state is fetched
+ * from system memory.
+ *
+ * The PIPE_CONTROL command has a "State Cache Invalidation Enable" bit
+ * which, according the PIPE_CONTROL instruction documentation in the
+ * Broadwell PRM:
+ *
+ * Setting this bit is independent of any other bit in this packet.
+ * This bit controls the invalidation of the L1 and L2 state caches
+ * at the top of the pipe i.e. at the parsing time.
+ *
+ * Unfortunately, experimentation seems to indicate that state cache
+ * invalidation through a PIPE_CONTROL does nothing whatsoever in
+ * regards to surface state and binding tables. In stead, it seems that
+ * invalidating the texture cache is what is actually needed.
+ *
+ * XXX: As far as we have been able to determine through
+ * experimentation, shows that flush the texture cache appears to be
+ * sufficient. The theory here is that all of the sampling/rendering
+ * units cache the binding table in the texture cache. However, we have
+ * yet to be able to actually confirm this.
+ */
+ anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
+ .TextureCacheInvalidationEnable = true);
+}
--- /dev/null
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "anv_private.h"
+
+static void
+emit_vertex_input(struct anv_pipeline *pipeline,
+ const VkPipelineVertexInputStateCreateInfo *info)
+{
+ const uint32_t num_dwords = 1 + info->attributeCount * 2;
+ uint32_t *p;
+ bool instancing_enable[32];
+
+ pipeline->vb_used = 0;
+ for (uint32_t i = 0; i < info->bindingCount; i++) {
+ const VkVertexInputBindingDescription *desc =
+ &info->pVertexBindingDescriptions[i];
+
+ pipeline->vb_used |= 1 << desc->binding;
+ pipeline->binding_stride[desc->binding] = desc->strideInBytes;
+
+ /* Step rate is programmed per vertex element (attribute), not
+ * binding. Set up a map of which bindings step per instance, for
+ * reference by vertex element setup. */
+ switch (desc->stepRate) {
+ default:
+ case VK_VERTEX_INPUT_STEP_RATE_VERTEX:
+ instancing_enable[desc->binding] = false;
+ break;
+ case VK_VERTEX_INPUT_STEP_RATE_INSTANCE:
+ instancing_enable[desc->binding] = true;
+ break;
+ }
+ }
+
+ p = anv_batch_emitn(&pipeline->batch, num_dwords,
+ GEN8_3DSTATE_VERTEX_ELEMENTS);
+
+ for (uint32_t i = 0; i < info->attributeCount; i++) {
+ const VkVertexInputAttributeDescription *desc =
+ &info->pVertexAttributeDescriptions[i];
+ const struct anv_format *format = anv_format_for_vk_format(desc->format);
+
+ struct GEN8_VERTEX_ELEMENT_STATE element = {
+ .VertexBufferIndex = desc->binding,
+ .Valid = true,
+ .SourceElementFormat = format->surface_format,
+ .EdgeFlagEnable = false,
+ .SourceElementOffset = desc->offsetInBytes,
+ .Component0Control = VFCOMP_STORE_SRC,
+ .Component1Control = format->num_channels >= 2 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
+ .Component2Control = format->num_channels >= 3 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
+ .Component3Control = format->num_channels >= 4 ? VFCOMP_STORE_SRC : VFCOMP_STORE_1_FP
+ };
+ GEN8_VERTEX_ELEMENT_STATE_pack(NULL, &p[1 + i * 2], &element);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_INSTANCING,
+ .InstancingEnable = instancing_enable[desc->binding],
+ .VertexElementIndex = i,
+ /* Vulkan so far doesn't have an instance divisor, so
+ * this is always 1 (ignored if not instancing). */
+ .InstanceDataStepRate = 1);
+ }
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_SGVS,
+ .VertexIDEnable = pipeline->vs_prog_data.uses_vertexid,
+ .VertexIDComponentNumber = 2,
+ .VertexIDElementOffset = info->bindingCount,
+ .InstanceIDEnable = pipeline->vs_prog_data.uses_instanceid,
+ .InstanceIDComponentNumber = 3,
+ .InstanceIDElementOffset = info->bindingCount);
+}
+
+static void
+emit_ia_state(struct anv_pipeline *pipeline,
+ const VkPipelineInputAssemblyStateCreateInfo *info,
+ const struct anv_graphics_pipeline_create_info *extra)
+{
+ static const uint32_t vk_to_gen_primitive_type[] = {
+ [VK_PRIMITIVE_TOPOLOGY_POINT_LIST] = _3DPRIM_POINTLIST,
+ [VK_PRIMITIVE_TOPOLOGY_LINE_LIST] = _3DPRIM_LINELIST,
+ [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP] = _3DPRIM_LINESTRIP,
+ [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = _3DPRIM_TRILIST,
+ [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = _3DPRIM_TRISTRIP,
+ [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN] = _3DPRIM_TRIFAN,
+ [VK_PRIMITIVE_TOPOLOGY_LINE_LIST_ADJ] = _3DPRIM_LINELIST_ADJ,
+ [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_ADJ] = _3DPRIM_LINESTRIP_ADJ,
+ [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_ADJ] = _3DPRIM_TRILIST_ADJ,
+ [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_ADJ] = _3DPRIM_TRISTRIP_ADJ,
+ [VK_PRIMITIVE_TOPOLOGY_PATCH] = _3DPRIM_PATCHLIST_1
+ };
+ uint32_t topology = vk_to_gen_primitive_type[info->topology];
+
+ if (extra && extra->use_rectlist)
+ topology = _3DPRIM_RECTLIST;
+
+ struct GEN8_3DSTATE_VF vf = {
+ GEN8_3DSTATE_VF_header,
+ .IndexedDrawCutIndexEnable = info->primitiveRestartEnable,
+ };
+ GEN8_3DSTATE_VF_pack(NULL, pipeline->state_vf, &vf);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_TOPOLOGY,
+ .PrimitiveTopologyType = topology);
+}
+
+static void
+emit_rs_state(struct anv_pipeline *pipeline,
+ const VkPipelineRasterStateCreateInfo *info,
+ const struct anv_graphics_pipeline_create_info *extra)
+{
+ static const uint32_t vk_to_gen_cullmode[] = {
+ [VK_CULL_MODE_NONE] = CULLMODE_NONE,
+ [VK_CULL_MODE_FRONT] = CULLMODE_FRONT,
+ [VK_CULL_MODE_BACK] = CULLMODE_BACK,
+ [VK_CULL_MODE_FRONT_AND_BACK] = CULLMODE_BOTH
+ };
+
+ static const uint32_t vk_to_gen_fillmode[] = {
+ [VK_FILL_MODE_POINTS] = RASTER_POINT,
+ [VK_FILL_MODE_WIREFRAME] = RASTER_WIREFRAME,
+ [VK_FILL_MODE_SOLID] = RASTER_SOLID
+ };
+
+ static const uint32_t vk_to_gen_front_face[] = {
+ [VK_FRONT_FACE_CCW] = CounterClockwise,
+ [VK_FRONT_FACE_CW] = Clockwise
+ };
+
+ struct GEN8_3DSTATE_SF sf = {
+ GEN8_3DSTATE_SF_header,
+ .ViewportTransformEnable = !(extra && extra->disable_viewport),
+ .TriangleStripListProvokingVertexSelect = 0,
+ .LineStripListProvokingVertexSelect = 0,
+ .TriangleFanProvokingVertexSelect = 0,
+ .PointWidthSource = pipeline->writes_point_size ? Vertex : State,
+ .PointWidth = 1.0,
+ };
+
+ /* FINISHME: VkBool32 rasterizerDiscardEnable; */
+
+ GEN8_3DSTATE_SF_pack(NULL, pipeline->state_sf, &sf);
+
+ struct GEN8_3DSTATE_RASTER raster = {
+ GEN8_3DSTATE_RASTER_header,
+ .FrontWinding = vk_to_gen_front_face[info->frontFace],
+ .CullMode = vk_to_gen_cullmode[info->cullMode],
+ .FrontFaceFillMode = vk_to_gen_fillmode[info->fillMode],
+ .BackFaceFillMode = vk_to_gen_fillmode[info->fillMode],
+ .ScissorRectangleEnable = !(extra && extra->disable_scissor),
+ .ViewportZClipTestEnable = info->depthClipEnable
+ };
+
+ GEN8_3DSTATE_RASTER_pack(NULL, pipeline->state_raster, &raster);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE,
+ .ForceVertexURBEntryReadLength = false,
+ .ForceVertexURBEntryReadOffset = false,
+ .PointSpriteTextureCoordinateOrigin = UPPERLEFT,
+ .NumberofSFOutputAttributes =
+ pipeline->wm_prog_data.num_varying_inputs);
+
+}
+
+static void
+emit_cb_state(struct anv_pipeline *pipeline,
+ const VkPipelineColorBlendStateCreateInfo *info)
+{
+ struct anv_device *device = pipeline->device;
+
+ static const uint32_t vk_to_gen_logic_op[] = {
+ [VK_LOGIC_OP_COPY] = LOGICOP_COPY,
+ [VK_LOGIC_OP_CLEAR] = LOGICOP_CLEAR,
+ [VK_LOGIC_OP_AND] = LOGICOP_AND,
+ [VK_LOGIC_OP_AND_REVERSE] = LOGICOP_AND_REVERSE,
+ [VK_LOGIC_OP_AND_INVERTED] = LOGICOP_AND_INVERTED,
+ [VK_LOGIC_OP_NOOP] = LOGICOP_NOOP,
+ [VK_LOGIC_OP_XOR] = LOGICOP_XOR,
+ [VK_LOGIC_OP_OR] = LOGICOP_OR,
+ [VK_LOGIC_OP_NOR] = LOGICOP_NOR,
+ [VK_LOGIC_OP_EQUIV] = LOGICOP_EQUIV,
+ [VK_LOGIC_OP_INVERT] = LOGICOP_INVERT,
+ [VK_LOGIC_OP_OR_REVERSE] = LOGICOP_OR_REVERSE,
+ [VK_LOGIC_OP_COPY_INVERTED] = LOGICOP_COPY_INVERTED,
+ [VK_LOGIC_OP_OR_INVERTED] = LOGICOP_OR_INVERTED,
+ [VK_LOGIC_OP_NAND] = LOGICOP_NAND,
+ [VK_LOGIC_OP_SET] = LOGICOP_SET,
+ };
+
+ static const uint32_t vk_to_gen_blend[] = {
+ [VK_BLEND_ZERO] = BLENDFACTOR_ZERO,
+ [VK_BLEND_ONE] = BLENDFACTOR_ONE,
+ [VK_BLEND_SRC_COLOR] = BLENDFACTOR_SRC_COLOR,
+ [VK_BLEND_ONE_MINUS_SRC_COLOR] = BLENDFACTOR_INV_SRC_COLOR,
+ [VK_BLEND_DEST_COLOR] = BLENDFACTOR_DST_COLOR,
+ [VK_BLEND_ONE_MINUS_DEST_COLOR] = BLENDFACTOR_INV_DST_COLOR,
+ [VK_BLEND_SRC_ALPHA] = BLENDFACTOR_SRC_ALPHA,
+ [VK_BLEND_ONE_MINUS_SRC_ALPHA] = BLENDFACTOR_INV_SRC_ALPHA,
+ [VK_BLEND_DEST_ALPHA] = BLENDFACTOR_DST_ALPHA,
+ [VK_BLEND_ONE_MINUS_DEST_ALPHA] = BLENDFACTOR_INV_DST_ALPHA,
+ [VK_BLEND_CONSTANT_COLOR] = BLENDFACTOR_CONST_COLOR,
+ [VK_BLEND_ONE_MINUS_CONSTANT_COLOR] = BLENDFACTOR_INV_CONST_COLOR,
+ [VK_BLEND_CONSTANT_ALPHA] = BLENDFACTOR_CONST_ALPHA,
+ [VK_BLEND_ONE_MINUS_CONSTANT_ALPHA] = BLENDFACTOR_INV_CONST_ALPHA,
+ [VK_BLEND_SRC_ALPHA_SATURATE] = BLENDFACTOR_SRC_ALPHA_SATURATE,
+ [VK_BLEND_SRC1_COLOR] = BLENDFACTOR_SRC1_COLOR,
+ [VK_BLEND_ONE_MINUS_SRC1_COLOR] = BLENDFACTOR_INV_SRC1_COLOR,
+ [VK_BLEND_SRC1_ALPHA] = BLENDFACTOR_SRC1_ALPHA,
+ [VK_BLEND_ONE_MINUS_SRC1_ALPHA] = BLENDFACTOR_INV_SRC1_ALPHA,
+ };
+
+ static const uint32_t vk_to_gen_blend_op[] = {
+ [VK_BLEND_OP_ADD] = BLENDFUNCTION_ADD,
+ [VK_BLEND_OP_SUBTRACT] = BLENDFUNCTION_SUBTRACT,
+ [VK_BLEND_OP_REVERSE_SUBTRACT] = BLENDFUNCTION_REVERSE_SUBTRACT,
+ [VK_BLEND_OP_MIN] = BLENDFUNCTION_MIN,
+ [VK_BLEND_OP_MAX] = BLENDFUNCTION_MAX,
+ };
+
+ uint32_t num_dwords = GEN8_BLEND_STATE_length;
+ pipeline->blend_state =
+ anv_state_pool_alloc(&device->dynamic_state_pool, num_dwords * 4, 64);
+
+ struct GEN8_BLEND_STATE blend_state = {
+ .AlphaToCoverageEnable = info->alphaToCoverageEnable,
+ };
+
+ for (uint32_t i = 0; i < info->attachmentCount; i++) {
+ const VkPipelineColorBlendAttachmentState *a = &info->pAttachments[i];
+
+ blend_state.Entry[i] = (struct GEN8_BLEND_STATE_ENTRY) {
+ .LogicOpEnable = info->logicOpEnable,
+ .LogicOpFunction = vk_to_gen_logic_op[info->logicOp],
+ .ColorBufferBlendEnable = a->blendEnable,
+ .PreBlendSourceOnlyClampEnable = false,
+ .PreBlendColorClampEnable = false,
+ .PostBlendColorClampEnable = false,
+ .SourceBlendFactor = vk_to_gen_blend[a->srcBlendColor],
+ .DestinationBlendFactor = vk_to_gen_blend[a->destBlendColor],
+ .ColorBlendFunction = vk_to_gen_blend_op[a->blendOpColor],
+ .SourceAlphaBlendFactor = vk_to_gen_blend[a->srcBlendAlpha],
+ .DestinationAlphaBlendFactor = vk_to_gen_blend[a->destBlendAlpha],
+ .AlphaBlendFunction = vk_to_gen_blend_op[a->blendOpAlpha],
+ .WriteDisableAlpha = !(a->channelWriteMask & VK_CHANNEL_A_BIT),
+ .WriteDisableRed = !(a->channelWriteMask & VK_CHANNEL_R_BIT),
+ .WriteDisableGreen = !(a->channelWriteMask & VK_CHANNEL_G_BIT),
+ .WriteDisableBlue = !(a->channelWriteMask & VK_CHANNEL_B_BIT),
+ };
+ }
+
+ GEN8_BLEND_STATE_pack(NULL, pipeline->blend_state.map, &blend_state);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_BLEND_STATE_POINTERS,
+ .BlendStatePointer = pipeline->blend_state.offset,
+ .BlendStatePointerValid = true);
+}
+
+static const uint32_t vk_to_gen_compare_op[] = {
+ [VK_COMPARE_OP_NEVER] = COMPAREFUNCTION_NEVER,
+ [VK_COMPARE_OP_LESS] = COMPAREFUNCTION_LESS,
+ [VK_COMPARE_OP_EQUAL] = COMPAREFUNCTION_EQUAL,
+ [VK_COMPARE_OP_LESS_EQUAL] = COMPAREFUNCTION_LEQUAL,
+ [VK_COMPARE_OP_GREATER] = COMPAREFUNCTION_GREATER,
+ [VK_COMPARE_OP_NOT_EQUAL] = COMPAREFUNCTION_NOTEQUAL,
+ [VK_COMPARE_OP_GREATER_EQUAL] = COMPAREFUNCTION_GEQUAL,
+ [VK_COMPARE_OP_ALWAYS] = COMPAREFUNCTION_ALWAYS,
+};
+
+static const uint32_t vk_to_gen_stencil_op[] = {
+ [VK_STENCIL_OP_KEEP] = 0,
+ [VK_STENCIL_OP_ZERO] = 0,
+ [VK_STENCIL_OP_REPLACE] = 0,
+ [VK_STENCIL_OP_INC_CLAMP] = 0,
+ [VK_STENCIL_OP_DEC_CLAMP] = 0,
+ [VK_STENCIL_OP_INVERT] = 0,
+ [VK_STENCIL_OP_INC_WRAP] = 0,
+ [VK_STENCIL_OP_DEC_WRAP] = 0
+};
+
+static void
+emit_ds_state(struct anv_pipeline *pipeline,
+ const VkPipelineDepthStencilStateCreateInfo *info)
+{
+ if (info == NULL) {
+ /* We're going to OR this together with the dynamic state. We need
+ * to make sure it's initialized to something useful.
+ */
+ memset(pipeline->state_wm_depth_stencil, 0,
+ sizeof(pipeline->state_wm_depth_stencil));
+ return;
+ }
+
+ /* VkBool32 depthBoundsEnable; // optional (depth_bounds_test) */
+
+ struct GEN8_3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil = {
+ .DepthTestEnable = info->depthTestEnable,
+ .DepthBufferWriteEnable = info->depthWriteEnable,
+ .DepthTestFunction = vk_to_gen_compare_op[info->depthCompareOp],
+ .DoubleSidedStencilEnable = true,
+
+ .StencilTestEnable = info->stencilTestEnable,
+ .StencilFailOp = vk_to_gen_stencil_op[info->front.stencilFailOp],
+ .StencilPassDepthPassOp = vk_to_gen_stencil_op[info->front.stencilPassOp],
+ .StencilPassDepthFailOp = vk_to_gen_stencil_op[info->front.stencilDepthFailOp],
+ .StencilTestFunction = vk_to_gen_compare_op[info->front.stencilCompareOp],
+ .BackfaceStencilFailOp = vk_to_gen_stencil_op[info->back.stencilFailOp],
+ .BackfaceStencilPassDepthPassOp = vk_to_gen_stencil_op[info->back.stencilPassOp],
+ .BackfaceStencilPassDepthFailOp =vk_to_gen_stencil_op[info->back.stencilDepthFailOp],
+ .BackfaceStencilTestFunction = vk_to_gen_compare_op[info->back.stencilCompareOp],
+ };
+
+ GEN8_3DSTATE_WM_DEPTH_STENCIL_pack(NULL, pipeline->state_wm_depth_stencil, &wm_depth_stencil);
+}
+
+VkResult
+gen8_graphics_pipeline_create(
+ VkDevice _device,
+ const VkGraphicsPipelineCreateInfo* pCreateInfo,
+ const struct anv_graphics_pipeline_create_info *extra,
+ VkPipeline* pPipeline)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_pipeline *pipeline;
+ VkResult result;
+ uint32_t offset, length;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
+
+ pipeline = anv_device_alloc(device, sizeof(*pipeline), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (pipeline == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ pipeline->device = device;
+ pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
+ memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
+
+ result = anv_reloc_list_init(&pipeline->batch_relocs, device);
+ if (result != VK_SUCCESS) {
+ anv_device_free(device, pipeline);
+ return result;
+ }
+ pipeline->batch.next = pipeline->batch.start = pipeline->batch_data;
+ pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data);
+ pipeline->batch.relocs = &pipeline->batch_relocs;
+
+ anv_state_stream_init(&pipeline->program_stream,
+ &device->instruction_block_pool);
+
+ for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
+ pipeline->shaders[pCreateInfo->pStages[i].stage] =
+ anv_shader_from_handle(pCreateInfo->pStages[i].shader);
+ }
+
+ if (pCreateInfo->pTessellationState)
+ anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO");
+ if (pCreateInfo->pViewportState)
+ anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO");
+ if (pCreateInfo->pMultisampleState)
+ anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO");
+
+ pipeline->use_repclear = extra && extra->use_repclear;
+
+ anv_compiler_run(device->compiler, pipeline);
+
+ /* FIXME: The compiler dead-codes FS inputs when we don't have a VS, so we
+ * hard code this to num_attributes - 2. This is because the attributes
+ * include VUE header and position, which aren't counted as varying
+ * inputs. */
+ if (pipeline->vs_simd8 == NO_KERNEL) {
+ pipeline->wm_prog_data.num_varying_inputs =
+ pCreateInfo->pVertexInputState->attributeCount - 2;
+ }
+
+ assert(pCreateInfo->pVertexInputState);
+ emit_vertex_input(pipeline, pCreateInfo->pVertexInputState);
+ assert(pCreateInfo->pInputAssemblyState);
+ emit_ia_state(pipeline, pCreateInfo->pInputAssemblyState, extra);
+ assert(pCreateInfo->pRasterState);
+ emit_rs_state(pipeline, pCreateInfo->pRasterState, extra);
+ emit_ds_state(pipeline, pCreateInfo->pDepthStencilState);
+ emit_cb_state(pipeline, pCreateInfo->pColorBlendState);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_STATISTICS,
+ .StatisticsEnable = true);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_HS, .Enable = false);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_TE, .TEEnable = false);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_DS, .FunctionEnable = false);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_STREAMOUT, .SOFunctionEnable = false);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_VS,
+ .ConstantBufferOffset = 0,
+ .ConstantBufferSize = 4);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_GS,
+ .ConstantBufferOffset = 4,
+ .ConstantBufferSize = 4);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_PS,
+ .ConstantBufferOffset = 8,
+ .ConstantBufferSize = 4);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM_CHROMAKEY,
+ .ChromaKeyKillEnable = false);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE_SWIZ);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_AA_LINE_PARAMETERS);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_CLIP,
+ .ClipEnable = true,
+ .ViewportXYClipTestEnable = !(extra && extra->disable_viewport),
+ .MinimumPointWidth = 0.125,
+ .MaximumPointWidth = 255.875);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM,
+ .StatisticsEnable = true,
+ .LineEndCapAntialiasingRegionWidth = _05pixels,
+ .LineAntialiasingRegionWidth = _10pixels,
+ .EarlyDepthStencilControl = NORMAL,
+ .ForceThreadDispatchEnable = NORMAL,
+ .PointRasterizationRule = RASTRULE_UPPER_RIGHT,
+ .BarycentricInterpolationMode =
+ pipeline->wm_prog_data.barycentric_interp_modes);
+
+ uint32_t samples = 1;
+ uint32_t log2_samples = __builtin_ffs(samples) - 1;
+ bool enable_sampling = samples > 1 ? true : false;
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_MULTISAMPLE,
+ .PixelPositionOffsetEnable = enable_sampling,
+ .PixelLocation = CENTER,
+ .NumberofMultisamples = log2_samples);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SAMPLE_MASK,
+ .SampleMask = 0xffff);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_VS,
+ .VSURBStartingAddress = pipeline->urb.vs_start,
+ .VSURBEntryAllocationSize = pipeline->urb.vs_size - 1,
+ .VSNumberofURBEntries = pipeline->urb.nr_vs_entries);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_GS,
+ .GSURBStartingAddress = pipeline->urb.gs_start,
+ .GSURBEntryAllocationSize = pipeline->urb.gs_size - 1,
+ .GSNumberofURBEntries = pipeline->urb.nr_gs_entries);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_HS,
+ .HSURBStartingAddress = pipeline->urb.vs_start,
+ .HSURBEntryAllocationSize = 0,
+ .HSNumberofURBEntries = 0);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_DS,
+ .DSURBStartingAddress = pipeline->urb.vs_start,
+ .DSURBEntryAllocationSize = 0,
+ .DSNumberofURBEntries = 0);
+
+ const struct brw_gs_prog_data *gs_prog_data = &pipeline->gs_prog_data;
+ offset = 1;
+ length = (gs_prog_data->base.vue_map.num_slots + 1) / 2 - offset;
+
+ if (pipeline->gs_vec4 == NO_KERNEL)
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS, .Enable = false);
+ else
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS,
+ .SingleProgramFlow = false,
+ .KernelStartPointer = pipeline->gs_vec4,
+ .VectorMaskEnable = Vmask,
+ .SamplerCount = 0,
+ .BindingTableEntryCount = 0,
+ .ExpectedVertexCount = pipeline->gs_vertex_count,
+
+ .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_GEOMETRY],
+ .PerThreadScratchSpace = ffs(gs_prog_data->base.base.total_scratch / 2048),
+
+ .OutputVertexSize = gs_prog_data->output_vertex_size_hwords * 2 - 1,
+ .OutputTopology = gs_prog_data->output_topology,
+ .VertexURBEntryReadLength = gs_prog_data->base.urb_read_length,
+ .DispatchGRFStartRegisterForURBData =
+ gs_prog_data->base.base.dispatch_grf_start_reg,
+
+ .MaximumNumberofThreads = device->info.max_gs_threads,
+ .ControlDataHeaderSize = gs_prog_data->control_data_header_size_hwords,
+ //pipeline->gs_prog_data.dispatch_mode |
+ .StatisticsEnable = true,
+ .IncludePrimitiveID = gs_prog_data->include_primitive_id,
+ .ReorderMode = TRAILING,
+ .Enable = true,
+
+ .ControlDataFormat = gs_prog_data->control_data_format,
+
+ /* FIXME: mesa sets this based on ctx->Transform.ClipPlanesEnabled:
+ * UserClipDistanceClipTestEnableBitmask_3DSTATE_GS(v)
+ * UserClipDistanceCullTestEnableBitmask(v)
+ */
+
+ .VertexURBEntryOutputReadOffset = offset,
+ .VertexURBEntryOutputLength = length);
+
+ const struct brw_vue_prog_data *vue_prog_data = &pipeline->vs_prog_data.base;
+ /* Skip the VUE header and position slots */
+ offset = 1;
+ length = (vue_prog_data->vue_map.num_slots + 1) / 2 - offset;
+
+ if (pipeline->vs_simd8 == NO_KERNEL || (extra && extra->disable_vs))
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
+ .FunctionEnable = false,
+ .VertexURBEntryOutputReadOffset = 1,
+ /* Even if VS is disabled, SBE still gets the amount of
+ * vertex data to read from this field. We use attribute
+ * count - 1, as we don't count the VUE header here. */
+ .VertexURBEntryOutputLength =
+ DIV_ROUND_UP(pCreateInfo->pVertexInputState->attributeCount - 1, 2));
+ else
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
+ .KernelStartPointer = pipeline->vs_simd8,
+ .SingleVertexDispatch = Multiple,
+ .VectorMaskEnable = Dmask,
+ .SamplerCount = 0,
+ .BindingTableEntryCount =
+ vue_prog_data->base.binding_table.size_bytes / 4,
+ .ThreadDispatchPriority = Normal,
+ .FloatingPointMode = IEEE754,
+ .IllegalOpcodeExceptionEnable = false,
+ .AccessesUAV = false,
+ .SoftwareExceptionEnable = false,
+
+ .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_VERTEX],
+ .PerThreadScratchSpace = ffs(vue_prog_data->base.total_scratch / 2048),
+
+ .DispatchGRFStartRegisterForURBData =
+ vue_prog_data->base.dispatch_grf_start_reg,
+ .VertexURBEntryReadLength = vue_prog_data->urb_read_length,
+ .VertexURBEntryReadOffset = 0,
+
+ .MaximumNumberofThreads = device->info.max_vs_threads - 1,
+ .StatisticsEnable = false,
+ .SIMD8DispatchEnable = true,
+ .VertexCacheDisable = false,
+ .FunctionEnable = true,
+
+ .VertexURBEntryOutputReadOffset = offset,
+ .VertexURBEntryOutputLength = length,
+ .UserClipDistanceClipTestEnableBitmask = 0,
+ .UserClipDistanceCullTestEnableBitmask = 0);
+
+ const struct brw_wm_prog_data *wm_prog_data = &pipeline->wm_prog_data;
+ uint32_t ksp0, ksp2, grf_start0, grf_start2;
+
+ ksp2 = 0;
+ grf_start2 = 0;
+ if (pipeline->ps_simd8 != NO_KERNEL) {
+ ksp0 = pipeline->ps_simd8;
+ grf_start0 = wm_prog_data->base.dispatch_grf_start_reg;
+ if (pipeline->ps_simd16 != NO_KERNEL) {
+ ksp2 = pipeline->ps_simd16;
+ grf_start2 = wm_prog_data->dispatch_grf_start_reg_16;
+ }
+ } else if (pipeline->ps_simd16 != NO_KERNEL) {
+ ksp0 = pipeline->ps_simd16;
+ grf_start0 = wm_prog_data->dispatch_grf_start_reg_16;
+ } else {
+ unreachable("no ps shader");
+ }
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS,
+ .KernelStartPointer0 = ksp0,
+
+ .SingleProgramFlow = false,
+ .VectorMaskEnable = true,
+ .SamplerCount = 1,
+
+ .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
+ .PerThreadScratchSpace = ffs(wm_prog_data->base.total_scratch / 2048),
+
+ .MaximumNumberofThreadsPerPSD = 64 - 2,
+ .PositionXYOffsetSelect = wm_prog_data->uses_pos_offset ?
+ POSOFFSET_SAMPLE: POSOFFSET_NONE,
+ .PushConstantEnable = wm_prog_data->base.nr_params > 0,
+ ._8PixelDispatchEnable = pipeline->ps_simd8 != NO_KERNEL,
+ ._16PixelDispatchEnable = pipeline->ps_simd16 != NO_KERNEL,
+ ._32PixelDispatchEnable = false,
+
+ .DispatchGRFStartRegisterForConstantSetupData0 = grf_start0,
+ .DispatchGRFStartRegisterForConstantSetupData1 = 0,
+ .DispatchGRFStartRegisterForConstantSetupData2 = grf_start2,
+
+ .KernelStartPointer1 = 0,
+ .KernelStartPointer2 = ksp2);
+
+ bool per_sample_ps = false;
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS_EXTRA,
+ .PixelShaderValid = true,
+ .PixelShaderKillsPixel = wm_prog_data->uses_kill,
+ .PixelShaderComputedDepthMode = wm_prog_data->computed_depth_mode,
+ .AttributeEnable = wm_prog_data->num_varying_inputs > 0,
+ .oMaskPresenttoRenderTarget = wm_prog_data->uses_omask,
+ .PixelShaderIsPerSample = per_sample_ps);
+
+ *pPipeline = anv_pipeline_to_handle(pipeline);
+
+ return VK_SUCCESS;
+}
+
+VkResult gen8_compute_pipeline_create(
+ VkDevice _device,
+ const VkComputePipelineCreateInfo* pCreateInfo,
+ VkPipeline* pPipeline)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_pipeline *pipeline;
+ VkResult result;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
+
+ pipeline = anv_device_alloc(device, sizeof(*pipeline), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (pipeline == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ pipeline->device = device;
+ pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
+
+ result = anv_reloc_list_init(&pipeline->batch_relocs, device);
+ if (result != VK_SUCCESS) {
+ anv_device_free(device, pipeline);
+ return result;
+ }
+ pipeline->batch.next = pipeline->batch.start = pipeline->batch_data;
+ pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data);
+ pipeline->batch.relocs = &pipeline->batch_relocs;
+
+ anv_state_stream_init(&pipeline->program_stream,
+ &device->instruction_block_pool);
+
+ memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
+
+ pipeline->shaders[VK_SHADER_STAGE_COMPUTE] =
+ anv_shader_from_handle(pCreateInfo->cs.shader);
+
+ pipeline->use_repclear = false;
+
+ anv_compiler_run(device->compiler, pipeline);
+
+ const struct brw_cs_prog_data *cs_prog_data = &pipeline->cs_prog_data;
+
+ anv_batch_emit(&pipeline->batch, GEN8_MEDIA_VFE_STATE,
+ .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
+ .PerThreadScratchSpace = ffs(cs_prog_data->base.total_scratch / 2048),
+ .ScratchSpaceBasePointerHigh = 0,
+ .StackSize = 0,
+
+ .MaximumNumberofThreads = device->info.max_cs_threads - 1,
+ .NumberofURBEntries = 2,
+ .ResetGatewayTimer = true,
+ .BypassGatewayControl = true,
+ .URBEntryAllocationSize = 2,
+ .CURBEAllocationSize = 0);
+
+ struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
+ uint32_t group_size = prog_data->local_size[0] *
+ prog_data->local_size[1] * prog_data->local_size[2];
+ pipeline->cs_thread_width_max = DIV_ROUND_UP(group_size, prog_data->simd_size);
+ uint32_t remainder = group_size & (prog_data->simd_size - 1);
+
+ if (remainder > 0)
+ pipeline->cs_right_mask = ~0u >> (32 - remainder);
+ else
+ pipeline->cs_right_mask = ~0u >> (32 - prog_data->simd_size);
+
+
+ *pPipeline = anv_pipeline_to_handle(pipeline);
+
+ return VK_SUCCESS;
+}
--- /dev/null
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "anv_private.h"
+
+VkResult gen8_CreateDynamicRasterState(
+ VkDevice _device,
+ const VkDynamicRasterStateCreateInfo* pCreateInfo,
+ VkDynamicRasterState* pState)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_dynamic_rs_state *state;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_RASTER_STATE_CREATE_INFO);
+
+ state = anv_device_alloc(device, sizeof(*state), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (state == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ struct GEN8_3DSTATE_SF sf = {
+ GEN8_3DSTATE_SF_header,
+ .LineWidth = pCreateInfo->lineWidth,
+ };
+
+ GEN8_3DSTATE_SF_pack(NULL, state->state_sf, &sf);
+
+ bool enable_bias = pCreateInfo->depthBias != 0.0f ||
+ pCreateInfo->slopeScaledDepthBias != 0.0f;
+ struct GEN8_3DSTATE_RASTER raster = {
+ .GlobalDepthOffsetEnableSolid = enable_bias,
+ .GlobalDepthOffsetEnableWireframe = enable_bias,
+ .GlobalDepthOffsetEnablePoint = enable_bias,
+ .GlobalDepthOffsetConstant = pCreateInfo->depthBias,
+ .GlobalDepthOffsetScale = pCreateInfo->slopeScaledDepthBias,
+ .GlobalDepthOffsetClamp = pCreateInfo->depthBiasClamp
+ };
+
+ GEN8_3DSTATE_RASTER_pack(NULL, state->state_raster, &raster);
+
+ *pState = anv_dynamic_rs_state_to_handle(state);
+
+ return VK_SUCCESS;
+}
+
+void
+gen8_fill_buffer_surface_state(void *state, const struct anv_format *format,
+ uint32_t offset, uint32_t range)
+{
+ /* This assumes RGBA float format. */
+ uint32_t stride = 4;
+ uint32_t num_elements = range / stride;
+
+ struct GEN8_RENDER_SURFACE_STATE surface_state = {
+ .SurfaceType = SURFTYPE_BUFFER,
+ .SurfaceArray = false,
+ .SurfaceFormat = format->surface_format,
+ .SurfaceVerticalAlignment = VALIGN4,
+ .SurfaceHorizontalAlignment = HALIGN4,
+ .TileMode = LINEAR,
+ .VerticalLineStride = 0,
+ .VerticalLineStrideOffset = 0,
+ .SamplerL2BypassModeDisable = true,
+ .RenderCacheReadWriteMode = WriteOnlyCache,
+ .MemoryObjectControlState = GEN8_MOCS,
+ .BaseMipLevel = 0.0,
+ .SurfaceQPitch = 0,
+ .Height = (num_elements >> 7) & 0x3fff,
+ .Width = num_elements & 0x7f,
+ .Depth = (num_elements >> 21) & 0x3f,
+ .SurfacePitch = stride - 1,
+ .MinimumArrayElement = 0,
+ .NumberofMultisamples = MULTISAMPLECOUNT_1,
+ .XOffset = 0,
+ .YOffset = 0,
+ .SurfaceMinLOD = 0,
+ .MIPCountLOD = 0,
+ .AuxiliarySurfaceMode = AUX_NONE,
+ .RedClearColor = 0,
+ .GreenClearColor = 0,
+ .BlueClearColor = 0,
+ .AlphaClearColor = 0,
+ .ShaderChannelSelectRed = SCS_RED,
+ .ShaderChannelSelectGreen = SCS_GREEN,
+ .ShaderChannelSelectBlue = SCS_BLUE,
+ .ShaderChannelSelectAlpha = SCS_ALPHA,
+ .ResourceMinLOD = 0.0,
+ /* FIXME: We assume that the image must be bound at this time. */
+ .SurfaceBaseAddress = { NULL, offset },
+ };
+
+ GEN8_RENDER_SURFACE_STATE_pack(NULL, state, &surface_state);
+}
+
+VkResult gen8_CreateBufferView(
+ VkDevice _device,
+ const VkBufferViewCreateInfo* pCreateInfo,
+ VkBufferView* pView)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_buffer_view *view;
+ VkResult result;
+
+ result = anv_buffer_view_create(device, pCreateInfo, &view);
+ if (result != VK_SUCCESS)
+ return result;
+
+ const struct anv_format *format =
+ anv_format_for_vk_format(pCreateInfo->format);
+
+ gen8_fill_buffer_surface_state(view->view.surface_state.map, format,
+ view->view.offset, pCreateInfo->range);
+
+ *pView = anv_buffer_view_to_handle(view);
+
+ return VK_SUCCESS;
+}
+
+VkResult gen8_CreateSampler(
+ VkDevice _device,
+ const VkSamplerCreateInfo* pCreateInfo,
+ VkSampler* pSampler)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_sampler *sampler;
+ uint32_t mag_filter, min_filter, max_anisotropy;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
+
+ sampler = anv_device_alloc(device, sizeof(*sampler), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (!sampler)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ static const uint32_t vk_to_gen_tex_filter[] = {
+ [VK_TEX_FILTER_NEAREST] = MAPFILTER_NEAREST,
+ [VK_TEX_FILTER_LINEAR] = MAPFILTER_LINEAR
+ };
+
+ static const uint32_t vk_to_gen_mipmap_mode[] = {
+ [VK_TEX_MIPMAP_MODE_BASE] = MIPFILTER_NONE,
+ [VK_TEX_MIPMAP_MODE_NEAREST] = MIPFILTER_NEAREST,
+ [VK_TEX_MIPMAP_MODE_LINEAR] = MIPFILTER_LINEAR
+ };
+
+ static const uint32_t vk_to_gen_tex_address[] = {
+ [VK_TEX_ADDRESS_WRAP] = TCM_WRAP,
+ [VK_TEX_ADDRESS_MIRROR] = TCM_MIRROR,
+ [VK_TEX_ADDRESS_CLAMP] = TCM_CLAMP,
+ [VK_TEX_ADDRESS_MIRROR_ONCE] = TCM_MIRROR_ONCE,
+ [VK_TEX_ADDRESS_CLAMP_BORDER] = TCM_CLAMP_BORDER,
+ };
+
+ static const uint32_t vk_to_gen_compare_op[] = {
+ [VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER,
+ [VK_COMPARE_OP_LESS] = PREFILTEROPLESS,
+ [VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL,
+ [VK_COMPARE_OP_LESS_EQUAL] = PREFILTEROPLEQUAL,
+ [VK_COMPARE_OP_GREATER] = PREFILTEROPGREATER,
+ [VK_COMPARE_OP_NOT_EQUAL] = PREFILTEROPNOTEQUAL,
+ [VK_COMPARE_OP_GREATER_EQUAL] = PREFILTEROPGEQUAL,
+ [VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS,
+ };
+
+ if (pCreateInfo->maxAnisotropy > 1) {
+ mag_filter = MAPFILTER_ANISOTROPIC;
+ min_filter = MAPFILTER_ANISOTROPIC;
+ max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
+ } else {
+ mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
+ min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
+ max_anisotropy = RATIO21;
+ }
+
+ struct GEN8_SAMPLER_STATE sampler_state = {
+ .SamplerDisable = false,
+ .TextureBorderColorMode = DX10OGL,
+ .LODPreClampMode = 0,
+ .BaseMipLevel = 0.0,
+ .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipMode],
+ .MagModeFilter = mag_filter,
+ .MinModeFilter = min_filter,
+ .TextureLODBias = pCreateInfo->mipLodBias * 256,
+ .AnisotropicAlgorithm = EWAApproximation,
+ .MinLOD = pCreateInfo->minLod,
+ .MaxLOD = pCreateInfo->maxLod,
+ .ChromaKeyEnable = 0,
+ .ChromaKeyIndex = 0,
+ .ChromaKeyMode = 0,
+ .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
+ .CubeSurfaceControlMode = 0,
+
+ .IndirectStatePointer =
+ device->border_colors.offset +
+ pCreateInfo->borderColor * sizeof(float) * 4,
+
+ .LODClampMagnificationMode = MIPNONE,
+ .MaximumAnisotropy = max_anisotropy,
+ .RAddressMinFilterRoundingEnable = 0,
+ .RAddressMagFilterRoundingEnable = 0,
+ .VAddressMinFilterRoundingEnable = 0,
+ .VAddressMagFilterRoundingEnable = 0,
+ .UAddressMinFilterRoundingEnable = 0,
+ .UAddressMagFilterRoundingEnable = 0,
+ .TrilinearFilterQuality = 0,
+ .NonnormalizedCoordinateEnable = 0,
+ .TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressU],
+ .TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressV],
+ .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressW],
+ };
+
+ GEN8_SAMPLER_STATE_pack(NULL, sampler->state, &sampler_state);
+
+ *pSampler = anv_sampler_to_handle(sampler);
+
+ return VK_SUCCESS;
+}
+
+VkResult gen8_CreateDynamicDepthStencilState(
+ VkDevice _device,
+ const VkDynamicDepthStencilStateCreateInfo* pCreateInfo,
+ VkDynamicDepthStencilState* pState)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_dynamic_ds_state *state;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_DEPTH_STENCIL_STATE_CREATE_INFO);
+
+ state = anv_device_alloc(device, sizeof(*state), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (state == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ struct GEN8_3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil = {
+ GEN8_3DSTATE_WM_DEPTH_STENCIL_header,
+
+ /* Is this what we need to do? */
+ .StencilBufferWriteEnable = pCreateInfo->stencilWriteMask != 0,
+
+ .StencilTestMask = pCreateInfo->stencilReadMask & 0xff,
+ .StencilWriteMask = pCreateInfo->stencilWriteMask & 0xff,
+
+ .BackfaceStencilTestMask = pCreateInfo->stencilReadMask & 0xff,
+ .BackfaceStencilWriteMask = pCreateInfo->stencilWriteMask & 0xff,
+ };
+
+ GEN8_3DSTATE_WM_DEPTH_STENCIL_pack(NULL, state->state_wm_depth_stencil,
+ &wm_depth_stencil);
+
+ struct GEN8_COLOR_CALC_STATE color_calc_state = {
+ .StencilReferenceValue = pCreateInfo->stencilFrontRef,
+ .BackFaceStencilReferenceValue = pCreateInfo->stencilBackRef
+ };
+
+ GEN8_COLOR_CALC_STATE_pack(NULL, state->state_color_calc, &color_calc_state);
+
+ *pState = anv_dynamic_ds_state_to_handle(state);
+
+ return VK_SUCCESS;
+}