[intel][vulkan] Use "softpin" for magma
Anvil performs the GPU address space management.
Add config parameter softpin_extra_page_count to accomodate
magma system driver's inter-mapping spacing.
MA-465 #comment
Test:
nuc:go/magma-tps#L1
nuc:go/magma-tps#S1
nuc:go/magma-tps#C0
nuc:go/magma-tps#P0
Change-Id: Idca3f2dce9241f322ff7710d77fd229de1a22ee6
diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index 83e82c4..3eed140 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -409,7 +409,8 @@
anv_gem_supports_syncobj_wait(fd);
device->has_context_priority = anv_gem_has_context_priority(fd);
- device->use_softpin = anv_gem_get_param(fd, I915_PARAM_HAS_EXEC_SOFTPIN)
+ device->softpin_extra_page_count = anv_gem_get_param(fd, I915_PARAM_HAS_EXEC_SOFTPIN);
+ device->use_softpin = device->softpin_extra_page_count
&& device->supports_48bit_addresses;
device->has_context_isolation =
@@ -2098,22 +2099,25 @@
bo->offset = 0;
+ const uint32_t page_size = 4096;
+ uint64_t size = bo->size + device->instance->physicalDevice.softpin_extra_page_count * page_size;
+
if (bo->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS &&
- device->vma_hi_available >= bo->size) {
- uint64_t addr = util_vma_heap_alloc(&device->vma_hi, bo->size, 4096);
+ device->vma_hi_available >= size) {
+ uint64_t addr = util_vma_heap_alloc(&device->vma_hi, size, 4096);
if (addr) {
bo->offset = gen_canonical_address(addr);
assert(addr == gen_48b_address(bo->offset));
- device->vma_hi_available -= bo->size;
+ device->vma_hi_available -= size;
}
}
- if (bo->offset == 0 && device->vma_lo_available >= bo->size) {
- uint64_t addr = util_vma_heap_alloc(&device->vma_lo, bo->size, 4096);
+ if (bo->offset == 0 && device->vma_lo_available >= size) {
+ uint64_t addr = util_vma_heap_alloc(&device->vma_lo, size, 4096);
if (addr) {
bo->offset = gen_canonical_address(addr);
assert(addr == gen_48b_address(bo->offset));
- device->vma_lo_available -= bo->size;
+ device->vma_lo_available -= size;
}
}
@@ -2132,15 +2136,17 @@
pthread_mutex_lock(&device->vma_mutex);
+ uint64_t size = bo->size + device->instance->physicalDevice.softpin_extra_page_count * 4096;
+
if (addr_48b >= LOW_HEAP_MIN_ADDRESS &&
addr_48b <= LOW_HEAP_MAX_ADDRESS) {
- util_vma_heap_free(&device->vma_lo, addr_48b, bo->size);
- device->vma_lo_available += bo->size;
+ util_vma_heap_free(&device->vma_lo, addr_48b, size);
+ device->vma_lo_available += size;
} else {
assert(addr_48b >= HIGH_HEAP_MIN_ADDRESS &&
addr_48b <= HIGH_HEAP_MAX_ADDRESS);
- util_vma_heap_free(&device->vma_hi, addr_48b, bo->size);
- device->vma_hi_available += bo->size;
+ util_vma_heap_free(&device->vma_hi, addr_48b, size);
+ device->vma_hi_available += size;
}
pthread_mutex_unlock(&device->vma_mutex);
diff --git a/src/intel/vulkan/anv_magma.c b/src/intel/vulkan/anv_magma.c
index c90c740..494903b 100644
--- a/src/intel/vulkan/anv_magma.c
+++ b/src/intel/vulkan/anv_magma.c
@@ -29,14 +29,7 @@
return -1;
}
- uint64_t extra_page_count;
- status = magma_query(device->fd, kMsdIntelGenQueryExtraPageCount, &extra_page_count);
- if (status != MAGMA_STATUS_OK) {
- DLOG("magma_query failed: %d", status);
- return -1;
- }
-
- device->connection = AnvMagmaCreateConnection(connection, extra_page_count);
+ device->connection = AnvMagmaCreateConnection(connection);
DLOG("created magma connection");
return 0;
@@ -214,6 +207,17 @@
case I915_PARAM_HAS_EXEC_FENCE_ARRAY: // Used for semaphores
value = 1;
break;
+ case I915_PARAM_HAS_EXEC_SOFTPIN: {
+ // client driver manages GPU address space
+ uint64_t extra_page_count = 0;
+ status = magma_query(fd, kMsdIntelGenQueryExtraPageCount, &extra_page_count);
+ if (status != MAGMA_STATUS_OK) {
+ DLOG("magma_query failed: %d", status);
+ break;
+ }
+ value = extra_page_count;
+ break;
+ }
default:
status = MAGMA_STATUS_INVALID_ARGS;
}
@@ -396,7 +400,8 @@
ANV_FROM_HANDLE(anv_device, device, vk_device);
ANV_FROM_HANDLE(anv_device_memory, memory, pGetZirconHandleInfo->memory);
- assert(pGetZirconHandleInfo->sType == VK_STRUCTURE_TYPE_TEMP_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA);
+ assert(pGetZirconHandleInfo->sType ==
+ VK_STRUCTURE_TYPE_TEMP_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA);
assert(pGetZirconHandleInfo->handleType ==
VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA);
diff --git a/src/intel/vulkan/anv_magma.h b/src/intel/vulkan/anv_magma.h
index beface5..c225391 100644
--- a/src/intel/vulkan/anv_magma.h
+++ b/src/intel/vulkan/anv_magma.h
@@ -31,8 +31,7 @@
#endif
// Transfer ownership of the |connection|.
-struct anv_connection* AnvMagmaCreateConnection(magma_connection_t connection,
- uint64_t extra_page_count);
+struct anv_connection* AnvMagmaCreateConnection(magma_connection_t connection);
void AnvMagmaReleaseConnection(struct anv_connection* connection);
diff --git a/src/intel/vulkan/anv_magma_connection.cc b/src/intel/vulkan/anv_magma_connection.cc
index 8f63954..5810647 100644
--- a/src/intel/vulkan/anv_magma_connection.cc
+++ b/src/intel/vulkan/anv_magma_connection.cc
@@ -4,13 +4,12 @@
#include "anv_magma.h"
#include "drm_command_buffer.h"
+#include "gen_gem.h"
#include "magma_sysmem.h"
#include "magma_util/inflight_list.h"
#include "magma_util/macros.h"
-#include "magma_util/simple_allocator.h"
#include <chrono>
-#include <limits.h>
-#include <mutex>
+#include <map>
#include <vector>
class Buffer : public anv_magma_buffer {
@@ -29,43 +28,35 @@
void AddMapping(uint64_t page_offset, uint64_t page_count, uint64_t addr)
{
- mappings_.push_back({addr, page_offset, page_count});
+ mappings_[addr] = {page_offset, page_count};
}
- bool HasMapping(uint64_t page_offset, uint64_t page_count, uint64_t* addr_out)
- {
- for (auto& mapping : mappings_) {
- if (mapping.page_offset == page_offset && mapping.page_count == page_count) {
- if (addr_out) {
- *addr_out = mapping.addr;
- }
- return true;
- }
- }
- return false;
- }
-
- struct Mapping {
- uint64_t addr = 0;
+ struct Segment {
uint64_t page_offset = 0;
uint64_t page_count = 0;
};
- void TakeMappings(std::vector<Mapping>* mappings_out)
+ bool HasMapping(uint64_t addr, Segment* segment_out) const
{
- *mappings_out = std::move(mappings_);
- mappings_.clear();
+ auto iter = mappings_.find(addr);
+ if (iter != mappings_.end()) {
+ if (segment_out) {
+ *segment_out = iter->second;
+ }
+ return true;
+ }
+ return false;
}
+ void RemoveMapping(uint64_t addr) { mappings_.erase(addr); }
+
private:
- std::vector<Mapping> mappings_;
+ std::map<uint64_t, Segment> mappings_;
};
class Connection : public anv_connection {
public:
- Connection(magma_connection_t magma_connection, uint64_t guard_page_count)
- : allocator_(magma::SimpleAllocator::Create(0, 1ull << 48)),
- guard_page_count_(guard_page_count)
+ Connection(magma_connection_t magma_connection)
{
anv_connection::connection = magma_connection;
}
@@ -82,30 +73,6 @@
magma::InflightList* inflight_list() { return &inflight_list_; }
- uint64_t guard_page_count() const { return guard_page_count_; }
-
- bool MapGpu(uint64_t page_count, uint64_t* gpu_addr_out)
- {
- std::lock_guard<std::mutex> lock(allocator_mutex_);
-
- uint64_t length = (page_count + guard_page_count_) * magma::page_size();
-
- if (length > allocator_->size())
- return DRETF(false, "length (0x%lx) > address space size (0x%lx)", length,
- allocator_->size());
-
- if (!allocator_->Alloc(length, magma::page_shift(), gpu_addr_out))
- return DRETF(false, "failed to allocate gpu address");
-
- return true;
- }
-
- void UnmapGpu(uint64_t gpu_addr)
- {
- std::lock_guard<std::mutex> lock(allocator_mutex_);
- allocator_->Free(gpu_addr);
- }
-
magma_status_t GetSysmemConnection(magma_sysmem_connection_t* sysmem_connection_out)
{
if (!sysmem_connection_) {
@@ -125,15 +92,11 @@
private:
magma_sysmem_connection_t sysmem_connection_{};
magma::InflightList inflight_list_;
- std::unique_ptr<magma::AddressSpaceAllocator> allocator_;
- // Protect the allocator from simultaneous Map and Unmap from different threads
- std::mutex allocator_mutex_;
- uint64_t guard_page_count_;
};
-anv_connection* AnvMagmaCreateConnection(magma_connection_t connection, uint64_t extra_page_count)
+anv_connection* AnvMagmaCreateConnection(magma_connection_t connection)
{
- return new Connection(connection, extra_page_count);
+ return new Connection(connection);
}
void AnvMagmaReleaseConnection(anv_connection* connection)
@@ -195,16 +158,26 @@
if (!magma::is_page_aligned(offset))
return DRET_MSG(-1, "offset (0x%lx) not page aligned", offset);
+ uint64_t gpu_addr = gen_48b_address(exec_objects[i].offset);
uint64_t page_offset = offset / magma::page_size();
uint64_t page_count =
magma::round_up(exec_objects[i].rsvd2, magma::page_size()) / magma::page_size();
- if (!buffer->HasMapping(page_offset, page_count, nullptr)) {
- uint64_t gpu_addr;
- if (!Connection::cast(connection)->MapGpu(page_count, &gpu_addr))
- return DRET_MSG(-1, "failed to map gpu addr");
+ Buffer::Segment segment;
+ bool has_mapping = buffer->HasMapping(gpu_addr, &segment);
+ if (has_mapping) {
+ assert(page_offset == segment.page_offset);
+ if (page_count > segment.page_count) {
+ // Growing an existing mapping.
+ buffer->RemoveMapping(gpu_addr);
+ has_mapping = false;
+ } else {
+ assert(page_count == segment.page_count);
+ }
+ }
- DLOG("mapping to gpu addr %lu: id %lu page_offset %lu page_count %lu\n", gpu_addr,
+ if (!has_mapping) {
+ DLOG("mapping to gpu addr 0x%lx: id %lu page_offset %lu page_count %lu", gpu_addr,
buffer_ids[i], page_offset, page_count);
magma_map_buffer_gpu(Connection::cast(connection)->magma_connection(), buffer->get(),
page_offset, page_count, gpu_addr, 0);
@@ -280,15 +253,6 @@
{
auto buffer = static_cast<Buffer*>(anv_buffer);
// Hardware mappings are released when the buffer is released.
- // Do this before unmapping to avoid remap before release.
buffer->release(Connection::cast(connection)->magma_connection());
-
- std::vector<Buffer::Mapping> mappings;
- buffer->TakeMappings(&mappings);
- // Each Unmap takes a lock, however multiple mappings per buffer is rare
- for (auto& mapping : mappings) {
- Connection::cast(connection)->UnmapGpu(mapping.addr);
- }
-
delete buffer;
}
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index fce08c4..38ce859 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -873,6 +873,7 @@
bool has_context_priority;
bool use_softpin;
bool has_context_isolation;
+ uint32_t softpin_extra_page_count;
struct anv_device_extension_table supported_extensions;