Files
third_party_mesa3d/src/vulkan/genX_cmd_buffer.c

283 lines
11 KiB
C

/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include <stdbool.h>
#include "anv_private.h"
#if (ANV_GEN == 9)
# include "gen9_pack.h"
#elif (ANV_GEN == 8)
# include "gen8_pack.h"
#elif (ANV_IS_HASWELL)
# include "gen75_pack.h"
#elif (ANV_GEN == 7)
# include "gen7_pack.h"
#endif
void
genX(cmd_buffer_emit_state_base_address)(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_device *device = cmd_buffer->device;
struct anv_bo *scratch_bo = NULL;
cmd_buffer->state.scratch_size =
anv_block_pool_size(&device->scratch_block_pool);
if (cmd_buffer->state.scratch_size > 0)
scratch_bo = &device->scratch_block_pool.bo;
/* XXX: Do we need this on more than just BDW? */
#if (ANV_GEN == 8)
/* Emit a render target cache flush.
*
* This isn't documented anywhere in the PRM. However, it seems to be
* necessary prior to changing the surface state base adress. Without
* this, we get GPU hangs when using multi-level command buffers which
* clear depth, reset state base address, and then go render stuff.
*/
anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
.RenderTargetCacheFlushEnable = true);
#endif
anv_batch_emit(&cmd_buffer->batch, GENX(STATE_BASE_ADDRESS),
.GeneralStateBaseAddress = { scratch_bo, 0 },
.GeneralStateMemoryObjectControlState = GENX(MOCS),
.GeneralStateBaseAddressModifyEnable = true,
.SurfaceStateBaseAddress = anv_cmd_buffer_surface_base_address(cmd_buffer),
.SurfaceStateMemoryObjectControlState = GENX(MOCS),
.SurfaceStateBaseAddressModifyEnable = true,
.DynamicStateBaseAddress = { &device->dynamic_state_block_pool.bo, 0 },
.DynamicStateMemoryObjectControlState = GENX(MOCS),
.DynamicStateBaseAddressModifyEnable = true,
.IndirectObjectBaseAddress = { NULL, 0 },
.IndirectObjectMemoryObjectControlState = GENX(MOCS),
.IndirectObjectBaseAddressModifyEnable = true,
.InstructionBaseAddress = { &device->instruction_block_pool.bo, 0 },
.InstructionMemoryObjectControlState = GENX(MOCS),
.InstructionBaseAddressModifyEnable = true,
# if (ANV_GEN >= 8)
/* Broadwell requires that we specify a buffer size for a bunch of
* these fields. However, since we will be growing the BO's live, we
* just set them all to the maximum.
*/
.GeneralStateBufferSize = 0xfffff,
.GeneralStateBufferSizeModifyEnable = true,
.DynamicStateBufferSize = 0xfffff,
.DynamicStateBufferSizeModifyEnable = true,
.IndirectObjectBufferSize = 0xfffff,
.IndirectObjectBufferSizeModifyEnable = true,
.InstructionBufferSize = 0xfffff,
.InstructionBuffersizeModifyEnable = true,
# endif
);
/* After re-setting the surface state base address, we have to do some
* cache flusing so that the sampler engine will pick up the new
* SURFACE_STATE objects and binding tables. From the Broadwell PRM,
* Shared Function > 3D Sampler > State > State Caching (page 96):
*
* Coherency with system memory in the state cache, like the texture
* cache is handled partially by software. It is expected that the
* command stream or shader will issue Cache Flush operation or
* Cache_Flush sampler message to ensure that the L1 cache remains
* coherent with system memory.
*
* [...]
*
* Whenever the value of the Dynamic_State_Base_Addr,
* Surface_State_Base_Addr are altered, the L1 state cache must be
* invalidated to ensure the new surface or sampler state is fetched
* from system memory.
*
* The PIPE_CONTROL command has a "State Cache Invalidation Enable" bit
* which, according the PIPE_CONTROL instruction documentation in the
* Broadwell PRM:
*
* Setting this bit is independent of any other bit in this packet.
* This bit controls the invalidation of the L1 and L2 state caches
* at the top of the pipe i.e. at the parsing time.
*
* Unfortunately, experimentation seems to indicate that state cache
* invalidation through a PIPE_CONTROL does nothing whatsoever in
* regards to surface state and binding tables. In stead, it seems that
* invalidating the texture cache is what is actually needed.
*
* XXX: As far as we have been able to determine through
* experimentation, shows that flush the texture cache appears to be
* sufficient. The theory here is that all of the sampling/rendering
* units cache the binding table in the texture cache. However, we have
* yet to be able to actually confirm this.
*/
anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL),
.TextureCacheInvalidationEnable = true);
}
void genX(CmdPipelineBarrier)(
VkCommandBuffer commandBuffer,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags destStageMask,
VkBool32 byRegion,
uint32_t memBarrierCount,
const void* const* ppMemBarriers)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
uint32_t b, *dw;
struct GENX(PIPE_CONTROL) cmd = {
GENX(PIPE_CONTROL_header),
.PostSyncOperation = NoWrite,
};
/* XXX: I think waitEvent is a no-op on our HW. We should verify that. */
if (anv_clear_mask(&srcStageMask, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT)) {
/* This is just what PIPE_CONTROL does */
}
if (anv_clear_mask(&srcStageMask,
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)) {
cmd.StallAtPixelScoreboard = true;
}
if (anv_clear_mask(&srcStageMask,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT)) {
cmd.CommandStreamerStallEnable = true;
}
if (anv_clear_mask(&srcStageMask, VK_PIPELINE_STAGE_HOST_BIT)) {
anv_finishme("VK_PIPE_EVENT_CPU_SIGNAL_BIT");
}
/* On our hardware, all stages will wait for execution as needed. */
(void)destStageMask;
/* We checked all known VkPipeEventFlags. */
anv_assert(srcStageMask == 0);
/* XXX: Right now, we're really dumb and just flush whatever categories
* the app asks for. One of these days we may make this a bit better
* but right now that's all the hardware allows for in most areas.
*/
VkAccessFlags src_flags = 0;
VkAccessFlags dst_flags = 0;
for (uint32_t i = 0; i < memBarrierCount; i++) {
const struct anv_common *common = ppMemBarriers[i];
switch (common->sType) {
case VK_STRUCTURE_TYPE_MEMORY_BARRIER: {
ANV_COMMON_TO_STRUCT(VkMemoryBarrier, barrier, common);
src_flags |= barrier->srcAccessMask;
dst_flags |= barrier->dstAccessMask;
break;
}
case VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER: {
ANV_COMMON_TO_STRUCT(VkBufferMemoryBarrier, barrier, common);
src_flags |= barrier->srcAccessMask;
dst_flags |= barrier->dstAccessMask;
break;
}
case VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER: {
ANV_COMMON_TO_STRUCT(VkImageMemoryBarrier, barrier, common);
src_flags |= barrier->srcAccessMask;
dst_flags |= barrier->dstAccessMask;
break;
}
default:
unreachable("Invalid memory barrier type");
}
}
for_each_bit(b, dst_flags) {
switch ((VkAccessFlagBits)(1 << b)) {
case VK_ACCESS_HOST_WRITE_BIT:
break; /* FIXME: Little-core systems */
case VK_ACCESS_SHADER_WRITE_BIT:
cmd.DCFlushEnable = true;
break;
case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT:
cmd.RenderTargetCacheFlushEnable = true;
break;
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT:
cmd.DepthCacheFlushEnable = true;
break;
case VK_ACCESS_TRANSFER_WRITE_BIT:
cmd.RenderTargetCacheFlushEnable = true;
cmd.DepthCacheFlushEnable = true;
break;
default:
assert(!"Not a write bit");
}
}
for_each_bit(b, src_flags) {
switch ((VkAccessFlagBits)(1 << b)) {
case VK_ACCESS_HOST_READ_BIT:
break; /* FIXME: Little-core systems */
case VK_ACCESS_INDIRECT_COMMAND_READ_BIT:
case VK_ACCESS_INDEX_READ_BIT:
case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT:
cmd.VFCacheInvalidationEnable = true;
break;
case VK_ACCESS_UNIFORM_READ_BIT:
cmd.ConstantCacheInvalidationEnable = true;
/* fallthrough */
case VK_ACCESS_SHADER_READ_BIT:
cmd.DCFlushEnable = true;
cmd.TextureCacheInvalidationEnable = true;
break;
case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT:
cmd.TextureCacheInvalidationEnable = true;
break;
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT:
cmd.DCFlushEnable = true;
break;
case VK_ACCESS_TRANSFER_READ_BIT:
cmd.TextureCacheInvalidationEnable = true;
break;
case VK_ACCESS_MEMORY_READ_BIT:
break; /* XXX: What is this? */
default:
assert(!"Not a read bit");
}
}
dw = anv_batch_emit_dwords(&cmd_buffer->batch, GENX(PIPE_CONTROL_length));
GENX(PIPE_CONTROL_pack)(&cmd_buffer->batch, dw, &cmd);
}