Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[viogpu3d] Virtio GPU 3D acceleration for windows #943

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions viogpu/common/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ extern "C" {
#include "kdebugprint.h"
#include "viogpu_pci.h"
#include "viogpu.h"
#include "viogpu_queue.h"
#include "viogpu_idr.h"
#include "viogpum.h"
#include "viogpu_idr.h"
#include "viogpu_queue.h"
}

#define MAX_CHILDREN 1
Expand Down
117 changes: 117 additions & 0 deletions viogpu/common/viogpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,19 @@ typedef struct virtio_gpu_rect {
}GPU_RECT, *PGPU_RECT;
#pragma pack()


#pragma pack(1)
typedef struct virtio_gpu_box {
ULONG x;
ULONG y;
ULONG z;
ULONG width;
ULONG height;
ULONG depth;
}GPU_BOX, * PGPU_BOX;
#pragma pack()


#define VIRTIO_GPU_FLAG_FENCE (1 << 0)

#pragma pack(1)
Expand Down Expand Up @@ -257,6 +270,110 @@ typedef struct virtio_gpu_resp_edid {
}GPU_RESP_EDID, *PGPU_RESP_EDID;
#pragma pack()

/* VIRTIO_GPU_CMD_GET_CAPSET_INFO */

#define VIRTIO_GPU_MAX_CAPSET_ID 63
#pragma pack(1)
typedef struct virtio_gpu_cmd_get_capset_info {
GPU_CTRL_HDR hdr;
ULONG capset_index;
ULONG padding;
}GPU_CMD_GET_CAPSET_INFO, * PGPU_CMD_GET_CASPSET_INFO;
#pragma pack()

/* VIRTIO_GPU_RESP_OK_CAPSET_INFO */
#pragma pack(1)
typedef struct virtio_gpu_resp_capset_info{
GPU_CTRL_HDR hdr;
ULONG capset_id;
ULONG capset_max_version;
ULONG capset_max_size;
ULONG padding;
}GPU_RESP_CAPSET_INFO, * PGPU_RESP_CAPSET_INFO;
#pragma pack()

/* VIRTIO_GPU_CMD_GET_CAPSET */
#pragma pack(1)
typedef struct virtio_gpu_cmd_get_capset {
GPU_CTRL_HDR hdr;
ULONG capset_id;
ULONG capset_version;
}GPU_CMD_GET_CAPSET, * PGPU_CMD_GET_CASPSET;
#pragma pack()

/* VIRTIO_GPU_RESP_OK_CAPSET_INFO */
#pragma pack(1)
typedef struct virtio_gpu_resp_capset {
GPU_CTRL_HDR hdr;
UCHAR capset_data[1];
}GPU_RESP_CAPSET, * PGPU_RESP_CAPSET;
#pragma pack()

/* VIRTIO_GPU_CMD_CTX_DESTROY */
#pragma pack(1)
typedef struct virtio_gpu_ctx_create {
GPU_CTRL_HDR hdr;
ULONG nlen;
ULONG context_init;
UCHAR debug_name[64];
}GPU_CMD_CTX_CREATE, * PGPU_CMD_CTX_CREATE;
#pragma pack()

/* VIRTIO_GPU_CMD_RESOURCE_CREATE_3D*/
#pragma pack(1)
typedef struct virtio_gpu_resource_create_3d {
GPU_CTRL_HDR hdr;
ULONG res_id;
ULONG target;
ULONG format;
ULONG bind;
ULONG width;
ULONG height;
ULONG depth;
ULONG array_size;
ULONG last_level;
ULONG nr_samples;
ULONG flags;
ULONG padding;
}GPU_CMD_RES_CREATE_3D, * PGPU_CMD_RES_CREATE_3D;
#pragma pack()

/* VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D, VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D */
typedef struct virtio_gpu_transfer_host_3d {
GPU_CTRL_HDR hdr;
GPU_BOX box;
ULONGLONG offset;
ULONG resource_id;
ULONG level;
ULONG stride;
ULONG layer_stride;
} GPU_CMD_TRANSFER_HOST_3D, *PGPU_CMD_TRANSFER_HOST_3D;



/* VIRTIO_GPU_CMD_CTX_DESTROY */
#pragma pack(1)
typedef struct virtio_gpu_ctx_destroy {
GPU_CTRL_HDR hdr;
}GPU_CMD_CTX_DESTROY, * PGPU_CMD_CTX_DESTROY;
#pragma pack()

#pragma pack(1)
typedef struct virtio_gpu_ctx_resource {
GPU_CTRL_HDR hdr;
ULONG resource_id;
ULONG padding;
} GPU_CMD_CTX_RESOURCE, *PGPU_CMD_CTX_RESOURCE;
#pragma pack()

#pragma pack(1)
typedef struct virtio_gpu_cmd_submit {
GPU_CTRL_HDR hdr;
ULONG size;
ULONG padding;
} GPU_CMD_SUBMIT, * PGPU_CMD_SUBMIT;
#pragma pack()

#define EDID_V1_BLOCK_SIZE 128


Expand Down
94 changes: 29 additions & 65 deletions viogpu/common/viogpu_idr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@
#include "viogpu_idr.tmh"
#endif


VioGpuIdr::VioGpuIdr()
{
m_uStartIndex = 0;
m_IdBitMap.SizeOfBitMap = 0;
m_IdBitMap.Buffer = NULL;
ExInitializeFastMutex(&m_IdBitMapMutex);
m_nextId = 0;
KeInitializeSpinLock(&m_lock);
InitializeListHead(&m_freeList);
}

VioGpuIdr::~VioGpuIdr()
Expand All @@ -49,81 +49,45 @@ VioGpuIdr::~VioGpuIdr()
BOOLEAN VioGpuIdr::Init(
_In_ ULONG start)
{
PUCHAR buf = NULL;
BOOLEAN ret = FALSE;
m_uStartIndex = start;

VIOGPU_ASSERT(m_IdBitMap.Buffer == NULL);
Lock();
buf = new (NonPagedPoolNx) UCHAR[PAGE_SIZE];
RtlZeroMemory(buf, (PAGE_SIZE * sizeof(UCHAR)));
if (buf) {
RtlInitializeBitMap(&m_IdBitMap,
(PULONG)buf,
CHAR_BIT * PAGE_SIZE);
RtlClearAllBits(&m_IdBitMap);
RtlSetBits(&m_IdBitMap, 0, m_uStartIndex);
ret = TRUE;
}
Unlock();
return ret;
}

#pragma warning( disable: 28167 )
//_IRQL_raises_(APC_LEVEL)
//_IRQL_saves_global_(OldIrql, m_IdBitMapMutex)
VOID VioGpuIdr::Lock(VOID)
{
ExAcquireFastMutex(&m_IdBitMapMutex);
}
Close();
m_nextId = start;

#pragma warning( disable: 28167 )
//_IRQL_requires_(APC_LEVEL)
//_IRQL_restores_global_(OldIrql, m_IdBitMapMutex)
VOID VioGpuIdr::Unlock(VOID)
{
ExReleaseFastMutex(&m_IdBitMapMutex);
return true;
}

ULONG VioGpuIdr::GetId(VOID)
{
ULONG id = 0;
Lock();
if (m_IdBitMap.Buffer != NULL)
{
id = RtlFindClearBitsAndSet(&m_IdBitMap, 1, 0);

FreeId* freeId = reinterpret_cast<FreeId*>(ExInterlockedRemoveHeadList(&m_freeList, &m_lock));
if (freeId != NULL) {
id = freeId->id;
delete freeId;
} else {
id = m_nextId++;
}
Unlock();
DbgPrint(TRACE_LEVEL_INFORMATION, ("[%s] id = %d\n", __FUNCTION__, id));
ASSERT(id < USHORT_MAX);

DbgPrint(TRACE_LEVEL_VERBOSE, ("[%s] id = %d\n", __FUNCTION__, id));

return id;
}

VOID VioGpuIdr::PutId(_In_ ULONG id)
{
ASSERT(id >= m_uStartIndex);
ASSERT(id <= (CHAR_BIT * PAGE_SIZE));
DbgPrint(TRACE_LEVEL_INFORMATION, ("[%s] bit %d\n", __FUNCTION__, id));
Lock();
if (m_IdBitMap.Buffer != NULL)
{
if (!RtlAreBitsSet(&m_IdBitMap, id, 1))
{
DbgPrint(TRACE_LEVEL_FATAL, ("[%s] bit %d is not set\n", __FUNCTION__, id - m_uStartIndex));
}
RtlClearBits(&m_IdBitMap, id, 1);
}
Unlock();
DbgPrint(TRACE_LEVEL_VERBOSE, ("[%s] id = %d\n", __FUNCTION__, id));
FreeId* freeId = new(NonPagedPoolNx) FreeId;
freeId->id = id;
ExInterlockedInsertTailList(&m_freeList, &freeId->list_entry, &m_lock);
}

VOID VioGpuIdr::Close(VOID)
{
Lock();
if (m_IdBitMap.Buffer != NULL)
{
delete[] m_IdBitMap.Buffer;
m_IdBitMap.Buffer = NULL;
}
m_uStartIndex = 0;
Unlock();

FreeId* freeId = NULL;
do {
freeId = reinterpret_cast<FreeId*>(ExInterlockedRemoveHeadList(&m_freeList, &m_lock));
if (freeId != NULL) {
delete freeId;
}
} while (freeId != NULL);
}
14 changes: 9 additions & 5 deletions viogpu/common/viogpu_idr.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#pragma once
#include "helper.h"


class VioGpuIdr
{
public:
Expand All @@ -39,10 +40,13 @@ class VioGpuIdr
VOID PutId(_In_ ULONG id);
private:
VOID Close(VOID);
VOID Lock(VOID);
VOID Unlock(VOID);
private:
ULONG m_uStartIndex;
RTL_BITMAP m_IdBitMap;
FAST_MUTEX m_IdBitMapMutex;
struct FreeId {
LIST_ENTRY list_entry;
ULONG id;
};

ULONG m_nextId;
KSPIN_LOCK m_lock;
LIST_ENTRY m_freeList;
};
18 changes: 8 additions & 10 deletions viogpu/common/viogpu_pci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
**********************************************************************/
#include "helper.h"
#include "viogpu.h"
#include "..\viogpudo\viogpudo.h"
#if !DBG
#include "viogpu_pci.tmh"
#endif
Expand Down Expand Up @@ -152,16 +151,15 @@ void mem_free_nonpaged_block(void *context, void *addr)

PAGED_CODE_SEG_BEGIN
static int PCIReadConfig(
VioGpuAdapter* pdev,
IVioGpuPCI* pDev,
int where,
void *buffer,
size_t length)
{
PAGED_CODE();

NTSTATUS Status;
VioGpuDod* pVioGpu = pdev->GetVioGpu();
PDXGKRNL_INTERFACE pDxgkInterface = pVioGpu->GetDxgkInterface();
PDXGKRNL_INTERFACE pDxgkInterface = pDev->GetDxgkInterface();
ULONG BytesRead = 0;

DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
Expand All @@ -188,42 +186,42 @@ static int PCIReadConfig(
static int pci_read_config_byte(void *context, int where, u8 *bVal)
{
PAGED_CODE();
VioGpuAdapter* pdev = static_cast<VioGpuAdapter*>(context);
IVioGpuPCI* pdev = static_cast<IVioGpuPCI*>(context);
return PCIReadConfig(pdev, where, bVal, sizeof(*bVal));
}

int pci_read_config_word(void *context, int where, u16 *wVal)
{
PAGED_CODE();
VioGpuAdapter* pdev = static_cast<VioGpuAdapter*>(context);
IVioGpuPCI* pdev = static_cast<IVioGpuPCI*>(context);
return PCIReadConfig(pdev, where, wVal, sizeof(*wVal));
}

int pci_read_config_dword(void *context, int where, u32 *dwVal)
{
PAGED_CODE();
VioGpuAdapter* pdev = static_cast<VioGpuAdapter*>(context);
IVioGpuPCI* pdev = static_cast<IVioGpuPCI*>(context);
return PCIReadConfig(pdev, where, dwVal, sizeof(*dwVal));
}
PAGED_CODE_SEG_END

size_t pci_get_resource_len(void *context, int bar)
{
VioGpuAdapter* pdev = static_cast<VioGpuAdapter*>(context);
IVioGpuPCI* pdev = static_cast<IVioGpuPCI*>(context);
return pdev->GetPciResources()->GetBarSize(bar);
}

void *pci_map_address_range(void *context, int bar, size_t offset, size_t maxlen)
{
UNREFERENCED_PARAMETER(maxlen);

VioGpuAdapter* pdev = static_cast<VioGpuAdapter*>(context);
IVioGpuPCI* pdev = static_cast<IVioGpuPCI*>(context);
return pdev->GetPciResources()->GetMappedAddress(bar, (ULONG)offset);
}

u16 vdev_get_msix_vector(void *context, int queue)
{
VioGpuAdapter* pdev = static_cast<VioGpuAdapter*>(context);
IVioGpuPCI* pdev = static_cast<IVioGpuPCI*>(context);
u16 vector = VIRTIO_MSI_NO_VECTOR;

if (queue >= 0) {
Expand Down
8 changes: 8 additions & 0 deletions viogpu/common/viogpu_pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,14 @@ class CPciResources
CPciBar m_Bars[PCI_TYPE0_ADDRESSES];
};

class IVioGpuPCI {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think better to move the interface declaration into an extra file, currently, it is not so big, just for the future.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure. IVioGpuPCI should implement methods that are required only for pci device, so it seems to make sense for it to be in viogpu_pci.h. If moving is required, then i would like to know how to name file that will contain interface.

public:
virtual PDXGKRNL_INTERFACE GetDxgkInterface() = 0;
virtual CPciResources* GetPciResources() = 0;
virtual BOOLEAN IsMSIEnabled() = 0;
//virtual
};

NTSTATUS
MapFrameBuffer(
_In_ PHYSICAL_ADDRESS PhysicalAddress,
Expand Down
Loading