1669 lines
58 KiB
C
1669 lines
58 KiB
C
#include "nvk_buffer.h"
|
|
#include "nvk_cmd_buffer.h"
|
|
#include "nvk_device.h"
|
|
#include "nvk_format.h"
|
|
#include "nvk_image.h"
|
|
#include "nvk_image_view.h"
|
|
#include "nvk_mme.h"
|
|
#include "nvk_physical_device.h"
|
|
#include "nvk_pipeline.h"
|
|
|
|
#include "nil_format.h"
|
|
#include "util/bitpack_helpers.h"
|
|
#include "vulkan/runtime/vk_render_pass.h"
|
|
#include "vulkan/util/vk_format.h"
|
|
|
|
#include "nouveau_context.h"
|
|
|
|
#include "nvk_cl9097.h"
|
|
#include "nvk_cla097.h"
|
|
#include "nvk_clb197.h"
|
|
#include "nvk_clc397.h"
|
|
#include "nvk_clc597.h"
|
|
#include "drf.h"
|
|
|
|
static inline uint16_t
|
|
nvk_cmd_buffer_3d_cls(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
return nvk_cmd_buffer_device(cmd)->ctx->eng3d.cls;
|
|
}
|
|
|
|
VkResult
|
|
nvk_queue_init_context_draw_state(struct nvk_queue *queue)
|
|
{
|
|
struct nvk_device *dev = nvk_queue_device(queue);
|
|
|
|
uint32_t push_data[768];
|
|
struct nv_push push;
|
|
nv_push_init(&push, push_data, ARRAY_SIZE(push_data));
|
|
struct nv_push *p = &push;
|
|
|
|
P_MTHD(p, NV9097, SET_OBJECT);
|
|
P_NV9097_SET_OBJECT(p, {
|
|
.class_id = dev->ctx->eng3d.cls,
|
|
.engine_id = 0,
|
|
});
|
|
|
|
for (uint32_t mme = 0, mme_pos = 0; mme < NVK_MME_COUNT; mme++) {
|
|
size_t size;
|
|
uint32_t *dw = nvk_build_mme(dev, mme, &size);
|
|
if (dw == NULL)
|
|
return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
assert(size % sizeof(uint32_t) == 0);
|
|
const uint32_t num_dw = size / sizeof(uint32_t);
|
|
|
|
P_MTHD(p, NV9097, LOAD_MME_START_ADDRESS_RAM_POINTER);
|
|
P_NV9097_LOAD_MME_START_ADDRESS_RAM_POINTER(p, mme);
|
|
P_NV9097_LOAD_MME_START_ADDRESS_RAM(p, mme_pos);
|
|
|
|
P_1INC(p, NV9097, LOAD_MME_INSTRUCTION_RAM_POINTER);
|
|
P_NV9097_LOAD_MME_INSTRUCTION_RAM_POINTER(p, mme_pos);
|
|
P_INLINE_ARRAY(p, dw, num_dw);
|
|
|
|
mme_pos += num_dw;
|
|
|
|
free(dw);
|
|
}
|
|
|
|
P_IMMD(p, NV9097, SET_RENDER_ENABLE_C, MODE_TRUE);
|
|
|
|
P_IMMD(p, NV9097, SET_Z_COMPRESSION, ENABLE_TRUE);
|
|
P_MTHD(p, NV9097, SET_COLOR_COMPRESSION(0));
|
|
for (unsigned i = 0; i < 8; i++)
|
|
P_NV9097_SET_COLOR_COMPRESSION(p, i, ENABLE_TRUE);
|
|
|
|
P_IMMD(p, NV9097, SET_CT_SELECT, { .target_count = 1 });
|
|
|
|
// P_MTHD(cmd->push, NVC0_3D, CSAA_ENABLE);
|
|
// P_INLINE_DATA(cmd->push, 0);
|
|
|
|
P_IMMD(p, NV9097, SET_ALIASED_LINE_WIDTH_ENABLE, V_TRUE);
|
|
|
|
P_IMMD(p, NV9097, SET_DA_PRIMITIVE_RESTART_VERTEX_ARRAY, ENABLE_TRUE);
|
|
|
|
P_IMMD(p, NV9097, SET_BLEND_SEPARATE_FOR_ALPHA, ENABLE_TRUE);
|
|
P_IMMD(p, NV9097, SET_SINGLE_CT_WRITE_CONTROL, ENABLE_TRUE);
|
|
P_IMMD(p, NV9097, SET_SINGLE_ROP_CONTROL, ENABLE_FALSE);
|
|
P_IMMD(p, NV9097, SET_TWO_SIDED_STENCIL_TEST, ENABLE_TRUE);
|
|
|
|
P_IMMD(p, NV9097, SET_SHADE_MODE, V_OGL_SMOOTH);
|
|
|
|
P_IMMD(p, NV9097, SET_API_VISIBLE_CALL_LIMIT, V__128);
|
|
|
|
P_IMMD(p, NV9097, SET_ZCULL_STATS, ENABLE_TRUE);
|
|
|
|
P_IMMD(p, NV9097, SET_L1_CONFIGURATION,
|
|
DIRECTLY_ADDRESSABLE_MEMORY_SIZE_48KB);
|
|
|
|
P_IMMD(p, NV9097, SET_REDUCE_COLOR_THRESHOLDS_ENABLE, V_FALSE);
|
|
P_IMMD(p, NV9097, SET_REDUCE_COLOR_THRESHOLDS_UNORM8, {
|
|
.all_covered_all_hit_once = 0xff,
|
|
});
|
|
P_MTHD(p, NV9097, SET_REDUCE_COLOR_THRESHOLDS_UNORM10);
|
|
P_NV9097_SET_REDUCE_COLOR_THRESHOLDS_UNORM10(p, {
|
|
.all_covered_all_hit_once = 0xff,
|
|
});
|
|
P_NV9097_SET_REDUCE_COLOR_THRESHOLDS_UNORM16(p, {
|
|
.all_covered_all_hit_once = 0xff,
|
|
});
|
|
P_NV9097_SET_REDUCE_COLOR_THRESHOLDS_FP11(p, {
|
|
.all_covered_all_hit_once = 0x3f,
|
|
});
|
|
P_NV9097_SET_REDUCE_COLOR_THRESHOLDS_FP16(p, {
|
|
.all_covered_all_hit_once = 0xff,
|
|
});
|
|
P_NV9097_SET_REDUCE_COLOR_THRESHOLDS_SRGB8(p, {
|
|
.all_covered_all_hit_once = 0xff,
|
|
});
|
|
|
|
if (dev->ctx->eng3d.cls < VOLTA_A)
|
|
P_IMMD(p, NV9097, SET_ALPHA_FRACTION, 0x3f);
|
|
|
|
P_IMMD(p, NV9097, CHECK_SPH_VERSION, {
|
|
.current = 3,
|
|
.oldest_supported = 3,
|
|
});
|
|
P_IMMD(p, NV9097, CHECK_AAM_VERSION, {
|
|
.current = 2,
|
|
.oldest_supported = 2,
|
|
});
|
|
|
|
if (dev->ctx->eng3d.cls < VOLTA_A)
|
|
P_IMMD(p, NV9097, SET_SHADER_SCHEDULING, MODE_OLDEST_THREAD_FIRST);
|
|
|
|
P_IMMD(p, NV9097, SET_L2_CACHE_CONTROL_FOR_ROP_PREFETCH_READ_REQUESTS,
|
|
POLICY_EVICT_NORMAL);
|
|
P_IMMD(p, NV9097, SET_L2_CACHE_CONTROL_FOR_ROP_NONINTERLOCKED_READ_REQUESTS,
|
|
POLICY_EVICT_NORMAL);
|
|
P_IMMD(p, NV9097, SET_L2_CACHE_CONTROL_FOR_ROP_INTERLOCKED_READ_REQUESTS,
|
|
POLICY_EVICT_NORMAL);
|
|
P_IMMD(p, NV9097, SET_L2_CACHE_CONTROL_FOR_ROP_NONINTERLOCKED_WRITE_REQUESTS,
|
|
POLICY_EVICT_NORMAL);
|
|
P_IMMD(p, NV9097, SET_L2_CACHE_CONTROL_FOR_ROP_INTERLOCKED_WRITE_REQUESTS,
|
|
POLICY_EVICT_NORMAL);
|
|
|
|
P_IMMD(p, NV9097, SET_BLEND_PER_FORMAT_ENABLE, SNORM8_UNORM16_SNORM16_TRUE);
|
|
|
|
P_IMMD(p, NV9097, SET_ATTRIBUTE_DEFAULT, {
|
|
.color_front_diffuse = COLOR_FRONT_DIFFUSE_VECTOR_0001,
|
|
.color_front_specular = COLOR_FRONT_SPECULAR_VECTOR_0001,
|
|
.generic_vector = GENERIC_VECTOR_VECTOR_0001,
|
|
.fixed_fnc_texture = FIXED_FNC_TEXTURE_VECTOR_0001,
|
|
.dx9_color0 = DX9_COLOR0_VECTOR_0001,
|
|
.dx9_color1_to_color15 = DX9_COLOR1_TO_COLOR15_VECTOR_0000,
|
|
});
|
|
|
|
P_IMMD(p, NV9097, SET_DA_OUTPUT, VERTEX_ID_USES_ARRAY_START_TRUE);
|
|
|
|
P_IMMD(p, NV9097, SET_RENDER_ENABLE_CONTROL,
|
|
CONDITIONAL_LOAD_CONSTANT_BUFFER_FALSE);
|
|
|
|
P_IMMD(p, NV9097, SET_PS_OUTPUT_SAMPLE_MASK_USAGE, {
|
|
.enable = ENABLE_TRUE,
|
|
.qualify_by_anti_alias_enable = QUALIFY_BY_ANTI_ALIAS_ENABLE_ENABLE,
|
|
});
|
|
|
|
if (dev->ctx->eng3d.cls < VOLTA_A)
|
|
P_IMMD(p, NV9097, SET_PRIM_CIRCULAR_BUFFER_THROTTLE, 0x3fffff);
|
|
|
|
P_IMMD(p, NV9097, SET_BLEND_OPT_CONTROL, ALLOW_FLOAT_PIXEL_KILLS_TRUE);
|
|
P_IMMD(p, NV9097, SET_BLEND_FLOAT_OPTION, ZERO_TIMES_ANYTHING_IS_ZERO_TRUE);
|
|
|
|
if (dev->ctx->eng3d.cls < VOLTA_A)
|
|
P_IMMD(p, NV9097, SET_MAX_TI_WARPS_PER_BATCH, 3);
|
|
|
|
if (dev->ctx->eng3d.cls >= KEPLER_A &&
|
|
dev->ctx->eng3d.cls < VOLTA_A) {
|
|
P_IMMD(p, NVA097, SET_TEXTURE_INSTRUCTION_OPERAND,
|
|
ORDERING_KEPLER_ORDER);
|
|
}
|
|
|
|
P_IMMD(p, NV9097, SET_ALPHA_TEST, ENABLE_FALSE);
|
|
P_IMMD(p, NV9097, SET_TWO_SIDED_LIGHT, ENABLE_FALSE);
|
|
P_IMMD(p, NV9097, SET_COLOR_CLAMP, ENABLE_TRUE);
|
|
P_IMMD(p, NV9097, SET_PS_SATURATE, {
|
|
.output0 = OUTPUT0_FALSE,
|
|
.output1 = OUTPUT1_FALSE,
|
|
.output2 = OUTPUT2_FALSE,
|
|
.output3 = OUTPUT3_FALSE,
|
|
.output4 = OUTPUT4_FALSE,
|
|
.output5 = OUTPUT5_FALSE,
|
|
.output6 = OUTPUT6_FALSE,
|
|
.output7 = OUTPUT7_FALSE,
|
|
});
|
|
|
|
P_IMMD(p, NV9097, SET_ATTRIBUTE_POINT_SIZE, {
|
|
.enable = ENABLE_FALSE,
|
|
.slot = 0,
|
|
});
|
|
P_IMMD(p, NV9097, SET_POINT_SIZE, fui(1.0));
|
|
|
|
P_IMMD(p, NV9097, SET_POINT_SPRITE_SELECT, {
|
|
.rmode = RMODE_ZERO,
|
|
.origin = ORIGIN_TOP,
|
|
.texture0 = TEXTURE0_PASSTHROUGH,
|
|
.texture1 = TEXTURE1_PASSTHROUGH,
|
|
.texture2 = TEXTURE2_PASSTHROUGH,
|
|
.texture3 = TEXTURE3_PASSTHROUGH,
|
|
.texture4 = TEXTURE4_PASSTHROUGH,
|
|
.texture5 = TEXTURE5_PASSTHROUGH,
|
|
.texture6 = TEXTURE6_PASSTHROUGH,
|
|
.texture7 = TEXTURE7_PASSTHROUGH,
|
|
.texture8 = TEXTURE8_PASSTHROUGH,
|
|
.texture9 = TEXTURE9_PASSTHROUGH,
|
|
});
|
|
P_IMMD(p, NV9097, SET_POINT_SPRITE, ENABLE_FALSE);
|
|
P_IMMD(p, NV9097, SET_ANTI_ALIASED_POINT, ENABLE_FALSE);
|
|
|
|
if (dev->ctx->eng3d.cls >= MAXWELL_B)
|
|
P_IMMD(p, NVB197, SET_FILL_VIA_TRIANGLE, MODE_DISABLED);
|
|
|
|
P_IMMD(p, NV9097, SET_POLY_SMOOTH, ENABLE_FALSE);
|
|
|
|
P_IMMD(p, NV9097, SET_VIEWPORT_PIXEL, CENTER_AT_HALF_INTEGERS);
|
|
|
|
P_IMMD(p, NV9097, SET_HYBRID_ANTI_ALIAS_CONTROL, {
|
|
.passes = 1,
|
|
.centroid = CENTROID_PER_FRAGMENT,
|
|
});
|
|
|
|
if (dev->ctx->eng3d.cls >= MAXWELL_B) {
|
|
P_IMMD(p, NVB197, SET_OFFSET_RENDER_TARGET_INDEX,
|
|
BY_VIEWPORT_INDEX_FALSE);
|
|
}
|
|
|
|
/* TODO: Vertex runout */
|
|
|
|
P_IMMD(p, NV9097, SET_WINDOW_ORIGIN, {
|
|
.mode = MODE_UPPER_LEFT,
|
|
.flip_y = FLIP_Y_FALSE,
|
|
});
|
|
|
|
P_MTHD(p, NV9097, SET_WINDOW_OFFSET_X);
|
|
P_NV9097_SET_WINDOW_OFFSET_X(p, 0);
|
|
P_NV9097_SET_WINDOW_OFFSET_Y(p, 0);
|
|
|
|
P_IMMD(p, NV9097, SET_ACTIVE_ZCULL_REGION, 0x3f);
|
|
P_IMMD(p, NV9097, SET_WINDOW_CLIP_ENABLE, V_FALSE);
|
|
P_IMMD(p, NV9097, SET_CLIP_ID_TEST, ENABLE_FALSE);
|
|
|
|
// P_IMMD(p, NV9097, X_X_X_SET_CLEAR_CONTROL, {
|
|
// .respect_stencil_mask = RESPECT_STENCIL_MASK_FALSE,
|
|
// .use_clear_rect = USE_CLEAR_RECT_FALSE,
|
|
// });
|
|
|
|
P_IMMD(p, NV9097, SET_VIEWPORT_SCALE_OFFSET, ENABLE_TRUE);
|
|
|
|
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,
|
|
});
|
|
|
|
for (unsigned i = 0; i < 16; i++)
|
|
P_IMMD(p, NV9097, SET_SCISSOR_ENABLE(i), V_FALSE);
|
|
|
|
P_IMMD(p, NV9097, SET_CT_MRT_ENABLE, V_TRUE);
|
|
|
|
for (uint32_t i = 0; i < 6; i++) {
|
|
P_IMMD(p, NV9097, SET_PIPELINE_SHADER(i), {
|
|
.enable = ENABLE_FALSE,
|
|
.type = i,
|
|
});
|
|
}
|
|
|
|
// P_MTHD(cmd->push, NVC0_3D, MACRO_GP_SELECT);
|
|
// P_INLINE_DATA(cmd->push, 0x40);
|
|
P_IMMD(p, NV9097, SET_RT_LAYER, {
|
|
.v = 0,
|
|
.control = CONTROL_V_SELECTS_LAYER,
|
|
});
|
|
// P_MTHD(cmd->push, NVC0_3D, MACRO_TEP_SELECT;
|
|
// P_INLINE_DATA(cmd->push, 0x30);
|
|
|
|
P_IMMD(p, NV9097, SET_POINT_CENTER_MODE, V_OGL);
|
|
P_IMMD(p, NV9097, SET_EDGE_FLAG, V_TRUE);
|
|
P_IMMD(p, NV9097, SET_SAMPLER_BINDING, V_INDEPENDENTLY);
|
|
|
|
uint64_t zero_addr = dev->zero_page->offset;
|
|
P_MTHD(p, NV9097, SET_VERTEX_STREAM_SUBSTITUTE_A);
|
|
P_NV9097_SET_VERTEX_STREAM_SUBSTITUTE_A(p, zero_addr >> 32);
|
|
P_NV9097_SET_VERTEX_STREAM_SUBSTITUTE_B(p, zero_addr);
|
|
|
|
return nvk_queue_submit_simple(queue, nv_push_dw_count(&push), push_data,
|
|
0, NULL, false /* sync */);
|
|
}
|
|
|
|
void
|
|
nvk_cmd_buffer_begin_graphics(struct nvk_cmd_buffer *cmd,
|
|
const VkCommandBufferBeginInfo *pBeginInfo)
|
|
{
|
|
if (cmd->vk.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY &&
|
|
(pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
|
|
char gcbiar_data[VK_GCBIARR_DATA_SIZE(NVK_MAX_RTS)];
|
|
const VkRenderingInfo *resume_info =
|
|
vk_get_command_buffer_inheritance_as_rendering_resume(cmd->vk.level,
|
|
pBeginInfo,
|
|
gcbiar_data);
|
|
if (resume_info) {
|
|
nvk_CmdBeginRendering(nvk_cmd_buffer_to_handle(cmd), resume_info);
|
|
} else {
|
|
const VkCommandBufferInheritanceRenderingInfo *inheritance_info =
|
|
vk_get_command_buffer_inheritance_rendering_info(cmd->vk.level,
|
|
pBeginInfo);
|
|
assert(inheritance_info);
|
|
|
|
struct nvk_rendering_state *render = &cmd->state.gfx.render;
|
|
render->flags = inheritance_info->flags;
|
|
render->area = (VkRect2D) { };
|
|
render->layer_count = 0;
|
|
render->view_mask = inheritance_info->viewMask;
|
|
|
|
render->color_att_count = inheritance_info->colorAttachmentCount;
|
|
for (uint32_t i = 0; i < render->color_att_count; i++) {
|
|
render->color_att[i].vk_format =
|
|
inheritance_info->pColorAttachmentFormats[i];
|
|
}
|
|
render->depth_att.vk_format =
|
|
inheritance_info->depthAttachmentFormat;
|
|
render->stencil_att.vk_format =
|
|
inheritance_info->stencilAttachmentFormat;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
nvk_attachment_init(struct nvk_attachment *att,
|
|
const VkRenderingAttachmentInfo *info)
|
|
{
|
|
if (info == NULL || info->imageView == VK_NULL_HANDLE) {
|
|
*att = (struct nvk_attachment) { .iview = NULL, };
|
|
return;
|
|
}
|
|
|
|
VK_FROM_HANDLE(nvk_image_view, iview, info->imageView);
|
|
*att = (struct nvk_attachment) {
|
|
.vk_format = iview->vk.format,
|
|
.iview = iview,
|
|
};
|
|
|
|
if (info->resolveMode != VK_RESOLVE_MODE_NONE) {
|
|
VK_FROM_HANDLE(nvk_image_view, res_iview, info->resolveImageView);
|
|
att->resolve_mode = info->resolveMode;
|
|
att->resolve_iview = res_iview;
|
|
}
|
|
}
|
|
|
|
static uint32_t
|
|
nil_to_nv9097_samples_mode(enum nil_sample_layout sample_layout)
|
|
{
|
|
#define MODE(S) [NIL_SAMPLE_LAYOUT_##S] = NV9097_SET_ANTI_ALIAS_SAMPLES_MODE_##S
|
|
uint16_t nil_to_nv9097[] = {
|
|
MODE(1X1),
|
|
MODE(2X1),
|
|
MODE(2X2),
|
|
MODE(4X2),
|
|
MODE(4X4),
|
|
};
|
|
#undef MODE
|
|
assert(sample_layout < ARRAY_SIZE(nil_to_nv9097));
|
|
|
|
return nil_to_nv9097[sample_layout];
|
|
}
|
|
|
|
void
|
|
nvk_CmdBeginRendering(VkCommandBuffer commandBuffer,
|
|
const VkRenderingInfo *pRenderingInfo)
|
|
{
|
|
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
|
|
struct nvk_rendering_state *render = &cmd->state.gfx.render;
|
|
|
|
memset(render, 0, sizeof(*render));
|
|
|
|
render->flags = pRenderingInfo->flags;
|
|
render->area = pRenderingInfo->renderArea;
|
|
render->view_mask = pRenderingInfo->viewMask;
|
|
render->layer_count = pRenderingInfo->layerCount;
|
|
|
|
const uint32_t layer_count =
|
|
render->view_mask ? util_last_bit(render->view_mask) :
|
|
render->layer_count;
|
|
|
|
render->color_att_count = pRenderingInfo->colorAttachmentCount;
|
|
for (uint32_t i = 0; i < render->color_att_count; i++) {
|
|
nvk_attachment_init(&render->color_att[i],
|
|
&pRenderingInfo->pColorAttachments[i]);
|
|
}
|
|
|
|
nvk_attachment_init(&render->depth_att,
|
|
pRenderingInfo->pDepthAttachment);
|
|
nvk_attachment_init(&render->stencil_att,
|
|
pRenderingInfo->pStencilAttachment);
|
|
|
|
/* If we don't have any attachments, emit a dummy color attachment */
|
|
if (render->color_att_count == 0 &&
|
|
render->depth_att.iview == NULL &&
|
|
render->stencil_att.iview == NULL)
|
|
render->color_att_count = 1;
|
|
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, render->color_att_count * 10 + 23);
|
|
|
|
P_MTHD(p, NV9097, SET_SURFACE_CLIP_HORIZONTAL);
|
|
P_NV9097_SET_SURFACE_CLIP_HORIZONTAL(p, {
|
|
.x = render->area.offset.x,
|
|
.width = render->area.extent.width,
|
|
});
|
|
P_NV9097_SET_SURFACE_CLIP_VERTICAL(p, {
|
|
.y = render->area.offset.y,
|
|
.height = render->area.extent.height,
|
|
});
|
|
|
|
enum nil_sample_layout sample_layout = NIL_SAMPLE_LAYOUT_INVALID;
|
|
for (uint32_t i = 0; i < render->color_att_count; i++) {
|
|
if (render->color_att[i].iview) {
|
|
const struct nvk_image_view *iview = render->color_att[i].iview;
|
|
const struct nvk_image *image = (struct nvk_image *)iview->vk.image;
|
|
const struct nil_image_level *level =
|
|
&image->nil.levels[iview->vk.base_mip_level];
|
|
struct nil_extent4d level_extent_sa =
|
|
nil_image_level_extent_sa(&image->nil, iview->vk.base_mip_level);
|
|
|
|
assert(sample_layout == NIL_SAMPLE_LAYOUT_INVALID ||
|
|
sample_layout == image->nil.sample_layout);
|
|
sample_layout = image->nil.sample_layout;
|
|
|
|
uint64_t addr = nvk_image_base_address(image) + level->offset_B;
|
|
|
|
P_MTHD(p, NV9097, SET_COLOR_TARGET_A(i));
|
|
P_NV9097_SET_COLOR_TARGET_A(p, i, addr >> 32);
|
|
P_NV9097_SET_COLOR_TARGET_B(p, i, addr);
|
|
assert(level->tiling.is_tiled);
|
|
P_NV9097_SET_COLOR_TARGET_WIDTH(p, i, level_extent_sa.w);
|
|
P_NV9097_SET_COLOR_TARGET_HEIGHT(p, i, level_extent_sa.h);
|
|
const enum pipe_format p_format =
|
|
vk_format_to_pipe_format(iview->vk.format);
|
|
const uint8_t ct_format = nil_format_to_color_target(p_format);
|
|
P_NV9097_SET_COLOR_TARGET_FORMAT(p, i, ct_format);
|
|
P_NV9097_SET_COLOR_TARGET_MEMORY(p, i, {
|
|
.block_width = BLOCK_WIDTH_ONE_GOB,
|
|
.block_height = level->tiling.y_log2,
|
|
.block_depth = level->tiling.z_log2,
|
|
.layout = LAYOUT_BLOCKLINEAR,
|
|
.third_dimension_control =
|
|
(image->nil.dim == NIL_IMAGE_DIM_3D) ?
|
|
THIRD_DIMENSION_CONTROL_THIRD_DIMENSION_DEFINES_DEPTH_SIZE :
|
|
THIRD_DIMENSION_CONTROL_THIRD_DIMENSION_DEFINES_ARRAY_SIZE,
|
|
});
|
|
P_NV9097_SET_COLOR_TARGET_THIRD_DIMENSION(p, i,
|
|
iview->vk.base_array_layer + layer_count);
|
|
P_NV9097_SET_COLOR_TARGET_ARRAY_PITCH(p, i,
|
|
image->nil.array_stride_B >> 2);
|
|
P_NV9097_SET_COLOR_TARGET_LAYER(p, i, iview->vk.base_array_layer);
|
|
} else {
|
|
P_MTHD(p, NV9097, SET_COLOR_TARGET_A(i));
|
|
P_NV9097_SET_COLOR_TARGET_A(p, i, 0);
|
|
P_NV9097_SET_COLOR_TARGET_B(p, i, 0);
|
|
P_NV9097_SET_COLOR_TARGET_WIDTH(p, i, 64);
|
|
P_NV9097_SET_COLOR_TARGET_HEIGHT(p, i, 0);
|
|
P_NV9097_SET_COLOR_TARGET_FORMAT(p, i, V_DISABLED);
|
|
P_NV9097_SET_COLOR_TARGET_MEMORY(p, i, {
|
|
.layout = LAYOUT_BLOCKLINEAR,
|
|
});
|
|
P_NV9097_SET_COLOR_TARGET_THIRD_DIMENSION(p, i, layer_count);
|
|
P_NV9097_SET_COLOR_TARGET_ARRAY_PITCH(p, i, 0);
|
|
P_NV9097_SET_COLOR_TARGET_LAYER(p, i, 0);
|
|
}
|
|
}
|
|
|
|
P_IMMD(p, NV9097, SET_CT_SELECT, {
|
|
.target_count = render->color_att_count,
|
|
.target0 = 0,
|
|
.target1 = 1,
|
|
.target2 = 2,
|
|
.target3 = 3,
|
|
.target4 = 4,
|
|
.target5 = 5,
|
|
.target6 = 6,
|
|
.target7 = 7,
|
|
});
|
|
|
|
if (render->depth_att.iview || render->stencil_att.iview) {
|
|
struct nvk_image_view *iview = render->depth_att.iview ?
|
|
render->depth_att.iview :
|
|
render->stencil_att.iview;
|
|
const struct nvk_image *image = (struct nvk_image *)iview->vk.image;
|
|
const struct nil_image_level *level =
|
|
&image->nil.levels[iview->vk.base_mip_level];
|
|
struct nil_extent4d level_extent_sa =
|
|
nil_image_level_extent_sa(&image->nil, iview->vk.base_mip_level);
|
|
|
|
assert(sample_layout == NIL_SAMPLE_LAYOUT_INVALID ||
|
|
sample_layout == image->nil.sample_layout);
|
|
sample_layout = image->nil.sample_layout;
|
|
|
|
uint64_t addr = nvk_image_base_address(image) + level->offset_B;
|
|
|
|
P_MTHD(p, NV9097, SET_ZT_A);
|
|
P_NV9097_SET_ZT_A(p, addr >> 32);
|
|
P_NV9097_SET_ZT_B(p, addr);
|
|
const enum pipe_format p_format =
|
|
vk_format_to_pipe_format(iview->vk.format);
|
|
const uint8_t zs_format = nil_format_to_depth_stencil(p_format);
|
|
P_NV9097_SET_ZT_FORMAT(p, zs_format);
|
|
assert(image->nil.dim != NIL_IMAGE_DIM_3D);
|
|
assert(level->tiling.z_log2 == 0);
|
|
P_NV9097_SET_ZT_BLOCK_SIZE(p, {
|
|
.width = WIDTH_ONE_GOB,
|
|
.height = level->tiling.y_log2,
|
|
.depth = DEPTH_ONE_GOB,
|
|
});
|
|
P_NV9097_SET_ZT_ARRAY_PITCH(p, image->nil.array_stride_B >> 2);
|
|
|
|
P_IMMD(p, NV9097, SET_ZT_SELECT, 1 /* target_count */);
|
|
|
|
P_MTHD(p, NV9097, SET_ZT_SIZE_A);
|
|
P_NV9097_SET_ZT_SIZE_A(p, level_extent_sa.w);
|
|
P_NV9097_SET_ZT_SIZE_B(p, level_extent_sa.h);
|
|
P_NV9097_SET_ZT_SIZE_C(p, {
|
|
.third_dimension = iview->vk.base_array_layer + layer_count,
|
|
.control = (image->nil.dim == NIL_IMAGE_DIM_3D) ?
|
|
CONTROL_ARRAY_SIZE_IS_ONE :
|
|
CONTROL_THIRD_DIMENSION_DEFINES_ARRAY_SIZE,
|
|
});
|
|
|
|
P_IMMD(p, NV9097, SET_ZT_LAYER, iview->vk.base_array_layer);
|
|
|
|
if (nvk_cmd_buffer_3d_cls(cmd) >= MAXWELL_B) {
|
|
P_IMMD(p, NVC597, SET_ZT_SPARSE, {
|
|
.enable = ENABLE_FALSE,
|
|
});
|
|
}
|
|
} else {
|
|
P_IMMD(p, NV9097, SET_ZT_SELECT, 0 /* target_count */);
|
|
}
|
|
|
|
if (sample_layout == NIL_SAMPLE_LAYOUT_INVALID)
|
|
sample_layout = NIL_SAMPLE_LAYOUT_1X1;
|
|
|
|
P_IMMD(p, NV9097, SET_ANTI_ALIAS, nil_to_nv9097_samples_mode(sample_layout));
|
|
|
|
if (render->flags & VK_RENDERING_RESUMING_BIT)
|
|
return;
|
|
|
|
uint32_t clear_count = 0;
|
|
VkClearAttachment clear_att[NVK_MAX_RTS + 1];
|
|
for (uint32_t i = 0; i < pRenderingInfo->colorAttachmentCount; i++) {
|
|
const VkRenderingAttachmentInfo *att_info =
|
|
&pRenderingInfo->pColorAttachments[i];
|
|
if (att_info->imageView == VK_NULL_HANDLE ||
|
|
att_info->loadOp != VK_ATTACHMENT_LOAD_OP_CLEAR)
|
|
continue;
|
|
|
|
clear_att[clear_count++] = (VkClearAttachment) {
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
.colorAttachment = i,
|
|
.clearValue = att_info->clearValue,
|
|
};
|
|
}
|
|
|
|
clear_att[clear_count] = (VkClearAttachment) { .aspectMask = 0, };
|
|
if (pRenderingInfo->pDepthAttachment != NULL &&
|
|
pRenderingInfo->pDepthAttachment->imageView != VK_NULL_HANDLE &&
|
|
pRenderingInfo->pDepthAttachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
|
|
clear_att[clear_count].aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
clear_att[clear_count].clearValue.depthStencil.depth =
|
|
pRenderingInfo->pDepthAttachment->clearValue.depthStencil.depth;
|
|
}
|
|
if (pRenderingInfo->pStencilAttachment != NULL &&
|
|
pRenderingInfo->pStencilAttachment->imageView != VK_NULL_HANDLE &&
|
|
pRenderingInfo->pStencilAttachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
|
|
clear_att[clear_count].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
|
clear_att[clear_count].clearValue.depthStencil.stencil =
|
|
pRenderingInfo->pStencilAttachment->clearValue.depthStencil.stencil;
|
|
}
|
|
if (clear_att[clear_count].aspectMask != 0)
|
|
clear_count++;
|
|
|
|
if (clear_count > 0) {
|
|
const VkClearRect clear_rect = {
|
|
.rect = render->area,
|
|
.baseArrayLayer = 0,
|
|
.layerCount = render->view_mask ? 1 : render->layer_count,
|
|
};
|
|
nvk_CmdClearAttachments(nvk_cmd_buffer_to_handle(cmd),
|
|
clear_count, clear_att, 1, &clear_rect);
|
|
}
|
|
|
|
/* TODO: Attachment clears */
|
|
}
|
|
|
|
void
|
|
nvk_CmdEndRendering(VkCommandBuffer commandBuffer)
|
|
{
|
|
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
|
|
struct nvk_rendering_state *render = &cmd->state.gfx.render;
|
|
|
|
bool need_resolve = false;
|
|
|
|
/* Translate render state back to VK for meta */
|
|
VkRenderingAttachmentInfo vk_color_att[NVK_MAX_RTS];
|
|
for (uint32_t i = 0; i < render->color_att_count; i++) {
|
|
if (render->color_att[i].resolve_mode != VK_RESOLVE_MODE_NONE)
|
|
need_resolve = true;
|
|
|
|
vk_color_att[i] = (VkRenderingAttachmentInfo) {
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
.imageView = nvk_image_view_to_handle(render->color_att[i].iview),
|
|
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
.resolveMode = render->color_att[i].resolve_mode,
|
|
.resolveImageView =
|
|
nvk_image_view_to_handle(render->color_att[i].resolve_iview),
|
|
.resolveImageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
};
|
|
}
|
|
|
|
const VkRenderingAttachmentInfo vk_depth_att = {
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
.imageView = nvk_image_view_to_handle(render->depth_att.iview),
|
|
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
.resolveMode = render->depth_att.resolve_mode,
|
|
.resolveImageView =
|
|
nvk_image_view_to_handle(render->depth_att.resolve_iview),
|
|
.resolveImageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
};
|
|
if (render->depth_att.resolve_mode != VK_RESOLVE_MODE_NONE)
|
|
need_resolve = true;
|
|
|
|
const VkRenderingAttachmentInfo vk_stencil_att = {
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
.imageView = nvk_image_view_to_handle(render->stencil_att.iview),
|
|
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
.resolveMode = render->stencil_att.resolve_mode,
|
|
.resolveImageView =
|
|
nvk_image_view_to_handle(render->stencil_att.resolve_iview),
|
|
.resolveImageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
};
|
|
if (render->stencil_att.resolve_mode != VK_RESOLVE_MODE_NONE)
|
|
need_resolve = true;
|
|
|
|
const VkRenderingInfo vk_render = {
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
|
.renderArea = render->area,
|
|
.layerCount = render->layer_count,
|
|
.viewMask = render->view_mask,
|
|
.colorAttachmentCount = render->color_att_count,
|
|
.pColorAttachments = vk_color_att,
|
|
.pDepthAttachment = &vk_depth_att,
|
|
.pStencilAttachment = &vk_stencil_att,
|
|
};
|
|
|
|
if (render->flags & VK_RENDERING_SUSPENDING_BIT)
|
|
need_resolve = false;
|
|
|
|
memset(render, 0, sizeof(*render));
|
|
|
|
if (need_resolve) {
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 2);
|
|
P_IMMD(p, NV9097, WAIT_FOR_IDLE, 0);
|
|
|
|
nvk_meta_resolve_rendering(cmd, &vk_render);
|
|
}
|
|
}
|
|
|
|
void
|
|
nvk_cmd_bind_graphics_pipeline(struct nvk_cmd_buffer *cmd,
|
|
struct nvk_graphics_pipeline *pipeline)
|
|
{
|
|
cmd->state.gfx.pipeline = pipeline;
|
|
vk_cmd_set_dynamic_graphics_state(&cmd->vk, &pipeline->dynamic);
|
|
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, pipeline->push_dw_count);
|
|
nv_push_raw(p, pipeline->push_data, pipeline->push_dw_count);
|
|
}
|
|
|
|
static void
|
|
nvk_flush_vi_state(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
struct nvk_device *dev = nvk_cmd_buffer_device(cmd);
|
|
struct nvk_physical_device *pdev = nvk_device_physical(dev);
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 256);
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VI)) {
|
|
u_foreach_bit(a, dyn->vi->attributes_valid) {
|
|
const struct nvk_va_format *fmt =
|
|
nvk_get_va_format(pdev, dyn->vi->attributes[a].format);
|
|
|
|
P_IMMD(p, NV9097, SET_VERTEX_ATTRIBUTE_A(a), {
|
|
.stream = dyn->vi->attributes[a].binding,
|
|
.offset = dyn->vi->attributes[a].offset,
|
|
.component_bit_widths = fmt->bit_widths,
|
|
.numerical_type = fmt->type,
|
|
.swap_r_and_b = fmt->swap_rb,
|
|
});
|
|
}
|
|
|
|
u_foreach_bit(b, dyn->vi->bindings_valid) {
|
|
const bool instanced = dyn->vi->bindings[b].input_rate ==
|
|
VK_VERTEX_INPUT_RATE_INSTANCE;
|
|
P_IMMD(p, NV9097, SET_VERTEX_STREAM_INSTANCE_A(b), instanced);
|
|
P_IMMD(p, NV9097, SET_VERTEX_STREAM_A_FREQUENCY(b),
|
|
dyn->vi->bindings[b].divisor);
|
|
}
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VI_BINDING_STRIDES)) {
|
|
for (uint32_t b = 0; b < 32; b++) {
|
|
P_IMMD(p, NV9097, SET_VERTEX_STREAM_A_FORMAT(b), {
|
|
.stride = dyn->vi_binding_strides[b],
|
|
.enable = (dyn->vi->bindings_valid & BITFIELD_BIT(b)) != 0,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
nvk_flush_ia_state(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
/** Nothing to do for MESA_VK_DYNAMIC_IA_PRIMITIVE_TOPOLOGY */
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_IA_PRIMITIVE_RESTART_ENABLE)) {
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 2);
|
|
P_IMMD(p, NV9097, SET_DA_PRIMITIVE_RESTART,
|
|
dyn->ia.primitive_restart_enable);
|
|
}
|
|
}
|
|
|
|
static void
|
|
nvk_flush_ts_state(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_TS_PATCH_CONTROL_POINTS)) {
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 2);
|
|
P_IMMD(p, NV9097, SET_PATCH, dyn->ts.patch_control_points);
|
|
}
|
|
}
|
|
|
|
static void
|
|
nvk_flush_vp_state(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
struct nv_push *p =
|
|
nvk_cmd_buffer_push(cmd, 16 * dyn->vp.viewport_count + 4 * NVK_MAX_VIEWPORTS);
|
|
|
|
/* Nothing to do for MESA_VK_DYNAMIC_VP_VIEWPORT_COUNT */
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_VIEWPORTS)) {
|
|
for (uint32_t i = 0; i < dyn->vp.viewport_count; i++) {
|
|
const VkViewport *vp = &dyn->vp.viewports[i];
|
|
|
|
P_MTHD(p, NV9097, SET_VIEWPORT_SCALE_X(i));
|
|
P_NV9097_SET_VIEWPORT_SCALE_X(p, i, fui(0.5f * vp->width));
|
|
P_NV9097_SET_VIEWPORT_SCALE_Y(p, i, fui(0.5f * vp->height));
|
|
P_NV9097_SET_VIEWPORT_SCALE_Z(p, i, fui(vp->maxDepth - vp->minDepth));
|
|
|
|
P_NV9097_SET_VIEWPORT_OFFSET_X(p, i, fui(vp->x + 0.5f * vp->width));
|
|
P_NV9097_SET_VIEWPORT_OFFSET_Y(p, i, fui(vp->y + 0.5f * vp->height));
|
|
P_NV9097_SET_VIEWPORT_OFFSET_Z(p, i, fui(vp->minDepth));
|
|
|
|
const uint32_t xmin = vp->x;
|
|
const uint32_t xmax = vp->x + vp->width;
|
|
const uint32_t ymin = MIN2(vp->y, vp->y + vp->height);
|
|
const uint32_t ymax = MAX2(vp->y, vp->y + vp->height);
|
|
assert(xmin <= xmax && ymin <= ymax);
|
|
|
|
P_MTHD(p, NV9097, SET_VIEWPORT_CLIP_HORIZONTAL(i));
|
|
P_NV9097_SET_VIEWPORT_CLIP_HORIZONTAL(p, i, {
|
|
.x0 = xmin,
|
|
.width = xmax - xmin,
|
|
});
|
|
P_NV9097_SET_VIEWPORT_CLIP_VERTICAL(p, i, {
|
|
.y0 = ymin,
|
|
.height = ymax - ymin,
|
|
});
|
|
P_NV9097_SET_VIEWPORT_CLIP_MIN_Z(p, i, fui(vp->minDepth));
|
|
P_NV9097_SET_VIEWPORT_CLIP_MAX_Z(p, i, fui(vp->maxDepth));
|
|
|
|
if (nvk_cmd_buffer_3d_cls(cmd) >= MAXWELL_B) {
|
|
P_IMMD(p, NVB197, SET_VIEWPORT_COORDINATE_SWIZZLE(i), {
|
|
.x = X_POS_X,
|
|
.y = Y_POS_Y,
|
|
.z = Z_POS_Z,
|
|
.w = W_POS_W,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE)) {
|
|
P_IMMD(p, NV9097, SET_VIEWPORT_Z_CLIP,
|
|
dyn->vp.depth_clip_negative_one_to_one ?
|
|
RANGE_NEGATIVE_W_TO_POSITIVE_W :
|
|
RANGE_ZERO_TO_POSITIVE_W);
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_SCISSOR_COUNT)) {
|
|
for (unsigned i = dyn->vp.scissor_count; i < NVK_MAX_VIEWPORTS; i++)
|
|
P_IMMD(p, NV9097, SET_SCISSOR_ENABLE(i), V_FALSE);
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_SCISSORS)) {
|
|
for (unsigned i = 0; i < dyn->vp.scissor_count; i++) {
|
|
const VkRect2D *s = &dyn->vp.scissors[i];
|
|
|
|
const uint32_t xmin = MIN2(16384, s->offset.x);
|
|
const uint32_t xmax = MIN2(16384, s->offset.x + s->extent.width);
|
|
const uint32_t ymin = MIN2(16384, s->offset.y);
|
|
const uint32_t ymax = MIN2(16384, s->offset.y + s->extent.height);
|
|
|
|
P_MTHD(p, NV9097, SET_SCISSOR_ENABLE(i));
|
|
P_NV9097_SET_SCISSOR_ENABLE(p, i, V_TRUE);
|
|
P_NV9097_SET_SCISSOR_HORIZONTAL(p, i, {
|
|
.xmin = xmin,
|
|
.xmax = xmax,
|
|
});
|
|
P_NV9097_SET_SCISSOR_VERTICAL(p, i, {
|
|
.ymin = ymin,
|
|
.ymax = ymax,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
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_cull_mode(VkCullModeFlags vk_cull_mode)
|
|
{
|
|
static const uint16_t vk_to_nv9097[] = {
|
|
[VK_CULL_MODE_FRONT_BIT] = NV9097_OGL_SET_CULL_FACE_V_FRONT,
|
|
[VK_CULL_MODE_BACK_BIT] = NV9097_OGL_SET_CULL_FACE_V_BACK,
|
|
[VK_CULL_MODE_FRONT_AND_BACK] = NV9097_OGL_SET_CULL_FACE_V_FRONT_AND_BACK,
|
|
};
|
|
assert(vk_cull_mode < ARRAY_SIZE(vk_to_nv9097));
|
|
return vk_to_nv9097[vk_cull_mode];
|
|
}
|
|
|
|
static uint32_t
|
|
vk_to_nv9097_front_face(VkFrontFace vk_face)
|
|
{
|
|
/* Vulkan and OpenGL are backwards here because Vulkan assumes the D3D
|
|
* convention in which framebuffer coordinates always start in the upper
|
|
* left while OpenGL has framebuffer coordinates starting in the lower
|
|
* left. Therefore, we want the reverse of the hardware enum name.
|
|
*/
|
|
ASSERTED static const uint16_t vk_to_nv9097[] = {
|
|
[VK_FRONT_FACE_COUNTER_CLOCKWISE] = NV9097_OGL_SET_FRONT_FACE_V_CCW,
|
|
[VK_FRONT_FACE_CLOCKWISE] = NV9097_OGL_SET_FRONT_FACE_V_CW,
|
|
};
|
|
assert(vk_face < ARRAY_SIZE(vk_to_nv9097));
|
|
|
|
uint32_t nv9097_face = 0x900 | (1 - vk_face);
|
|
assert(nv9097_face == vk_to_nv9097[vk_face]);
|
|
return nv9097_face;
|
|
}
|
|
|
|
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
|
|
nvk_flush_rs_state(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 32);
|
|
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_RASTERIZER_DISCARD_ENABLE))
|
|
P_IMMD(p, NV9097, SET_RASTER_ENABLE, !dyn->rs.rasterizer_discard_enable);
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_POLYGON_MODE)) {
|
|
uint32_t polygon_mode = vk_to_nv9097_polygon_mode(dyn->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);
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_CULL_MODE)) {
|
|
P_IMMD(p, NV9097, OGL_SET_CULL, dyn->rs.cull_mode != VK_CULL_MODE_NONE);
|
|
|
|
if (dyn->rs.cull_mode != VK_CULL_MODE_NONE) {
|
|
uint32_t face = vk_to_nv9097_cull_mode(dyn->rs.cull_mode);
|
|
P_IMMD(p, NV9097, OGL_SET_CULL_FACE, face);
|
|
}
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_FRONT_FACE)) {
|
|
P_IMMD(p, NV9097, OGL_SET_FRONT_FACE,
|
|
vk_to_nv9097_front_face(dyn->rs.front_face));
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_PROVOKING_VERTEX)) {
|
|
P_IMMD(p, NV9097, SET_PROVOKING_VERTEX,
|
|
vk_to_nv9097_provoking_vertex(dyn->rs.provoking_vertex));
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_DEPTH_BIAS_ENABLE)) {
|
|
P_MTHD(p, NV9097, SET_POLY_OFFSET_POINT);
|
|
P_NV9097_SET_POLY_OFFSET_POINT(p, dyn->rs.depth_bias.enable);
|
|
P_NV9097_SET_POLY_OFFSET_LINE(p, dyn->rs.depth_bias.enable);
|
|
P_NV9097_SET_POLY_OFFSET_FILL(p, dyn->rs.depth_bias.enable);
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_DEPTH_BIAS_FACTORS)) {
|
|
P_IMMD(p, NV9097, SET_DEPTH_BIAS, fui(dyn->rs.depth_bias.constant));
|
|
P_IMMD(p, NV9097, SET_SLOPE_SCALE_DEPTH_BIAS, fui(dyn->rs.depth_bias.slope));
|
|
P_IMMD(p, NV9097, SET_DEPTH_BIAS_CLAMP, fui(dyn->rs.depth_bias.clamp));
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_LINE_WIDTH)) {
|
|
P_MTHD(p, NV9097, SET_LINE_WIDTH_FLOAT);
|
|
P_NV9097_SET_LINE_WIDTH_FLOAT(p, fui(dyn->rs.line.width));
|
|
P_NV9097_SET_ALIASED_LINE_WIDTH_FLOAT(p, fui(dyn->rs.line.width));
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_LINE_STIPPLE_ENABLE))
|
|
P_IMMD(p, NV9097, SET_LINE_STIPPLE, dyn->rs.line.stipple.enable);
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_LINE_STIPPLE)) {
|
|
P_IMMD(p, NV9097, SET_LINE_STIPPLE_PARAMETERS, {
|
|
.factor = dyn->rs.line.stipple.factor,
|
|
.pattern = dyn->rs.line.stipple.pattern,
|
|
});
|
|
}
|
|
}
|
|
|
|
static VkSampleLocationEXT
|
|
vk_sample_location(const struct vk_sample_locations_state *sl,
|
|
uint32_t x, uint32_t y, uint32_t s)
|
|
{
|
|
x = x % sl->grid_size.width;
|
|
y = y % sl->grid_size.height;
|
|
|
|
return sl->locations[(x + y * sl->grid_size.width) * sl->per_pixel + s];
|
|
}
|
|
|
|
struct nvk_sample_location {
|
|
uint8_t x_u4:4;
|
|
uint8_t y_u4:4;
|
|
};
|
|
|
|
static struct nvk_sample_location
|
|
vk_to_nvk_sample_location(VkSampleLocationEXT loc)
|
|
{
|
|
return (struct nvk_sample_location) {
|
|
.x_u4 = util_bitpack_ufixed(loc.x, 0, 3, 4),
|
|
.y_u4 = util_bitpack_ufixed(loc.y, 0, 3, 4),
|
|
};
|
|
}
|
|
|
|
static void
|
|
nvk_flush_ms_state(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_MS_SAMPLE_LOCATIONS)) {
|
|
const struct vk_sample_locations_state *sl = dyn->ms.sample_locations;
|
|
|
|
if (nvk_cmd_buffer_3d_cls(cmd) >= MAXWELL_B) {
|
|
struct nvk_sample_location loc[16];
|
|
for (uint32_t n = 0; n < ARRAY_SIZE(loc); n++) {
|
|
const uint32_t s = n % sl->per_pixel;
|
|
const uint32_t px = n / sl->per_pixel;
|
|
const uint32_t x = px % 2;
|
|
const uint32_t y = px / 2;
|
|
|
|
loc[n] = vk_to_nvk_sample_location(vk_sample_location(sl, x, y, s));
|
|
}
|
|
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 5);
|
|
|
|
P_MTHD(p, NVB197, SET_ANTI_ALIAS_SAMPLE_POSITIONS(0));
|
|
for (uint32_t i = 0; i < 4; i++) {
|
|
P_NVB197_SET_ANTI_ALIAS_SAMPLE_POSITIONS(p, i, {
|
|
.x0 = loc[i * 4 + 0].x_u4,
|
|
.y0 = loc[i * 4 + 0].y_u4,
|
|
.x1 = loc[i * 4 + 1].x_u4,
|
|
.y1 = loc[i * 4 + 1].y_u4,
|
|
.x2 = loc[i * 4 + 2].x_u4,
|
|
.y2 = loc[i * 4 + 2].y_u4,
|
|
.x3 = loc[i * 4 + 3].x_u4,
|
|
.y3 = loc[i * 4 + 3].y_u4,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static uint32_t
|
|
vk_to_nv9097_compare_op(VkCompareOp vk_op)
|
|
{
|
|
ASSERTED static const uint16_t vk_to_nv9097[] = {
|
|
[VK_COMPARE_OP_NEVER] = NV9097_SET_DEPTH_FUNC_V_OGL_NEVER,
|
|
[VK_COMPARE_OP_LESS] = NV9097_SET_DEPTH_FUNC_V_OGL_LESS,
|
|
[VK_COMPARE_OP_EQUAL] = NV9097_SET_DEPTH_FUNC_V_OGL_EQUAL,
|
|
[VK_COMPARE_OP_LESS_OR_EQUAL] = NV9097_SET_DEPTH_FUNC_V_OGL_LEQUAL,
|
|
[VK_COMPARE_OP_GREATER] = NV9097_SET_DEPTH_FUNC_V_OGL_GREATER,
|
|
[VK_COMPARE_OP_NOT_EQUAL] = NV9097_SET_DEPTH_FUNC_V_OGL_NOTEQUAL,
|
|
[VK_COMPARE_OP_GREATER_OR_EQUAL] = NV9097_SET_DEPTH_FUNC_V_OGL_GEQUAL,
|
|
[VK_COMPARE_OP_ALWAYS] = NV9097_SET_DEPTH_FUNC_V_OGL_ALWAYS,
|
|
};
|
|
assert(vk_op < ARRAY_SIZE(vk_to_nv9097));
|
|
|
|
uint32_t nv9097_op = 0x200 | vk_op;
|
|
assert(nv9097_op == vk_to_nv9097[vk_op]);
|
|
return nv9097_op;
|
|
}
|
|
|
|
static uint32_t
|
|
vk_to_nv9097_stencil_op(VkStencilOp vk_op)
|
|
{
|
|
#define OP(vk, nv) [VK_STENCIL_OP_##vk] = NV9097_SET_STENCIL_OP_FAIL_V_##nv
|
|
ASSERTED static const uint16_t vk_to_nv9097[] = {
|
|
OP(KEEP, D3D_KEEP),
|
|
OP(ZERO, D3D_ZERO),
|
|
OP(REPLACE, D3D_REPLACE),
|
|
OP(INCREMENT_AND_CLAMP, D3D_INCRSAT),
|
|
OP(DECREMENT_AND_CLAMP, D3D_DECRSAT),
|
|
OP(INVERT, D3D_INVERT),
|
|
OP(INCREMENT_AND_WRAP, D3D_INCR),
|
|
OP(DECREMENT_AND_WRAP, D3D_DECR),
|
|
};
|
|
assert(vk_op < ARRAY_SIZE(vk_to_nv9097));
|
|
#undef OP
|
|
|
|
uint32_t nv9097_op = vk_op + 1;
|
|
assert(nv9097_op == vk_to_nv9097[vk_op]);
|
|
return nv9097_op;
|
|
}
|
|
|
|
static void
|
|
nvk_flush_ds_state(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 35);
|
|
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_TEST_ENABLE))
|
|
P_IMMD(p, NV9097, SET_DEPTH_TEST, dyn->ds.depth.test_enable);
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_WRITE_ENABLE))
|
|
P_IMMD(p, NV9097, SET_DEPTH_WRITE, dyn->ds.depth.write_enable);
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_COMPARE_OP)) {
|
|
const uint32_t func = vk_to_nv9097_compare_op(dyn->ds.depth.compare_op);
|
|
P_IMMD(p, NV9097, SET_DEPTH_FUNC, func);
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_ENABLE))
|
|
P_IMMD(p, NV9097, SET_DEPTH_BOUNDS_TEST, dyn->ds.depth.bounds_test.enable);
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_BOUNDS)) {
|
|
P_MTHD(p, NV9097, SET_DEPTH_BOUNDS_MIN);
|
|
P_NV9097_SET_DEPTH_BOUNDS_MIN(p, fui(dyn->ds.depth.bounds_test.min));
|
|
P_NV9097_SET_DEPTH_BOUNDS_MAX(p, fui(dyn->ds.depth.bounds_test.max));
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE))
|
|
P_IMMD(p, NV9097, SET_STENCIL_TEST, dyn->ds.stencil.test_enable);
|
|
|
|
const struct vk_stencil_test_face_state *front = &dyn->ds.stencil.front;
|
|
const struct vk_stencil_test_face_state *back = &dyn->ds.stencil.back;
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_OP)) {
|
|
P_MTHD(p, NV9097, SET_STENCIL_OP_FAIL);
|
|
P_NV9097_SET_STENCIL_OP_FAIL(p, vk_to_nv9097_stencil_op(front->op.fail));
|
|
P_NV9097_SET_STENCIL_OP_ZFAIL(p, vk_to_nv9097_stencil_op(front->op.depth_fail));
|
|
P_NV9097_SET_STENCIL_OP_ZPASS(p, vk_to_nv9097_stencil_op(front->op.pass));
|
|
P_NV9097_SET_STENCIL_FUNC(p, vk_to_nv9097_compare_op(front->op.compare));
|
|
|
|
P_MTHD(p, NV9097, SET_BACK_STENCIL_OP_FAIL);
|
|
P_NV9097_SET_BACK_STENCIL_OP_FAIL(p, vk_to_nv9097_stencil_op(back->op.fail));
|
|
P_NV9097_SET_BACK_STENCIL_OP_ZFAIL(p, vk_to_nv9097_stencil_op(back->op.depth_fail));
|
|
P_NV9097_SET_BACK_STENCIL_OP_ZPASS(p, vk_to_nv9097_stencil_op(back->op.pass));
|
|
P_NV9097_SET_BACK_STENCIL_FUNC(p, vk_to_nv9097_compare_op(back->op.compare));
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK)) {
|
|
P_IMMD(p, NV9097, SET_STENCIL_FUNC_MASK, front->compare_mask);
|
|
P_IMMD(p, NV9097, SET_BACK_STENCIL_FUNC_MASK, back->compare_mask);
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK)) {
|
|
P_IMMD(p, NV9097, SET_STENCIL_MASK, front->write_mask);
|
|
P_IMMD(p, NV9097, SET_BACK_STENCIL_MASK, back->write_mask);
|
|
}
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE)) {
|
|
P_IMMD(p, NV9097, SET_STENCIL_FUNC_REF, front->reference);
|
|
P_IMMD(p, NV9097, SET_BACK_STENCIL_FUNC_REF, back->reference);
|
|
}
|
|
}
|
|
|
|
static uint32_t
|
|
vk_to_nv9097_logic_op(VkLogicOp vk_op)
|
|
{
|
|
ASSERTED uint16_t vk_to_nv9097[] = {
|
|
[VK_LOGIC_OP_CLEAR] = NV9097_SET_LOGIC_OP_FUNC_V_CLEAR,
|
|
[VK_LOGIC_OP_AND] = NV9097_SET_LOGIC_OP_FUNC_V_AND,
|
|
[VK_LOGIC_OP_AND_REVERSE] = NV9097_SET_LOGIC_OP_FUNC_V_AND_REVERSE,
|
|
[VK_LOGIC_OP_COPY] = NV9097_SET_LOGIC_OP_FUNC_V_COPY,
|
|
[VK_LOGIC_OP_AND_INVERTED] = NV9097_SET_LOGIC_OP_FUNC_V_AND_INVERTED,
|
|
[VK_LOGIC_OP_NO_OP] = NV9097_SET_LOGIC_OP_FUNC_V_NOOP,
|
|
[VK_LOGIC_OP_XOR] = NV9097_SET_LOGIC_OP_FUNC_V_XOR,
|
|
[VK_LOGIC_OP_OR] = NV9097_SET_LOGIC_OP_FUNC_V_OR,
|
|
[VK_LOGIC_OP_NOR] = NV9097_SET_LOGIC_OP_FUNC_V_NOR,
|
|
[VK_LOGIC_OP_EQUIVALENT] = NV9097_SET_LOGIC_OP_FUNC_V_EQUIV,
|
|
[VK_LOGIC_OP_INVERT] = NV9097_SET_LOGIC_OP_FUNC_V_INVERT,
|
|
[VK_LOGIC_OP_OR_REVERSE] = NV9097_SET_LOGIC_OP_FUNC_V_OR_REVERSE,
|
|
[VK_LOGIC_OP_COPY_INVERTED] = NV9097_SET_LOGIC_OP_FUNC_V_COPY_INVERTED,
|
|
[VK_LOGIC_OP_OR_INVERTED] = NV9097_SET_LOGIC_OP_FUNC_V_OR_INVERTED,
|
|
[VK_LOGIC_OP_NAND] = NV9097_SET_LOGIC_OP_FUNC_V_NAND,
|
|
[VK_LOGIC_OP_SET] = NV9097_SET_LOGIC_OP_FUNC_V_SET,
|
|
};
|
|
assert(vk_op < ARRAY_SIZE(vk_to_nv9097));
|
|
|
|
uint32_t nv9097_op = 0x1500 | vk_op;
|
|
assert(nv9097_op == vk_to_nv9097[vk_op]);
|
|
return nv9097_op;
|
|
}
|
|
|
|
static void
|
|
nvk_flush_cb_state(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 9);
|
|
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_LOGIC_OP_ENABLE))
|
|
P_IMMD(p, NV9097, SET_LOGIC_OP, dyn->cb.logic_op_enable);
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_LOGIC_OP)) {
|
|
const uint32_t func = vk_to_nv9097_logic_op(dyn->cb.logic_op);
|
|
P_IMMD(p, NV9097, SET_LOGIC_OP_FUNC, func);
|
|
}
|
|
|
|
/* MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES */
|
|
|
|
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS)) {
|
|
P_MTHD(p, NV9097, SET_BLEND_CONST_RED);
|
|
P_NV9097_SET_BLEND_CONST_RED(p, fui(dyn->cb.blend_constants[0]));
|
|
P_NV9097_SET_BLEND_CONST_GREEN(p, fui(dyn->cb.blend_constants[1]));
|
|
P_NV9097_SET_BLEND_CONST_BLUE(p, fui(dyn->cb.blend_constants[2]));
|
|
P_NV9097_SET_BLEND_CONST_ALPHA(p, fui(dyn->cb.blend_constants[3]));
|
|
}
|
|
}
|
|
|
|
static void
|
|
nvk_flush_dynamic_state(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
if (!vk_dynamic_graphics_state_any_dirty(dyn))
|
|
return;
|
|
|
|
nvk_flush_vi_state(cmd);
|
|
nvk_flush_ia_state(cmd);
|
|
nvk_flush_ts_state(cmd);
|
|
nvk_flush_vp_state(cmd);
|
|
nvk_flush_rs_state(cmd);
|
|
|
|
/* MESA_VK_DYNAMIC_FSR */
|
|
|
|
nvk_flush_ms_state(cmd);
|
|
nvk_flush_ds_state(cmd);
|
|
nvk_flush_cb_state(cmd);
|
|
|
|
vk_dynamic_graphics_state_clear_dirty(dyn);
|
|
}
|
|
|
|
static void
|
|
nvk_flush_descriptors(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
struct nvk_descriptor_state *desc = &cmd->state.gfx.descriptors;
|
|
VkResult result;
|
|
|
|
nvk_cmd_buffer_flush_push_descriptors(cmd, desc);
|
|
|
|
uint64_t root_table_addr;
|
|
result = nvk_cmd_buffer_upload_data(cmd, &desc->root, sizeof(desc->root),
|
|
NVK_MIN_UBO_ALIGNMENT,
|
|
&root_table_addr);
|
|
if (unlikely(result != VK_SUCCESS)) {
|
|
vk_command_buffer_set_error(&cmd->vk, result);
|
|
return;
|
|
}
|
|
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 26);
|
|
|
|
P_MTHD(p, NV9097, SET_CONSTANT_BUFFER_SELECTOR_A);
|
|
P_NV9097_SET_CONSTANT_BUFFER_SELECTOR_A(p, sizeof(desc->root));
|
|
P_NV9097_SET_CONSTANT_BUFFER_SELECTOR_B(p, root_table_addr >> 32);
|
|
P_NV9097_SET_CONSTANT_BUFFER_SELECTOR_C(p, root_table_addr);
|
|
|
|
for (uint32_t i = 0; i < 5; i++) {
|
|
P_IMMD(p, NV9097, BIND_GROUP_CONSTANT_BUFFER(i), {
|
|
.valid = VALID_TRUE,
|
|
.shader_slot = 0,
|
|
});
|
|
P_IMMD(p, NV9097, BIND_GROUP_CONSTANT_BUFFER(i), {
|
|
.valid = VALID_TRUE,
|
|
.shader_slot = 1,
|
|
});
|
|
}
|
|
|
|
assert(nvk_cmd_buffer_3d_cls(cmd) >= KEPLER_A);
|
|
P_IMMD(p, NVA097, INVALIDATE_SHADER_CACHES_NO_WFI, {
|
|
.constant = CONSTANT_TRUE,
|
|
});
|
|
}
|
|
|
|
static void
|
|
nvk_flush_gfx_state(struct nvk_cmd_buffer *cmd)
|
|
{
|
|
nvk_flush_dynamic_state(cmd);
|
|
nvk_flush_descriptors(cmd);
|
|
}
|
|
|
|
static uint32_t
|
|
vk_to_nv_index_format(VkIndexType type)
|
|
{
|
|
switch (type) {
|
|
case VK_INDEX_TYPE_UINT16:
|
|
return NVC597_SET_INDEX_BUFFER_E_INDEX_SIZE_TWO_BYTES;
|
|
case VK_INDEX_TYPE_UINT32:
|
|
return NVC597_SET_INDEX_BUFFER_E_INDEX_SIZE_FOUR_BYTES;
|
|
case VK_INDEX_TYPE_UINT8_EXT:
|
|
return NVC597_SET_INDEX_BUFFER_E_INDEX_SIZE_ONE_BYTE;
|
|
default:
|
|
unreachable("Invalid index type");
|
|
}
|
|
}
|
|
|
|
static uint32_t
|
|
vk_index_to_restart(VkIndexType index_type)
|
|
{
|
|
switch (index_type) {
|
|
case VK_INDEX_TYPE_UINT16:
|
|
return 0xffff;
|
|
case VK_INDEX_TYPE_UINT32:
|
|
return 0xffffffff;
|
|
case VK_INDEX_TYPE_UINT8_EXT:
|
|
return 0xff;
|
|
default:
|
|
unreachable("unexpected index type");
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
nvk_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,
|
|
VkBuffer _buffer,
|
|
VkDeviceSize offset,
|
|
VkIndexType indexType)
|
|
{
|
|
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
|
|
VK_FROM_HANDLE(nvk_buffer, buffer, _buffer);
|
|
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 10);
|
|
|
|
uint64_t addr, range;
|
|
if (buffer) {
|
|
addr = nvk_buffer_address(buffer, offset);
|
|
range = vk_buffer_range(&buffer->vk, offset, VK_WHOLE_SIZE);
|
|
} else {
|
|
range = addr = 0;
|
|
}
|
|
|
|
P_IMMD(p, NV9097, SET_DA_PRIMITIVE_RESTART_INDEX,
|
|
vk_index_to_restart(indexType));
|
|
|
|
P_MTHD(p, NV9097, SET_INDEX_BUFFER_A);
|
|
P_NV9097_SET_INDEX_BUFFER_A(p, addr >> 32);
|
|
P_NV9097_SET_INDEX_BUFFER_B(p, addr);
|
|
|
|
if (nvk_cmd_buffer_3d_cls(cmd) >= TURING_A) {
|
|
P_MTHD(p, NVC597, SET_INDEX_BUFFER_SIZE_A);
|
|
P_NVC597_SET_INDEX_BUFFER_SIZE_A(p, range >> 32);
|
|
P_NVC597_SET_INDEX_BUFFER_SIZE_B(p, range);
|
|
} else {
|
|
uint64_t limit = addr + range;
|
|
P_MTHD(p, NV9097, SET_INDEX_BUFFER_C);
|
|
P_NV9097_SET_INDEX_BUFFER_C(p, limit >> 32);
|
|
P_NV9097_SET_INDEX_BUFFER_D(p, limit);
|
|
}
|
|
|
|
P_IMMD(p, NV9097, SET_INDEX_BUFFER_E, vk_to_nv_index_format(indexType));
|
|
}
|
|
|
|
void
|
|
nvk_cmd_bind_vertex_buffer(struct nvk_cmd_buffer *cmd, uint32_t vb_idx,
|
|
struct nvk_addr_range addr_range)
|
|
{
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 6);
|
|
|
|
P_MTHD(p, NV9097, SET_VERTEX_STREAM_A_LOCATION_A(vb_idx));
|
|
P_NV9097_SET_VERTEX_STREAM_A_LOCATION_A(p, vb_idx, addr_range.addr >> 32);
|
|
P_NV9097_SET_VERTEX_STREAM_A_LOCATION_B(p, vb_idx, addr_range.addr);
|
|
|
|
if (nvk_cmd_buffer_3d_cls(cmd) >= TURING_A) {
|
|
P_MTHD(p, NVC597, SET_VERTEX_STREAM_SIZE_A(vb_idx));
|
|
P_NVC597_SET_VERTEX_STREAM_SIZE_A(p, vb_idx, addr_range.range >> 32);
|
|
P_NVC597_SET_VERTEX_STREAM_SIZE_B(p, vb_idx, addr_range.range);
|
|
} else {
|
|
uint64_t limit = addr_range.addr + addr_range.range - 1;
|
|
P_MTHD(p, NV9097, SET_VERTEX_STREAM_LIMIT_A_A(vb_idx));
|
|
P_NV9097_SET_VERTEX_STREAM_LIMIT_A_A(p, vb_idx, limit >> 32);
|
|
P_NV9097_SET_VERTEX_STREAM_LIMIT_A_B(p, vb_idx, limit);
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
nvk_CmdBindVertexBuffers2(VkCommandBuffer commandBuffer,
|
|
uint32_t firstBinding,
|
|
uint32_t bindingCount,
|
|
const VkBuffer *pBuffers,
|
|
const VkDeviceSize *pOffsets,
|
|
const VkDeviceSize *pSizes,
|
|
const VkDeviceSize *pStrides)
|
|
{
|
|
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
|
|
|
|
if (pStrides) {
|
|
vk_cmd_set_vertex_binding_strides(&cmd->vk, firstBinding,
|
|
bindingCount, pStrides);
|
|
}
|
|
|
|
for (uint32_t i = 0; i < bindingCount; i++) {
|
|
VK_FROM_HANDLE(nvk_buffer, buffer, pBuffers[i]);
|
|
uint32_t idx = firstBinding + i;
|
|
|
|
uint64_t size = pSizes ? pSizes[i] : VK_WHOLE_SIZE;
|
|
struct nvk_addr_range addr_range = { };
|
|
if (buffer) {
|
|
addr_range.addr = nvk_buffer_address(buffer, pOffsets[i]);
|
|
addr_range.range = vk_buffer_range(&buffer->vk, pOffsets[i], size);
|
|
}
|
|
|
|
/* Used for meta save/restore */
|
|
if (idx == 0)
|
|
cmd->state.gfx.vb0 = addr_range;
|
|
|
|
nvk_cmd_bind_vertex_buffer(cmd, idx, addr_range);
|
|
}
|
|
}
|
|
|
|
static uint32_t
|
|
vk_to_nv9097_primitive_topology(VkPrimitiveTopology prim)
|
|
{
|
|
switch (prim) {
|
|
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
|
|
return NV9097_BEGIN_OP_POINTS;
|
|
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
|
|
return NV9097_BEGIN_OP_LINES;
|
|
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
|
|
return NV9097_BEGIN_OP_LINE_STRIP;
|
|
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wswitch"
|
|
case VK_PRIMITIVE_TOPOLOGY_META_RECT_LIST_MESA:
|
|
#pragma GCC diagnostic pop
|
|
return NV9097_BEGIN_OP_TRIANGLES;
|
|
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
|
|
return NV9097_BEGIN_OP_TRIANGLE_STRIP;
|
|
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
|
|
return NV9097_BEGIN_OP_TRIANGLE_FAN;
|
|
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
|
|
return NV9097_BEGIN_OP_LINELIST_ADJCY;
|
|
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
|
|
return NV9097_BEGIN_OP_LINESTRIP_ADJCY;
|
|
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
|
|
return NV9097_BEGIN_OP_TRIANGLELIST_ADJCY;
|
|
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
|
|
return NV9097_BEGIN_OP_TRIANGLESTRIP_ADJCY;
|
|
case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
|
|
return NV9097_BEGIN_OP_PATCH;
|
|
default:
|
|
unreachable("Invalid primitive topology");
|
|
}
|
|
}
|
|
|
|
static void
|
|
nvk_build_mme_draw(struct mme_builder *b, struct mme_value begin)
|
|
{
|
|
/* These are in VkDrawIndirectCommand order */
|
|
struct mme_value vertex_count = mme_load(b);
|
|
struct mme_value instance_count = mme_load(b);
|
|
struct mme_value first_vertex = mme_load(b);
|
|
struct mme_value first_instance = mme_load(b);
|
|
|
|
mme_mthd(b, NV9097_SET_GLOBAL_BASE_INSTANCE_INDEX);
|
|
mme_emit(b, first_instance);
|
|
|
|
mme_loop(b, instance_count) {
|
|
mme_mthd(b, NV9097_BEGIN);
|
|
mme_emit(b, begin);
|
|
|
|
mme_mthd(b, NV9097_SET_VERTEX_ARRAY_START);
|
|
mme_emit(b, first_vertex);
|
|
mme_emit(b, vertex_count);
|
|
|
|
mme_mthd(b, NV9097_END);
|
|
mme_emit(b, mme_zero());
|
|
|
|
mme_set_field_enum(b, begin, NV9097_BEGIN_INSTANCE_ID, SUBSEQUENT);
|
|
}
|
|
}
|
|
|
|
void
|
|
nvk_mme_draw(struct nvk_device *dev, struct mme_builder *b)
|
|
{
|
|
struct mme_value begin = mme_load(b);
|
|
|
|
nvk_build_mme_draw(b, begin);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
nvk_CmdDraw(VkCommandBuffer commandBuffer,
|
|
uint32_t vertexCount,
|
|
uint32_t instanceCount,
|
|
uint32_t firstVertex,
|
|
uint32_t firstInstance)
|
|
{
|
|
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
nvk_flush_gfx_state(cmd);
|
|
|
|
uint32_t begin;
|
|
V_NV9097_BEGIN(begin, {
|
|
.op = vk_to_nv9097_primitive_topology(dyn->ia.primitive_topology),
|
|
.primitive_id = NV9097_BEGIN_PRIMITIVE_ID_FIRST,
|
|
.instance_id = NV9097_BEGIN_INSTANCE_ID_FIRST,
|
|
.split_mode = SPLIT_MODE_NORMAL_BEGIN_NORMAL_END,
|
|
});
|
|
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 6);
|
|
P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_DRAW));
|
|
P_INLINE_DATA(p, begin);
|
|
P_INLINE_DATA(p, vertexCount);
|
|
P_INLINE_DATA(p, instanceCount);
|
|
P_INLINE_DATA(p, firstVertex);
|
|
P_INLINE_DATA(p, firstInstance);
|
|
}
|
|
|
|
static void
|
|
nvk_mme_build_draw_indexed(struct mme_builder *b,
|
|
struct mme_value begin)
|
|
{
|
|
/* These are in VkDrawIndexedIndirectCommand order */
|
|
struct mme_value index_count = mme_load(b);
|
|
struct mme_value instance_count = mme_load(b);
|
|
struct mme_value first_index = mme_load(b);
|
|
struct mme_value vertex_offset = mme_load(b);
|
|
struct mme_value first_instance = mme_load(b);
|
|
|
|
mme_mthd(b, NV9097_SET_GLOBAL_BASE_VERTEX_INDEX);
|
|
mme_emit(b, vertex_offset);
|
|
|
|
mme_mthd(b, NV9097_SET_VERTEX_ID_BASE);
|
|
mme_emit(b, vertex_offset);
|
|
|
|
mme_mthd(b, NV9097_SET_GLOBAL_BASE_INSTANCE_INDEX);
|
|
mme_emit(b, first_instance);
|
|
|
|
mme_loop(b, instance_count) {
|
|
mme_mthd(b, NV9097_BEGIN);
|
|
mme_emit(b, begin);
|
|
|
|
mme_mthd(b, NV9097_SET_INDEX_BUFFER_F);
|
|
mme_emit(b, first_index);
|
|
mme_emit(b, index_count);
|
|
|
|
mme_mthd(b, NV9097_END);
|
|
mme_emit(b, mme_zero());
|
|
|
|
mme_set_field_enum(b, begin, NV9097_BEGIN_INSTANCE_ID, SUBSEQUENT);
|
|
}
|
|
}
|
|
|
|
void
|
|
nvk_mme_draw_indexed(struct nvk_device *dev, struct mme_builder *b)
|
|
{
|
|
struct mme_value begin = mme_load(b);
|
|
|
|
nvk_mme_build_draw_indexed(b, begin);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
nvk_CmdDrawIndexed(VkCommandBuffer commandBuffer,
|
|
uint32_t indexCount,
|
|
uint32_t instanceCount,
|
|
uint32_t firstIndex,
|
|
int32_t vertexOffset,
|
|
uint32_t firstInstance)
|
|
{
|
|
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
nvk_flush_gfx_state(cmd);
|
|
|
|
uint32_t begin;
|
|
V_NV9097_BEGIN(begin, {
|
|
.op = vk_to_nv9097_primitive_topology(dyn->ia.primitive_topology),
|
|
.primitive_id = NV9097_BEGIN_PRIMITIVE_ID_FIRST,
|
|
.instance_id = NV9097_BEGIN_INSTANCE_ID_FIRST,
|
|
.split_mode = SPLIT_MODE_NORMAL_BEGIN_NORMAL_END,
|
|
});
|
|
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 7);
|
|
P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_DRAW_INDEXED));
|
|
P_INLINE_DATA(p, begin);
|
|
P_INLINE_DATA(p, indexCount);
|
|
P_INLINE_DATA(p, instanceCount);
|
|
P_INLINE_DATA(p, firstIndex);
|
|
P_INLINE_DATA(p, vertexOffset);
|
|
P_INLINE_DATA(p, firstInstance);
|
|
}
|
|
|
|
void
|
|
nvk_mme_draw_indirect(struct nvk_device *dev, struct mme_builder *b)
|
|
{
|
|
struct mme_value begin = mme_load(b);
|
|
struct mme_value64 draw_addr = mme_load_addr64(b);
|
|
struct mme_value draw_count = mme_load(b);
|
|
struct mme_value stride = mme_load(b);
|
|
|
|
struct mme_value draw = mme_mov(b, mme_zero());
|
|
mme_while(b, ult, draw, draw_count) {
|
|
mme_tu104_read_fifoed(b, draw_addr, mme_imm(4));
|
|
|
|
nvk_build_mme_draw(b, begin);
|
|
|
|
mme_add_to(b, draw, draw, mme_imm(1));
|
|
mme_add64_to(b, draw_addr, draw_addr, mme_value64(stride, mme_zero()));
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
nvk_CmdDrawIndirect(VkCommandBuffer commandBuffer,
|
|
VkBuffer _buffer,
|
|
VkDeviceSize offset,
|
|
uint32_t drawCount,
|
|
uint32_t stride)
|
|
{
|
|
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
|
|
VK_FROM_HANDLE(nvk_buffer, buffer, _buffer);
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
nvk_flush_gfx_state(cmd);
|
|
|
|
uint32_t begin;
|
|
V_NV9097_BEGIN(begin, {
|
|
.op = vk_to_nv9097_primitive_topology(dyn->ia.primitive_topology),
|
|
.primitive_id = NV9097_BEGIN_PRIMITIVE_ID_FIRST,
|
|
.instance_id = NV9097_BEGIN_INSTANCE_ID_FIRST,
|
|
.split_mode = SPLIT_MODE_NORMAL_BEGIN_NORMAL_END,
|
|
});
|
|
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 8);
|
|
P_IMMD(p, NVC597, SET_MME_DATA_FIFO_CONFIG, FIFO_SIZE_SIZE_4KB);
|
|
P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_DRAW_INDIRECT));
|
|
P_INLINE_DATA(p, begin);
|
|
uint64_t draw_addr = nvk_buffer_address(buffer, offset);
|
|
P_INLINE_DATA(p, draw_addr >> 32);
|
|
P_INLINE_DATA(p, draw_addr);
|
|
P_INLINE_DATA(p, drawCount);
|
|
P_INLINE_DATA(p, stride);
|
|
}
|
|
|
|
void
|
|
nvk_mme_draw_indexed_indirect(struct nvk_device *dev, struct mme_builder *b)
|
|
{
|
|
struct mme_value begin = mme_load(b);
|
|
struct mme_value64 draw_addr = mme_load_addr64(b);
|
|
struct mme_value draw_count = mme_load(b);
|
|
struct mme_value stride = mme_load(b);
|
|
|
|
struct mme_value draw = mme_mov(b, mme_zero());
|
|
mme_while(b, ult, draw, draw_count) {
|
|
mme_tu104_read_fifoed(b, draw_addr, mme_imm(5));
|
|
|
|
nvk_mme_build_draw_indexed(b, begin);
|
|
|
|
mme_add_to(b, draw, draw, mme_imm(1));
|
|
mme_add64_to(b, draw_addr, draw_addr, mme_value64(stride, mme_zero()));
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
nvk_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,
|
|
VkBuffer _buffer,
|
|
VkDeviceSize offset,
|
|
uint32_t drawCount,
|
|
uint32_t stride)
|
|
{
|
|
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
|
|
VK_FROM_HANDLE(nvk_buffer, buffer, _buffer);
|
|
const struct vk_dynamic_graphics_state *dyn =
|
|
&cmd->vk.dynamic_graphics_state;
|
|
|
|
nvk_flush_gfx_state(cmd);
|
|
|
|
uint32_t begin;
|
|
V_NV9097_BEGIN(begin, {
|
|
.op = vk_to_nv9097_primitive_topology(dyn->ia.primitive_topology),
|
|
.primitive_id = NV9097_BEGIN_PRIMITIVE_ID_FIRST,
|
|
.instance_id = NV9097_BEGIN_INSTANCE_ID_FIRST,
|
|
.split_mode = SPLIT_MODE_NORMAL_BEGIN_NORMAL_END,
|
|
});
|
|
|
|
struct nv_push *p = nvk_cmd_buffer_push(cmd, 8);
|
|
P_IMMD(p, NVC597, SET_MME_DATA_FIFO_CONFIG, FIFO_SIZE_SIZE_4KB);
|
|
P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_DRAW_INDEXED_INDIRECT));
|
|
P_INLINE_DATA(p, begin);
|
|
uint64_t draw_addr = nvk_buffer_address(buffer, offset);
|
|
P_INLINE_DATA(p, draw_addr >> 32);
|
|
P_INLINE_DATA(p, draw_addr);
|
|
P_INLINE_DATA(p, drawCount);
|
|
P_INLINE_DATA(p, stride);
|
|
}
|