[magma] Stub support for advanced context features.
Multiple address spaces: Intel supports creating multiple address
spaces and sharing them between contexts. We can assume for now only
a single address space is actually used for executing command buffers
and detect when that assumption is violated.
Command buffer ordering across engines: Intel supports this in the
system driver. We can assume for now only a single engine is
targeted per context and detect when that assumption is violated.
Test:all nuc_env packages under //src/media/codec/examples
Bug:110484
Change-Id: If2bd5f6866b7a4388ea769c1216064a7c2e76266
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/github.com/intel/media-driver/+/731823
Reviewed-by: John Bauman <jbauman@google.com>
diff --git a/media_driver/linux/common/os/magma/mos_bufmgr_magma.cpp b/media_driver/linux/common/os/magma/mos_bufmgr_magma.cpp
index 143d455..3c9edb0 100644
--- a/media_driver/linux/common/os/magma/mos_bufmgr_magma.cpp
+++ b/media_driver/linux/common/os/magma/mos_bufmgr_magma.cpp
@@ -74,6 +74,22 @@
InflightList* inflight_list() { return &inflight_list_;}
+ uint32_t next_vm_id() {
+ uint32_t id = next_pseudo_vm_id_.fetch_add(1);
+ // Don't support wrap around.
+ assert(id != 0);
+ return id;
+ }
+
+ static constexpr uint32_t kInvalidVmId = 0;
+
+ // Sets the pseudo VM ID if not already set.
+ uint32_t GetVmId(uint32_t vm_id) {
+ uint32_t invalid_id = kInvalidVmId;
+ vm_id_.compare_exchange_strong(invalid_id, vm_id);
+ return vm_id_.load();
+ }
+
private:
magma_connection_t connection_ {};
magma_handle_t notification_handle_{};
@@ -81,6 +97,8 @@
std::mutex allocator_mutex_;
std::unique_ptr<SimpleAllocator> allocator_ __attribute__((__guarded_by__(allocator_mutex_)));
InflightList inflight_list_;
+ std::atomic_uint next_pseudo_vm_id_ {1};
+ std::atomic_uint vm_id_ { kInvalidVmId };
};
@@ -214,8 +232,37 @@
const std::vector<uint32_t>& target_engines() { return target_engines_; }
+ // Should only be called once.
+ void set_vm_id(uint32_t vm_id) {
+ assert(vm_id != 0);
+ assert(vm_id_ == 0);
+ vm_id_ = vm_id;
+ }
+
+ uint32_t vm_id() { return vm_id_; }
+
+ // Should only be called once.
+ void set_ensure_ordering_across_engines() {
+ assert(!ensure_ordering_across_engines_);
+ ensure_ordering_across_engines_ = true;
+ }
+
+ bool ensure_ordering_across_engines() { return ensure_ordering_across_engines_; }
+
+ static constexpr uint64_t kInitialFlags = 0;
+
+ // Sets the command buffer flags if not already set.
+ uint64_t GetCommandBufferFlags(uint64_t command_buffer_flags) {
+ uint64_t unset = kInitialFlags;
+ command_buffer_flags_.compare_exchange_strong(unset, command_buffer_flags);
+ return command_buffer_flags_.load();
+ }
+
private:
std::vector<uint32_t> target_engines_;
+ uint32_t vm_id_ = 0;
+ bool ensure_ordering_across_engines_ = false;
+ std::atomic_uint64_t command_buffer_flags_ {kInitialFlags};
};
static void bufmgr_destroy(struct mos_bufmgr* mos_bufmgr)
@@ -596,12 +643,40 @@
return context;
}
-struct mos_linux_context* mos_gem_context_create_ext(struct mos_bufmgr *bufmgr, __u32 flags)
+struct mos_linux_context *mos_gem_context_create_ext(struct mos_bufmgr *bufmgr, __u32 flags)
{
assert(flags == 0);
return mos_gem_context_create(bufmgr);
}
+// Creates a new context and associates with it the pseudo VM referenced by the given context.
+// Note the reference context may not have been created with mos_gem_context_create_shared.
+// The pseudo VMs are just IDs and are used to track which "VMs" are used to execute command
+// buffers. We assume that only one VM is ever used for all executed contexts, but if that
+// assumption proves false then we'll have to create additional connections for each VM.
+struct mos_linux_context* mos_gem_context_create_shared(struct mos_bufmgr *bufmgr,
+ mos_linux_context* ref_context, __u32 flags)
+{
+ LOG_VERBOSE("mos_gem_context_create_shared vm_id %u flags 0x%x", ref_context->vm->vm_id, flags);
+
+ bool ensure_ordering_across_engines = flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE;
+
+ flags &= ~I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE;
+ assert(flags == 0);
+
+ auto context = static_cast<MagmaContext*>(mos_gem_context_create(bufmgr));
+ if (!context)
+ return nullptr;
+
+ context->set_vm_id(ref_context->vm->vm_id);
+
+ if (ensure_ordering_across_engines) {
+ context->set_ensure_ordering_across_engines();
+ }
+
+ return context;
+}
+
void mos_gem_context_destroy(struct mos_linux_context *mos_context)
{
auto context = static_cast<MagmaContext*>(mos_context);
@@ -652,6 +727,30 @@
return 0;
}
+struct drm_i915_gem_vm_control* mos_gem_vm_create(struct mos_bufmgr *mos_bufmgr)
+{
+ // Magma only supports one VM per connection, so for now we fake this support, assuming that
+ // contexts used for command buffer submission will only use one shared VM.
+ auto bufmgr = static_cast<MagmaBufMgr*>(mos_bufmgr);
+
+ auto vm = new drm_i915_gem_vm_control;
+
+ vm->extensions = 0;
+ vm->flags = 0;
+ vm->vm_id = bufmgr->next_vm_id();
+
+ LOG_VERBOSE("mos_gem_vm_create vm_id %u", vm->vm_id);
+
+ return vm;
+}
+
+void mos_gem_vm_destroy(struct mos_bufmgr *bufmgr, struct drm_i915_gem_vm_control* vm)
+{
+ LOG_VERBOSE("mos_gem_vm_destroy vm_id %u", vm->vm_id);
+
+ delete vm;
+}
+
int mos_bufmgr_gem_get_devid(struct mos_bufmgr *mos_bufmgr)
{
auto bufmgr = static_cast<MagmaBufMgr*>(mos_bufmgr);
@@ -717,9 +816,29 @@
uint64_t magma_flags = get_magma_flags(context, flags & I915_EXEC_RING_MASK);
- LOG_VERBOSE("mos_gem_bo_context_exec2 bo %lu used %d context_id %u num_cliprects %d DR4 %d "
- "flags 0x%x kAllowedFlags 0x%x magma_flags 0x%lx",
- bo->id(), used, context->ctx_id, num_cliprects, DR4, flags, kAllowedFlags, magma_flags);
+ uint32_t vm_id = bufmgr->GetVmId(context->vm_id());
+
+ LOG_VERBOSE("mos_gem_bo_context_exec2 bo %lu used %d context_id %u vm_id %u bufmgr vm_id %u "
+ "num_cliprects %d DR4 %d flags 0x%x kAllowedFlags 0x%x magma_flags 0x%lx",
+ bo->id(), used, context->ctx_id, context->vm_id(), vm_id, num_cliprects, DR4,
+ flags, kAllowedFlags, magma_flags);
+
+ if (vm_id != context->vm_id()) {
+ // We don't support more than one VM per connection (see mos_gem_context_create_shared)
+ LOG_VERBOSE("Incompatible VM bufmgr vm_id %u context vm_id %u", vm_id, context->vm_id());
+ assert(false);
+ return -1;
+ }
+
+ if (context->ensure_ordering_across_engines()) {
+ uint64_t flags = context->GetCommandBufferFlags(magma_flags);
+ if (flags != magma_flags) {
+ LOG_VERBOSE("Ordering across engines not implemented flags 0x%lx magma_flags 0x%lx",
+ flags, magma_flags);
+ assert(false);
+ return -1;
+ }
+ }
// TODO(fxbug.78281)
uint64_t* semaphore_ids = nullptr;
diff --git a/media_driver/linux/common/os/magma/mos_bufmgr_stub.c b/media_driver/linux/common/os/magma/mos_bufmgr_stub.c
index cc8d0b1..a525fab 100644
--- a/media_driver/linux/common/os/magma/mos_bufmgr_stub.c
+++ b/media_driver/linux/common/os/magma/mos_bufmgr_stub.c
@@ -94,19 +94,6 @@
return 0;
}
-struct drm_i915_gem_vm_control* mos_gem_vm_create(struct mos_bufmgr *bufmgr)
-{
- LOG_VERBOSE("mos_gem_vm_create unimplemented");
- return NULL;
-}
-
-struct mos_linux_context *
-mos_gem_context_create_shared(struct mos_bufmgr *bufmgr, mos_linux_context* ctx, __u32 flags)
-{
- LOG_VERBOSE("mos_gem_context_create_shared unimplemented");
- return NULL;
-}
-
int
mos_get_reset_stats(struct mos_linux_context *ctx,
uint32_t *reset_count,
@@ -117,11 +104,6 @@
return 0;
}
-void mos_gem_vm_destroy(struct mos_bufmgr *bufmgr, struct drm_i915_gem_vm_control* vm)
-{
- LOG_VERBOSE("mos_gem_vm_destroy unimplemented");
-}
-
int mos_get_context_param_sseu(struct mos_linux_context *ctx,
struct drm_i915_gem_context_param_sseu *sseu) {
LOG_VERBOSE("mos_get_context_param_sseu unimplemented");
diff --git a/media_driver/linux/common/os/mos_interface.cpp b/media_driver/linux/common/os/mos_interface.cpp
index fcc0aec..90176da 100644
--- a/media_driver/linux/common/os/mos_interface.cpp
+++ b/media_driver/linux/common/os/mos_interface.cpp
@@ -433,7 +433,10 @@
context->bIsAtomSOC = false;
context->bFreeContext = true;
-#if !defined(ANDROID) && !defined(__Fuchsia__)
+#if defined(__Fuchsia__)
+ // TODO(TBD)
+ context->bKMDHasVCS2 = false;
+#elif !defined(ANDROID)
{
drm_i915_getparam_t gp;
int32_t ret = -1;
@@ -453,9 +456,6 @@
context->bKMDHasVCS2 = false;
}
}
-#else
- //TODO(fxbug.dev/78281) - remove
- fprintf(stderr, "%s:%d MosInterface::InitStreamParameters not implemented\n", __FILE__, __LINE__);
#endif
// read "Linux PerformanceTag Enable" user feature key