diff options
author | Sahan Fernando <sahan.h.fernando@gmail.com> | 2022-02-13 16:45:30 +1100 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2022-03-09 14:58:48 +0330 |
commit | fd6a536c60d1bedae92cf2e6e1e1b203980317c2 (patch) | |
tree | 4c37ac6600f1ed03216d6e84665c8fcc0de4df0a /Kernel/Graphics | |
parent | 966989afe8ec95283cde5145e8306aa3ff9d708c (diff) | |
download | serenity-fd6a536c60d1bedae92cf2e6e1e1b203980317c2.zip |
Kernel: Implement basic VirGL device
This commit flips VirtIOGPU back to using a Mutex for its operation
lock (instead of a spinlock). This is necessary for avoiding a few
system hangs when queuing actions on the driver from multiple
processes, which becomes much more of an issue when using VirGL from
multiple userspace process.
This does result in a few code paths where we inevitably have to grab
a mutex from inside a spinlock, the only way to fix both issues is to
move to issuing asynchronous virtio gpu commands.
Diffstat (limited to 'Kernel/Graphics')
-rw-r--r-- | Kernel/Graphics/VirtIOGPU/FramebufferDevice.cpp | 6 | ||||
-rw-r--r-- | Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp | 97 | ||||
-rw-r--r-- | Kernel/Graphics/VirtIOGPU/GPU3DDevice.h | 111 | ||||
-rw-r--r-- | Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp | 119 | ||||
-rw-r--r-- | Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h | 18 | ||||
-rw-r--r-- | Kernel/Graphics/VirtIOGPU/Protocol.h | 159 |
6 files changed, 502 insertions, 8 deletions
diff --git a/Kernel/Graphics/VirtIOGPU/FramebufferDevice.cpp b/Kernel/Graphics/VirtIOGPU/FramebufferDevice.cpp index 9e4d3a9c01..74c4bef463 100644 --- a/Kernel/Graphics/VirtIOGPU/FramebufferDevice.cpp +++ b/Kernel/Graphics/VirtIOGPU/FramebufferDevice.cpp @@ -108,7 +108,7 @@ ErrorOr<void> FramebufferDevice::flush_head_buffer(size_t) } ErrorOr<void> FramebufferDevice::flush_rectangle(size_t buffer_index, FBRect const& rect) { - SpinlockLocker locker(adapter()->operation_lock()); + MutexLocker locker(adapter()->operation_lock()); Protocol::Rect dirty_rect { .x = rect.x, .y = rect.y, @@ -165,7 +165,7 @@ FramebufferDevice::~FramebufferDevice() ErrorOr<void> FramebufferDevice::create_framebuffer() { - SpinlockLocker locker(adapter()->operation_lock()); + MutexLocker locker(adapter()->operation_lock()); // First delete any existing framebuffers to free the memory first m_framebuffer = nullptr; m_framebuffer_sink_vmobject = nullptr; @@ -255,7 +255,7 @@ void FramebufferDevice::flush_displayed_image(Protocol::Rect const& dirty_rect, void FramebufferDevice::set_buffer(int buffer_index) { auto& buffer = buffer_index == 0 ? m_main_buffer : m_back_buffer; - SpinlockLocker locker(adapter()->operation_lock()); + MutexLocker locker(adapter()->operation_lock()); if (&buffer == m_current_buffer) return; m_current_buffer = &buffer; diff --git a/Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp b/Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp new file mode 100644 index 0000000000..7114216da5 --- /dev/null +++ b/Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021, Sahan Fernando <sahan.h.fernando@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <Kernel/API/VirGL.h> +#include <Kernel/Graphics/GraphicsManagement.h> +#include <Kernel/Graphics/VirtIOGPU/Console.h> +#include <Kernel/Graphics/VirtIOGPU/GPU3DDevice.h> +#include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h> +#include <Kernel/Graphics/VirtIOGPU/Protocol.h> +#include <Kernel/Random.h> +#include <LibC/sys/ioctl_numbers.h> + +namespace Kernel::Graphics::VirtIOGPU { + +GPU3DDevice::GPU3DDevice(GraphicsAdapter& graphics_adapter) + : CharacterDevice(28, 0) + , m_graphics_adapter(graphics_adapter) +{ + m_kernel_context_id = m_graphics_adapter.create_context(); + + // Setup memory transfer region + auto region_result = MM.allocate_kernel_region( + NUM_TRANSFER_REGION_PAGES * PAGE_SIZE, + "VIRGL3D upload buffer", + Memory::Region::Access::ReadWrite, + AllocationStrategy::AllocateNow); + VERIFY(!region_result.is_error()); + m_transfer_buffer_region = region_result.release_value(); +} + +ErrorOr<void> GPU3DDevice::ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) +{ + // TODO: We really should have ioctls for destroying resources as well + switch (request) { + case VIRGL_IOCTL_TRANSFER_DATA: { + auto user_transfer_descriptor = static_ptr_cast<VirGLTransferDescriptor const*>(arg); + auto transfer_descriptor = TRY(copy_typed_from_user(user_transfer_descriptor)); + if (transfer_descriptor.direction == VIRGL_DATA_DIR_GUEST_TO_HOST) { + if (transfer_descriptor.offset_in_region + transfer_descriptor.num_bytes > NUM_TRANSFER_REGION_PAGES * PAGE_SIZE) { + return EOVERFLOW; + } + auto target = m_transfer_buffer_region->vaddr().offset(transfer_descriptor.offset_in_region).as_ptr(); + return copy_from_user(target, transfer_descriptor.data, transfer_descriptor.num_bytes); + } else if (transfer_descriptor.direction == VIRGL_DATA_DIR_HOST_TO_GUEST) { + if (transfer_descriptor.offset_in_region + transfer_descriptor.num_bytes > NUM_TRANSFER_REGION_PAGES * PAGE_SIZE) { + return EOVERFLOW; + } + auto source = m_transfer_buffer_region->vaddr().offset(transfer_descriptor.offset_in_region).as_ptr(); + return copy_to_user(transfer_descriptor.data, source, transfer_descriptor.num_bytes); + } else { + return EINVAL; + } + } + case VIRGL_IOCTL_SUBMIT_CMD: { + MutexLocker locker(m_graphics_adapter.operation_lock()); + auto user_command_buffer = static_ptr_cast<VirGLCommandBuffer const*>(arg); + auto command_buffer = TRY(copy_typed_from_user(user_command_buffer)); + m_graphics_adapter.submit_command_buffer(m_kernel_context_id, [&](Bytes buffer) { + auto num_bytes = command_buffer.num_elems * sizeof(u32); + VERIFY(num_bytes <= buffer.size()); + MUST(copy_from_user(buffer.data(), command_buffer.data, num_bytes)); + return num_bytes; + }); + return {}; + } + case VIRGL_IOCTL_CREATE_RESOURCE: { + auto user_spec = static_ptr_cast<VirGL3DResourceSpec const*>(arg); + VirGL3DResourceSpec spec = TRY(copy_typed_from_user(user_spec)); + + Protocol::Resource3DSpecification const resource_spec = { + .target = static_cast<Protocol::Gallium::PipeTextureTarget>(spec.target), + .format = spec.format, + .bind = spec.bind, + .width = spec.width, + .height = spec.height, + .depth = spec.depth, + .array_size = spec.array_size, + .last_level = spec.last_level, + .nr_samples = spec.nr_samples, + .flags = spec.flags + }; + MutexLocker locker(m_graphics_adapter.operation_lock()); + auto resource_id = m_graphics_adapter.create_3d_resource(resource_spec).value(); + m_graphics_adapter.attach_resource_to_context(resource_id, m_kernel_context_id); + m_graphics_adapter.ensure_backing_storage(resource_id, *m_transfer_buffer_region, 0, NUM_TRANSFER_REGION_PAGES * PAGE_SIZE); + spec.created_resource_id = resource_id; + // FIXME: We should delete the resource we just created if we fail to copy the resource id out + return copy_to_user(static_ptr_cast<VirGL3DResourceSpec*>(arg), &spec); + } + } + return EINVAL; +} + +} diff --git a/Kernel/Graphics/VirtIOGPU/GPU3DDevice.h b/Kernel/Graphics/VirtIOGPU/GPU3DDevice.h new file mode 100644 index 0000000000..2e41e9ef79 --- /dev/null +++ b/Kernel/Graphics/VirtIOGPU/GPU3DDevice.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021, Sahan Fernando <sahan.h.fernando@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/DistinctNumeric.h> +#include <Kernel/Devices/CharacterDevice.h> +#include <Kernel/Graphics/VirtIOGPU/FramebufferDevice.h> +#include <Kernel/Graphics/VirtIOGPU/Protocol.h> + +namespace Kernel::Graphics::VirtIOGPU { + +enum class VirGLCommand : u32 { + NOP = 0, + CREATE_OBJECT = 1, + BIND_OBJECT, + DESTROY_OBJECT, + SET_VIEWPORT_STATE, + SET_FRAMEBUFFER_STATE, + SET_VERTEX_BUFFERS, + CLEAR, + DRAW_VBO, + RESOURCE_INLINE_WRITE, + SET_SAMPLER_VIEWS, + SET_INDEX_BUFFER, + SET_CONSTANT_BUFFER, + SET_STENCIL_REF, + SET_BLEND_COLOR, + SET_SCISSOR_STATE, + BLIT, + RESOURCE_COPY_REGION, + BIND_SAMPLER_STATES, + BEGIN_QUERY, + END_QUERY, + GET_QUERY_RESULT, + SET_POLYGON_STIPPLE, + SET_CLIP_STATE, + SET_SAMPLE_MASK, + SET_STREAMOUT_TARGETS, + SET_RENDER_CONDITION, + SET_UNIFORM_BUFFER, + + SET_SUB_CTX, + CREATE_SUB_CTX, + DESTROY_SUB_CTX, + BIND_SHADER, + SET_TESS_STATE, + SET_MIN_SAMPLES, + SET_SHADER_BUFFERS, + SET_SHADER_IMAGES, + MEMORY_BARRIER, + LAUNCH_GRID, + SET_FRAMEBUFFER_STATE_NO_ATTACH, + TEXTURE_BARRIER, + SET_ATOMIC_BUFFERS, + SET_DBG_FLAGS, + GET_QUERY_RESULT_QBO, + TRANSFER3D, + END_TRANSFERS, + COPY_TRANSFER3D, + SET_TWEAKS, + CLEAR_TEXTURE, + PIPE_RESOURCE_CREATE, + PIPE_RESOURCE_SET_TYPE, + GET_MEMORY_INFO, + SEND_STRING_MARKER, + MAX_COMMANDS +}; + +union ClearType { + struct { + u32 depth : 1; + u32 stencil : 1; + u32 color0 : 1; + u32 color1 : 1; + u32 color2 : 1; + u32 color3 : 1; + u32 color4 : 1; + u32 color5 : 1; + u32 color6 : 1; + u32 color7 : 1; + } flags; + u32 value; +}; + +class GPU3DDevice : public CharacterDevice { +public: + GPU3DDevice() = delete; + explicit GPU3DDevice(GraphicsAdapter& graphics_adapter); + + virtual bool can_read(const OpenFileDescription&, u64) const override { return true; } + virtual bool can_write(const OpenFileDescription&, u64) const override { return true; } + virtual ErrorOr<size_t> read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override { return ENOTSUP; } + virtual ErrorOr<size_t> write(OpenFileDescription&, u64, const UserOrKernelBuffer&, size_t) override { return ENOTSUP; } + virtual StringView class_name() const override { return "virgl3d"; } + + virtual ErrorOr<void> ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg) override; + +private: + Kernel::Graphics::VirtIOGPU::GraphicsAdapter& m_graphics_adapter; + // Context used for kernel operations (e.g. flushing resources to scanout) + ContextID m_kernel_context_id; + // Memory management for backing buffers + OwnPtr<Memory::Region> m_transfer_buffer_region; + constexpr static size_t NUM_TRANSFER_REGION_PAGES = 256; +}; + +} diff --git a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp index 6580a9a2cf..62e3c0e714 100644 --- a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp +++ b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp @@ -7,10 +7,12 @@ #include <AK/BinaryBufferWriter.h> #include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/IDs.h> +#include <Kernel/Devices/DeviceManagement.h> #include <Kernel/Graphics/Console/GenericFramebufferConsole.h> #include <Kernel/Graphics/GraphicsManagement.h> #include <Kernel/Graphics/VirtIOGPU/Console.h> #include <Kernel/Graphics/VirtIOGPU/FramebufferDevice.h> +#include <Kernel/Graphics/VirtIOGPU/GPU3DDevice.h> #include <Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h> namespace Kernel::Graphics::VirtIOGPU { @@ -74,8 +76,11 @@ void GraphicsAdapter::initialize() m_device_configuration = config; bool success = negotiate_features([&](u64 supported_features) { u64 negotiated = 0; - if (is_feature_set(supported_features, VIRTIO_GPU_F_VIRGL)) - dbgln_if(VIRTIO_DEBUG, "VirtIO::GraphicsAdapter: VIRGL is not yet supported!"); + if (is_feature_set(supported_features, VIRTIO_GPU_F_VIRGL)) { + dbgln_if(VIRTIO_DEBUG, "VirtIO::GraphicsAdapter: VirGL is available, enabling"); + negotiated |= VIRTIO_GPU_F_VIRGL; + m_has_virgl_support = true; + } if (is_feature_set(supported_features, VIRTIO_GPU_F_EDID)) negotiated |= VIRTIO_GPU_F_EDID; return negotiated; @@ -89,7 +94,8 @@ void GraphicsAdapter::initialize() } VERIFY(success); finish_init(); - SpinlockLocker locker(m_operation_lock); + initialize_3d_device(); + MutexLocker locker(m_operation_lock); // Get display information using VIRTIO_GPU_CMD_GET_DISPLAY_INFO query_display_information(); query_display_edid({}); @@ -265,6 +271,28 @@ ResourceID GraphicsAdapter::create_2d_resource(Protocol::Rect rect) return resource_id; } +ResourceID GraphicsAdapter::create_3d_resource(Protocol::Resource3DSpecification const& resource_3d_specification) +{ + VERIFY(m_operation_lock.is_locked()); + auto writer = create_scratchspace_writer(); + auto& request = writer.append_structure<Protocol::ResourceCreate3D>(); + auto& response = writer.append_structure<Protocol::ControlHeader>(); + + populate_virtio_gpu_request_header(request.header, Protocol::CommandType::VIRTIO_GPU_CMD_RESOURCE_CREATE_3D, VIRTIO_GPU_FLAG_FENCE); + + auto resource_id = allocate_resource_id(); + request.resource_id = resource_id.value(); + // TODO: Abstract this out a bit more + u32* start_of_copied_fields = &request.target; + memcpy(start_of_copied_fields, &resource_3d_specification, sizeof(Protocol::Resource3DSpecification)); + + synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response)); + + VERIFY(response.type == static_cast<u32>(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); + dbgln_if(VIRTIO_DEBUG, "VirtIO::GraphicsAdapter: Allocated 3d resource with id {}", resource_id.value()); + return resource_id; +} + void GraphicsAdapter::ensure_backing_storage(ResourceID resource_id, Memory::Region const& region, size_t buffer_offset, size_t buffer_length) { VERIFY(m_operation_lock.is_locked()); @@ -395,7 +423,7 @@ void GraphicsAdapter::populate_virtio_gpu_request_header(Protocol::ControlHeader void GraphicsAdapter::flush_dirty_rectangle(ScanoutID scanout_id, ResourceID resource_id, Protocol::Rect const& dirty_rect) { - SpinlockLocker locker(m_operation_lock); + MutexLocker locker(m_operation_lock); transfer_framebuffer_data_to_host(scanout_id, resource_id, dirty_rect); flush_displayed_image(resource_id, dirty_rect); } @@ -407,6 +435,14 @@ ResourceID GraphicsAdapter::allocate_resource_id() return m_resource_id_counter; } +ContextID GraphicsAdapter::allocate_context_id() +{ + // FIXME: This should really be tracked using a bitmap, instead of an atomic counter + VERIFY(m_operation_lock.is_locked()); + m_context_id_counter = m_context_id_counter.value() + 1; + return m_context_id_counter; +} + void GraphicsAdapter::delete_resource(ResourceID resource_id) { VERIFY(m_operation_lock.is_locked()); @@ -422,4 +458,79 @@ void GraphicsAdapter::delete_resource(ResourceID resource_id) VERIFY(response.type == to_underlying(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); } +void GraphicsAdapter::initialize_3d_device() +{ + if (m_has_virgl_support) { + MutexLocker locker(m_operation_lock); + m_3d_device = MUST(DeviceManagement::try_create_device<VirtIOGPU::GPU3DDevice>(*this)); + } +} + +ContextID GraphicsAdapter::create_context() +{ + VERIFY(m_operation_lock.is_locked()); + auto ctx_id = allocate_context_id(); + auto writer = create_scratchspace_writer(); + auto& request = writer.append_structure<Protocol::ContextCreate>(); + auto& response = writer.append_structure<Protocol::ControlHeader>(); + + constexpr char const* region_name = "Serenity VirGL3D Context"; + populate_virtio_gpu_request_header(request.header, Protocol::CommandType::VIRTIO_GPU_CMD_CTX_CREATE, VIRTIO_GPU_FLAG_FENCE); + request.header.context_id = ctx_id.value(); + request.name_length = strlen(region_name); + memset(request.debug_name.data(), 0, 64); + VERIFY(request.name_length <= 64); + memcpy(request.debug_name.data(), region_name, request.name_length); + + synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response)); + + VERIFY(response.type == to_underlying(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); + return ctx_id; +} + +void GraphicsAdapter::submit_command_buffer(ContextID context_id, Function<size_t(Bytes)> buffer_writer) +{ + VERIFY(m_operation_lock.is_locked()); + auto writer = create_scratchspace_writer(); + auto& request = writer.append_structure<Protocol::CommandSubmit>(); + + populate_virtio_gpu_request_header(request.header, Protocol::CommandType::VIRTIO_GPU_CMD_SUBMIT_3D, VIRTIO_GPU_FLAG_FENCE); + request.header.context_id = context_id.value(); + + auto max_command_buffer_length = m_scratch_space->size() - sizeof(request) - sizeof(Protocol::ControlHeader); + // Truncate to nearest multiple of alignment, to ensure padding loop doesn't exhaust allocated space + max_command_buffer_length -= max_command_buffer_length % alignof(Protocol::ControlHeader); + Bytes command_buffer_buffer(m_scratch_space->vaddr().offset(sizeof(request)).as_ptr(), max_command_buffer_length); + request.size = buffer_writer(command_buffer_buffer); + writer.skip_bytes(request.size); + // The alignment of a ControlHeader may be a few words larger than the length of a command buffer, so + // we pad with no-ops until we reach the correct alignment + while (writer.current_offset() % alignof(Protocol::ControlHeader) != 0) { + VERIFY((writer.current_offset() % alignof(Protocol::ControlHeader)) % sizeof(u32) == 0); + writer.append_structure<u32>() = to_underlying(VirGLCommand::NOP); + request.size += 4; + } + dbgln_if(VIRTIO_DEBUG, "VirtIO::GraphicsAdapter: Sending command buffer of length {}", request.size); + auto& response = writer.append_structure<Protocol::ControlHeader>(); + + synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request) + request.size, sizeof(response)); + + VERIFY(response.type == to_underlying(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); +} + +void GraphicsAdapter::attach_resource_to_context(ResourceID resource_id, ContextID context_id) +{ + VERIFY(m_operation_lock.is_locked()); + auto writer = create_scratchspace_writer(); + auto& request = writer.append_structure<Protocol::ContextAttachResource>(); + auto& response = writer.append_structure<Protocol::ControlHeader>(); + populate_virtio_gpu_request_header(request.header, Protocol::CommandType::VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE, VIRTIO_GPU_FLAG_FENCE); + request.header.context_id = context_id.value(); + request.resource_id = resource_id.value(); + + synchronous_virtio_gpu_command(start_of_scratch_space(), sizeof(request), sizeof(response)); + + VERIFY(response.type == to_underlying(Protocol::CommandType::VIRTIO_GPU_RESP_OK_NODATA)); +} + } diff --git a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h index a04e241d59..579aafb69c 100644 --- a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h +++ b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.h @@ -19,6 +19,8 @@ namespace Kernel::Graphics::VirtIOGPU { +class GPU3DDevice; + #define VIRTIO_GPU_F_VIRGL (1 << 0) #define VIRTIO_GPU_F_EDID (1 << 1) @@ -47,6 +49,7 @@ public: virtual bool vga_compatible() const override { return false; } virtual void initialize() override; + void initialize_3d_device(); ErrorOr<ByteBuffer> get_edid(size_t output_port_index) const override; @@ -109,8 +112,15 @@ private: u32 get_pending_events(); void clear_pending_events(u32 event_bitmask); + // 3D Command stuff + ContextID create_context(); + void attach_resource_to_context(ResourceID resource_id, ContextID context_id); + void submit_command_buffer(ContextID, Function<size_t(Bytes)> buffer_writer); + Protocol::TextureFormat get_framebuffer_format() const { return Protocol::TextureFormat::VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM; } + auto& operation_lock() { return m_operation_lock; } ResourceID allocate_resource_id(); + ContextID allocate_context_id(); PhysicalAddress start_of_scratch_space() const { return m_scratch_space->physical_page(0)->paddr(); } AK::BinaryBufferWriter create_scratchspace_writer() @@ -123,6 +133,7 @@ private: void query_display_information(); void query_display_edid(Optional<ScanoutID>); ResourceID create_2d_resource(Protocol::Rect rect); + ResourceID create_3d_resource(Protocol::Resource3DSpecification const& resource_3d_specification); void delete_resource(ResourceID resource_id); void ensure_backing_storage(ResourceID resource_id, Memory::Region const& region, size_t buffer_offset, size_t buffer_length); void detach_backing_storage(ResourceID resource_id); @@ -138,10 +149,15 @@ private: VirtIO::Configuration const* m_device_configuration { nullptr }; ResourceID m_resource_id_counter { 0 }; + ContextID m_context_id_counter { 0 }; + RefPtr<GPU3DDevice> m_3d_device; + bool m_has_virgl_support { false }; // Synchronous commands WaitQueue m_outstanding_request; - Spinlock m_operation_lock; + Mutex m_operation_lock; OwnPtr<Memory::Region> m_scratch_space; + + friend class Kernel::Graphics::VirtIOGPU::GPU3DDevice; }; } diff --git a/Kernel/Graphics/VirtIOGPU/Protocol.h b/Kernel/Graphics/VirtIOGPU/Protocol.h index 704f565352..e8c3483185 100644 --- a/Kernel/Graphics/VirtIOGPU/Protocol.h +++ b/Kernel/Graphics/VirtIOGPU/Protocol.h @@ -11,10 +11,28 @@ #define VIRTIO_GPU_MAX_SCANOUTS 16 namespace Kernel::Graphics::VirtIOGPU { +TYPEDEF_DISTINCT_ORDERED_ID(u32, ContextID); TYPEDEF_DISTINCT_ORDERED_ID(u32, ResourceID); TYPEDEF_DISTINCT_ORDERED_ID(u32, ScanoutID); }; +#define VREND_MAX_CTX 64 + +#define VIRGL_BIND_DEPTH_STENCIL (1 << 0) +#define VIRGL_BIND_RENDER_TARGET (1 << 1) +#define VIRGL_BIND_SAMPLER_VIEW (1 << 3) +#define VIRGL_BIND_VERTEX_BUFFER (1 << 4) +#define VIRGL_BIND_INDEX_BUFFER (1 << 5) +#define VIRGL_BIND_CONSTANT_BUFFER (1 << 6) +#define VIRGL_BIND_DISPLAY_TARGET (1 << 7) +#define VIRGL_BIND_COMMAND_ARGS (1 << 8) +#define VIRGL_BIND_STREAM_OUTPUT (1 << 11) +#define VIRGL_BIND_SHADER_BUFFER (1 << 14) +#define VIRGL_BIND_QUERY_BUFFER (1 << 15) +#define VIRGL_BIND_CURSOR (1 << 16) +#define VIRGL_BIND_CUSTOM (1 << 17) +#define VIRGL_BIND_SCANOUT (1 << 18) + namespace Kernel::Graphics::VirtIOGPU::Protocol { // Specification equivalent: enum virtio_gpu_ctrl_type @@ -32,6 +50,18 @@ enum class CommandType : u32 { VIRTIO_GPU_CMD_GET_CAPSET, VIRTIO_GPU_CMD_GET_EDID, + /* 3d commands */ + VIRTIO_GPU_CMD_CTX_CREATE = 0x0200, + VIRTIO_GPU_CMD_CTX_DESTROY, + VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE, + VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE, + VIRTIO_GPU_CMD_RESOURCE_CREATE_3D, + VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D, + VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D, + VIRTIO_GPU_CMD_SUBMIT_3D, + VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB, + VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB, + /* cursor commands */ VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300, VIRTIO_GPU_CMD_MOVE_CURSOR, @@ -52,6 +82,54 @@ enum class CommandType : u32 { VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER, }; +enum class ObjectType : u32 { + NONE, + BLEND, + RASTERIZER, + DSA, + SHADER, + VERTEX_ELEMENTS, + SAMPLER_VIEW, + SAMPLER_STATE, + SURFACE, + QUERY, + STREAMOUT_TARGET, + MSAA_SURFACE, + MAX_OBJECTS, +}; + +enum class PipeTextureTarget : u32 { + BUFFER = 0, + TEXTURE_1D, + TEXTURE_2D, + TEXTURE_3D, + TEXTURE_CUBE, + TEXTURE_RECT, + TEXTURE_1D_ARRAY, + TEXTURE_2D_ARRAY, + TEXTURE_CUBE_ARRAY, + MAX +}; + +enum class PipePrimitiveTypes : u32 { + POINTS = 0, + LINES, + LINE_LOOP, + LINE_STRIP, + TRIANGLES, + TRIANGLE_STRIP, + TRIANGLE_FAN, + QUADS, + QUAD_STRIP, + POLYGON, + LINES_ADJACENCY, + LINE_STRIP_ADJACENCY, + TRIANGLES_ADJACENCY, + TRIANGLE_STRIP_ADJACENCY, + PATCHES, + MAX +}; + // Specification equivalent: struct virtio_gpu_ctrl_hdr struct ControlHeader { u32 type; @@ -103,6 +181,23 @@ struct ResourceCreate2D { u32 height; }; +// Specification equivalent: struct virtio_gpu_resource_create_3d +struct ResourceCreate3D { + ControlHeader header; + u32 resource_id; + u32 target; + u32 format; + u32 bind; + u32 width; + u32 height; + u32 depth; + u32 array_size; + u32 last_level; + u32 nr_samples; + u32 flags; + u32 padding; +}; + // Specification equivalent: struct virtio_gpu_resource_unref struct ResourceUnref { ControlHeader header; @@ -171,4 +266,68 @@ struct GetEDIDResponse { u8 edid[1024]; }; +// No equivalent in specification +struct ContextCreate { + ControlHeader header; + u32 name_length; + u32 padding; + AK::Array<char, 64> debug_name; +}; + +static_assert(sizeof(ContextCreate::debug_name) == 64); + +// No equivalent in specification +struct ContextAttachResource { + ControlHeader header; + u32 resource_id; + u32 padding; +}; + +// No equivalent in specification +struct CommandSubmit { + ControlHeader header; + u32 size; + u32 padding; +}; + +namespace Gallium { + +enum class PipeTextureTarget : u32 { + BUFFER, + TEXTURE_1D, + TEXTURE_2D, + TEXTURE_3D, + TEXTURE_CUBE, + TEXTURE_RECT, + TEXTURE_1D_ARRAY, + TEXTURE_2D_ARRAY, + TEXTURE_CUBE_ARRAY, + MAX_TEXTURE_TYPES, +}; + +enum class ShaderType : u32 { + SHADER_VERTEX = 0, + SHADER_FRAGMENT, + SHADER_GEOMETRY, + SHADER_TESS_CTRL, + SHADER_TESS_EVAL, + SHADER_COMPUTE, + SHADER_TYPES +}; + +} + +struct Resource3DSpecification { + Gallium::PipeTextureTarget target; + u32 format; + u32 bind; + u32 width; + u32 height; + u32 depth; + u32 array_size; + u32 last_level; + u32 nr_samples; + u32 flags; +}; + } |