2015-05-08 22:32:37 -07:00
|
|
|
/*
|
|
|
|
|
* 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 "private.h"
|
|
|
|
|
|
|
|
|
|
// Shader functions
|
|
|
|
|
|
|
|
|
|
VkResult VKAPI vkCreateShader(
|
|
|
|
|
VkDevice _device,
|
|
|
|
|
const VkShaderCreateInfo* pCreateInfo,
|
|
|
|
|
VkShader* pShader)
|
|
|
|
|
{
|
|
|
|
|
struct anv_device *device = (struct anv_device *) _device;
|
|
|
|
|
struct anv_shader *shader;
|
|
|
|
|
|
|
|
|
|
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_CREATE_INFO);
|
|
|
|
|
|
|
|
|
|
shader = anv_device_alloc(device, sizeof(*shader) + pCreateInfo->codeSize, 8,
|
|
|
|
|
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
|
|
|
|
if (shader == NULL)
|
|
|
|
|
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
|
|
shader->size = pCreateInfo->codeSize;
|
|
|
|
|
memcpy(shader->data, pCreateInfo->pCode, shader->size);
|
|
|
|
|
|
|
|
|
|
*pShader = (VkShader) shader;
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pipeline functions
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
emit_vertex_input(struct anv_pipeline *pipeline, VkPipelineVertexInputCreateInfo *info)
|
|
|
|
|
{
|
|
|
|
|
const uint32_t num_dwords = 1 + info->attributeCount * 2;
|
|
|
|
|
uint32_t *p;
|
|
|
|
|
bool instancing_enable[32];
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < info->bindingCount; i++) {
|
|
|
|
|
const VkVertexInputBindingDescription *desc =
|
|
|
|
|
&info->pVertexBindingDescriptions[i];
|
|
|
|
|
|
|
|
|
|
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 = {
|
2015-05-11 22:25:52 -07:00
|
|
|
.VertexBufferIndex = desc->binding,
|
2015-05-08 22:32:37 -07:00
|
|
|
.Valid = true,
|
|
|
|
|
.SourceElementFormat = format->format,
|
|
|
|
|
.EdgeFlagEnable = false,
|
|
|
|
|
.SourceElementOffset = desc->offsetInBytes,
|
|
|
|
|
.Component0Control = VFCOMP_STORE_SRC,
|
|
|
|
|
.Component1Control = format->channels >= 2 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
|
|
|
|
|
.Component2Control = format->channels >= 3 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
|
|
|
|
|
.Component3Control = format->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
|
2015-05-11 23:20:01 -07:00
|
|
|
emit_ia_state(struct anv_pipeline *pipeline,
|
|
|
|
|
VkPipelineIaStateCreateInfo *info,
|
|
|
|
|
const struct anv_pipeline_create_info *extra)
|
2015-05-08 22:32:37 -07:00
|
|
|
{
|
|
|
|
|
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_LISTSTRIP_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
|
|
|
|
|
};
|
2015-05-11 23:20:01 -07:00
|
|
|
uint32_t topology = vk_to_gen_primitive_type[info->topology];
|
|
|
|
|
|
|
|
|
|
if (extra && extra->use_rectlist)
|
|
|
|
|
topology = _3DPRIM_RECTLIST;
|
2015-05-08 22:32:37 -07:00
|
|
|
|
|
|
|
|
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF,
|
|
|
|
|
.IndexedDrawCutIndexEnable = info->primitiveRestartEnable,
|
|
|
|
|
.CutIndex = info->primitiveRestartIndex);
|
|
|
|
|
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_TOPOLOGY,
|
2015-05-11 23:20:01 -07:00
|
|
|
.PrimitiveTopologyType = topology);
|
2015-05-08 22:32:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-11 23:20:01 -07:00
|
|
|
emit_rs_state(struct anv_pipeline *pipeline, VkPipelineRsStateCreateInfo *info,
|
|
|
|
|
const struct anv_pipeline_create_info *extra)
|
|
|
|
|
|
2015-05-08 22:32:37 -07:00
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const uint32_t vk_to_gen_coordinate_origin[] = {
|
|
|
|
|
[VK_COORDINATE_ORIGIN_UPPER_LEFT] = UPPERLEFT,
|
|
|
|
|
[VK_COORDINATE_ORIGIN_LOWER_LEFT] = LOWERLEFT
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct GEN8_3DSTATE_SF sf = {
|
|
|
|
|
GEN8_3DSTATE_SF_header,
|
2015-05-11 23:20:01 -07:00
|
|
|
.ViewportTransformEnable = !(extra && extra->disable_viewport),
|
2015-05-08 22:32:37 -07:00
|
|
|
.TriangleStripListProvokingVertexSelect =
|
|
|
|
|
info->provokingVertex == VK_PROVOKING_VERTEX_FIRST ? 0 : 2,
|
|
|
|
|
.LineStripListProvokingVertexSelect =
|
|
|
|
|
info->provokingVertex == VK_PROVOKING_VERTEX_FIRST ? 0 : 1,
|
|
|
|
|
.TriangleFanProvokingVertexSelect =
|
|
|
|
|
info->provokingVertex == VK_PROVOKING_VERTEX_FIRST ? 0 : 2,
|
|
|
|
|
.PointWidthSource = info->programPointSize ? Vertex : State,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* bool32_t rasterizerDiscardEnable; */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GEN8_3DSTATE_SF_pack(NULL, pipeline->state_sf, &sf);
|
|
|
|
|
|
|
|
|
|
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_RASTER,
|
|
|
|
|
.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],
|
2015-05-12 12:52:53 -07:00
|
|
|
.ScissorRectangleEnable = !(extra && extra->disable_scissor),
|
2015-05-08 22:32:37 -07:00
|
|
|
.ViewportZClipTestEnable = info->depthClipEnable);
|
|
|
|
|
|
|
|
|
|
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE,
|
|
|
|
|
.ForceVertexURBEntryReadLength = false,
|
|
|
|
|
.ForceVertexURBEntryReadOffset = false,
|
|
|
|
|
.PointSpriteTextureCoordinateOrigin =
|
|
|
|
|
vk_to_gen_coordinate_origin[info->pointOrigin],
|
|
|
|
|
.NumberofSFOutputAttributes =
|
|
|
|
|
pipeline->wm_prog_data.num_varying_inputs);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult VKAPI vkCreateGraphicsPipeline(
|
2015-05-11 23:20:01 -07:00
|
|
|
VkDevice device,
|
|
|
|
|
const VkGraphicsPipelineCreateInfo* pCreateInfo,
|
|
|
|
|
VkPipeline* pPipeline)
|
|
|
|
|
{
|
|
|
|
|
return anv_pipeline_create(device, pCreateInfo, NULL, pPipeline);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
|
anv_pipeline_create(
|
2015-05-08 22:32:37 -07:00
|
|
|
VkDevice _device,
|
|
|
|
|
const VkGraphicsPipelineCreateInfo* pCreateInfo,
|
2015-05-11 23:20:01 -07:00
|
|
|
const struct anv_pipeline_create_info * extra,
|
2015-05-08 22:32:37 -07:00
|
|
|
VkPipeline* pPipeline)
|
|
|
|
|
{
|
|
|
|
|
struct anv_device *device = (struct anv_device *) _device;
|
|
|
|
|
struct anv_pipeline *pipeline;
|
|
|
|
|
const struct anv_common *common;
|
|
|
|
|
VkPipelineShaderStageCreateInfo *shader_create_info;
|
|
|
|
|
VkPipelineIaStateCreateInfo *ia_info;
|
|
|
|
|
VkPipelineRsStateCreateInfo *rs_info;
|
|
|
|
|
VkPipelineVertexInputCreateInfo *vi_info;
|
|
|
|
|
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 = (struct anv_pipeline_layout *) pCreateInfo->layout;
|
|
|
|
|
memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
|
|
|
|
|
result = anv_batch_init(&pipeline->batch, device);
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
for (common = pCreateInfo->pNext; common; common = common->pNext) {
|
|
|
|
|
switch (common->sType) {
|
|
|
|
|
case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO:
|
|
|
|
|
vi_info = (VkPipelineVertexInputCreateInfo *) common;
|
|
|
|
|
break;
|
|
|
|
|
case VK_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO:
|
|
|
|
|
ia_info = (VkPipelineIaStateCreateInfo *) common;
|
|
|
|
|
break;
|
|
|
|
|
case VK_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO:
|
|
|
|
|
case VK_STRUCTURE_TYPE_PIPELINE_VP_STATE_CREATE_INFO:
|
|
|
|
|
break;
|
|
|
|
|
case VK_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO:
|
|
|
|
|
rs_info = (VkPipelineRsStateCreateInfo *) common;
|
|
|
|
|
break;
|
|
|
|
|
case VK_STRUCTURE_TYPE_PIPELINE_MS_STATE_CREATE_INFO:
|
|
|
|
|
case VK_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO:
|
|
|
|
|
case VK_STRUCTURE_TYPE_PIPELINE_DS_STATE_CREATE_INFO:
|
|
|
|
|
case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO:
|
|
|
|
|
shader_create_info = (VkPipelineShaderStageCreateInfo *) common;
|
|
|
|
|
pipeline->shaders[shader_create_info->shader.stage] =
|
|
|
|
|
(struct anv_shader *) shader_create_info->shader.shader;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-11 23:20:01 -07:00
|
|
|
pipeline->use_repclear = extra && extra->use_repclear;
|
2015-05-08 22:32:37 -07:00
|
|
|
|
|
|
|
|
anv_compiler_run(device->compiler, pipeline);
|
|
|
|
|
|
2015-05-11 22:17:04 -07:00
|
|
|
/* 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 = vi_info->attributeCount - 2;
|
|
|
|
|
|
2015-05-08 22:32:37 -07:00
|
|
|
emit_vertex_input(pipeline, vi_info);
|
2015-05-11 23:20:01 -07:00
|
|
|
emit_ia_state(pipeline, ia_info, extra);
|
|
|
|
|
emit_rs_state(pipeline, rs_info, extra);
|
|
|
|
|
|
|
|
|
|
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_CLIP,
|
|
|
|
|
.ClipEnable = true,
|
|
|
|
|
.ViewportXYClipTestEnable = !(extra && extra->disable_viewport));
|
2015-05-08 22:32:37 -07:00
|
|
|
|
|
|
|
|
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_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,
|
|
|
|
|
|
|
|
|
|
.PerThreadScratchSpace = 0,
|
|
|
|
|
.ScratchSpaceBasePointer = 0,
|
|
|
|
|
|
|
|
|
|
.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);
|
|
|
|
|
|
|
|
|
|
//trp_generate_blend_hw_cmds(batch, pipeline);
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2015-05-11 22:17:04 -07:00
|
|
|
if (pipeline->vs_simd8 == NO_KERNEL)
|
|
|
|
|
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(vi_info->attributeCount - 1, 2));
|
|
|
|
|
else
|
|
|
|
|
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
|
|
|
|
|
.KernelStartPointer = pipeline->vs_simd8,
|
|
|
|
|
.SingleVertexDispatch = Multiple,
|
|
|
|
|
.VectorMaskEnable = Dmask,
|
|
|
|
|
.SamplerCount = 0,
|
|
|
|
|
.BindingTableEntryCount =
|
2015-05-08 22:32:37 -07:00
|
|
|
vue_prog_data->base.binding_table.size_bytes / 4,
|
2015-05-11 22:17:04 -07:00
|
|
|
.ThreadDispatchPriority = Normal,
|
|
|
|
|
.FloatingPointMode = IEEE754,
|
|
|
|
|
.IllegalOpcodeExceptionEnable = false,
|
|
|
|
|
.AccessesUAV = false,
|
|
|
|
|
.SoftwareExceptionEnable = false,
|
|
|
|
|
|
|
|
|
|
/* FIXME: pointer needs to be assigned outside as it aliases
|
|
|
|
|
* PerThreadScratchSpace.
|
|
|
|
|
*/
|
|
|
|
|
.ScratchSpaceBasePointer = 0,
|
|
|
|
|
.PerThreadScratchSpace = 0,
|
|
|
|
|
|
|
|
|
|
.DispatchGRFStartRegisterForURBData =
|
2015-05-08 22:32:37 -07:00
|
|
|
vue_prog_data->base.dispatch_grf_start_reg,
|
2015-05-11 22:17:04 -07:00
|
|
|
.VertexURBEntryReadLength = vue_prog_data->urb_read_length,
|
|
|
|
|
.VertexURBEntryReadOffset = 0,
|
|
|
|
|
|
|
|
|
|
.MaximumNumberofThreads = device->info.max_vs_threads - 1,
|
|
|
|
|
.StatisticsEnable = false,
|
|
|
|
|
.SIMD8DispatchEnable = true,
|
|
|
|
|
.VertexCacheDisable = ia_info->disableVertexReuse,
|
|
|
|
|
.FunctionEnable = true,
|
|
|
|
|
|
|
|
|
|
.VertexURBEntryOutputReadOffset = offset,
|
|
|
|
|
.VertexURBEntryOutputLength = length,
|
|
|
|
|
.UserClipDistanceClipTestEnableBitmask = 0,
|
|
|
|
|
.UserClipDistanceCullTestEnableBitmask = 0);
|
2015-05-08 22:32:37 -07:00
|
|
|
|
|
|
|
|
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 = 0,
|
|
|
|
|
|
|
|
|
|
.ScratchSpaceBasePointer = 0,
|
|
|
|
|
.PerThreadScratchSpace = 0,
|
|
|
|
|
|
|
|
|
|
.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 = (VkPipeline) pipeline;
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
anv_device_free(device, pipeline);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
|
anv_pipeline_destroy(struct anv_pipeline *pipeline)
|
|
|
|
|
{
|
|
|
|
|
anv_compiler_free(pipeline);
|
|
|
|
|
anv_batch_finish(&pipeline->batch, pipeline->device);
|
|
|
|
|
anv_device_free(pipeline->device, pipeline);
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult VKAPI vkCreateGraphicsPipelineDerivative(
|
|
|
|
|
VkDevice device,
|
|
|
|
|
const VkGraphicsPipelineCreateInfo* pCreateInfo,
|
|
|
|
|
VkPipeline basePipeline,
|
|
|
|
|
VkPipeline* pPipeline)
|
|
|
|
|
{
|
2015-05-12 13:44:43 -07:00
|
|
|
stub_return(VK_UNSUPPORTED);
|
2015-05-08 22:32:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult VKAPI vkCreateComputePipeline(
|
|
|
|
|
VkDevice device,
|
|
|
|
|
const VkComputePipelineCreateInfo* pCreateInfo,
|
|
|
|
|
VkPipeline* pPipeline)
|
|
|
|
|
{
|
2015-05-12 13:44:43 -07:00
|
|
|
stub_return(VK_UNSUPPORTED);
|
2015-05-08 22:32:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult VKAPI vkStorePipeline(
|
|
|
|
|
VkDevice device,
|
|
|
|
|
VkPipeline pipeline,
|
|
|
|
|
size_t* pDataSize,
|
|
|
|
|
void* pData)
|
|
|
|
|
{
|
2015-05-12 13:44:43 -07:00
|
|
|
stub_return(VK_UNSUPPORTED);
|
2015-05-08 22:32:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult VKAPI vkLoadPipeline(
|
|
|
|
|
VkDevice device,
|
|
|
|
|
size_t dataSize,
|
|
|
|
|
const void* pData,
|
|
|
|
|
VkPipeline* pPipeline)
|
|
|
|
|
{
|
2015-05-12 13:44:43 -07:00
|
|
|
stub_return(VK_UNSUPPORTED);
|
2015-05-08 22:32:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult VKAPI vkLoadPipelineDerivative(
|
|
|
|
|
VkDevice device,
|
|
|
|
|
size_t dataSize,
|
|
|
|
|
const void* pData,
|
|
|
|
|
VkPipeline basePipeline,
|
|
|
|
|
VkPipeline* pPipeline)
|
|
|
|
|
{
|
2015-05-12 13:44:43 -07:00
|
|
|
stub_return(VK_UNSUPPORTED);
|
2015-05-08 22:32:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pipeline layout functions
|
|
|
|
|
|
|
|
|
|
VkResult VKAPI vkCreatePipelineLayout(
|
|
|
|
|
VkDevice _device,
|
|
|
|
|
const VkPipelineLayoutCreateInfo* pCreateInfo,
|
|
|
|
|
VkPipelineLayout* pPipelineLayout)
|
|
|
|
|
{
|
|
|
|
|
struct anv_device *device = (struct anv_device *) _device;
|
|
|
|
|
struct anv_pipeline_layout *layout;
|
2015-05-13 14:43:08 -07:00
|
|
|
struct anv_pipeline_layout_entry *sampler_entry, *surface_entry;
|
|
|
|
|
uint32_t sampler_total, surface_total;
|
2015-05-08 22:32:37 -07:00
|
|
|
size_t size;
|
|
|
|
|
|
|
|
|
|
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
|
|
|
|
|
|
2015-05-13 14:43:08 -07:00
|
|
|
sampler_total = 0;
|
|
|
|
|
surface_total = 0;
|
2015-05-08 22:32:37 -07:00
|
|
|
for (uint32_t i = 0; i < pCreateInfo->descriptorSetCount; i++) {
|
|
|
|
|
struct anv_descriptor_set_layout *set_layout =
|
|
|
|
|
(struct anv_descriptor_set_layout *) pCreateInfo->pSetLayouts[i];
|
2015-05-13 14:43:08 -07:00
|
|
|
for (uint32_t j = 0; j < set_layout->count; j++) {
|
|
|
|
|
sampler_total += set_layout->sampler_total;
|
|
|
|
|
surface_total += set_layout->surface_total;
|
|
|
|
|
}
|
2015-05-08 22:32:37 -07:00
|
|
|
}
|
|
|
|
|
|
2015-05-13 14:43:08 -07:00
|
|
|
size = sizeof(*layout) +
|
|
|
|
|
(sampler_total + surface_total) * sizeof(layout->entries[0]);
|
2015-05-08 22:32:37 -07:00
|
|
|
layout = anv_device_alloc(device, size, 8,
|
|
|
|
|
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
|
|
|
|
if (layout == NULL)
|
|
|
|
|
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
2015-05-13 14:43:08 -07:00
|
|
|
sampler_entry = layout->entries;
|
|
|
|
|
surface_entry = layout->entries + sampler_total;
|
2015-05-08 22:32:37 -07:00
|
|
|
for (uint32_t s = 0; s < VK_NUM_SHADER_STAGE; s++) {
|
2015-05-13 14:43:08 -07:00
|
|
|
layout->stage[s].sampler_entries = sampler_entry;
|
|
|
|
|
layout->stage[s].surface_entries = surface_entry;
|
2015-05-08 22:32:37 -07:00
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < pCreateInfo->descriptorSetCount; i++) {
|
|
|
|
|
struct anv_descriptor_set_layout *set_layout =
|
|
|
|
|
(struct anv_descriptor_set_layout *) pCreateInfo->pSetLayouts[i];
|
2015-05-13 14:43:08 -07:00
|
|
|
for (uint32_t j = 0; j < set_layout->count; j++) {
|
2015-05-08 22:32:37 -07:00
|
|
|
if (set_layout->bindings[j].mask & (1 << s)) {
|
2015-05-13 14:43:08 -07:00
|
|
|
switch (set_layout->bindings[j].type) {
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
|
|
|
|
sampler_entry->type = set_layout->bindings[j].type;
|
|
|
|
|
sampler_entry->set = i;
|
|
|
|
|
sampler_entry->index = j;
|
|
|
|
|
sampler_entry++;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
|
|
|
|
sampler_entry->type = set_layout->bindings[j].type;
|
|
|
|
|
sampler_entry->set = i;
|
|
|
|
|
sampler_entry->index = j;
|
|
|
|
|
sampler_entry++;
|
|
|
|
|
/* fall through */
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
|
|
|
|
surface_entry->type = set_layout->bindings[j].type;
|
|
|
|
|
surface_entry->set = i;
|
|
|
|
|
surface_entry->index = j;
|
|
|
|
|
surface_entry++;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-05-08 22:32:37 -07:00
|
|
|
}
|
2015-05-13 14:43:08 -07:00
|
|
|
}
|
2015-05-08 22:32:37 -07:00
|
|
|
}
|
|
|
|
|
|
2015-05-13 14:43:08 -07:00
|
|
|
layout->stage[s].sampler_count =
|
|
|
|
|
sampler_entry - layout->stage[s].sampler_entries;
|
|
|
|
|
layout->stage[s].surface_count =
|
|
|
|
|
surface_entry - layout->stage[s].surface_entries;
|
2015-05-08 22:32:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*pPipelineLayout = (VkPipelineLayout) layout;
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|