blob: 42595714255661db5eaeafd8d07526ce79e15a36 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "magma_system_context.h"
#include <memory>
#include <unordered_set>
#include <vector>
#include "magma_system_connection.h"
#include "magma_system_device.h"
#include "magma_util/macros.h"
#include "platform_trace.h"
magma::Status MagmaSystemContext::ExecuteCommandBufferWithResources(
std::unique_ptr<magma_command_buffer> cmd_buf, std::vector<magma_exec_resource> resources,
std::vector<uint64_t> semaphores) {
// used to keep resources in scope until msd_context_execute_command_buffer returns
std::vector<std::shared_ptr<MagmaSystemBuffer>> system_resources;
system_resources.reserve(cmd_buf->resource_count);
// the resources to be sent to the MSD driver
auto msd_resources = std::vector<msd_buffer_t*>();
msd_resources.reserve(cmd_buf->resource_count);
// validate batch buffer index
if (cmd_buf->resource_count > 0 &&
cmd_buf->batch_buffer_resource_index >= cmd_buf->resource_count)
return DRET_MSG(MAGMA_STATUS_INVALID_ARGS,
"ExecuteCommandBuffer: batch buffer resource index invalid");
if (cmd_buf->resource_count == 0) {
// These shouldn't be used.
cmd_buf->batch_buffer_resource_index = 0;
cmd_buf->batch_start_offset = 0;
}
// validate exec resources
for (uint32_t i = 0; i < cmd_buf->resource_count; i++) {
uint64_t id = resources[i].buffer_id;
auto buf = owner_->LookupBufferForContext(id);
if (!buf)
return DRET_MSG(MAGMA_STATUS_INVALID_ARGS,
"ExecuteCommandBuffer: exec resource has invalid buffer handle");
system_resources.push_back(buf);
msd_resources.push_back(buf->msd_buf());
if (i == cmd_buf->batch_buffer_resource_index) {
// validate batch start
if (cmd_buf->batch_start_offset >= buf->size())
return DRET_MSG(MAGMA_STATUS_INVALID_ARGS, "invalid batch start offset 0x%lx",
cmd_buf->batch_start_offset);
}
}
// used to keep semaphores in scope until msd_context_execute_command_buffer returns
std::vector<msd_semaphore_t*> msd_wait_semaphores(cmd_buf->wait_semaphore_count);
std::vector<msd_semaphore_t*> msd_signal_semaphores(cmd_buf->signal_semaphore_count);
// validate semaphores
for (uint32_t i = 0; i < cmd_buf->wait_semaphore_count; i++) {
auto semaphore = owner_->LookupSemaphoreForContext(semaphores[i]);
if (!semaphore)
return DRET_MSG(MAGMA_STATUS_INVALID_ARGS, "wait semaphore id not found 0x%" PRIx64,
semaphores[i]);
msd_wait_semaphores[i] = semaphore->msd_semaphore();
}
for (uint32_t i = 0; i < cmd_buf->signal_semaphore_count; i++) {
auto semaphore =
owner_->LookupSemaphoreForContext(semaphores[cmd_buf->wait_semaphore_count + i]);
if (!semaphore)
return DRET_MSG(MAGMA_STATUS_INVALID_ARGS, "signal semaphore id not found 0x%" PRIx64,
semaphores[cmd_buf->wait_semaphore_count + i]);
msd_signal_semaphores[i] = semaphore->msd_semaphore();
}
// submit command buffer to driver
magma_status_t result = msd_context_execute_command_buffer_with_resources(
msd_ctx(), cmd_buf.get(), resources.data(), msd_resources.data(), msd_wait_semaphores.data(),
msd_signal_semaphores.data());
return DRET_MSG(result, "ExecuteCommandBuffer: msd_context_execute_command_buffer failed: %d",
result);
}
magma::Status MagmaSystemContext::ExecuteImmediateCommands(uint64_t commands_size, void* commands,
uint64_t semaphore_count,
uint64_t* semaphore_ids) {
TRACE_DURATION("magma", "MagmaSystemContext::ExecuteImmediateCommands");
std::vector<msd_semaphore_t*> msd_semaphores(semaphore_count);
for (uint32_t i = 0; i < semaphore_count; i++) {
auto semaphore = owner_->LookupSemaphoreForContext(semaphore_ids[i]);
if (!semaphore)
return DRET_MSG(MAGMA_STATUS_INVALID_ARGS, "semaphore id not found 0x%" PRIx64,
semaphore_ids[i]);
msd_semaphores[i] = semaphore->msd_semaphore();
// This is used to connect with command submission in
// src/ui/scenic/lib/gfx/engine/engine.cc and
// src/ui/scenic/lib/flatland/renderer/vk_renderer.cc, so it uses the koid.
TRACE_FLOW_END("gfx", "semaphore", semaphore->platform_semaphore()->global_id());
}
magma_status_t result = msd_context_execute_immediate_commands(
msd_ctx(), commands_size, commands, semaphore_count, msd_semaphores.data());
return DRET_MSG(result,
"ExecuteImmediateCommands: msd_context_execute_immediate_commands failed: %d",
result);
}