anv: fix index buffer emission

In the following case :

  vkCmdBindPipeline(compute_pipeline);
  vkCmdDispatch(...);
  vkCmdBindPipeline(graphics_pipeline);
  vkCmdBindIndexBuffer(buffer)
  vkCmdDraw(...);

We're emitting the 3DSTATE_INDEX_BUFFER instruction while the HW is
still in GPGPU mode, because we're dealing the pipeline selection to
vkCmdDraw().

Found while debugging Age Of Empire 4, HW is hung on
3DSTATE_INDEX_BUFFER instruction.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Cc: mesa-stable
Reviewed-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17153>
This commit is contained in:
Lionel Landwerlin
2022-06-12 23:54:12 +03:00
committed by Marge Bot
parent 21ea19d504
commit 4f10eddf77
4 changed files with 69 additions and 112 deletions

View File

@@ -2888,11 +2888,9 @@ struct anv_cmd_graphics_state {
uint32_t primitive_topology;
struct {
struct anv_buffer *index_buffer;
uint32_t index_type; /**< 3DSTATE_INDEX_BUFFER.IndexFormat */
uint32_t index_offset;
} gfx7;
};
enum anv_depth_reg_mode {

View File

@@ -7425,6 +7425,51 @@ void genX(CmdWaitEvents2)(
cmd_buffer_barrier(cmd_buffer, pDependencyInfos, "wait event");
}
static uint32_t vk_to_intel_index_type(VkIndexType type)
{
switch (type) {
case VK_INDEX_TYPE_UINT8_EXT:
return INDEX_BYTE;
case VK_INDEX_TYPE_UINT16:
return INDEX_WORD;
case VK_INDEX_TYPE_UINT32:
return INDEX_DWORD;
default:
unreachable("invalid index type");
}
}
static uint32_t restart_index_for_type(VkIndexType type)
{
switch (type) {
case VK_INDEX_TYPE_UINT8_EXT:
return UINT8_MAX;
case VK_INDEX_TYPE_UINT16:
return UINT16_MAX;
case VK_INDEX_TYPE_UINT32:
return UINT32_MAX;
default:
unreachable("invalid index type");
}
}
void genX(CmdBindIndexBuffer)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
VkIndexType indexType)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
cmd_buffer->state.restart_index = restart_index_for_type(indexType);
cmd_buffer->state.gfx.index_buffer = buffer;
cmd_buffer->state.gfx.index_type = vk_to_intel_index_type(indexType);
cmd_buffer->state.gfx.index_offset = offset;
cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_INDEX_BUFFER;
}
VkResult genX(CmdSetPerformanceOverrideINTEL)(
VkCommandBuffer commandBuffer,
const VkPerformanceOverrideInfoINTEL* pOverrideInfo)

View File

@@ -33,54 +33,6 @@
#include "genxml/gen_macros.h"
#include "genxml/genX_pack.h"
#if GFX_VERx10 == 70
#endif
static uint32_t vk_to_intel_index_type(VkIndexType type)
{
switch (type) {
case VK_INDEX_TYPE_UINT8_EXT:
return INDEX_BYTE;
case VK_INDEX_TYPE_UINT16:
return INDEX_WORD;
case VK_INDEX_TYPE_UINT32:
return INDEX_DWORD;
default:
unreachable("invalid index type");
}
}
static uint32_t restart_index_for_type(VkIndexType type)
{
switch (type) {
case VK_INDEX_TYPE_UINT8_EXT:
return UINT8_MAX;
case VK_INDEX_TYPE_UINT16:
return UINT16_MAX;
case VK_INDEX_TYPE_UINT32:
return UINT32_MAX;
default:
unreachable("invalid index type");
}
}
void genX(CmdBindIndexBuffer)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
VkIndexType indexType)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_INDEX_BUFFER;
if (GFX_VERx10 == 75)
cmd_buffer->state.restart_index = restart_index_for_type(indexType);
cmd_buffer->state.gfx.gfx7.index_buffer = buffer;
cmd_buffer->state.gfx.gfx7.index_type = vk_to_intel_index_type(indexType);
cmd_buffer->state.gfx.gfx7.index_offset = offset;
}
static uint32_t
get_depth_format(struct anv_cmd_buffer *cmd_buffer)
{
@@ -244,12 +196,12 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
}
}
if (cmd_buffer->state.gfx.gfx7.index_buffer &&
if (cmd_buffer->state.gfx.index_buffer &&
cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
ANV_CMD_DIRTY_INDEX_BUFFER |
ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE)) {
struct anv_buffer *buffer = cmd_buffer->state.gfx.gfx7.index_buffer;
uint32_t offset = cmd_buffer->state.gfx.gfx7.index_offset;
struct anv_buffer *buffer = cmd_buffer->state.gfx.index_buffer;
uint32_t offset = cmd_buffer->state.gfx.index_offset;
#if GFX_VERx10 == 75
anv_batch_emit(&cmd_buffer->batch, GFX75_3DSTATE_VF, vf) {
@@ -262,7 +214,7 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
#if GFX_VERx10 != 75
ib.CutIndexEnable = d->primitive_restart_enable;
#endif
ib.IndexFormat = cmd_buffer->state.gfx.gfx7.index_type;
ib.IndexFormat = cmd_buffer->state.gfx.index_type;
ib.MOCS = anv_mocs(cmd_buffer->device,
buffer->address.bo,
ISL_SURF_USAGE_INDEX_BUFFER_BIT);

View File

@@ -592,6 +592,23 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
}
}
if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_INDEX_BUFFER) {
struct anv_buffer *buffer = cmd_buffer->state.gfx.index_buffer;
uint32_t offset = cmd_buffer->state.gfx.index_offset;
anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_INDEX_BUFFER), ib) {
ib.IndexFormat = cmd_buffer->state.gfx.index_type;
ib.MOCS = anv_mocs(cmd_buffer->device,
buffer->address.bo,
ISL_SURF_USAGE_INDEX_BUFFER_BIT);
#if GFX_VER >= 12
ib.L3BypassDisable = true;
#endif
ib.BufferStartingAddress = anv_address_add(buffer->address, offset);
ib.BufferSize = vk_buffer_range(&buffer->vk, offset,
VK_WHOLE_SIZE);
}
}
#if GFX_VERx10 >= 125
if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE)) {
@@ -712,58 +729,3 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
cmd_buffer->state.gfx.dirty = 0;
}
static uint32_t vk_to_intel_index_type(VkIndexType type)
{
switch (type) {
case VK_INDEX_TYPE_UINT8_EXT:
return INDEX_BYTE;
case VK_INDEX_TYPE_UINT16:
return INDEX_WORD;
case VK_INDEX_TYPE_UINT32:
return INDEX_DWORD;
default:
unreachable("invalid index type");
}
}
static uint32_t restart_index_for_type(VkIndexType type)
{
switch (type) {
case VK_INDEX_TYPE_UINT8_EXT:
return UINT8_MAX;
case VK_INDEX_TYPE_UINT16:
return UINT16_MAX;
case VK_INDEX_TYPE_UINT32:
return UINT32_MAX;
default:
unreachable("invalid index type");
}
}
void genX(CmdBindIndexBuffer)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
VkIndexType indexType)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
cmd_buffer->state.restart_index = restart_index_for_type(indexType);
anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_INDEX_BUFFER), ib) {
ib.IndexFormat = vk_to_intel_index_type(indexType);
ib.MOCS = anv_mocs(cmd_buffer->device,
buffer->address.bo,
ISL_SURF_USAGE_INDEX_BUFFER_BIT);
#if GFX_VER >= 12
ib.L3BypassDisable = true;
#endif
ib.BufferStartingAddress = anv_address_add(buffer->address, offset);
ib.BufferSize = vk_buffer_range(&buffer->vk, offset,
VK_WHOLE_SIZE);
}
cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_INDEX_BUFFER;
}