Skip to content

Commit

Permalink
Bug fixes for client pointers, server
Browse files Browse the repository at this point in the history
* SGL_RUN_WITH_LOW_PRIORITY is now false by default
* fixed allocations above 4 GiB, writes uint64_t to registers
* added pb_memcpy_unaligned for unaligned writes
* added pb_realign to realign push buffer
* fixed totals for 3.2, 3.3 in README
  • Loading branch information
dmaivel committed Jul 11, 2024
1 parent 657e1de commit 61634e9
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 84 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.5.0)
project(sharedgl VERSION 0.7.0 LANGUAGES C)
project(sharedgl VERSION 0.7.1 LANGUAGES C)

include_directories(${CMAKE_SOURCE_DIR}/inc)

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Variables labeled with `host` get their values from the host/server when their o
| GLX_VERSION_OVERRIDE | Digit.Digit | 1.4 | Override the GLX version on the client side. Only available for Linux clients. |
| GLSL_VERSION_OVERRIDE | Digit.Digit | | Override the GLSL version on the client side. Available for both Windows and Linux clients. |
| SGL_NET_OVER_SHARED | Ip:Port | | If networking is enabled, this environment variable must exist on the guest. Available for both Windows and Linux clients. |
| SGL_RUN_WITH_LOW_PRIORITY | Boolean | true | On older CPUs, by setting the process priority to low / `IDLE_PRIORITY_CLASS`, applications will run smoother as the kernel driver is given more CPU time. This may not be needed on systems with newer CPUs. Only available for Windows clients. |
| SGL_RUN_WITH_LOW_PRIORITY | Boolean | false | On single core setups, by setting the process priority to low / `IDLE_PRIORITY_CLASS`, applications will run smoother as the kernel driver is given more CPU time. Only set to `true` if the VM has only a single VCPU. Only available for Windows clients. |
| SGL_WINED3D_DONT_VFLIP | Boolean | false | If running a DirectX application via WineD3D, ensure this variable is set to `true` in order for the application to render the framebuffer in the proper orientation. Only available for Windows clients. |
## Windows (in a VM)
Expand Down Expand Up @@ -241,8 +241,8 @@ This list describes the amount of functions left from each standard to implement
- [x] OpenGL 3
- [x] 3.0 (~84 total)
- [x] 3.1 (~15 total)
- [x] 3.2 (~14 remaining)
- [x] 3.3 (~29 remaining)
- [x] 3.2 (~19 total)
- [x] 3.3 (~58 total)
- [x] OpenGL 4
- [x] 4.0 (~46 total)
- [x] 4.1 (~89 total)
Expand Down
3 changes: 3 additions & 0 deletions inc/client/pb.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ void pb_write(int s, int c);
void pb_copy(void *data, int s, size_t length);
void pb_memcpy(const void *src, size_t length);

void pb_memcpy_unaligned(const void *src, size_t length);
void pb_realign();

void *pb_ptr(size_t offs);

/*
Expand Down
4 changes: 2 additions & 2 deletions inc/sharedgl.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#define SGL_OFFSET_REGISTER_CLAIM_ID (sizeof(int) * 4)
#define SGL_OFFSET_REGISTER_CONNECT (sizeof(int) * 5)
#define SGL_OFFSET_REGISTER_FBSTART (sizeof(int) * 6)
#define SGL_OFFSET_REGISTER_MEMSIZE (sizeof(int) * 10)
#define SGL_OFFSET_REGISTER_MEMSIZE (sizeof(int) * 8)
#define SGL_OFFSET_REGISTER_GLMAJ (sizeof(int) * 11)
#define SGL_OFFSET_REGISTER_GLMIN (sizeof(int) * 12)
#define SGL_OFFSET_REGISTER_RETVAL_V (sizeof(int) * 13)
Expand Down Expand Up @@ -64,7 +64,7 @@
# define FORCEINLINE __attribute__((always_inline))
#endif

inline bool is_value_likely_an_offset(const void *p)
static inline bool is_value_likely_an_offset(const void *p)
{
uintptr_t v = (uintptr_t)p;
return v < 0x100000;
Expand Down
134 changes: 70 additions & 64 deletions src/client/glimpl.c
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ void *glimpl_fb_address()
/* fake framebuffer used with network feature only */
if (fake_framebuffer)
return fake_framebuffer;
return pb_ptr(pb_read(SGL_OFFSET_REGISTER_FBSTART));
return pb_ptr(pb_read64(SGL_OFFSET_REGISTER_FBSTART));
}

void glimpl_init()
Expand Down Expand Up @@ -683,6 +683,33 @@ static inline size_t glimpl_get_pixel_size(GLenum format)
}
}

static inline size_t glimpl_type_size(GLenum type)
{
switch(type) {
case GL_BYTE:
case GL_UNSIGNED_BYTE:
return sizeof(GLbyte);
case GL_SHORT:
case GL_UNSIGNED_SHORT:
return sizeof(GLshort);
case GL_INT_2_10_10_10_REV:
case GL_INT:
case GL_UNSIGNED_INT_2_10_10_10_REV:
case GL_UNSIGNED_INT:
return sizeof(GLint);
case GL_FLOAT:
return sizeof(GLfloat);
case GL_DOUBLE:
return sizeof(GLdouble);
case GL_FIXED:
return sizeof(GLfixed);
case GL_HALF_FLOAT:
return sizeof(GLshort);
}

return 1;
}

static inline void glimpl_upload_buffer(const void *data, size_t size)
{
pb_push(SGL_CMD_VP_UPLOAD);
Expand Down Expand Up @@ -723,75 +750,59 @@ static void glimpl_upload_texture(GLsizei width, GLsizei height, GLsizei depth,
glimpl_upload_buffer(pixels, total_size);
}

static inline void glimpl_push_client_pointers(int mode, int max_index)
static inline bool glimpl_push_client_pointer(int count, int size, int type, int stride, const void *pointer)
{
if (glimpl_normal_ptr.in_use) {
pb_push(SGL_CMD_VP_UPLOAD);
pb_push(max_index * glimpl_vertex_ptr.size);
const float *fvertices = glimpl_normal_ptr.pointer;

for (int i = 0; i < max_index; i++) {
for (int j = 0; j < glimpl_vertex_ptr.size; j++)
pb_pushf(*fvertices++);
for (int j = 0; j < (glimpl_normal_ptr.stride / sizeof(float)) - glimpl_vertex_ptr.size; j++)
fvertices++;
const unsigned char *data = pointer;
size_t sizeof_type = glimpl_type_size(type);

if (is_value_likely_an_offset(pointer))
return false;

pb_push(SGL_CMD_VP_UPLOAD);
pb_push((count * size) / CEIL_DIV(sizeof(int), sizeof_type));

if (stride == 0)
pb_memcpy(data, count * size * sizeof_type);
else {
for (int i = 0; i < count; i++) {
void *real_data = ((char*)data + i * stride);
pb_memcpy_unaligned(real_data, size * sizeof_type);
}
pb_realign();
}

return true;
}

static inline void glimpl_push_client_pointers(int mode, int count)
{
if (glimpl_normal_ptr.in_use) {
bool status = glimpl_push_client_pointer(count, glimpl_vertex_ptr.size,
glimpl_normal_ptr.type, glimpl_normal_ptr.stride, glimpl_normal_ptr.pointer);

pb_push(SGL_CMD_NORMALPOINTER);
pb_push(glimpl_normal_ptr.type);
pb_push(0);
pb_push(status);
pb_push(status ? 0 : (int)(uintptr_t)glimpl_normal_ptr.pointer);
}

if (glimpl_color_ptr.in_use) {
pb_push(SGL_CMD_VP_UPLOAD);
pb_push(max_index);
const unsigned char *color = glimpl_color_ptr.pointer;
for (int i = 0; i < max_index; i++) {
pb_push(*(unsigned int*)color);
color += (glimpl_color_ptr.stride);
}
bool status = glimpl_push_client_pointer(count, glimpl_color_ptr.size,
glimpl_color_ptr.type, glimpl_color_ptr.stride, glimpl_color_ptr.pointer);

pb_push(SGL_CMD_COLORPOINTER);
pb_push(glimpl_color_ptr.size);
pb_push(glimpl_color_ptr.type);
pb_push(0);
pb_push(status);
pb_push(status ? 0 : (int)(uintptr_t)glimpl_color_ptr.pointer);
}

for (int t = 0; t < GLIMPL_MAX_TEXTURES; t++) {
if (glimpl_tex_coord_ptr[t].in_use) {
switch (glimpl_tex_coord_ptr[t].type) {
case GL_SHORT: {
pb_push(SGL_CMD_VP_UPLOAD);
pb_push(max_index * glimpl_tex_coord_ptr[t].size / 2);

const short *svertices = glimpl_tex_coord_ptr[t].pointer;

// assuming size = 2
for (int i = 0; i < max_index; i++) {
for (int j = 0; j < glimpl_tex_coord_ptr[t].size; j += 2) {
pb_push((svertices[0] << 16) | svertices[1]);
svertices++;
svertices++;
}
for (int j = 0; j < (glimpl_tex_coord_ptr[t].stride / sizeof(short)) - glimpl_tex_coord_ptr[t].size; j++)
svertices++;
// svertices += glimpl_tex_coord_ptr[t].stride / sizeof(short);
}
}
default: {
pb_push(SGL_CMD_VP_UPLOAD);
pb_push(max_index * glimpl_tex_coord_ptr[t].size);

const float *fvertices = glimpl_tex_coord_ptr[t].pointer;

for (int i = 0; i < max_index; i++) {
for (int j = 0; j < glimpl_tex_coord_ptr[t].size; j++)
pb_pushf(*fvertices++);
for (int j = 0; j < (glimpl_tex_coord_ptr[t].stride / sizeof(float)) - glimpl_tex_coord_ptr[t].size; j++)
fvertices++;
}
}
}
bool status = glimpl_push_client_pointer(count, glimpl_tex_coord_ptr[t].size,
glimpl_tex_coord_ptr[t].type, glimpl_tex_coord_ptr[t].stride, glimpl_tex_coord_ptr[t].pointer);

pb_push(SGL_CMD_CLIENTACTIVETEXTURE);
pb_push(GL_TEXTURE0 + t);
Expand All @@ -803,25 +814,21 @@ static inline void glimpl_push_client_pointers(int mode, int max_index)
pb_push(glimpl_tex_coord_ptr[t].size);
pb_push(glimpl_tex_coord_ptr[t].type);
pb_push(0);
pb_push(status);
pb_push(status ? 0 : (int)(uintptr_t)glimpl_tex_coord_ptr[t].pointer);
}
}

if (glimpl_vertex_ptr.in_use) {
pb_push(SGL_CMD_VP_UPLOAD);
pb_push(max_index * glimpl_vertex_ptr.size);
const float *fvertices = glimpl_vertex_ptr.pointer;

for (int i = 0; i < max_index; i++) {
for (int j = 0; j < glimpl_vertex_ptr.size; j++)
pb_pushf(*fvertices++);
for (int j = 0; j < (glimpl_vertex_ptr.stride / sizeof(float)) - glimpl_vertex_ptr.size; j++)
fvertices++;
}
bool status = glimpl_push_client_pointer(count, glimpl_vertex_ptr.size,
glimpl_vertex_ptr.type, glimpl_vertex_ptr.stride, glimpl_vertex_ptr.pointer);

pb_push(SGL_CMD_VERTEXPOINTER);
pb_push(glimpl_vertex_ptr.size);
pb_push(glimpl_vertex_ptr.type);
pb_push(0);
pb_push(status);
pb_push(status ? 0 : (int)(uintptr_t)glimpl_vertex_ptr.pointer);
}
}

Expand Down Expand Up @@ -1352,8 +1359,7 @@ void glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_grou

void glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
struct gl_vertex_attrib_pointer *vap = glimpl_get_enabled_vap();

// struct gl_vertex_attrib_pointer *vap = glimpl_get_enabled_vap();
// if (vap) {
// if (vap->client_managed) {
// if (!is_value_likely_an_offset(vap->ptr)) {
Expand Down
19 changes: 18 additions & 1 deletion src/client/pb.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void pb_set(int fd)
{
ptr = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

int alloc_size = *(int*)(ptr + SGL_OFFSET_REGISTER_MEMSIZE);
uintptr_t alloc_size = *(uintptr_t*)(ptr + SGL_OFFSET_REGISTER_MEMSIZE);
munmap(ptr, 0x1000);
ptr = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

Expand Down Expand Up @@ -195,6 +195,23 @@ void pb_memcpy(const void *src, size_t length)
in_cur += CEIL_DIV(length, 4);
}

void pb_memcpy_unaligned(const void *src, size_t length)
{
// length = length - (length % 4);
memcpy(in_cur, src, length);
in_cur = (int*)((char*)in_cur + length);
}

static inline uintptr_t align_to_4(uintptr_t ptr)
{
return (ptr + 3) & ~3;
}

void pb_realign()
{
in_cur = (int*)align_to_4((uintptr_t)in_cur);
}

void *pb_ptr(size_t offs)
{
if (net_hooks._pb_ptr)
Expand Down
4 changes: 2 additions & 2 deletions src/client/winmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved)
* more CPU time, which is crucial because the kernel driver is how data
* between the VM and host move.
*
* appears to benefit systems with a single core the most
* appears to benefit systems with a single VCPU the most
*/
DWORD result = GetEnvironmentVariableA("SGL_RUN_WITH_LOW_PRIORITY", env_value, 16);
if (result == 0 || strcmp(env_value, "true") == 0)
if (strcmp(env_value, "true") == 0)
SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);

/*
Expand Down
30 changes: 19 additions & 11 deletions src/server/processor.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,15 @@ void sgl_cmd_processor_start(struct sgl_cmd_processor_args args)

struct net_context *net_ctx = NULL;

if ((signed)fifo_size < 0) {
if ((intptr_t)fifo_size < 0) {
PRINT_LOG("framebuffer too big, try increasing memory!\n");
return;
}

memset(p + SGL_OFFSET_COMMAND_START, 0, fifo_size);

*(int*)(p + SGL_OFFSET_REGISTER_FBSTART) = SGL_OFFSET_COMMAND_START + fifo_size;
*(int*)(p + SGL_OFFSET_REGISTER_MEMSIZE) = args.memory_size;
*(uint64_t*)(p + SGL_OFFSET_REGISTER_FBSTART) = SGL_OFFSET_COMMAND_START + fifo_size;
*(uint64_t*)(p + SGL_OFFSET_REGISTER_MEMSIZE) = args.memory_size;
*(int*)(p + SGL_OFFSET_REGISTER_GLMAJ) = args.gl_major;
*(int*)(p + SGL_OFFSET_REGISTER_GLMIN) = args.gl_minor;
*(int*)(p + SGL_OFFSET_REGISTER_CONNECT) = 0;
Expand Down Expand Up @@ -917,31 +917,39 @@ void sgl_cmd_processor_start(struct sgl_cmd_processor_args args)
case SGL_CMD_COLORPOINTER: {
int size = *pb++,
type = *pb++,
stride = *pb++;
glColorPointer(size, type, stride, uploaded);
stride = *pb++,
use_upload = *pb++,
offs = *pb++;
glColorPointer(size, type, stride, use_upload ? uploaded : (const void*)(uintptr_t)offs);
//// printf("glColorPointer(0x%x, 0x%x, %d, [%f, %f, %f, %f, %f, %f, ...]);\n", size, type, stride, ((float*)uploaded)[0], ((float*)uploaded)[1], ((float*)uploaded)[2], ((float*)uploaded)[3], ((float*)uploaded)[4], ((float*)uploaded)[5]);
break;
}
case SGL_CMD_NORMALPOINTER: {
int type = *pb++,
stride = *pb++;
glNormalPointer(type, stride, uploaded);
stride = *pb++,
use_upload = *pb++,
offs = *pb++;
glNormalPointer(type, stride, use_upload ? uploaded : (const void*)(uintptr_t)offs);
//// printf("glNormalPointer(0x%x, %d, [%f, %f, %f, %f, %f, %f, ...]);\n", type, stride, ((float*)uploaded)[0], ((float*)uploaded)[1], ((float*)uploaded)[2], ((float*)uploaded)[3], ((float*)uploaded)[4], ((float*)uploaded)[5]);
break;
}
case SGL_CMD_TEXCOORDPOINTER: {
int size = *pb++,
type = *pb++,
stride = *pb++;
glTexCoordPointer(size, type, stride, uploaded);
stride = *pb++,
use_upload = *pb++,
offs = *pb++;
glTexCoordPointer(size, type, stride, use_upload ? uploaded : (const void*)(uintptr_t)offs);
//// printf("glTexCoordPointer(0x%x, 0x%x, %d, [%f, %f, %f, %f, %f, %f, ...]);\n", size, type, stride, ((float*)uploaded)[0], ((float*)uploaded)[1], ((float*)uploaded)[2], ((float*)uploaded)[3], ((float*)uploaded)[4], ((float*)uploaded)[5]);
break;
}
case SGL_CMD_VERTEXPOINTER: {
int size = *pb++,
type = *pb++,
stride = *pb++;
glVertexPointer(size, type, stride, uploaded);
stride = *pb++,
use_upload = *pb++,
offs = *pb++;
glVertexPointer(size, type, stride, use_upload ? uploaded : (const void*)(uintptr_t)offs);
//// printf("glVertexPointer(0x%x, 0x%x, %d, [%f, %f, %f, %f, %f, %f, ...]);\n", size, type, stride, ((float*)uploaded)[0], ((float*)uploaded)[1], ((float*)uploaded)[2], ((float*)uploaded)[3], ((float*)uploaded)[4], ((float*)uploaded)[5]);
break;
}
Expand Down

0 comments on commit 61634e9

Please sign in to comment.