tu: Implement VK_EXT_vertex_input_dynamic_state
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17554>
This commit is contained in:
@@ -578,7 +578,7 @@ Khronos extensions that are not part of any Vulkan version:
|
||||
VK_EXT_shader_module_identifier DONE (anv, radv, tu)
|
||||
VK_EXT_transform_feedback DONE (anv, lvp, radv, tu, vn)
|
||||
VK_EXT_vertex_attribute_divisor DONE (anv, radv, lvp, tu, v3dv)
|
||||
VK_EXT_vertex_input_dynamic_state DONE (lvp, radv)
|
||||
VK_EXT_vertex_input_dynamic_state DONE (lvp, radv, tu)
|
||||
VK_EXT_ycbcr_image_arrays DONE (anv, radv)
|
||||
VK_ANDROID_external_memory_android_hardware_buffer DONE (anv, radv, vn)
|
||||
VK_ANDROID_native_buffer DONE (anv, radv, tu, v3dv, vn)
|
||||
|
@@ -1867,6 +1867,105 @@ tu_BeginCommandBuffer(VkCommandBuffer commandBuffer,
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
tu6_emit_vertex_strides(struct tu_cmd_buffer *cmd, unsigned num_vbs)
|
||||
{
|
||||
struct tu_cs cs;
|
||||
cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].iova =
|
||||
tu_cs_draw_state(&cmd->sub_cs, &cs, 2 * num_vbs).iova;
|
||||
|
||||
for (uint32_t i = 0; i < num_vbs; i++)
|
||||
tu_cs_emit_regs(&cs, A6XX_VFD_FETCH_STRIDE(i, cmd->state.vb[i].stride));
|
||||
|
||||
cmd->state.dirty |= TU_CMD_DIRTY_VB_STRIDE;
|
||||
}
|
||||
|
||||
static struct tu_cs
|
||||
tu_cmd_dynamic_state(struct tu_cmd_buffer *cmd, uint32_t id, uint32_t size)
|
||||
{
|
||||
struct tu_cs cs;
|
||||
|
||||
assert(id < ARRAY_SIZE(cmd->state.dynamic_state));
|
||||
cmd->state.dynamic_state[id] = tu_cs_draw_state(&cmd->sub_cs, &cs, size);
|
||||
|
||||
/* note: this also avoids emitting draw states before renderpass clears,
|
||||
* which may use the 3D clear path (for MSAA cases)
|
||||
*/
|
||||
if (cmd->state.dirty & TU_CMD_DIRTY_DRAW_STATE)
|
||||
return cs;
|
||||
|
||||
tu_cs_emit_pkt7(&cmd->draw_cs, CP_SET_DRAW_STATE, 3);
|
||||
tu_cs_emit_draw_state(&cmd->draw_cs, TU_DRAW_STATE_DYNAMIC + id, cmd->state.dynamic_state[id]);
|
||||
|
||||
return cs;
|
||||
}
|
||||
|
||||
static void
|
||||
tu_cmd_end_dynamic_state(struct tu_cmd_buffer *cmd, struct tu_cs *cs,
|
||||
uint32_t id)
|
||||
{
|
||||
assert(id < ARRAY_SIZE(cmd->state.dynamic_state));
|
||||
cmd->state.dynamic_state[id] = tu_cs_end_draw_state(&cmd->sub_cs, cs);
|
||||
|
||||
/* note: this also avoids emitting draw states before renderpass clears,
|
||||
* which may use the 3D clear path (for MSAA cases)
|
||||
*/
|
||||
if (cmd->state.dirty & TU_CMD_DIRTY_DRAW_STATE)
|
||||
return;
|
||||
|
||||
tu_cs_emit_pkt7(&cmd->draw_cs, CP_SET_DRAW_STATE, 3);
|
||||
tu_cs_emit_draw_state(&cmd->draw_cs, TU_DRAW_STATE_DYNAMIC + id, cmd->state.dynamic_state[id]);
|
||||
}
|
||||
|
||||
static void
|
||||
tu_update_num_vbs(struct tu_cmd_buffer *cmd, unsigned num_vbs)
|
||||
{
|
||||
/* the vertex_buffers draw state always contains all the currently
|
||||
* bound vertex buffers. update its size to only emit the vbs which
|
||||
* are actually used by the pipeline
|
||||
* note there is a HW optimization which makes it so the draw state
|
||||
* is not re-executed completely when only the size changes
|
||||
*/
|
||||
if (cmd->state.vertex_buffers.size != num_vbs * 4) {
|
||||
cmd->state.vertex_buffers.size = num_vbs * 4;
|
||||
cmd->state.dirty |= TU_CMD_DIRTY_VERTEX_BUFFERS;
|
||||
}
|
||||
|
||||
if (cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].size != num_vbs * 2) {
|
||||
cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].size = num_vbs * 2;
|
||||
cmd->state.dirty |= TU_CMD_DIRTY_VB_STRIDE;
|
||||
}
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
tu_CmdSetVertexInputEXT(VkCommandBuffer commandBuffer,
|
||||
uint32_t vertexBindingDescriptionCount,
|
||||
const VkVertexInputBindingDescription2EXT *pVertexBindingDescriptions,
|
||||
uint32_t vertexAttributeDescriptionCount,
|
||||
const VkVertexInputAttributeDescription2EXT *pVertexAttributeDescriptions)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer);
|
||||
struct tu_cs cs;
|
||||
|
||||
unsigned num_vbs = 0;
|
||||
for (unsigned i = 0; i < vertexBindingDescriptionCount; i++) {
|
||||
const VkVertexInputBindingDescription2EXT *binding =
|
||||
&pVertexBindingDescriptions[i];
|
||||
num_vbs = MAX2(num_vbs, binding->binding + 1);
|
||||
cmd->state.vb[binding->binding].stride = binding->stride;
|
||||
}
|
||||
|
||||
tu6_emit_vertex_strides(cmd, num_vbs);
|
||||
tu_update_num_vbs(cmd, num_vbs);
|
||||
|
||||
tu_cs_begin_sub_stream(&cmd->sub_cs, TU6_EMIT_VERTEX_INPUT_MAX_DWORDS, &cs);
|
||||
tu6_emit_vertex_input(&cs, vertexBindingDescriptionCount,
|
||||
pVertexBindingDescriptions,
|
||||
vertexAttributeDescriptionCount,
|
||||
pVertexAttributeDescriptions);
|
||||
tu_cmd_end_dynamic_state(cmd, &cs, TU_DYNAMIC_STATE_VERTEX_INPUT);
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
tu_CmdBindVertexBuffers2EXT(VkCommandBuffer commandBuffer,
|
||||
uint32_t firstBinding,
|
||||
@@ -1903,15 +2002,8 @@ tu_CmdBindVertexBuffers2EXT(VkCommandBuffer commandBuffer,
|
||||
|
||||
cmd->state.dirty |= TU_CMD_DIRTY_VERTEX_BUFFERS;
|
||||
|
||||
if (pStrides) {
|
||||
cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].iova =
|
||||
tu_cs_draw_state(&cmd->sub_cs, &cs, 2 * MAX_VBS).iova;
|
||||
|
||||
for (uint32_t i = 0; i < MAX_VBS; i++)
|
||||
tu_cs_emit_regs(&cs, A6XX_VFD_FETCH_STRIDE(i, cmd->state.vb[i].stride));
|
||||
|
||||
cmd->state.dirty |= TU_CMD_DIRTY_VB_STRIDE;
|
||||
}
|
||||
if (pStrides)
|
||||
tu6_emit_vertex_strides(cmd, MAX_VBS);
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
@@ -2390,26 +2482,6 @@ tu_EndCommandBuffer(VkCommandBuffer commandBuffer)
|
||||
return cmd_buffer->record_result;
|
||||
}
|
||||
|
||||
static struct tu_cs
|
||||
tu_cmd_dynamic_state(struct tu_cmd_buffer *cmd, uint32_t id, uint32_t size)
|
||||
{
|
||||
struct tu_cs cs;
|
||||
|
||||
assert(id < ARRAY_SIZE(cmd->state.dynamic_state));
|
||||
cmd->state.dynamic_state[id] = tu_cs_draw_state(&cmd->sub_cs, &cs, size);
|
||||
|
||||
/* note: this also avoids emitting draw states before renderpass clears,
|
||||
* which may use the 3D clear path (for MSAA cases)
|
||||
*/
|
||||
if (cmd->state.dirty & TU_CMD_DIRTY_DRAW_STATE)
|
||||
return cs;
|
||||
|
||||
tu_cs_emit_pkt7(&cmd->draw_cs, CP_SET_DRAW_STATE, 3);
|
||||
tu_cs_emit_draw_state(&cmd->draw_cs, TU_DRAW_STATE_DYNAMIC + id, cmd->state.dynamic_state[id]);
|
||||
|
||||
return cs;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
tu_CmdBindPipeline(VkCommandBuffer commandBuffer,
|
||||
VkPipelineBindPoint pipelineBindPoint,
|
||||
@@ -2438,11 +2510,10 @@ tu_CmdBindPipeline(VkCommandBuffer commandBuffer,
|
||||
if (!(cmd->state.dirty & TU_CMD_DIRTY_DRAW_STATE)) {
|
||||
uint32_t mask = ~pipeline->dynamic_state_mask & BITFIELD_MASK(TU_DYNAMIC_STATE_COUNT);
|
||||
|
||||
tu_cs_emit_pkt7(cs, CP_SET_DRAW_STATE, 3 * (7 + util_bitcount(mask)));
|
||||
tu_cs_emit_pkt7(cs, CP_SET_DRAW_STATE, 3 * (6 + util_bitcount(mask)));
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM_CONFIG, pipeline->program.config_state);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM, pipeline->program.state);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM_BINNING, pipeline->program.binning_state);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_VI, pipeline->vi.state);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_RAST, pipeline->rast_state);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PRIM_MODE_SYSMEM, pipeline->prim_order_state_sysmem);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PRIM_MODE_GMEM, pipeline->prim_order_state_gmem);
|
||||
@@ -2486,22 +2557,8 @@ tu_CmdBindPipeline(VkCommandBuffer commandBuffer,
|
||||
cmd->state.dirty |= TU_CMD_DIRTY_VIEWPORTS;
|
||||
}
|
||||
|
||||
/* the vertex_buffers draw state always contains all the currently
|
||||
* bound vertex buffers. update its size to only emit the vbs which
|
||||
* are actually used by the pipeline
|
||||
* note there is a HW optimization which makes it so the draw state
|
||||
* is not re-executed completely when only the size changes
|
||||
*/
|
||||
if (cmd->state.vertex_buffers.size != pipeline->num_vbs * 4) {
|
||||
cmd->state.vertex_buffers.size = pipeline->num_vbs * 4;
|
||||
cmd->state.dirty |= TU_CMD_DIRTY_VERTEX_BUFFERS;
|
||||
}
|
||||
|
||||
if ((pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_VB_STRIDE)) &&
|
||||
cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].size != pipeline->num_vbs * 2) {
|
||||
cmd->state.dynamic_state[TU_DYNAMIC_STATE_VB_STRIDE].size = pipeline->num_vbs * 2;
|
||||
cmd->state.dirty |= TU_CMD_DIRTY_VB_STRIDE;
|
||||
}
|
||||
if (!(pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_VERTEX_INPUT)))
|
||||
tu_update_num_vbs(cmd, pipeline->num_vbs);
|
||||
|
||||
#define UPDATE_REG(X, Y) { \
|
||||
/* note: would be better to have pipeline bits already masked */ \
|
||||
@@ -4478,7 +4535,6 @@ tu6_draw_common(struct tu_cmd_buffer *cmd,
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM_CONFIG, pipeline->program.config_state);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM, pipeline->program.state);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PROGRAM_BINNING, pipeline->program.binning_state);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_VI, pipeline->vi.state);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_RAST, pipeline->rast_state);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PRIM_MODE_SYSMEM, pipeline->prim_order_state_sysmem);
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_PRIM_MODE_GMEM, pipeline->prim_order_state_gmem);
|
||||
|
@@ -25,7 +25,6 @@ enum tu_draw_state_group_id
|
||||
TU_DRAW_STATE_PROGRAM,
|
||||
TU_DRAW_STATE_PROGRAM_BINNING,
|
||||
TU_DRAW_STATE_VB,
|
||||
TU_DRAW_STATE_VI,
|
||||
TU_DRAW_STATE_RAST,
|
||||
TU_DRAW_STATE_CONST,
|
||||
TU_DRAW_STATE_DESC_SETS,
|
||||
|
@@ -212,6 +212,7 @@ get_device_extensions(const struct tu_physical_device *device,
|
||||
.EXT_image_view_min_lod = true,
|
||||
.EXT_pipeline_creation_feedback = true,
|
||||
.EXT_pipeline_creation_cache_control = true,
|
||||
.EXT_vertex_input_dynamic_state = true,
|
||||
#ifndef TU_USE_KGSL
|
||||
.EXT_physical_device_drm = true,
|
||||
#endif
|
||||
@@ -900,6 +901,12 @@ tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
|
||||
features->shaderModuleIdentifier = true;
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: {
|
||||
VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *features =
|
||||
(VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *)ext;
|
||||
features->vertexInputDynamicState = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@@ -1851,63 +1851,42 @@ tu6_emit_program(struct tu_cs *cs,
|
||||
}
|
||||
}
|
||||
|
||||
#define TU6_EMIT_VERTEX_INPUT_MAX_DWORDS (MAX_VERTEX_ATTRIBS * 2 + 1)
|
||||
|
||||
static void
|
||||
tu6_emit_vertex_input(struct tu_pipeline *pipeline,
|
||||
struct tu_draw_state *vi_state,
|
||||
const VkPipelineVertexInputStateCreateInfo *info)
|
||||
void
|
||||
tu6_emit_vertex_input(struct tu_cs *cs,
|
||||
uint32_t binding_count,
|
||||
const VkVertexInputBindingDescription2EXT *bindings,
|
||||
uint32_t unsorted_attr_count,
|
||||
const VkVertexInputAttributeDescription2EXT *unsorted_attrs)
|
||||
{
|
||||
uint32_t binding_instanced = 0; /* bitmask of instanced bindings */
|
||||
uint32_t step_rate[MAX_VBS];
|
||||
|
||||
struct tu_cs cs;
|
||||
tu_cs_begin_sub_stream(&pipeline->cs,
|
||||
TU6_EMIT_VERTEX_INPUT_MAX_DWORDS, &cs);
|
||||
|
||||
for (uint32_t i = 0; i < info->vertexBindingDescriptionCount; i++) {
|
||||
const VkVertexInputBindingDescription *binding =
|
||||
&info->pVertexBindingDescriptions[i];
|
||||
|
||||
if (!(pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_VB_STRIDE))) {
|
||||
tu_cs_emit_regs(&cs,
|
||||
A6XX_VFD_FETCH_STRIDE(binding->binding, binding->stride));
|
||||
}
|
||||
for (uint32_t i = 0; i < binding_count; i++) {
|
||||
const VkVertexInputBindingDescription2EXT *binding = &bindings[i];
|
||||
|
||||
if (binding->inputRate == VK_VERTEX_INPUT_RATE_INSTANCE)
|
||||
binding_instanced |= 1 << binding->binding;
|
||||
binding_instanced |= 1u << binding->binding;
|
||||
|
||||
step_rate[binding->binding] = 1;
|
||||
step_rate[binding->binding] = binding->divisor;
|
||||
}
|
||||
|
||||
const VkPipelineVertexInputDivisorStateCreateInfoEXT *div_state =
|
||||
vk_find_struct_const(info->pNext, PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT);
|
||||
if (div_state) {
|
||||
for (uint32_t i = 0; i < div_state->vertexBindingDivisorCount; i++) {
|
||||
const VkVertexInputBindingDivisorDescriptionEXT *desc =
|
||||
&div_state->pVertexBindingDivisors[i];
|
||||
step_rate[desc->binding] = desc->divisor;
|
||||
}
|
||||
}
|
||||
|
||||
const VkVertexInputAttributeDescription *attrs[MAX_VERTEX_ATTRIBS] = { };
|
||||
const VkVertexInputAttributeDescription2EXT *attrs[MAX_VERTEX_ATTRIBS] = { };
|
||||
unsigned attr_count = 0;
|
||||
for (uint32_t i = 0; i < info->vertexAttributeDescriptionCount; i++) {
|
||||
const VkVertexInputAttributeDescription *attr =
|
||||
&info->pVertexAttributeDescriptions[i];
|
||||
for (uint32_t i = 0; i < unsorted_attr_count; i++) {
|
||||
const VkVertexInputAttributeDescription2EXT *attr = &unsorted_attrs[i];
|
||||
attrs[attr->location] = attr;
|
||||
attr_count = MAX2(attr_count, attr->location + 1);
|
||||
}
|
||||
|
||||
if (attr_count != 0)
|
||||
tu_cs_emit_pkt4(&cs, REG_A6XX_VFD_DECODE_INSTR(0), attr_count * 2);
|
||||
tu_cs_emit_pkt4(cs, REG_A6XX_VFD_DECODE_INSTR(0), attr_count * 2);
|
||||
|
||||
for (uint32_t loc = 0; loc < attr_count; loc++) {
|
||||
const VkVertexInputAttributeDescription *attr = attrs[loc];
|
||||
const VkVertexInputAttributeDescription2EXT *attr = attrs[loc];
|
||||
|
||||
if (attr) {
|
||||
const struct tu_native_format format = tu6_format_vtx(attr->format);
|
||||
tu_cs_emit(&cs, A6XX_VFD_DECODE_INSTR(0,
|
||||
tu_cs_emit(cs, A6XX_VFD_DECODE_INSTR(0,
|
||||
.idx = attr->binding,
|
||||
.offset = attr->offset,
|
||||
.instanced = binding_instanced & (1 << attr->binding),
|
||||
@@ -1915,14 +1894,12 @@ tu6_emit_vertex_input(struct tu_pipeline *pipeline,
|
||||
.swap = format.swap,
|
||||
.unk30 = 1,
|
||||
._float = !vk_format_is_int(attr->format)).value);
|
||||
tu_cs_emit(&cs, A6XX_VFD_DECODE_STEP_RATE(0, step_rate[attr->binding]).value);
|
||||
tu_cs_emit(cs, A6XX_VFD_DECODE_STEP_RATE(0, step_rate[attr->binding]).value);
|
||||
} else {
|
||||
tu_cs_emit(&cs, 0);
|
||||
tu_cs_emit(&cs, 0);
|
||||
tu_cs_emit(cs, 0);
|
||||
tu_cs_emit(cs, 0);
|
||||
}
|
||||
}
|
||||
|
||||
*vi_state = tu_cs_end_draw_state(&pipeline->cs, &cs);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -3212,6 +3189,10 @@ tu_pipeline_builder_parse_dynamic(struct tu_pipeline_builder *builder,
|
||||
*/
|
||||
pipeline->dynamic_state_mask |= BIT(TU_DYNAMIC_STATE_COLOR_WRITE_ENABLE);
|
||||
break;
|
||||
case VK_DYNAMIC_STATE_VERTEX_INPUT_EXT:
|
||||
pipeline->dynamic_state_mask |= BIT(TU_DYNAMIC_STATE_VERTEX_INPUT) |
|
||||
BIT(TU_DYNAMIC_STATE_VB_STRIDE);
|
||||
break;
|
||||
default:
|
||||
assert(!"unsupported dynamic state");
|
||||
break;
|
||||
@@ -3274,33 +3255,6 @@ tu_pipeline_builder_parse_shader_stages(struct tu_pipeline_builder *builder,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tu_pipeline_builder_parse_vertex_input(struct tu_pipeline_builder *builder,
|
||||
struct tu_pipeline *pipeline)
|
||||
{
|
||||
const VkPipelineVertexInputStateCreateInfo *vi_info =
|
||||
builder->create_info->pVertexInputState;
|
||||
|
||||
/* Bindings may contain holes */
|
||||
for (unsigned i = 0; i < vi_info->vertexBindingDescriptionCount; i++) {
|
||||
pipeline->num_vbs =
|
||||
MAX2(pipeline->num_vbs, vi_info->pVertexBindingDescriptions[i].binding + 1);
|
||||
}
|
||||
|
||||
tu6_emit_vertex_input(pipeline, &pipeline->vi.state, vi_info);
|
||||
}
|
||||
|
||||
static void
|
||||
tu_pipeline_builder_parse_input_assembly(struct tu_pipeline_builder *builder,
|
||||
struct tu_pipeline *pipeline)
|
||||
{
|
||||
const VkPipelineInputAssemblyStateCreateInfo *ia_info =
|
||||
builder->create_info->pInputAssemblyState;
|
||||
|
||||
pipeline->ia.primtype = tu6_primtype(ia_info->topology);
|
||||
pipeline->ia.primitive_restart = ia_info->primitiveRestartEnable;
|
||||
}
|
||||
|
||||
static bool
|
||||
tu_pipeline_static_state(struct tu_pipeline *pipeline, struct tu_cs *cs,
|
||||
uint32_t id, uint32_t size)
|
||||
@@ -3314,6 +3268,90 @@ tu_pipeline_static_state(struct tu_pipeline *pipeline, struct tu_cs *cs,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
tu_pipeline_builder_parse_vertex_input(struct tu_pipeline_builder *builder,
|
||||
struct tu_pipeline *pipeline)
|
||||
{
|
||||
if (pipeline->dynamic_state_mask & BIT(TU_DYNAMIC_STATE_VERTEX_INPUT))
|
||||
return;
|
||||
|
||||
const VkPipelineVertexInputStateCreateInfo *vi_info =
|
||||
builder->create_info->pVertexInputState;
|
||||
|
||||
struct tu_cs cs;
|
||||
if (tu_pipeline_static_state(pipeline, &cs, TU_DYNAMIC_STATE_VB_STRIDE,
|
||||
2 * vi_info->vertexBindingDescriptionCount)) {
|
||||
for (uint32_t i = 0; i < vi_info->vertexBindingDescriptionCount; i++) {
|
||||
const VkVertexInputBindingDescription *binding =
|
||||
&vi_info->pVertexBindingDescriptions[i];
|
||||
|
||||
tu_cs_emit_regs(&cs,
|
||||
A6XX_VFD_FETCH_STRIDE(binding->binding, binding->stride));
|
||||
}
|
||||
}
|
||||
|
||||
VkVertexInputBindingDescription2EXT bindings[MAX_VBS];
|
||||
VkVertexInputAttributeDescription2EXT attrs[MAX_VERTEX_ATTRIBS];
|
||||
|
||||
for (unsigned i = 0; i < vi_info->vertexBindingDescriptionCount; i++) {
|
||||
const VkVertexInputBindingDescription *binding =
|
||||
&vi_info->pVertexBindingDescriptions[i];
|
||||
bindings[i] = (VkVertexInputBindingDescription2EXT) {
|
||||
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
|
||||
.pNext = NULL,
|
||||
.binding = binding->binding,
|
||||
.inputRate = binding->inputRate,
|
||||
.stride = binding->stride,
|
||||
.divisor = 1,
|
||||
};
|
||||
|
||||
/* Bindings may contain holes */
|
||||
pipeline->num_vbs = MAX2(pipeline->num_vbs, binding->binding + 1);
|
||||
}
|
||||
|
||||
const VkPipelineVertexInputDivisorStateCreateInfoEXT *div_state =
|
||||
vk_find_struct_const(vi_info->pNext, PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT);
|
||||
if (div_state) {
|
||||
for (uint32_t i = 0; i < div_state->vertexBindingDivisorCount; i++) {
|
||||
const VkVertexInputBindingDivisorDescriptionEXT *desc =
|
||||
&div_state->pVertexBindingDivisors[i];
|
||||
bindings[desc->binding].divisor = desc->divisor;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < vi_info->vertexAttributeDescriptionCount; i++) {
|
||||
const VkVertexInputAttributeDescription *attr =
|
||||
&vi_info->pVertexAttributeDescriptions[i];
|
||||
attrs[i] = (VkVertexInputAttributeDescription2EXT) {
|
||||
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
|
||||
.pNext = NULL,
|
||||
.binding = attr->binding,
|
||||
.location = attr->location,
|
||||
.offset = attr->offset,
|
||||
.format = attr->format,
|
||||
};
|
||||
}
|
||||
|
||||
tu_cs_begin_sub_stream(&pipeline->cs,
|
||||
TU6_EMIT_VERTEX_INPUT_MAX_DWORDS, &cs);
|
||||
tu6_emit_vertex_input(&cs,
|
||||
vi_info->vertexBindingDescriptionCount, bindings,
|
||||
vi_info->vertexAttributeDescriptionCount, attrs);
|
||||
pipeline->dynamic_state[TU_DYNAMIC_STATE_VERTEX_INPUT] =
|
||||
tu_cs_end_draw_state(&pipeline->cs, &cs);
|
||||
}
|
||||
|
||||
static void
|
||||
tu_pipeline_builder_parse_input_assembly(struct tu_pipeline_builder *builder,
|
||||
struct tu_pipeline *pipeline)
|
||||
{
|
||||
const VkPipelineInputAssemblyStateCreateInfo *ia_info =
|
||||
builder->create_info->pInputAssemblyState;
|
||||
|
||||
pipeline->ia.primtype = tu6_primtype(ia_info->topology);
|
||||
pipeline->ia.primitive_restart = ia_info->primitiveRestartEnable;
|
||||
}
|
||||
|
||||
static void
|
||||
tu_pipeline_builder_parse_tessellation(struct tu_pipeline_builder *builder,
|
||||
struct tu_pipeline *pipeline)
|
||||
|
@@ -26,6 +26,7 @@ enum tu_dynamic_state
|
||||
TU_DYNAMIC_STATE_VB_STRIDE,
|
||||
TU_DYNAMIC_STATE_RASTERIZER_DISCARD,
|
||||
TU_DYNAMIC_STATE_BLEND,
|
||||
TU_DYNAMIC_STATE_VERTEX_INPUT,
|
||||
TU_DYNAMIC_STATE_COUNT,
|
||||
/* no associated draw state: */
|
||||
TU_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY = TU_DYNAMIC_STATE_COUNT,
|
||||
@@ -164,11 +165,6 @@ struct tu_pipeline
|
||||
struct tu_program_descriptor_linkage link[MESA_SHADER_STAGES];
|
||||
} program;
|
||||
|
||||
struct
|
||||
{
|
||||
struct tu_draw_state state;
|
||||
} vi;
|
||||
|
||||
struct
|
||||
{
|
||||
enum pc_di_primtype primtype;
|
||||
@@ -227,6 +223,14 @@ tu6_emit_depth_bias(struct tu_cs *cs,
|
||||
float clamp,
|
||||
float slope_factor);
|
||||
|
||||
#define TU6_EMIT_VERTEX_INPUT_MAX_DWORDS (MAX_VERTEX_ATTRIBS * 2 + 1)
|
||||
|
||||
void tu6_emit_vertex_input(struct tu_cs *cs,
|
||||
uint32_t binding_count,
|
||||
const VkVertexInputBindingDescription2EXT *bindings,
|
||||
uint32_t attr_count,
|
||||
const VkVertexInputAttributeDescription2EXT *attrs);
|
||||
|
||||
uint32_t tu6_rb_mrt_control_rop(VkLogicOp op, bool *rop_reads_dst);
|
||||
|
||||
struct tu_pvtmem_config {
|
||||
|
Reference in New Issue
Block a user