mirror of
https://github.com/Kbz-8/Pulse.git
synced 2026-01-11 15:33:34 +00:00
yes
This commit is contained in:
@@ -24,6 +24,8 @@ PulseBackendFlags WebGPUCheckSupport(PulseBackendFlags candidates, PulseShaderFo
|
||||
|
||||
bool WebGPULoadBackend(PulseBackend backend, PulseDebugLevel debug_level)
|
||||
{
|
||||
PULSE_UNUSED(backend);
|
||||
PULSE_UNUSED(debug_level);
|
||||
WebGPUDriverData* driver_data = (WebGPUDriverData*)calloc(1, sizeof(WebGPUDriverData));
|
||||
PULSE_CHECK_ALLOCATION_RETVAL(driver_data, false);
|
||||
driver_data->instance = wgpuCreateInstance(PULSE_NULLPTR);
|
||||
|
||||
@@ -23,4 +23,3 @@ PulseBackendFlags WebGPUCheckSupport(PulseBackendFlags candidates, PulseShaderFo
|
||||
#endif // PULSE_WEBGPU_H_
|
||||
|
||||
#endif // PULSE_ENABLE_WEBGPU_BACKEND
|
||||
|
||||
|
||||
@@ -2,19 +2,149 @@
|
||||
// This file is part of "Pulse"
|
||||
// For conditions of distribution and use, see copyright notice in LICENSE
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <Pulse.h>
|
||||
#include "../../PulseInternal.h"
|
||||
#include "WebGPU.h"
|
||||
#include "WebGPUDevice.h"
|
||||
#include "webgpu.h"
|
||||
#include "WebGPUBuffer.h"
|
||||
|
||||
PulseBuffer WebGPUCreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos)
|
||||
{
|
||||
WebGPUDevice* webgpu_device = WEBGPU_RETRIEVE_DRIVER_DATA_AS(device, WebGPUDevice*);
|
||||
|
||||
PulseBufferHandler* buffer = (PulseBufferHandler*)calloc(1, sizeof(PulseBufferHandler));
|
||||
PULSE_CHECK_ALLOCATION_RETVAL(buffer, PULSE_NULL_HANDLE);
|
||||
|
||||
WebGPUBuffer* webgpu_buffer = (WebGPUBuffer*)calloc(1, sizeof(WebGPUBuffer));
|
||||
PULSE_CHECK_ALLOCATION_RETVAL(webgpu_buffer, PULSE_NULL_HANDLE);
|
||||
|
||||
buffer->device = device;
|
||||
buffer->driver_data = webgpu_buffer;
|
||||
buffer->size = create_infos->size;
|
||||
buffer->usage = create_infos->usage;
|
||||
|
||||
bool is_storage = false;
|
||||
|
||||
WGPUBufferDescriptor descriptor = { 0 };
|
||||
descriptor.mappedAtCreation = false;
|
||||
descriptor.size = buffer->size;
|
||||
if(buffer->usage & PULSE_BUFFER_USAGE_STORAGE_READ || buffer->usage & PULSE_BUFFER_USAGE_STORAGE_WRITE)
|
||||
{
|
||||
descriptor.usage |= WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst | WGPUBufferUsage_CopySrc;
|
||||
is_storage = true;
|
||||
}
|
||||
if(buffer->usage & PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD)
|
||||
{
|
||||
descriptor.usage |= WGPUBufferUsage_CopyDst;
|
||||
if(!is_storage)
|
||||
descriptor.usage |= WGPUBufferUsage_MapRead;
|
||||
}
|
||||
if(buffer->usage & PULSE_BUFFER_USAGE_TRANSFER_UPLOAD)
|
||||
descriptor.usage |= WGPUBufferUsage_CopyDst | WGPUBufferUsage_CopySrc;
|
||||
if(buffer->usage & PULSE_INTERNAL_BUFFER_USAGE_UNIFORM_ACCESS)
|
||||
descriptor.usage |= WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst | WGPUBufferUsage_CopySrc;
|
||||
|
||||
webgpu_buffer->buffer = wgpuDeviceCreateBuffer(webgpu_device->device, &descriptor);
|
||||
if(webgpu_buffer->buffer == PULSE_NULLPTR)
|
||||
{
|
||||
free(webgpu_buffer);
|
||||
free(buffer);
|
||||
return PULSE_NULL_HANDLE;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool WebGPUMapBuffer(PulseBuffer buffer, void** data)
|
||||
#include <stdio.h>
|
||||
|
||||
static void WebGPUMapBufferCallback(WGPUMapAsyncStatus status, WGPUStringView message, void* userdata1, void* userdata2)
|
||||
{
|
||||
atomic_int* mapping_finished = (atomic_int*)userdata1;
|
||||
PulseBuffer buffer = (PulseBuffer)userdata2;
|
||||
puts("test");
|
||||
if(status == WGPUMapAsyncStatus_Success)
|
||||
atomic_store(mapping_finished, 1);
|
||||
else
|
||||
{
|
||||
const char* reasons[] = {
|
||||
"nvm it was successfull",
|
||||
"instance has been dropped",
|
||||
"an error occured",
|
||||
"mapping was aborted",
|
||||
};
|
||||
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(buffer->device->backend))
|
||||
PulseLogErrorFmt(buffer->device->backend, "(WebGPU) buffer mapping failed because %s. %.*s", reasons[status], message.length, message.data);
|
||||
PulseSetInternalError(PULSE_ERROR_MAP_FAILED);
|
||||
atomic_store(mapping_finished, 2);
|
||||
}
|
||||
}
|
||||
|
||||
bool WebGPUMapBuffer(PulseBuffer buffer, PulseMapMode mode, void** data)
|
||||
{
|
||||
WebGPUBuffer* webgpu_buffer = WEBGPU_RETRIEVE_DRIVER_DATA_AS(buffer, WebGPUBuffer*);
|
||||
|
||||
// If we only upload we can just use wgpuQueueWriteBuffer
|
||||
// https://toji.dev/webgpu-best-practices/buffer-uploads.html
|
||||
if(mode == PULSE_MAP_WRITE)
|
||||
{
|
||||
if(webgpu_buffer->map == PULSE_NULLPTR)
|
||||
webgpu_buffer->map = malloc(buffer->size);
|
||||
else
|
||||
webgpu_buffer->map = realloc(webgpu_buffer->map, buffer->size);
|
||||
PULSE_CHECK_ALLOCATION_RETVAL(webgpu_buffer->map, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
atomic_int mapping_finished;
|
||||
atomic_store(&mapping_finished, 0);
|
||||
|
||||
const uint32_t timeout = 5000;
|
||||
clock_t start = clock();
|
||||
|
||||
webgpu_buffer->map = PULSE_NULLPTR;
|
||||
|
||||
WGPUBufferMapCallbackInfo callback_info = { 0 };
|
||||
callback_info.mode = WGPUCallbackMode_AllowSpontaneous;
|
||||
callback_info.callback = WebGPUMapBufferCallback;
|
||||
callback_info.userdata1 = &mapping_finished;
|
||||
callback_info.userdata2 = buffer;
|
||||
wgpuBufferMapAsync(webgpu_buffer->buffer, WGPUMapMode_Read, 0, buffer->size, callback_info);
|
||||
|
||||
while(atomic_load(&mapping_finished) == 0)
|
||||
{
|
||||
clock_t elapsed = clock() - start;
|
||||
if(elapsed > timeout)
|
||||
{
|
||||
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(buffer->device->backend))
|
||||
PulseLogError(buffer->device->backend, "(WebGPU) buffer mapping failed (timeout)");
|
||||
PulseSetInternalError(PULSE_ERROR_MAP_FAILED);
|
||||
return false;
|
||||
}
|
||||
PulseSleep(1); // 1ms
|
||||
}
|
||||
|
||||
if(atomic_load(&mapping_finished) == 1)
|
||||
webgpu_buffer->map = (void*)wgpuBufferGetConstMappedRange(webgpu_buffer->buffer, 0, WGPU_WHOLE_MAP_SIZE);
|
||||
}
|
||||
if(webgpu_buffer->map == PULSE_NULLPTR)
|
||||
return false;
|
||||
webgpu_buffer->current_map_mode = mode;
|
||||
*data = webgpu_buffer->map;
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebGPUUnmapBuffer(PulseBuffer buffer)
|
||||
{
|
||||
WebGPUDevice* webgpu_device = WEBGPU_RETRIEVE_DRIVER_DATA_AS(buffer->device, WebGPUDevice*);
|
||||
WebGPUBuffer* webgpu_buffer = WEBGPU_RETRIEVE_DRIVER_DATA_AS(buffer, WebGPUBuffer*);
|
||||
if(webgpu_buffer->current_map_mode == PULSE_MAP_WRITE)
|
||||
wgpuQueueWriteBuffer(webgpu_device->queue, webgpu_buffer->buffer, 0, webgpu_buffer->map, buffer->size);
|
||||
else
|
||||
wgpuBufferUnmap(webgpu_buffer->buffer);
|
||||
webgpu_buffer->map = PULSE_NULLPTR;
|
||||
}
|
||||
|
||||
bool WebGPUCopyBufferToBuffer(PulseCommandList cmd, const PulseBufferRegion* src, const PulseBufferRegion* dst)
|
||||
@@ -27,4 +157,9 @@ bool WebGPUCopyBufferToImage(PulseCommandList cmd, const PulseBufferRegion* src,
|
||||
|
||||
void WebGPUDestroyBuffer(PulseDevice device, PulseBuffer buffer)
|
||||
{
|
||||
PULSE_UNUSED(device);
|
||||
WebGPUBuffer* webgpu_buffer = WEBGPU_RETRIEVE_DRIVER_DATA_AS(buffer, WebGPUBuffer*);
|
||||
wgpuBufferRelease(webgpu_buffer->buffer);
|
||||
free(webgpu_buffer);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
@@ -10,14 +10,16 @@
|
||||
#include <webgpu/webgpu.h>
|
||||
|
||||
#include <Pulse.h>
|
||||
#include "../../PulseInternal.h"
|
||||
|
||||
typedef struct WebGPUBuffer
|
||||
{
|
||||
WGPUBuffer buffer;
|
||||
void* map;
|
||||
PulseMapMode current_map_mode;
|
||||
} WebGPUBuffer;
|
||||
|
||||
PulseBuffer WebGPUCreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos);
|
||||
bool WebGPUMapBuffer(PulseBuffer buffer, void** data);
|
||||
bool WebGPUMapBuffer(PulseBuffer buffer, PulseMapMode mode, void** data);
|
||||
void WebGPUUnmapBuffer(PulseBuffer buffer);
|
||||
bool WebGPUCopyBufferToBuffer(PulseCommandList cmd, const PulseBufferRegion* src, const PulseBufferRegion* dst);
|
||||
bool WebGPUCopyBufferToImage(PulseCommandList cmd, const PulseBufferRegion* src, const PulseImageRegion* dst);
|
||||
|
||||
@@ -41,15 +41,17 @@ PulseCommandList WebGPURequestCommandList(PulseDevice device, PulseCommandListUs
|
||||
return cmd;
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static void WebGPUFenceCallback(WGPUQueueWorkDoneStatus status, void* userdata1, void* userdata2)
|
||||
{
|
||||
PULSE_UNUSED(userdata2);
|
||||
WebGPUFence* webgpu_fence = (WebGPUFence*)userdata1;
|
||||
PulseCommandList cmd = (PulseCommandList)userdata2;
|
||||
if(status == WGPUQueueWorkDoneStatus_Success)
|
||||
atomic_store(&webgpu_fence->signal, true);
|
||||
puts("test");
|
||||
{
|
||||
if(webgpu_fence != PULSE_NULLPTR)
|
||||
atomic_store(&webgpu_fence->signal, true);
|
||||
cmd->state = PULSE_COMMAND_LIST_STATE_READY;
|
||||
}
|
||||
}
|
||||
|
||||
bool WebGPUSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFence fence)
|
||||
@@ -60,17 +62,23 @@ bool WebGPUSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFenc
|
||||
WGPUCommandBufferDescriptor command_buffer_descriptor = { 0 };
|
||||
WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish(webgpu_cmd->encoder, &command_buffer_descriptor);
|
||||
|
||||
wgpuQueueSubmit(webgpu_device->queue, 1, &command_buffer);
|
||||
|
||||
WebGPUFence* webgpu_fence = WEBGPU_RETRIEVE_DRIVER_DATA_AS(fence, WebGPUFence*);
|
||||
atomic_store(&webgpu_fence->signal, false);
|
||||
|
||||
WGPUQueueWorkDoneCallbackInfo callback = { 0 };
|
||||
callback.mode = WGPUCallbackMode_AllowSpontaneous;
|
||||
callback.callback = WebGPUFenceCallback;
|
||||
callback.userdata1 = webgpu_fence;
|
||||
callback.userdata1 = PULSE_NULLPTR;
|
||||
callback.userdata2 = cmd;
|
||||
if(fence != PULSE_NULL_HANDLE)
|
||||
{
|
||||
WebGPUFence* webgpu_fence = WEBGPU_RETRIEVE_DRIVER_DATA_AS(fence, WebGPUFence*);
|
||||
callback.userdata1 = webgpu_fence;
|
||||
atomic_store(&webgpu_fence->signal, false);
|
||||
fence->cmd = cmd;
|
||||
}
|
||||
wgpuQueueOnSubmittedWorkDone(webgpu_device->queue, callback);
|
||||
|
||||
cmd->state = PULSE_COMMAND_LIST_STATE_SENT;
|
||||
wgpuQueueSubmit(webgpu_device->queue, 1, &command_buffer);
|
||||
|
||||
wgpuCommandBufferRelease(command_buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// For conditions of distribution and use, see copyright notice in LICENSE
|
||||
|
||||
#include <Pulse.h>
|
||||
#include "../../PulseInternal.h"
|
||||
#include "WebGPU.h"
|
||||
#include "WebGPUDevice.h"
|
||||
#include "WebGPUComputePass.h"
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
device->adapter = adapter;
|
||||
}
|
||||
#else
|
||||
static uint64_t WebGPUScoreAdapter(WGPUInstance instance, WGPUAdapter adapter)
|
||||
static uint64_t WebGPUScoreAdapter(WGPUAdapter adapter)
|
||||
{
|
||||
uint64_t score = 0;
|
||||
WGPUAdapterInfo infos;
|
||||
@@ -172,7 +172,7 @@ PulseDevice WebGPUCreateDevice(PulseBackend backend, PulseDevice* forbiden_devic
|
||||
{
|
||||
if(WebGPUIsDeviceForbidden(adapters[i], forbiden_devices, forbiden_devices_count))
|
||||
continue;
|
||||
uint64_t current_device_score = WebGPUScoreAdapter(instance, adapters[i]);
|
||||
uint64_t current_device_score = WebGPUScoreAdapter(adapters[i]);
|
||||
if(current_device_score > best_device_score)
|
||||
{
|
||||
best_device_score = current_device_score;
|
||||
@@ -196,7 +196,7 @@ PulseDevice WebGPUCreateDevice(PulseBackend backend, PulseDevice* forbiden_devic
|
||||
|
||||
WGPUDeviceLostCallbackInfo lost_callback = { 0 };
|
||||
lost_callback.callback = WebGPUDeviceLostCallback;
|
||||
lost_callback.mode = WGPUCallbackMode_AllowProcessEvents;
|
||||
lost_callback.mode = WGPUCallbackMode_AllowSpontaneous;
|
||||
lost_callback.userdata1 = device;
|
||||
lost_callback.userdata2 = backend;
|
||||
WGPUUncapturedErrorCallbackInfo uncaptured_callback = { 0 };
|
||||
@@ -209,7 +209,7 @@ PulseDevice WebGPUCreateDevice(PulseBackend backend, PulseDevice* forbiden_devic
|
||||
descriptor.uncapturedErrorCallbackInfo = uncaptured_callback;
|
||||
WGPURequestDeviceCallbackInfo device_callback = { 0 };
|
||||
device_callback.callback = WebGPURequestDeviceCallback;
|
||||
device_callback.mode = WGPUCallbackMode_AllowProcessEvents;
|
||||
device_callback.mode = WGPUCallbackMode_AllowSpontaneous;
|
||||
device_callback.userdata1 = device;
|
||||
device_callback.userdata2 = backend;
|
||||
wgpuAdapterRequestDevice(device->adapter, &descriptor, device_callback);
|
||||
|
||||
@@ -35,11 +35,9 @@ bool WebGPUIsFenceReady(PulseDevice device, PulseFence fence)
|
||||
{
|
||||
PULSE_UNUSED(device);
|
||||
WebGPUFence* webgpu_fence = WEBGPU_RETRIEVE_DRIVER_DATA_AS(fence, WebGPUFence*);
|
||||
return atomic_load(&webgpu_fence->signal) == true;
|
||||
return atomic_load(&webgpu_fence->signal);
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
bool WebGPUWaitForFences(PulseDevice device, const PulseFence* fences, uint32_t fences_count, bool wait_for_all)
|
||||
{
|
||||
PULSE_UNUSED(device);
|
||||
|
||||
Reference in New Issue
Block a user