blob: 79238888442eb1a3e9ef42f26e35a6894cfe8b3b [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.
#ifndef MSD_INTEL_CONTEXT_H
#define MSD_INTEL_CONTEXT_H
#include <lib/async/cpp/wait.h>
#include <lib/magma/platform/platform_logger.h>
#include <lib/magma/util/status.h>
#include <lib/magma_service/msd.h>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include "command_buffer.h"
#include "msd_intel_buffer.h"
#include "ppgtt.h"
#include "ringbuffer.h"
#include "types.h"
class MsdIntelConnection;
// Base context, not tied to a connection.
class MsdIntelContext {
public:
// Context for handling a wait semaphore.
class HandleWaitContext {
public:
HandleWaitContext(MsdIntelContext* context, EngineCommandStreamerId id, zx::handle object,
std::shared_ptr<magma::PlatformSemaphore> semaphore);
~HandleWaitContext() { waiter_.Cancel(); }
zx_status_t Begin(async_dispatcher_t* dispatcher) { return waiter_.Begin(dispatcher); }
EngineCommandStreamerId id() const { return id_; }
const std::shared_ptr<magma::PlatformSemaphore>& semaphore() const { return semaphore_; }
private:
void Handler(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
const zx_packet_signal_t* signal);
MsdIntelContext* context_;
EngineCommandStreamerId id_;
zx::handle object_;
std::shared_ptr<magma::PlatformSemaphore> semaphore_;
async::WaitMethod<HandleWaitContext, &HandleWaitContext::Handler> waiter_;
};
explicit MsdIntelContext(std::shared_ptr<AddressSpace> address_space)
: address_space_(std::move(address_space)) {
DASSERT(address_space_);
}
MsdIntelContext(std::shared_ptr<AddressSpace> address_space,
std::weak_ptr<MsdIntelConnection> connection)
: address_space_(std::move(address_space)), connection_(std::move(connection)) {}
void SetTargetCommandStreamer(EngineCommandStreamerId id) {
target_command_streamers_.insert(id);
presubmit_map_.insert({id, PerEnginePresubmit{}});
}
std::set<EngineCommandStreamerId> GetTargetCommandStreamers() {
return target_command_streamers_;
}
void SetEngineState(EngineCommandStreamerId id, std::unique_ptr<MsdIntelBuffer> context_buffer,
std::unique_ptr<Ringbuffer> ringbuffer);
bool Map(std::shared_ptr<AddressSpace> address_space, EngineCommandStreamerId id);
bool Unmap(EngineCommandStreamerId id);
// The HW context state refers to the indirect context batch, so keep a reference to the batch
// and its underlying GPU mapping.
void SetIndirectContextBatch(std::shared_ptr<IndirectContextBatch> batch) {
indirect_context_batch_ = std::move(batch);
}
std::weak_ptr<MsdIntelConnection> connection() { return connection_; }
bool killed() const { return killed_; }
void Kill();
size_t GetQueueSize(EngineCommandStreamerId id) {
auto iter = presubmit_map_.find(id);
DASSERT(iter != presubmit_map_.end());
PerEnginePresubmit& presubmit = iter->second;
return presubmit.queue.size();
}
// Gets the gpu address of the context buffer if mapped.
bool GetGpuAddress(EngineCommandStreamerId id, gpu_addr_t* addr_out);
bool GetRingbufferGpuAddress(EngineCommandStreamerId id, gpu_addr_t* addr_out);
MsdIntelBuffer* get_context_buffer(EngineCommandStreamerId id) {
auto iter = state_map_.find(id);
return iter == state_map_.end() ? nullptr : iter->second.context_buffer.get();
}
void* GetCachedContextBufferCpuAddr(EngineCommandStreamerId id) {
auto iter = state_map_.find(id);
if (iter == state_map_.end())
return nullptr;
if (!iter->second.context_buffer_cpu_addr) {
MsdIntelBuffer* context_buffer = iter->second.context_buffer.get();
if (!context_buffer)
return nullptr;
if (!context_buffer->platform_buffer()->MapCpu(&iter->second.context_buffer_cpu_addr))
return DRETP(nullptr, "Failed to map context buffer");
}
return iter->second.context_buffer_cpu_addr;
}
Ringbuffer* get_ringbuffer(EngineCommandStreamerId id) {
auto iter = state_map_.find(id);
return iter == state_map_.end() ? nullptr : iter->second.ringbuffer.get();
}
bool IsInitializedForEngine(EngineCommandStreamerId id) {
return state_map_.find(id) != state_map_.end();
}
std::queue<std::unique_ptr<MappedBatch>>& pending_batch_queue(EngineCommandStreamerId id) {
auto iter = state_map_.find(id);
DASSERT(iter != state_map_.end());
return iter->second.pending_batch_queue;
}
std::shared_ptr<AddressSpace> exec_address_space() { return address_space_; }
magma::Status SubmitCommandBuffer(std::unique_ptr<CommandBuffer> cmd_buf);
magma::Status SubmitBatch(std::unique_ptr<MappedBatch> batch);
std::vector<std::shared_ptr<magma::PlatformSemaphore>> GetWaitSemaphores(
EngineCommandStreamerId id) const;
void UpdateWaitSet(EngineCommandStreamerId id);
void Shutdown();
private:
void AddToWaitset(EngineCommandStreamerId id, std::shared_ptr<MsdIntelConnection> connection,
std::shared_ptr<magma::PlatformSemaphore> semaphore);
void WaitComplete(HandleWaitContext* wait_context, zx_status_t status);
magma::Status ProcessPresubmitQueue(EngineCommandStreamerId id);
struct PerEngineState {
std::shared_ptr<MsdIntelBuffer> context_buffer;
std::unique_ptr<GpuMapping> context_mapping;
std::unique_ptr<Ringbuffer> ringbuffer;
std::queue<std::unique_ptr<MappedBatch>> pending_batch_queue;
gpu_addr_t ringbuffer_gpu_addr = 0;
void* context_buffer_cpu_addr = nullptr;
};
std::shared_ptr<IndirectContextBatch> indirect_context_batch_;
std::set<EngineCommandStreamerId> target_command_streamers_;
std::map<EngineCommandStreamerId, PerEngineState> state_map_;
std::shared_ptr<AddressSpace> address_space_;
std::weak_ptr<MsdIntelConnection> connection_;
struct PerEnginePresubmit {
// The wait set tracks pending semaphores for the head of the presubmit queue
std::vector<std::unique_ptr<HandleWaitContext>> wait_set;
std::queue<std::unique_ptr<MappedBatch>> queue;
};
std::map<EngineCommandStreamerId, PerEnginePresubmit> presubmit_map_;
bool killed_ = false;
friend class TestContext;
};
class MsdIntelAbiContext : public msd::Context {
public:
explicit MsdIntelAbiContext(std::shared_ptr<MsdIntelContext> ptr) : ptr_(std::move(ptr)) {}
~MsdIntelAbiContext() override;
std::shared_ptr<MsdIntelContext> ptr() { return ptr_; }
magma_status_t ExecuteCommandBufferWithResources(msd::magma_command_buffer* command_buffer,
magma_exec_resource* exec_resources,
msd::Buffer** buffers,
msd::Semaphore** wait_semaphores,
msd::Semaphore** signal_semaphores) override;
private:
std::shared_ptr<MsdIntelContext> ptr_;
};
#endif // MSD_INTEL_CONTEXT_H