Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
484 changes: 421 additions & 63 deletions gpu/vk/vk_draw.cpp

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions gpu/vk/vk_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,17 @@ struct Device {
VkDevice device = VK_NULL_HANDLE;
uint32_t queue_family = 0;
VkQueue queue = VK_NULL_HANDLE;
// (local) a transfer-only queue (the DMA engine): the mirrors' write-backs to guest memory cross PCIe there, beside
// the next submission's work (vk_memory.cpp, "write-backs by DMA"); none: on the queue, as before. RX_VK_WB_DMA=0: none
uint32_t xfer_family = UINT32_MAX;
VkQueue xfer_queue = VK_NULL_HANDLE;
// extensions in use
bool mesh_shader = false, external_memory_host = false, pipeline_library = false,
graphics_pipeline_library = false, custom_border_color = false, dynamic_state3 = false,
depth_clip_control = false, null_descriptor = false, index_uint8 = false, push_descriptor = false,
conditional_rendering = false, provoking_vertex = false, vertex_divisor = false, stencil_export = false, memory_budget = false,
checkpoints = false, // (RX_VK_CHECKPOINTS: VK_NV_device_diagnostic_checkpoints)
amd_markers = false, // ((local) RX_VK_CHECKPOINTS=1: VK_AMD_buffer_marker, the same checkpoints on AMD)
device_fault = false, // (VK_EXT_device_fault: what a lost device faulted on)
sparse_images = false, // (sparse resident 2D images on the queue: the terrain's huge arrays)
view_2d_of_3d = false, // (VK_EXT_image_2d_view_of_3d: a 3D texture a 2D sample instruction reads)
Expand All @@ -53,6 +58,7 @@ struct Device {
VkPhysicalDeviceVulkan12Features vk12{};
VkPhysicalDeviceVulkan13Features vk13{};
VkShaderStageFlags sg32_stages = 0; // (stages that run at 32 lanes when asked: the size the translated programs assume)
uint32_t max_subgroup = 32; // (local) the widest the driver may run a stage it does not pin (AMD: 64)
uint32_t max_push_descriptors = 0;
// no window (HOS_HEADLESS): presents go to an image of their own, which RX_VK_SHOTS can write out
bool offscreen = false;
Expand Down Expand Up @@ -168,6 +174,8 @@ void memory_drop_shadow(uint64_t guest, uint64_t size); // (a write the captur
/// (EvilBoyce) the newest submission value whose write-back reaches into [guest, guest + size) (0: none ever); *ever set
/// when any write-back ever did
uint64_t memory_writeback_value(uint64_t guest, uint64_t size, bool* ever);
void memory_note_readback(uint64_t guest, uint64_t size); // (local) a CPU read of GPU results: see memory_rb_refresh
bool memory_rb_refresh(VkCommandBuffer up);
uint32_t memory_generation();
/// 1: a page of [guest, guest + size) was written after generation gen; 0: none was
bool memory_written_since(uint64_t guest, uint64_t size, uint32_t gen);
Expand Down Expand Up @@ -196,6 +204,21 @@ void destroy_image(VkImage image, VmaAllocation allocation);
bool create_buffer(uint64_t size, VkBufferUsageFlags usage, bool host_visible, VkBuffer& buffer,
VmaAllocation& allocation, void** mapped);
void destroy_buffer(VkBuffer buffer, VmaAllocation allocation);
/// (local) A buffer in VRAM both queues use (the graphics queue and the DMA queue: concurrent sharing)
bool create_buffer_shared(uint64_t size, VkBufferUsageFlags usage, VkBuffer& buffer, VmaAllocation& allocation);

// ---- (local) write-backs by DMA (vk_replay.cpp's transfer submits, vk_memory.cpp's staging ring) ----
struct DmaCopy {
VkBuffer dst; // (a guest pool's imported buffer)
VkBufferCopy c; // (from the staging ring)
};
bool wb_dma_on(); // (a transfer queue, and RX_VK_WB_DMA not 0)
uint64_t xfer_done(); // (the transfer submits the DMA queue has finished)
VkResult xfer_wait(uint64_t value); // (until the DMA queue has finished this one)
VkBuffer memory_dma_ring();
void memory_dma_wait(uint64_t gpu, uint64_t size); // (before a GPU read of guest memory there: the DMA copies done)
void memory_take_dma(std::vector<DmaCopy>& out); // (this submission's copies: for its transfer submit)
void memory_dma_tag(uint64_t xfer_value); // (the transfer submit that carries them: their staging is free after it)
/// A buffer in VRAM only (within the driver's budget), or false
bool create_device_buffer(uint64_t size, VkBufferUsageFlags usage, VkBuffer& buffer, VmaAllocation& allocation);
/// Device-local memory this process uses and what the driver allows it now (VK_EXT_memory_budget), summed over the
Expand Down
3 changes: 2 additions & 1 deletion gpu/vk/vk_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
X(vkCreateCommandPool) \
X(vkDestroyCommandPool) \
X(vkResetCommandPool) \
X(vkResetCommandBuffer) \
X(vkAllocateCommandBuffers) \
X(vkBeginCommandBuffer) \
X(vkEndCommandBuffer) \
Expand Down Expand Up @@ -155,7 +156,7 @@
X(vkCmdResetQueryPool) X(vkCmdBeginQuery) X(vkCmdEndQuery) X(vkCmdCopyQueryPoolResults) X(vkGetQueryPoolResults) \
X(vkResetQueryPool) \
X(vkCmdSetDepthClipEnableEXT) X(vkCmdSetLogicOpEXT) X(vkCmdClearAttachments) X(vkCmdSetDepthBoundsTestEnable) \
X(vkCmdSetCheckpointNV) X(vkGetQueueCheckpointDataNV) X(vkGetDeviceFaultInfoEXT)
X(vkCmdSetCheckpointNV) X(vkGetQueueCheckpointDataNV) X(vkGetDeviceFaultInfoEXT) X(vkCmdWriteBufferMarkerAMD)

namespace vkx {
#define VKX_DECLARE(f) extern PFN_##f f;
Expand Down
26 changes: 23 additions & 3 deletions gpu/vk/vk_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ bool create_device() {
if (!getenv("RX_VK_CHECKPOINTS") || strcmp(getenv("RX_VK_CHECKPOINTS"), "0") != 0)
optional(VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME, dev.checkpoints);
optional(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, dev.device_fault);
// (local) AMD's markers for the checkpoints, asked for only (each draw writes two): which command a lost device hung in
if (getenv("RX_VK_CHECKPOINTS") && strcmp(getenv("RX_VK_CHECKPOINTS"), "0") != 0 && strcmp(getenv("RX_VK_CHECKPOINTS"), "ext") != 0)
optional(VK_AMD_BUFFER_MARKER_EXTENSION_NAME, dev.amd_markers);
optional(VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME, dev.coop_matrix);

// the queue: one family for graphics, compute and transfer
Expand All @@ -203,10 +206,22 @@ bool create_device() {
dev.queue_family = i;
if (dev.queue_family == UINT32_MAX) return false;
const float priority = 1.0f;
VkDeviceQueueCreateInfo q{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO};
VkDeviceQueueCreateInfo qs[2]{{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}, {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}};
VkDeviceQueueCreateInfo& q = qs[0];
q.queueFamilyIndex = dev.queue_family;
q.queueCount = 1;
q.pQueuePriorities = &priority;
// (local) the DMA engine's family: transfer only (AMD's SDMA). RX_VK_WB_DMA=0: not asked for
if (!getenv("RX_VK_WB_DMA") || atoi(getenv("RX_VK_WB_DMA")) != 0)
for (uint32_t i = 0; i < n && dev.xfer_family == UINT32_MAX; i++)
if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) && !(families[i].queueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)) &&
families[i].queueCount > 0)
dev.xfer_family = i;
if (dev.xfer_family != UINT32_MAX) {
qs[1].queueFamilyIndex = dev.xfer_family;
qs[1].queueCount = 1;
qs[1].pQueuePriorities = &priority;
}

// features: what the hardware has of what the replay uses (all of them on the GPUs MKW-class hardware maps to)
VkPhysicalDeviceMeshShaderFeaturesEXT mesh{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT};
Expand Down Expand Up @@ -286,6 +301,7 @@ bool create_device() {
vkGetPhysicalDeviceProperties2(dev.physical, &p2);
const bool pin = f13.subgroupSizeControl && sc.minSubgroupSize <= 32 && sc.maxSubgroupSize >= 32 && !getenv("RX_VK_NO_SUBGROUP_PIN");
dev.sg32_stages = pin ? sc.requiredSubgroupSizeStages : 0;
dev.max_subgroup = std::max(sg.subgroupSize, sc.maxSubgroupSize);
logf("vk: subgroups: default %u lanes, %u-%u, pinned to 32 on stages %#x", sg.subgroupSize, sc.minSubgroupSize, sc.maxSubgroupSize,
(unsigned)dev.sg32_stages);
}
Expand All @@ -302,8 +318,8 @@ bool create_device() {
f.features.sparseResidencyImage2D && !(getenv("RX_VK_SPARSE") && !atoi(getenv("RX_VK_SPARSE")));
VkDeviceCreateInfo ci{VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
ci.pNext = &f;
ci.queueCreateInfoCount = 1;
ci.pQueueCreateInfos = &q;
ci.queueCreateInfoCount = dev.xfer_family != UINT32_MAX ? 2 : 1;
ci.pQueueCreateInfos = qs;
ci.enabledExtensionCount = (uint32_t)want.size();
ci.ppEnabledExtensionNames = want.data();
if (vkCreateDevice(dev.physical, &ci, nullptr, &dev.device) != VK_SUCCESS) {
Expand All @@ -314,6 +330,10 @@ bool create_device() {

load_device(dev.device);
vkGetDeviceQueue(dev.device, dev.queue_family, 0, &dev.queue);
if (dev.xfer_family != UINT32_MAX) {
vkGetDeviceQueue(dev.device, dev.xfer_family, 0, &dev.xfer_queue);
logf("vk: write-backs by DMA: transfer queue family %u", dev.xfer_family);
}
coopmat_init();
if (dev.push_descriptor) {
VkPhysicalDevicePushDescriptorPropertiesKHR pp{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR};
Expand Down
Loading