blob: 2a671c4be4551a12b68bd325ddf9eddda5c44f66 [file] [edit]
/*
* Copyright © 2022 Collabora Ltd. and Red Hat Inc.
* SPDX-License-Identifier: MIT
*/
#include "nvk_event.h"
#include "nvk_buffer.h"
#include "nvk_cmd_buffer.h"
#include "nvk_device.h"
#include "nvk_entrypoints.h"
#include "nvk_mme.h"
#include "vk_synchronization.h"
#include "nv_push_cl906f.h"
#include "nv_push_cl9097.h"
#include "nv_push_cl90b5.h"
#include "nv_push_cl90c0.h"
#define NVK_EVENT_MEM_SIZE sizeof(VkResult)
VKAPI_ATTR VkResult VKAPI_CALL
nvk_CreateEvent(VkDevice device,
const VkEventCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkEvent *pEvent)
{
VK_FROM_HANDLE(nvk_device, dev, device);
struct nvk_event *event;
VkResult result;
event = vk_object_zalloc(&dev->vk, pAllocator, sizeof(*event),
VK_OBJECT_TYPE_EVENT);
if (!event)
return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
result = nvk_heap_alloc(dev, &dev->event_heap,
NVK_EVENT_MEM_SIZE, NVK_EVENT_MEM_SIZE,
&event->addr, (void **)&event->status);
if (result != VK_SUCCESS) {
vk_object_free(&dev->vk, pAllocator, event);
return result;
}
*event->status = VK_EVENT_RESET;
*pEvent = nvk_event_to_handle(event);
return VK_SUCCESS;
}
VKAPI_ATTR void VKAPI_CALL
nvk_DestroyEvent(VkDevice device,
VkEvent _event,
const VkAllocationCallbacks *pAllocator)
{
VK_FROM_HANDLE(nvk_device, dev, device);
VK_FROM_HANDLE(nvk_event, event, _event);
if (!event)
return;
nvk_heap_free(dev, &dev->event_heap, event->addr, NVK_EVENT_MEM_SIZE);
vk_object_free(&dev->vk, pAllocator, event);
}
VKAPI_ATTR VkResult VKAPI_CALL
nvk_GetEventStatus(VkDevice device,
VkEvent _event)
{
VK_FROM_HANDLE(nvk_event, event, _event);
return *event->status;
}
VKAPI_ATTR VkResult VKAPI_CALL
nvk_SetEvent(VkDevice device,
VkEvent _event)
{
VK_FROM_HANDLE(nvk_event, event, _event);
*event->status = VK_EVENT_SET;
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
nvk_ResetEvent(VkDevice device,
VkEvent _event)
{
VK_FROM_HANDLE(nvk_event, event, _event);
*event->status = VK_EVENT_RESET;
return VK_SUCCESS;
}
static bool
clear_bits64(uint64_t *bitfield, uint64_t bits)
{
bool has_bits = (*bitfield & bits) != 0;
*bitfield &= ~bits;
return has_bits;
}
uint32_t
vk_stage_flags_to_nv9097_pipeline_location(VkPipelineStageFlags2 flags)
{
if (clear_bits64(&flags, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT |
VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT |
VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT |
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT|
VK_PIPELINE_STAGE_2_COPY_BIT|
VK_PIPELINE_STAGE_2_RESOLVE_BIT|
VK_PIPELINE_STAGE_2_BLIT_BIT|
VK_PIPELINE_STAGE_2_CLEAR_BIT))
return NV9097_SET_REPORT_SEMAPHORE_D_PIPELINE_LOCATION_ALL;
if (clear_bits64(&flags, VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT))
return NV9097_SET_REPORT_SEMAPHORE_D_PIPELINE_LOCATION_DEPTH_TEST;
if (clear_bits64(&flags, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT))
return NV9097_SET_REPORT_SEMAPHORE_D_PIPELINE_LOCATION_PIXEL_SHADER;
if (clear_bits64(&flags, VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT))
return NV9097_SET_REPORT_SEMAPHORE_D_PIPELINE_LOCATION_ZCULL;
if (clear_bits64(&flags, VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT))
return NV9097_SET_REPORT_SEMAPHORE_D_PIPELINE_LOCATION_STREAMING_OUTPUT;
if (clear_bits64(&flags, VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT |
VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT))
return NV9097_SET_REPORT_SEMAPHORE_D_PIPELINE_LOCATION_GEOMETRY_SHADER;
if (clear_bits64(&flags, VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT))
return NV9097_SET_REPORT_SEMAPHORE_D_PIPELINE_LOCATION_TESSELATION_SHADER;
if (clear_bits64(&flags, VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT))
return NV9097_SET_REPORT_SEMAPHORE_D_PIPELINE_LOCATION_TESSELATION_INIT_SHADER;
if (clear_bits64(&flags, VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT))
return NV9097_SET_REPORT_SEMAPHORE_D_PIPELINE_LOCATION_VERTEX_SHADER;
if (clear_bits64(&flags, VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT |
VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT |
VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT))
return NV9097_SET_REPORT_SEMAPHORE_D_PIPELINE_LOCATION_DATA_ASSEMBLER;
clear_bits64(&flags, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT |
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT |
VK_PIPELINE_STAGE_2_HOST_BIT |
VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT);
clear_bits64(&flags, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
assert(flags == 0);
return NV9097_SET_REPORT_SEMAPHORE_D_PIPELINE_LOCATION_NONE;
}
static void
nvk_event_report_semaphore(struct nvk_cmd_buffer *cmd,
VkPipelineStageFlags2 stages,
uint64_t addr, uint32_t value)
{
uint8_t subc = nvk_cmd_buffer_last_subchannel(cmd);
if (subc == SUBC_NV9097) {
struct nv_push *p = nvk_cmd_buffer_push(cmd, 7);
P_IMMD(p, NV9097, FLUSH_PENDING_WRITES, 0);
P_MTHD(p, NV9097, SET_REPORT_SEMAPHORE_A);
P_NV9097_SET_REPORT_SEMAPHORE_A(p, addr >> 32);
P_NV9097_SET_REPORT_SEMAPHORE_B(p, addr);
P_NV9097_SET_REPORT_SEMAPHORE_C(p, value);
P_NV9097_SET_REPORT_SEMAPHORE_D(p, {
.operation = OPERATION_RELEASE,
.release = RELEASE_AFTER_ALL_PRECEEDING_WRITES_COMPLETE,
.pipeline_location = vk_stage_flags_to_nv9097_pipeline_location(stages),
.structure_size = STRUCTURE_SIZE_ONE_WORD,
});
} else if (subc == SUBC_NV90C0) {
struct nv_push *p = nvk_cmd_buffer_push(cmd, 5);
P_MTHD(p, NV90C0, SET_REPORT_SEMAPHORE_A);
P_NV90C0_SET_REPORT_SEMAPHORE_A(p, addr >> 32);
P_NV90C0_SET_REPORT_SEMAPHORE_B(p, addr);
P_NV90C0_SET_REPORT_SEMAPHORE_C(p, value);
P_NV90C0_SET_REPORT_SEMAPHORE_D(p, {
.operation = OPERATION_RELEASE,
.structure_size = STRUCTURE_SIZE_ONE_WORD,
});
} else {
assert(subc == SUBC_NV90B5);
struct nv_push *p = nvk_cmd_buffer_push(cmd, 6);
P_MTHD(p, NV90B5, SET_SEMAPHORE_A);
P_NV90B5_SET_SEMAPHORE_A(p, addr >> 32);
P_NV90B5_SET_SEMAPHORE_B(p, addr);
P_NV90B5_SET_SEMAPHORE_PAYLOAD(p, value);
P_IMMD(p, NV90B5, LAUNCH_DMA, {
.data_transfer_type = DATA_TRANSFER_TYPE_NONE,
.semaphore_type = SEMAPHORE_TYPE_RELEASE_ONE_WORD_SEMAPHORE,
.flush_enable = FLUSH_ENABLE_TRUE,
/* Note: FLUSH_TYPE=SYS implicitly for NVC3B5+ */
});
}
}
VKAPI_ATTR void VKAPI_CALL
nvk_CmdSetEvent2(VkCommandBuffer commandBuffer,
VkEvent _event,
const VkDependencyInfo *pDependencyInfo)
{
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
VK_FROM_HANDLE(nvk_event, event, _event);
nvk_cmd_flush_wait_dep(cmd, pDependencyInfo, false);
VkPipelineStageFlags2 stages =
vk_collect_dependency_info_src_stages(pDependencyInfo);
nvk_event_report_semaphore(cmd, stages, event->addr, VK_EVENT_SET);
}
VKAPI_ATTR void VKAPI_CALL
nvk_CmdResetEvent2(VkCommandBuffer commandBuffer,
VkEvent _event,
VkPipelineStageFlags2 stageMask)
{
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
VK_FROM_HANDLE(nvk_event, event, _event);
nvk_event_report_semaphore(cmd, stageMask, event->addr, VK_EVENT_RESET);
}
VKAPI_ATTR void VKAPI_CALL
nvk_CmdWaitEvents2(VkCommandBuffer commandBuffer,
uint32_t eventCount,
const VkEvent *pEvents,
const VkDependencyInfo *pDependencyInfos)
{
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
for (uint32_t i = 0; i < eventCount; i++) {
VK_FROM_HANDLE(nvk_event, event, pEvents[i]);
struct nv_push *p = nvk_cmd_buffer_push(cmd, 5);
__push_mthd(p, nvk_cmd_buffer_last_subchannel(cmd), NV906F_SEMAPHOREA);
P_NV906F_SEMAPHOREA(p, event->addr >> 32);
P_NV906F_SEMAPHOREB(p, (event->addr & UINT32_MAX) >> 2);
P_NV906F_SEMAPHOREC(p, VK_EVENT_SET);
P_NV906F_SEMAPHORED(p, {
.operation = OPERATION_ACQUIRE,
.acquire_switch = ACQUIRE_SWITCH_ENABLED,
.release_size = RELEASE_SIZE_4BYTE,
});
}
nvk_cmd_invalidate_deps(cmd, eventCount, pDependencyInfos);
}
VKAPI_ATTR void VKAPI_CALL
nvk_CmdWriteBufferMarker2AMD(VkCommandBuffer commandBuffer,
VkPipelineStageFlags2 stage,
VkBuffer _buffer,
VkDeviceSize offset,
uint32_t marker)
{
VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer);
VK_FROM_HANDLE(nvk_buffer, buffer, _buffer);
const uint64_t marker_addr = vk_buffer_address(&buffer->vk, offset);
nvk_event_report_semaphore(cmd, stage, marker_addr, marker);
}