nvk: Graphics pipelines

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
Faith Ekstrand
2023-01-30 20:11:52 -06:00
committed by Marge Bot
parent c9e28274cc
commit 83598f44a9
5 changed files with 348 additions and 10 deletions
+1
View File
@@ -25,6 +25,7 @@ nvk_files = files(
'nvk_device_memory.h',
'nvk_format.c',
'nvk_format.h',
'nvk_graphics_pipeline.c',
'nvk_image.c',
'nvk_image.h',
'nvk_image_view.c',
+5
View File
@@ -3,6 +3,7 @@
#include "nvk_image.h"
#include "nvk_image_view.h"
#include "nvk_physical_device.h"
#include "nvk_pipeline.h"
#include "nil_format.h"
#include "vulkan/runtime/vk_render_pass.h"
@@ -558,7 +559,11 @@ void
nvk_cmd_bind_graphics_pipeline(struct nvk_cmd_buffer *cmd,
struct nvk_graphics_pipeline *pipeline)
{
struct nouveau_ws_push *p = cmd->push;
cmd->state.gfx.pipeline = pipeline;
vk_cmd_set_dynamic_graphics_state(&cmd->vk, &pipeline->dynamic);
nouveau_ws_push_append(p, &pipeline->push);
}
#define VFMT(vk_fmt, widths, swap_rb, type) \
+321
View File
@@ -0,0 +1,321 @@
#include "nvk_pipeline.h"
#include "nvk_device.h"
#include "nvk_pipeline_layout.h"
#include "nvk_shader.h"
#include "vk_nir.h"
#include "vk_pipeline.h"
#include "nouveau_context.h"
#include "nvk_cl9097.h"
#include "nvk_clc397.h"
static void
emit_pipeline_ts_state(struct nvk_graphics_pipeline *pipeline,
const struct vk_tessellation_state *ts)
{
assert(ts->domain_origin == VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT);
}
static void
emit_pipeline_vp_state(struct nvk_graphics_pipeline *pipeline,
const struct vk_viewport_state *vp)
{
struct nouveau_ws_push *p = &pipeline->push;
P_IMMD(p, NV9097, SET_VIEWPORT_Z_CLIP, vp->depth_clip_negative_one_to_one ?
RANGE_NEGATIVE_W_TO_POSITIVE_W :
RANGE_ZERO_TO_POSITIVE_W);
}
static uint32_t
vk_to_nv9097_polygon_mode(VkPolygonMode vk_mode)
{
ASSERTED uint16_t vk_to_nv9097[] = {
[VK_POLYGON_MODE_FILL] = NV9097_SET_FRONT_POLYGON_MODE_V_FILL,
[VK_POLYGON_MODE_LINE] = NV9097_SET_FRONT_POLYGON_MODE_V_LINE,
[VK_POLYGON_MODE_POINT] = NV9097_SET_FRONT_POLYGON_MODE_V_POINT,
};
assert(vk_mode < ARRAY_SIZE(vk_to_nv9097));
uint32_t nv9097_mode = 0x1b00 | (2 - vk_mode);
assert(nv9097_mode == vk_to_nv9097[vk_mode]);
return nv9097_mode;
}
static uint32_t
vk_to_nv9097_provoking_vertex(VkProvokingVertexModeEXT vk_mode)
{
STATIC_ASSERT(VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT ==
NV9097_SET_PROVOKING_VERTEX_V_FIRST);
STATIC_ASSERT(VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT ==
NV9097_SET_PROVOKING_VERTEX_V_LAST);
return vk_mode;
}
static void
emit_pipeline_rs_state(struct nvk_graphics_pipeline *pipeline,
const struct vk_rasterization_state *rs)
{
struct nouveau_ws_push *p = &pipeline->push;
/* TODO: Depth clip/clamp? */
P_IMMD(p, NV9097, SET_VIEWPORT_CLIP_CONTROL, {
.min_z_zero_max_z_one = MIN_Z_ZERO_MAX_Z_ONE_TRUE,
.pixel_min_z = PIXEL_MIN_Z_CLAMP,
.pixel_max_z = PIXEL_MAX_Z_CLIP,
.geometry_guardband = GEOMETRY_GUARDBAND_SCALE_256,
.line_point_cull_guardband = LINE_POINT_CULL_GUARDBAND_SCALE_256,
.geometry_clip = GEOMETRY_CLIP_WZERO_CLIP,
.geometry_guardband_z = GEOMETRY_GUARDBAND_Z_SAME_AS_XY_GUARDBAND,
});
const uint32_t polygon_mode = vk_to_nv9097_polygon_mode(rs->polygon_mode);
P_MTHD(p, NV9097, SET_FRONT_POLYGON_MODE);
P_NV9097_SET_FRONT_POLYGON_MODE(p, polygon_mode);
P_NV9097_SET_BACK_POLYGON_MODE(p, polygon_mode);
P_IMMD(p, NV9097, SET_PROVOKING_VERTEX,
vk_to_nv9097_provoking_vertex(rs->provoking_vertex));
assert(rs->rasterization_stream == 0);
assert(rs->line.mode == VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT);
P_IMMD(p, NV9097, SET_LINE_STIPPLE, rs->line.stipple.enable);
}
static void
emit_pipeline_ms_state(struct nvk_graphics_pipeline *pipeline,
const struct vk_multisample_state *ms)
{
struct nouveau_ws_push *p = &pipeline->push;
P_IMMD(p, NV9097, SET_ANTI_ALIAS, ffs(ms->rasterization_samples) - 1);
P_IMMD(p, NV9097, SET_ANTI_ALIAS_ENABLE, ms->sample_shading_enable);
P_IMMD(p, NV9097, SET_ANTI_ALIAS_ALPHA_CONTROL, {
.alpha_to_coverage = ms->alpha_to_coverage_enable,
.alpha_to_one = ms->alpha_to_one_enable,
});
/* TODO */
P_IMMD(p, NV9097, SET_ANTI_ALIASED_LINE, ENABLE_FALSE);
}
static uint32_t
vk_to_nv9097_blend_op(VkBlendOp vk_op)
{
#define OP(vk, nv) [VK_BLEND_OP_##vk] = NV9097_SET_BLEND_COLOR_OP_V_OGL_##nv
ASSERTED uint16_t vk_to_nv9097[] = {
OP(ADD, FUNC_ADD),
OP(SUBTRACT, FUNC_SUBTRACT),
OP(REVERSE_SUBTRACT, FUNC_REVERSE_SUBTRACT),
OP(MIN, MIN),
OP(MAX, MAX),
};
assert(vk_op < ARRAY_SIZE(vk_to_nv9097));
#undef OP
return vk_to_nv9097[vk_op];
}
static uint32_t
vk_to_nv9097_blend_factor(VkBlendFactor vk_factor)
{
#define FACTOR(vk, nv) [VK_BLEND_FACTOR_##vk] = \
NV9097_SET_BLEND_COLOR_SOURCE_COEFF_V_##nv
ASSERTED uint16_t vk_to_nv9097[] = {
FACTOR(ZERO, OGL_ZERO),
FACTOR(ONE, OGL_ONE),
FACTOR(SRC_COLOR, OGL_SRC_COLOR),
FACTOR(ONE_MINUS_SRC_COLOR, OGL_ONE_MINUS_SRC_COLOR),
FACTOR(DST_COLOR, OGL_DST_COLOR),
FACTOR(ONE_MINUS_DST_COLOR, OGL_ONE_MINUS_DST_COLOR),
FACTOR(SRC_ALPHA, OGL_SRC_ALPHA),
FACTOR(ONE_MINUS_SRC_ALPHA, OGL_ONE_MINUS_SRC_ALPHA),
FACTOR(DST_ALPHA, OGL_DST_ALPHA),
FACTOR(ONE_MINUS_DST_ALPHA, OGL_ONE_MINUS_DST_ALPHA),
FACTOR(CONSTANT_COLOR, OGL_CONSTANT_COLOR),
FACTOR(ONE_MINUS_CONSTANT_COLOR, OGL_ONE_MINUS_CONSTANT_COLOR),
FACTOR(CONSTANT_ALPHA, OGL_CONSTANT_ALPHA),
FACTOR(ONE_MINUS_CONSTANT_ALPHA, OGL_ONE_MINUS_CONSTANT_ALPHA),
FACTOR(SRC_ALPHA_SATURATE, OGL_SRC_ALPHA_SATURATE),
FACTOR(SRC1_COLOR, OGL_SRC1COLOR),
FACTOR(ONE_MINUS_SRC1_COLOR, OGL_INVSRC1COLOR),
FACTOR(SRC1_ALPHA, OGL_SRC1ALPHA),
FACTOR(ONE_MINUS_SRC1_ALPHA, OGL_INVSRC1ALPHA),
};
assert(vk_factor < ARRAY_SIZE(vk_to_nv9097));
#undef FACTOR
return vk_to_nv9097[vk_factor];
}
static void
emit_pipeline_cb_state(struct nvk_graphics_pipeline *pipeline,
const struct vk_color_blend_state *cb)
{
struct nouveau_ws_push *p = &pipeline->push;
P_IMMD(p, NV9097, SET_BLEND_STATE_PER_TARGET, ENABLE_TRUE);
P_IMMD(p, NV9097, SET_LOGIC_OP, cb->logic_op_enable);
for (uint32_t a = 0; a < cb->attachment_count; a++) {
const struct vk_color_blend_attachment_state *att = &cb->attachments[a];
P_IMMD(p, NV9097, SET_BLEND(a), att->blend_enable);
P_MTHD(p, NV9097, SET_BLEND_PER_TARGET_SEPARATE_FOR_ALPHA(a));
P_NV9097_SET_BLEND_PER_TARGET_SEPARATE_FOR_ALPHA(p, a, ENABLE_TRUE);
P_NV9097_SET_BLEND_PER_TARGET_COLOR_OP(p, a,
vk_to_nv9097_blend_op(att->color_blend_op));
P_NV9097_SET_BLEND_PER_TARGET_COLOR_SOURCE_COEFF(p, a,
vk_to_nv9097_blend_factor(att->src_color_blend_factor));
P_NV9097_SET_BLEND_PER_TARGET_COLOR_DEST_COEFF(p, a,
vk_to_nv9097_blend_factor(att->dst_color_blend_factor));
P_NV9097_SET_BLEND_PER_TARGET_ALPHA_OP(p, a,
vk_to_nv9097_blend_op(att->alpha_blend_op));
P_NV9097_SET_BLEND_PER_TARGET_ALPHA_SOURCE_COEFF(p, a,
vk_to_nv9097_blend_factor(att->src_alpha_blend_factor));
P_NV9097_SET_BLEND_PER_TARGET_ALPHA_DEST_COEFF(p, a,
vk_to_nv9097_blend_factor(att->dst_alpha_blend_factor));
P_IMMD(p, NV9097, SET_CT_WRITE(a), {
.r_enable = (att->write_mask & BITFIELD_BIT(0)) != 0,
.g_enable = (att->write_mask & BITFIELD_BIT(1)) != 0,
.b_enable = (att->write_mask & BITFIELD_BIT(2)) != 0,
.a_enable = (att->write_mask & BITFIELD_BIT(3)) != 0,
});
}
}
static const uint32_t mesa_to_nv9097_shader_type[] = {
[MESA_SHADER_VERTEX] = NV9097_SET_PIPELINE_SHADER_TYPE_VERTEX,
[MESA_SHADER_TESS_CTRL] = NV9097_SET_PIPELINE_SHADER_TYPE_TESSELLATION_INIT,
[MESA_SHADER_TESS_EVAL] = NV9097_SET_PIPELINE_SHADER_TYPE_TESSELLATION,
[MESA_SHADER_GEOMETRY] = NV9097_SET_PIPELINE_SHADER_TYPE_GEOMETRY,
[MESA_SHADER_FRAGMENT] = NV9097_SET_PIPELINE_SHADER_TYPE_PIXEL,
};
VkResult
nvk_graphics_pipeline_create(struct nvk_device *device,
struct vk_pipeline_cache *cache,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipeline)
{
VK_FROM_HANDLE(nvk_pipeline_layout, pipeline_layout, pCreateInfo->layout);
struct nvk_physical_device *pdevice = nvk_device_physical(device);
struct nvk_graphics_pipeline *pipeline;
VkResult result = VK_SUCCESS;
pipeline = vk_object_zalloc(&device->vk, pAllocator, sizeof(*pipeline),
VK_OBJECT_TYPE_PIPELINE);
if (pipeline == NULL)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
pipeline->base.type = NVK_PIPELINE_GRAPHICS;
for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
const VkPipelineShaderStageCreateInfo *sinfo = &pCreateInfo->pStages[i];
gl_shader_stage stage = vk_to_mesa_shader_stage(sinfo->stage);
const nir_shader_compiler_options *nir_options =
nvk_physical_device_nir_options(pdevice, stage);
const struct spirv_to_nir_options *spirv_options =
nvk_physical_device_spirv_options(pdevice);
nir_shader *nir;
result = vk_pipeline_shader_stage_to_nir(&device->vk, sinfo,
spirv_options, nir_options,
NULL, &nir);
if (result != VK_SUCCESS)
goto fail;
nvk_lower_nir(device, nir, pipeline_layout);
result = nvk_compile_nir(pdevice, nir, &pipeline->base.shaders[stage]);
ralloc_free(nir);
if (result != VK_SUCCESS)
goto fail;
nvk_shader_upload(device, &pipeline->base.shaders[stage]);
}
nouveau_ws_push_init_cpu(&pipeline->push, &pipeline->push_data,
sizeof(pipeline->push_data));
struct nouveau_ws_push *p = &pipeline->push;
for (gl_shader_stage stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
struct nvk_shader *shader = &pipeline->base.shaders[stage];
uint32_t idx = mesa_to_nv9097_shader_type[stage];
P_IMMD(p, NV9097, SET_PIPELINE_SHADER(idx), {
.enable = shader->bo != NULL,
.type = mesa_to_nv9097_shader_type[stage],
});
if (shader->bo == NULL)
continue;
uint64_t addr = nvk_shader_address(shader);
assert(device->ctx->eng3d.cls >= VOLTA_A);
P_MTHD(p, NVC397, SET_PIPELINE_PROGRAM_ADDRESS_A(idx));
P_NVC397_SET_PIPELINE_PROGRAM_ADDRESS_A(p, idx, addr >> 32 );
P_NVC397_SET_PIPELINE_PROGRAM_ADDRESS_B(p, idx, addr);
P_IMMD(p, NV9097, SET_PIPELINE_REGISTER_COUNT(idx), shader->num_gprs);
switch (stage) {
case MESA_SHADER_VERTEX:
break;
case MESA_SHADER_FRAGMENT:
P_IMMD(p, NV9097, SET_SUBTILING_PERF_KNOB_A, {
.fraction_of_spm_register_file_per_subtile = 0x10,
.fraction_of_spm_pixel_output_buffer_per_subtile = 0x40,
.fraction_of_spm_triangle_ram_per_subtile = 0x16,
.fraction_of_max_quads_per_subtile = 0x20,
});
P_NV9097_SET_SUBTILING_PERF_KNOB_B(p, 0x20);
P_MTHD(p, NV9097, SET_ZCULL_BOUNDS);
P_INLINE_DATA(p, shader->flags[0]);
break;
default:
unreachable("Unsupported shader stage");
}
}
/* TODO: prog_selects_layer */
P_IMMD(p, NV9097, SET_RT_LAYER, {
.v = 0,
.control = CONTROL_V_SELECTS_LAYER,
});
struct vk_graphics_pipeline_all_state all;
struct vk_graphics_pipeline_state state = {};
result = vk_graphics_pipeline_state_fill(&device->vk, &state, pCreateInfo,
NULL, &all, NULL, 0, NULL);
assert(result == VK_SUCCESS);
if (state.ts) emit_pipeline_ts_state(pipeline, state.ts);
if (state.vp) emit_pipeline_vp_state(pipeline, state.vp);
if (state.rs) emit_pipeline_rs_state(pipeline, state.rs);
if (state.ms) emit_pipeline_ms_state(pipeline, state.ms);
if (state.cb) emit_pipeline_cb_state(pipeline, state.cb);
pipeline->dynamic.vi = &pipeline->_dynamic_vi;
pipeline->dynamic.ms.sample_locations = &pipeline->_dynamic_ms_sl;
vk_dynamic_graphics_state_fill(&pipeline->dynamic, &state);
*pPipeline = nvk_pipeline_to_handle(&pipeline->base);
return VK_SUCCESS;
fail:
vk_object_free(&device->vk, pAllocator, pipeline);
return result;
}
-10
View File
@@ -37,16 +37,6 @@ nvk_pipeline_free(struct nvk_device *device,
vk_object_free(&device->vk, pAllocator, pipeline);
}
static VkResult
nvk_graphics_pipeline_create(struct nvk_device *device,
struct vk_pipeline_cache *cache,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipeline)
{
unreachable("Graphics pipelines not yet implemented");
}
VKAPI_ATTR VkResult VKAPI_CALL
nvk_CreateGraphicsPipelines(VkDevice _device,
VkPipelineCache pipelineCache,
+21
View File
@@ -4,6 +4,9 @@
#include "nvk_private.h"
#include "nvk_shader.h"
#include "nouveau_push.h"
#include "vk_graphics_state.h"
#include "vk_object.h"
struct vk_pipeline_cache;
@@ -46,4 +49,22 @@ nvk_compute_pipeline_create(struct nvk_device *device,
const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipeline);
struct nvk_graphics_pipeline {
struct nvk_pipeline base;
struct nouveau_ws_push push;
uint32_t push_data[64];
struct vk_vertex_input_state _dynamic_vi;
struct vk_sample_locations_state _dynamic_ms_sl;
struct vk_dynamic_graphics_state dynamic;
};
VkResult
nvk_graphics_pipeline_create(struct nvk_device *device,
struct vk_pipeline_cache *cache,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipeline *pPipeline);
#endif