This commit is contained in:
2025-03-23 20:27:10 +01:00
parent f3a8252ff1
commit d7679857aa
11 changed files with 240 additions and 102 deletions

View File

@@ -4,7 +4,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define WGSL_SOURCE(...) #__VA_ARGS__ #define GLSL_SOURCE(...) #__VA_ARGS__
#define BUFFER_SIZE (256 * sizeof(uint32_t))
void DebugCallBack(PulseDebugMessageSeverity severity, const char* message) void DebugCallBack(PulseDebugMessageSeverity severity, const char* message)
{ {
@@ -28,6 +30,13 @@ int main(int ac, char** av)
PulseSetDebugCallback(backend, DebugCallBack); PulseSetDebugCallback(backend, DebugCallBack);
PulseDevice device = PulseCreateDevice(backend, NULL, 0); PulseDevice device = PulseCreateDevice(backend, NULL, 0);
PulseBufferCreateInfo buffer_create_info = { 0 };
buffer_create_info.size = BUFFER_SIZE;
buffer_create_info.usage = PULSE_BUFFER_USAGE_STORAGE_READ | PULSE_BUFFER_USAGE_STORAGE_WRITE | PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD;
PulseBuffer buffer = PulseCreateBuffer(device, &buffer_create_info);
PulseDestroyBuffer(device, buffer);
PulseDestroyDevice(device); PulseDestroyDevice(device);
PulseUnloadBackend(backend); PulseUnloadBackend(backend);
printf("Successfully executed Pulse example using %s !\n", backend_type == PULSE_BACKEND_OPENGL ? "OpenGL" : "OpenGL ES"); printf("Successfully executed Pulse example using %s !\n", backend_type == PULSE_BACKEND_OPENGL ? "OpenGL" : "OpenGL ES");

View File

@@ -29,4 +29,3 @@ PULSE_EGL_FUNCTION(eglTerminate, PFNEGLTERMINATEPROC)
PULSE_EGL_FUNCTION_EXT(eglQueryDevicesEXT, PFNEGLQUERYDEVICESEXTPROC) PULSE_EGL_FUNCTION_EXT(eglQueryDevicesEXT, PFNEGLQUERYDEVICESEXTPROC)
PULSE_EGL_FUNCTION_EXT(eglGetPlatformDisplayEXT, PFNEGLGETPLATFORMDISPLAYEXTPROC) PULSE_EGL_FUNCTION_EXT(eglGetPlatformDisplayEXT, PFNEGLGETPLATFORMDISPLAYEXTPROC)
PULSE_EGL_FUNCTION_EXT(eglQueryDeviceStringEXT, PFNEGLQUERYDEVICESTRINGEXTPROC)

View File

@@ -62,6 +62,63 @@ static bool EGLLoadFunctions(EGLInstance* instance)
return true; return true;
} }
bool EGLLoadOpenGLContext(EGLInstance* instance, EGLDisplay* display, EGLDeviceEXT device, EGLConfig* config, EGLSurface* surface, EGLContext* context, bool es_context)
{
if(device != EGL_NO_DEVICE_EXT)
*display = instance->eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, device, PULSE_NULLPTR);
else
*display = instance->eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(display == EGL_NO_DISPLAY || !instance->eglInitialize(*display, PULSE_NULLPTR, PULSE_NULLPTR))
return false;
EGLint attribs[] = {
EGL_RENDERABLE_TYPE, es_context ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_BIT,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_NONE
};
EGLint num_configs;
instance->eglChooseConfig(*display, attribs, config, 1, &num_configs);
instance->eglBindAPI(es_context ? EGL_OPENGL_ES_API : EGL_OPENGL_API);
EGLint pbufferAttribs[] = {
EGL_WIDTH, 1,
EGL_HEIGHT, 1,
EGL_NONE
};
*surface = instance->eglCreatePbufferSurface(*display, *config, pbufferAttribs);
if(es_context)
{
EGLint ctx_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
*context = instance->eglCreateContext(*display, *config, EGL_NO_CONTEXT, ctx_attribs);
}
else
{
EGLint ctx_attribs[] = {
EGL_CONTEXT_MAJOR_VERSION, 4,
EGL_CONTEXT_MINOR_VERSION_KHR, 3,
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
EGL_NONE
};
*context = instance->eglCreateContext(*display, *config, EGL_NO_CONTEXT, ctx_attribs);
}
if(*context == EGL_NO_CONTEXT)
{
instance->eglDestroySurface(*display, *surface);
instance->eglTerminate(*display);
return false;
}
if(!instance->eglMakeCurrent(*display, *surface, *surface, *context))
{
instance->eglDestroySurface(*display, *surface);
instance->eglDestroyContext(display, *context);
instance->eglTerminate(*display);
return false;
}
return true;
}
bool EGLLoadInstance(EGLInstance* instance, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count, bool es_context) bool EGLLoadInstance(EGLInstance* instance, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count, bool es_context)
{ {
PULSE_CHECK_PTR_RETVAL(instance, false); PULSE_CHECK_PTR_RETVAL(instance, false);
@@ -71,10 +128,9 @@ bool EGLLoadInstance(EGLInstance* instance, PulseDevice* forbiden_devices, uint3
instance->device = EGL_NO_DEVICE_EXT; instance->device = EGL_NO_DEVICE_EXT;
if(instance->eglGetPlatformDisplayEXT && instance->eglQueryDevicesEXT && instance->eglQueryDeviceStringEXT) if(instance->eglGetPlatformDisplayEXT && instance->eglQueryDevicesEXT)
{ {
EGLDeviceEXT* devices = PULSE_NULLPTR; EGLDeviceEXT* devices = PULSE_NULLPTR;
EGLDeviceEXT chosen_one = EGL_NO_DEVICE_EXT;
int32_t device_count; int32_t device_count;
uint64_t best_device_score = 0; uint64_t best_device_score = 0;
@@ -85,50 +141,12 @@ bool EGLLoadInstance(EGLInstance* instance, PulseDevice* forbiden_devices, uint3
for(int32_t i = 0; i < device_count; i++) for(int32_t i = 0; i < device_count; i++)
{ {
EGLDisplay display = instance->eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, devices[i], PULSE_NULLPTR); EGLDisplay display;
if(display == EGL_NO_DISPLAY || !instance->eglInitialize(display, PULSE_NULLPTR, PULSE_NULLPTR))
continue;
EGLint attribs[] = {
EGL_RENDERABLE_TYPE, es_context ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_BIT,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_NONE
};
EGLint num_configs;
EGLConfig config; EGLConfig config;
instance->eglChooseConfig(display, attribs, &config, 1, &num_configs); EGLSurface surface;
instance->eglBindAPI(es_context ? EGL_OPENGL_ES_API : EGL_OPENGL_API);
EGLint pbufferAttribs[] = {
EGL_WIDTH, 1,
EGL_HEIGHT, 1,
EGL_NONE
};
EGLSurface surface = instance->eglCreatePbufferSurface(display, config, pbufferAttribs);
EGLContext context; EGLContext context;
if(es_context) if(!EGLLoadOpenGLContext(instance, &display, devices[i], &config, &surface, &context, es_context))
{
EGLint ctx_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
context = instance->eglCreateContext(display, config, EGL_NO_CONTEXT, ctx_attribs);
}
else
{
EGLint ctx_attribs[] = {
EGL_CONTEXT_MAJOR_VERSION, 4,
EGL_CONTEXT_MINOR_VERSION_KHR, 3,
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
EGL_NONE
};
context = instance->eglCreateContext(display, config, EGL_NO_CONTEXT, ctx_attribs);
}
if(context != EGL_NO_CONTEXT && !instance->eglMakeCurrent(display, surface, surface, context))
{
instance->eglDestroySurface(display, surface);
instance->eglTerminate(display);
continue; continue;
}
PFNGLGETINTEGERI_VPROC glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)instance->eglGetProcAddress("glGetIntegeri_v"); PFNGLGETINTEGERI_VPROC glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)instance->eglGetProcAddress("glGetIntegeri_v");
PFNGLGETINTEGERVPROC glGetIntegerv = (PFNGLGETINTEGERVPROC)instance->eglGetProcAddress("glGetIntegerv"); PFNGLGETINTEGERVPROC glGetIntegerv = (PFNGLGETINTEGERVPROC)instance->eglGetProcAddress("glGetIntegerv");
@@ -145,14 +163,11 @@ bool EGLLoadInstance(EGLInstance* instance, PulseDevice* forbiden_devices, uint3
// Check for forbiden devices // Check for forbiden devices
{ {
char* hash_string = (char*)calloc(1024, 1024); uint32_t device_id = PulseHashString((const char*)glGetString(GL_VENDOR));
snprintf(hash_string, 1024 * 1024, "%s|%s|", glGetString(GL_VENDOR), glGetString(GL_RENDERER)); device_id = PulseHashCombine(device_id, PulseHashString((const char*)glGetString(GL_RENDERER)));
GLint gl_extension_count = 0; GLint gl_extension_count = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &gl_extension_count);
for(int i = 0; i < gl_extension_count; i++) for(int i = 0; i < gl_extension_count; i++)
snprintf(hash_string, 1024 * 1024 - strlen(hash_string), "%s|", glGetStringi(GL_EXTENSIONS, i)); device_id = PulseHashCombine(device_id, PulseHashString((const char*)glGetStringi(GL_EXTENSIONS, i)));
uint32_t device_id = PulseHashString(hash_string);
free(hash_string);
for(uint32_t j = 0; j < forbiden_devices_count; j++) for(uint32_t j = 0; j < forbiden_devices_count; j++)
{ {
@@ -198,54 +213,12 @@ bool EGLLoadInstance(EGLInstance* instance, PulseDevice* forbiden_devices, uint3
if(current_device_score > best_device_score) if(current_device_score > best_device_score)
{ {
best_device_score = current_device_score; best_device_score = current_device_score;
chosen_one = devices[i]; instance->device = devices[i];
} }
} }
instance->display = instance->eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, chosen_one, PULSE_NULLPTR);
} }
else
instance->display = instance->eglGetDisplay(EGL_DEFAULT_DISPLAY);
PULSE_CHECK_PTR_RETVAL(instance->display, false);
instance->eglInitialize(instance->display, PULSE_NULLPTR, PULSE_NULLPTR); return EGLLoadOpenGLContext(instance, &instance->display, instance->device, &instance->config, &instance->surface, &instance->context, es_context);
EGLint attribs[] = {
EGL_RENDERABLE_TYPE, es_context ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_BIT,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_NONE
};
EGLint num_configs;
instance->eglChooseConfig(instance->display, attribs, &instance->config, 1, &num_configs);
instance->eglBindAPI(es_context ? EGL_OPENGL_ES_API : EGL_OPENGL_API);
if(es_context)
{
EGLint ctx_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
instance->context = instance->eglCreateContext(instance->display, instance->config, EGL_NO_CONTEXT, ctx_attribs);
}
else
{
EGLint ctx_attribs[] = {
EGL_CONTEXT_MAJOR_VERSION, 4,
EGL_CONTEXT_MINOR_VERSION_KHR, 3,
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
EGL_NONE
};
instance->context = instance->eglCreateContext(instance->display, instance->config, EGL_NO_CONTEXT, ctx_attribs);
}
PULSE_CHECK_PTR_RETVAL(instance->context, false);
EGLint pbufferAttribs[] = {
EGL_WIDTH, 1,
EGL_HEIGHT, 1,
EGL_NONE
};
instance->surface = instance->eglCreatePbufferSurface(instance->display, instance->config, pbufferAttribs);
PULSE_CHECK_PTR_RETVAL(instance->surface, false);
return instance->eglMakeCurrent(instance->display, instance->surface, instance->surface, instance->context);
} }
void EGLUnloadInstance(EGLInstance* instance) void EGLUnloadInstance(EGLInstance* instance)

View File

@@ -2,31 +2,81 @@
// This file is part of "Pulse" // This file is part of "Pulse"
// For conditions of distribution and use, see copyright notice in LICENSE // For conditions of distribution and use, see copyright notice in LICENSE
#include <string.h>
#include <Pulse.h> #include <Pulse.h>
#include "../../PulseInternal.h" #include "../../PulseInternal.h"
#include "OpenGLBuffer.h" #include "OpenGLBuffer.h"
#include "OpenGLDevice.h"
#include "OpenGLCommandList.h"
PulseBuffer OpenGLCreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos) PulseBuffer OpenGLCreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos)
{ {
OpenGLDevice* opengl_device = OPENGL_RETRIEVE_DRIVER_DATA_AS(device, OpenGLDevice*);
PulseBufferHandler* buffer = (PulseBufferHandler*)calloc(1, sizeof(PulseBufferHandler));
PULSE_CHECK_ALLOCATION_RETVAL(buffer, PULSE_NULL_HANDLE);
OpenGLBuffer* opengl_buffer = (OpenGLBuffer*)calloc(1, sizeof(OpenGLBuffer));
PULSE_CHECK_ALLOCATION_RETVAL(opengl_buffer, PULSE_NULL_HANDLE);
buffer->device = device;
buffer->driver_data = opengl_buffer;
buffer->size = create_infos->size;
buffer->usage = create_infos->usage;
opengl_device->glGenBuffers(device, 1, &opengl_buffer->buffer);
return buffer;
} }
bool OpenGLMapBuffer(PulseBuffer buffer, PulseMapMode mode, void** data) bool OpenGLMapBuffer(PulseBuffer buffer, PulseMapMode mode, void** data)
{ {
OpenGLBuffer* opengl_buffer = OPENGL_RETRIEVE_DRIVER_DATA_AS(buffer, OpenGLBuffer*);
OpenGLDevice* opengl_device = OPENGL_RETRIEVE_DRIVER_DATA_AS(buffer->device, OpenGLDevice*);
opengl_device->glBindBuffer(buffer->device, GL_SHADER_STORAGE_BUFFER, opengl_buffer->buffer);
*data = opengl_device->glMapBufferRange(buffer->device, GL_SHADER_STORAGE_BUFFER, mode == PULSE_MAP_READ ? GL_READ_ONLY : GL_WRITE_ONLY, 0, buffer->size);
return *data != PULSE_NULLPTR;
} }
void OpenGLUnmapBuffer(PulseBuffer buffer) void OpenGLUnmapBuffer(PulseBuffer buffer)
{ {
OpenGLBuffer* opengl_buffer = OPENGL_RETRIEVE_DRIVER_DATA_AS(buffer, OpenGLBuffer*);
OpenGLDevice* opengl_device = OPENGL_RETRIEVE_DRIVER_DATA_AS(buffer->device, OpenGLDevice*);
opengl_device->glBindBuffer(buffer->device, GL_SHADER_STORAGE_BUFFER, opengl_buffer->buffer);
opengl_device->glUnmapBuffer(buffer->device, GL_SHADER_STORAGE_BUFFER);
} }
bool OpenGLCopyBufferToBuffer(PulseCommandList cmd, const PulseBufferRegion* src, const PulseBufferRegion* dst) bool OpenGLCopyBufferToBuffer(PulseCommandList cmd, const PulseBufferRegion* src, const PulseBufferRegion* dst)
{ {
OpenGLCommand command = { 0 };
command.type = OPENGL_COMMAND_COPY_BUFFER_TO_BUFFER;
command.CopyBufferToBuffer.src = (PulseBufferRegion*)malloc(sizeof(PulseBufferRegion));
command.CopyBufferToBuffer.dst = (PulseBufferRegion*)malloc(sizeof(PulseBufferRegion));
memcpy((void*)command.CopyBufferToBuffer.src, src, sizeof(PulseBufferRegion));
memcpy((void*)command.CopyBufferToBuffer.dst, dst, sizeof(PulseBufferRegion));
OpenGLQueueCommand(cmd, command);
return true;
} }
bool OpenGLCopyBufferToImage(PulseCommandList cmd, const PulseBufferRegion* src, const PulseImageRegion* dst) bool OpenGLCopyBufferToImage(PulseCommandList cmd, const PulseBufferRegion* src, const PulseImageRegion* dst)
{ {
OpenGLCommand command = { 0 };
command.type = OPENGL_COMMAND_COPY_BUFFER_TO_IMAGE;
command.CopyBufferToImage.src = (PulseBufferRegion*)malloc(sizeof(PulseBufferRegion));
command.CopyBufferToImage.dst = (PulseImageRegion*)malloc(sizeof(PulseImageRegion));
memcpy((void*)command.CopyBufferToImage.src, src, sizeof(PulseBufferRegion));
memcpy((void*)command.CopyBufferToImage.dst, dst, sizeof(PulseImageRegion));
OpenGLQueueCommand(cmd, command);
return true;
} }
void OpenGLDestroyBuffer(PulseDevice device, PulseBuffer buffer) void OpenGLDestroyBuffer(PulseDevice device, PulseBuffer buffer)
{ {
OpenGLBuffer* opengl_buffer = OPENGL_RETRIEVE_DRIVER_DATA_AS(buffer, OpenGLBuffer*);
OpenGLDevice* opengl_device = OPENGL_RETRIEVE_DRIVER_DATA_AS(device, OpenGLDevice*);
opengl_device->glDeleteBuffers(device, 1, &opengl_buffer->buffer);
free(opengl_buffer);
free(buffer);
} }

View File

@@ -12,6 +12,7 @@
typedef struct OpenGLBuffer typedef struct OpenGLBuffer
{ {
GLuint buffer;
} OpenGLBuffer; } OpenGLBuffer;
PulseBuffer OpenGLCreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos); PulseBuffer OpenGLCreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos);

View File

@@ -8,10 +8,48 @@
#include "OpenGL.h" #include "OpenGL.h"
#include "OpenGLCommandList.h" #include "OpenGLCommandList.h"
static void OpenGLCommandsRunner(PulseCommandList cmd)
{
PULSE_CHECK_PTR(cmd);
OpenGLCommandList* opengl_cmd = OPENGL_RETRIEVE_DRIVER_DATA_AS(cmd, OpenGLCommandList*);
PULSE_CHECK_PTR(opengl_cmd);
for(uint32_t i = 0; i < opengl_cmd->commands_count; i++)
{
OpenGLCommand* command = &opengl_cmd->commands[i];
switch(command->type)
{
case OPENGL_COMMAND_COPY_BUFFER_TO_BUFFER: OpenGLCommandCopyBufferToBuffer(command); break;
case OPENGL_COMMAND_COPY_BUFFER_TO_IMAGE: break;
case OPENGL_COMMAND_COPY_IMAGE_TO_BUFFER: break;
case OPENGL_COMMAND_DISPATCH: OpenGLCommandDispatch(command); break;
case OPENGL_COMMAND_DISPATCH_INDIRECT: break;
default: break;
}
}
if(opengl_cmd->fence != PULSE_NULL_HANDLE)
{
OpenGLFence* fence = OPENGL_RETRIEVE_DRIVER_DATA_AS(opengl_cmd->fence, OpenGLFence*);
atomic_store(&fence->signal, true);
}
cmd->state = PULSE_COMMAND_LIST_STATE_READY;
}
PulseCommandList OpenGLRequestCommandList(PulseDevice device, PulseCommandListUsage usage) PulseCommandList OpenGLRequestCommandList(PulseDevice device, PulseCommandListUsage usage)
{ {
} }
void OpenGLQueueCommand(PulseCommandList cmd, OpenGLCommand command)
{
OpenGLCommandList* opengl_cmd = OPENGL_RETRIEVE_DRIVER_DATA_AS(cmd, OpenGLCommandList*);
PULSE_EXPAND_ARRAY_IF_NEEDED(opengl_cmd->commands, OpenGLCommand, opengl_cmd->commands_count, opengl_cmd->commands_capacity, 8);
opengl_cmd->commands[opengl_cmd->commands_count] = command;
opengl_cmd->commands_count++;
}
bool OpenGLSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFence fence) bool OpenGLSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFence fence)
{ {
} }

View File

@@ -11,11 +11,61 @@
#include "OpenGL.h" #include "OpenGL.h"
#include "OpenGLBuffer.h" #include "OpenGLBuffer.h"
typedef struct OpenGLCommand
{
OpenGLCommandType type;
union
{
struct
{
const PulseImageRegion* src;
const PulseImageRegion* dst;
} BlitImages;
struct
{
const PulseBufferRegion* src;
const PulseBufferRegion* dst;
} CopyBufferToBuffer;
struct
{
const PulseBufferRegion* src;
const PulseImageRegion* dst;
} CopyBufferToImage;
struct
{
const PulseImageRegion* src;
const PulseBufferRegion* dst;
} CopyImageToBuffer;
struct
{
PulseComputePipeline pipeline;
uint32_t groupcount_x;
uint32_t groupcount_y;
uint32_t groupcount_z;
} Dispatch;
struct
{
PulseComputePipeline pipeline;
PulseBuffer buffer;
uint32_t offset;
} DispatchIndirect;
};
} OpenGLCommand;
typedef struct OpenGLCommandList typedef struct OpenGLCommandList
{ {
OpenGLCommand* commands;
uint32_t commands_count;
uint32_t commands_capacity;
} OpenGLCommandList; } OpenGLCommandList;
PulseCommandList OpenGLRequestCommandList(PulseDevice device, PulseCommandListUsage usage); PulseCommandList OpenGLRequestCommandList(PulseDevice device, PulseCommandListUsage usage);
void OpenGLQueueCommand(PulseCommandList cmd, OpenGLCommand command);
bool OpenGLSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFence fence); bool OpenGLSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFence fence);
void OpenGLReleaseCommandList(PulseDevice device, PulseCommandList cmd); void OpenGLReleaseCommandList(PulseDevice device, PulseCommandList cmd);

View File

@@ -188,14 +188,11 @@ PulseDevice OpenGLCreateDevice(PulseBackend backend, PulseDevice* forbiden_devic
PULSE_LOAD_DRIVER_DEVICE(OpenGL); PULSE_LOAD_DRIVER_DEVICE(OpenGL);
char* hash_string = (char*)calloc(1024, 1024); device->device_id = PulseHashString((const char*)device->glGetString(pulse_device, GL_VENDOR));
snprintf(hash_string, 1024 * 1024, "%s|%s|", device->glGetString(pulse_device, GL_VENDOR), device->glGetString(pulse_device, GL_RENDERER)); device->device_id = PulseHashCombine(device->device_id, PulseHashString((const char*)device->glGetString(pulse_device, GL_RENDERER)));
GLint gl_extension_count = 0; GLint gl_extension_count = 0;
device->glGetIntegerv(pulse_device, GL_NUM_EXTENSIONS, &gl_extension_count);
for(int i = 0; i < gl_extension_count; i++) for(int i = 0; i < gl_extension_count; i++)
snprintf(hash_string, 1024 * 1024 - strlen(hash_string), "%s|", device->glGetStringi(pulse_device, GL_EXTENSIONS, i)); device->device_id = PulseHashCombine(device->device_id, PulseHashString((const char*)device->glGetStringi(pulse_device, GL_EXTENSIONS, i)));
device->device_id = PulseHashString(hash_string);
free(hash_string);
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(backend)) if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(backend))
PulseLogInfoFmt(backend, "%s created device from %s", backend->backend == PULSE_BACKEND_OPENGL ? "(OpenGL)" : "(OpenGL ES)", device->glGetString(pulse_device, GL_RENDERER)); PulseLogInfoFmt(backend, "%s created device from %s", backend->backend == PULSE_BACKEND_OPENGL ? "(OpenGL)" : "(OpenGL ES)", device->glGetString(pulse_device, GL_RENDERER));

View File

@@ -12,7 +12,7 @@ typedef enum OpenGLContextType
OPENGL_CONTEXT_EGL = 0, OPENGL_CONTEXT_EGL = 0,
OPENGL_CONTEXT_WGL, OPENGL_CONTEXT_WGL,
OPENGL_CONTEXT_END_ENUM // For internal use only OPENGL_CONTEXT_END_ENUM
} OpenGLContextType; } OpenGLContextType;
typedef enum OpenGLFunctionIndex typedef enum OpenGLFunctionIndex
@@ -24,6 +24,19 @@ typedef enum OpenGLFunctionIndex
OPENGL_FUNCTION_INDEX_END_ENUM OPENGL_FUNCTION_INDEX_END_ENUM
} OpenGLFunctionIndex; } OpenGLFunctionIndex;
typedef enum OpenGLCommandType
{
OPENGL_COMMAND_NONE = 0,
OPENGL_COMMAND_BLIT_IMAGES,
OPENGL_COMMAND_COPY_BUFFER_TO_BUFFER,
OPENGL_COMMAND_COPY_BUFFER_TO_IMAGE,
OPENGL_COMMAND_COPY_IMAGE_TO_BUFFER,
OPENGL_COMMAND_DISPATCH,
OPENGL_COMMAND_DISPATCH_INDIRECT,
OPENGL_COMMAND_END_ENUM
} OpenGLCommandType;
#endif // PULSE_OPENGL_ENUMS_H_ #endif // PULSE_OPENGL_ENUMS_H_
#endif // PULSE_ENABLE_OPENGL_BACKEND #endif // PULSE_ENABLE_OPENGL_BACKEND

View File

@@ -91,3 +91,9 @@ uint32_t PulseHashString(const char* str)
hash = ((hash << 5) + hash) + str[i]; hash = ((hash << 5) + hash) + str[i];
return hash; return hash;
} }
uint32_t PulseHashCombine(uint32_t lhs, uint32_t rhs)
{
lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
return lhs;
}

View File

@@ -187,7 +187,9 @@ PFN_PulseLibFunction PulseLoadSymbolFromLibModule(PulseLibModule module, const c
void PulseUnloadLibrary(PulseLibModule module); void PulseUnloadLibrary(PulseLibModule module);
void PulseSetInternalError(PulseErrorType error); void PulseSetInternalError(PulseErrorType error);
uint32_t PulseHashString(const char* str); uint32_t PulseHashString(const char* str);
uint32_t PulseHashCombine(uint32_t lhs, uint32_t rhs);
void PulseLogBackend(PulseBackend backend, PulseDebugMessageSeverity type, const char* message, const char* file, const char* function, int line, ...); void PulseLogBackend(PulseBackend backend, PulseDebugMessageSeverity type, const char* message, const char* file, const char* function, int line, ...);