| // 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 "drm_command_buffer.h" |
| #include "magma_system.h" |
| #include "magma_util/dlog.h" |
| #include "magma_util/macros.h" |
| |
| uint64_t DrmCommandBuffer::RequiredSize(drm_i915_gem_execbuffer2* execbuf, |
| uint32_t wait_semaphore_count, |
| uint32_t signal_semaphore_count) |
| { |
| auto execobjects = reinterpret_cast<drm_i915_gem_exec_object2*>(execbuf->buffers_ptr); |
| |
| const uint32_t num_resources = execbuf->buffer_count; |
| |
| uint32_t num_relocations = 0; |
| for (uint32_t res_index = 0; res_index < num_resources; res_index++) { |
| num_relocations += execobjects[res_index].relocation_count; |
| } |
| |
| return sizeof(magma_system_command_buffer) + |
| (wait_semaphore_count + signal_semaphore_count) * sizeof(uint64_t) + |
| sizeof(magma_system_exec_resource) * num_resources + |
| sizeof(magma_system_relocation_entry) * num_relocations; |
| } |
| |
| bool DrmCommandBuffer::Translate(drm_i915_gem_execbuffer2* execbuf, |
| std::vector<uint64_t> wait_semaphore_ids, |
| std::vector<uint64_t> signal_semaphore_ids, |
| void* command_buffer_out) |
| { |
| DASSERT((execbuf->flags & I915_EXEC_HANDLE_LUT) != 0); |
| |
| auto execobjects = reinterpret_cast<drm_i915_gem_exec_object2*>(execbuf->buffers_ptr); |
| const uint32_t num_resources = execbuf->buffer_count; |
| |
| magma_system_command_buffer* command_buffer = |
| reinterpret_cast<magma_system_command_buffer*>(command_buffer_out); |
| uint64_t* dst_wait_semaphore_ids = reinterpret_cast<uint64_t*>(command_buffer + 1); |
| uint64_t* dst_signal_semaphore_ids = |
| reinterpret_cast<uint64_t*>(dst_wait_semaphore_ids + wait_semaphore_ids.size()); |
| magma_system_exec_resource* exec_resources = reinterpret_cast<magma_system_exec_resource*>( |
| dst_signal_semaphore_ids + signal_semaphore_ids.size()); |
| magma_system_relocation_entry* relocation_entries = |
| reinterpret_cast<magma_system_relocation_entry*>(exec_resources + num_resources); |
| |
| for (uint32_t i = 0; i < wait_semaphore_ids.size(); i++) { |
| dst_wait_semaphore_ids[i] = wait_semaphore_ids[i]; |
| } |
| for (uint32_t i = 0; i < signal_semaphore_ids.size(); i++) { |
| dst_signal_semaphore_ids[i] = signal_semaphore_ids[i]; |
| } |
| |
| uint32_t res_reloc_base = 0; |
| |
| for (uint32_t res_index = 0; res_index < num_resources; res_index++) { |
| auto dst_res = &exec_resources[res_index]; |
| auto src_res = &execobjects[res_index]; |
| auto src_res_relocs = reinterpret_cast<drm_i915_gem_relocation_entry*>(src_res->relocs_ptr); |
| |
| DLOG("translating res_index %u handle 0x%" PRIx64 " start_offset 0x%" PRIx64 |
| " length 0x%" PRIx64, |
| res_index, src_res->handle, src_res->rsvd1, src_res->rsvd2); |
| |
| uint32_t num_relocations = dst_res->num_relocations = src_res->relocation_count; |
| |
| auto relocations = &relocation_entries[res_reloc_base]; |
| dst_res->buffer_id = magma_system_get_buffer_id(src_res->handle); |
| dst_res->offset = src_res->rsvd1; |
| dst_res->length = src_res->rsvd2; |
| |
| for (uint32_t reloc_index = 0; reloc_index < dst_res->num_relocations; reloc_index++) { |
| auto dst_reloc = &relocations[reloc_index]; |
| auto src_reloc = &src_res_relocs[reloc_index]; |
| |
| DLOG("translating reloc_index %u: target_handle 0x%x", reloc_index, |
| src_reloc->target_handle); |
| |
| // anvil sends indices for target_handles |
| uint32_t target_index = src_reloc->target_handle; |
| if (target_index >= num_resources) |
| return DRETF(false, "invalid target index %u", src_reloc->target_handle); |
| |
| dst_reloc->offset = src_reloc->offset; // offset in the batch buffer; |
| dst_reloc->target_resource_index = src_reloc->target_handle; |
| dst_reloc->target_offset = src_reloc->delta; // offset in the target buffer |
| dst_reloc->read_domains_bitfield = |
| src_reloc->read_domains; // memory domains in which the target is readable |
| dst_reloc->write_domains_bitfield = src_reloc->write_domain; // memory |
| } |
| |
| res_reloc_base += num_relocations; |
| } |
| |
| command_buffer->num_resources = num_resources; |
| command_buffer->batch_buffer_resource_index = num_resources - 1; // by drm convention |
| command_buffer->batch_start_offset = execbuf->batch_start_offset; |
| command_buffer->wait_semaphore_count = wait_semaphore_ids.size(); |
| command_buffer->signal_semaphore_count = signal_semaphore_ids.size(); |
| |
| return true; |
| } |