From cbcc1b7e25588b5632dd75060366de70597ca016 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Mon, 17 Mar 2025 14:57:48 +0100 Subject: [PATCH] yes --- Includes/Pulse.h | 31 +++-- Sources/Backends/Vulkan/VulkanImage.c | 2 +- Sources/Backends/WebGPU/WebGPUImage.c | 163 ++++++++++++++++++++++++++ Sources/Backends/WebGPU/WebGPUImage.h | 1 + Sources/PulseBackend.c | 1 + 5 files changed, 188 insertions(+), 10 deletions(-) diff --git a/Includes/Pulse.h b/Includes/Pulse.h index c0229f8..8b8d36b 100644 --- a/Includes/Pulse.h +++ b/Includes/Pulse.h @@ -79,8 +79,10 @@ typedef PulseFlags PulseShaderFormatsFlags; // Enums typedef enum PulseCommandListUsage { - PULSE_COMMAND_LIST_GENERAL, - PULSE_COMMAND_LIST_TRANSFER_ONLY + PULSE_COMMAND_LIST_GENERAL = 0, + PULSE_COMMAND_LIST_TRANSFER_ONLY, + + PULSE_COMMAND_LIST_MAX_ENUM, } PulseCommandListUsage; typedef enum PulseDebugLevel @@ -88,19 +90,23 @@ typedef enum PulseDebugLevel PULSE_NO_DEBUG = 0, PULSE_LOW_DEBUG = 1, PULSE_HIGH_DEBUG = 2, - PULSE_PARANOID_DEBUG = 3 // Causes every warning to be treated as error + PULSE_PARANOID_DEBUG = 3, // Causes every warning to be treated as error + + PULSE_DEBUG_MAX_ENUM, } PulseDebugLevel; typedef enum PulseDebugMessageSeverity { - PULSE_DEBUG_MESSAGE_SEVERITY_INFO, + PULSE_DEBUG_MESSAGE_SEVERITY_INFO = 0, PULSE_DEBUG_MESSAGE_SEVERITY_WARNING, - PULSE_DEBUG_MESSAGE_SEVERITY_ERROR + PULSE_DEBUG_MESSAGE_SEVERITY_ERROR, + + PULSE_DEBUG_MESSAGE_SEVERITY_MAX_ENUM, } PulseDebugMessageSeverity; typedef enum PulseErrorType { - PULSE_ERROR_NONE, + PULSE_ERROR_NONE = 0, PULSE_ERROR_BACKENDS_CANDIDATES_SHADER_FORMAT_MISMATCH, PULSE_ERROR_INVALID_BACKEND, PULSE_ERROR_INITIALIZATION_FAILED, @@ -114,15 +120,20 @@ typedef enum PulseErrorType PULSE_ERROR_INVALID_REGION, PULSE_ERROR_INVALID_BUFFER_USAGE, PULSE_ERROR_INVALID_IMAGE_USAGE, + PULSE_ERROR_INVALID_IMAGE_FORMAT, + + PULSE_ERROR_TYPE_MAX_ENUM, } PulseErrorType; typedef enum PulseImageType { - PULSE_IMAGE_TYPE_2D, + PULSE_IMAGE_TYPE_2D = 0, PULSE_IMAGE_TYPE_2D_ARRAY, PULSE_IMAGE_TYPE_3D, PULSE_IMAGE_TYPE_CUBE, - PULSE_IMAGE_TYPE_CUBE_ARRAY + PULSE_IMAGE_TYPE_CUBE_ARRAY, + + PULSE_IMAGE_TYPE_MAX_ENUM, } PulseImageType; typedef enum PulseImageFormat @@ -194,8 +205,10 @@ typedef enum PulseImageFormat typedef enum PulseMapMode { - PULSE_MAP_READ, + PULSE_MAP_READ = 0, PULSE_MAP_WRITE, + + PULSE_MAP_MAX_ENUM, } PulseMapMode; // Structs diff --git a/Sources/Backends/Vulkan/VulkanImage.c b/Sources/Backends/Vulkan/VulkanImage.c index 97b75d6..4739868 100644 --- a/Sources/Backends/Vulkan/VulkanImage.c +++ b/Sources/Backends/Vulkan/VulkanImage.c @@ -169,7 +169,7 @@ PulseImage VulkanCreateImage(PulseDevice device, const PulseImageCreateInfo* cre bool VulkanIsImageFormatValid(PulseDevice device, PulseImageFormat format, PulseImageType type, PulseImageUsageFlags usage) { - (void)usage; + PULSE_UNUSED(usage); VulkanDriverData* vulkan_driver_data = VULKAN_RETRIEVE_DRIVER_DATA_AS(device->backend, VulkanDriverData*); VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*); VkImageCreateFlags vulkan_flags = 0; diff --git a/Sources/Backends/WebGPU/WebGPUImage.c b/Sources/Backends/WebGPU/WebGPUImage.c index b2c6d79..016b365 100644 --- a/Sources/Backends/WebGPU/WebGPUImage.c +++ b/Sources/Backends/WebGPU/WebGPUImage.c @@ -3,14 +3,172 @@ // For conditions of distribution and use, see copyright notice in LICENSE #include +#include "../../PulseInternal.h" #include "WebGPU.h" +#include "WebGPUDevice.h" +#include "WebGPUImage.h" +#include "WebGPUCommandList.h" + +static WGPUTextureFormat PulseImageFormatToWGPUTextureFormat[] = { + WGPUTextureFormat_Undefined, // INVALID + WGPUTextureFormat_R8Unorm, // A8_UNORM + WGPUTextureFormat_R8Unorm, // R8_UNORM + WGPUTextureFormat_RG8Unorm, // R8G8_UNORM + WGPUTextureFormat_RGBA8Unorm, // R8G8B8A8_UNORM + WGPUTextureFormat_R16Uint, // R16_UNORM + WGPUTextureFormat_RG16Uint, // R16G16_UNORM + WGPUTextureFormat_RGBA16Uint, // R16G16B16A16_UNORM + WGPUTextureFormat_RGB10A2Unorm, // R10G10B10A2_UNORM + WGPUTextureFormat_Undefined, // B5G6R5_UNORM + WGPUTextureFormat_Undefined, // B5G5R5A1_UNORM + WGPUTextureFormat_Undefined, // B4G4R4A4_UNORM + WGPUTextureFormat_BGRA8Unorm, // B8G8R8A8_UNORM + WGPUTextureFormat_BC1RGBAUnorm, // BC1_UNORM + WGPUTextureFormat_BC2RGBAUnorm, // BC2_UNORM + WGPUTextureFormat_BC3RGBAUnorm, // BC3_UNORM + WGPUTextureFormat_BC4RUnorm, // BC4_UNORM + WGPUTextureFormat_BC5RGUnorm, // BC5_UNORM + WGPUTextureFormat_BC7RGBAUnorm, // BC7_UNORM + WGPUTextureFormat_BC6HRGBFloat, // BC6H_FLOAT + WGPUTextureFormat_BC6HRGBUfloat, // BC6H_UFLOAT + WGPUTextureFormat_R8Snorm, // R8_SNORM + WGPUTextureFormat_RG8Snorm, // R8G8_SNORM + WGPUTextureFormat_RGBA8Snorm, // R8G8B8A8_SNORM + WGPUTextureFormat_R16Sint, // R16_SNORM + WGPUTextureFormat_RG16Sint, // R16G16_SNORM + WGPUTextureFormat_RGBA16Sint, // R16G16B16A16_SNORM + WGPUTextureFormat_R16Float, // R16_FLOAT + WGPUTextureFormat_RG16Float, // R16G16_FLOAT + WGPUTextureFormat_RGBA16Float, // R16G16B16A16_FLOAT + WGPUTextureFormat_R32Float, // R32_FLOAT + WGPUTextureFormat_RG32Float, // R32G32_FLOAT + WGPUTextureFormat_RGBA32Float, // R32G32B32A32_FLOAT + WGPUTextureFormat_RG11B10Ufloat, // R11G11B10_UFLOAT + WGPUTextureFormat_R8Uint, // R8_UINT + WGPUTextureFormat_RG8Unorm, // R8G8_UINT + WGPUTextureFormat_RGBA8Uint, // R8G8B8A8_UINT + WGPUTextureFormat_R16Uint, // R16_UINT + WGPUTextureFormat_RG16Uint, // R16G16_UINT + WGPUTextureFormat_RGBA16Uint, // R16G16B16A16_UINT + WGPUTextureFormat_R32Uint, // R32_UINT + WGPUTextureFormat_RG32Uint, // R32G32_UINT + WGPUTextureFormat_RGBA32Uint, // R32G32B32A32_UINT + WGPUTextureFormat_R8Sint, // R8_INT + WGPUTextureFormat_RG8Sint, // R8G8_INT + WGPUTextureFormat_RGBA8Sint, // R8G8B8A8_INT + WGPUTextureFormat_R16Sint, // R16_INT + WGPUTextureFormat_RG16Sint, // R16G16_INT + WGPUTextureFormat_RGBA16Sint, // R16G16B16A16_INT + WGPUTextureFormat_R32Sint, // R32_INT + WGPUTextureFormat_RG32Sint, // R32G32_INT + WGPUTextureFormat_RGBA32Sint, // R32G32B32A32_INT +}; +PULSE_STATIC_ASSERT(PulseImageFormatToWGPUTextureFormat, (sizeof(PulseImageFormatToWGPUTextureFormat) / sizeof(WGPUTextureFormat)) == PULSE_IMAGE_FORMAT_MAX_ENUM); + +static WGPUTextureDimension PulseImageTypeToWGPUTextureDimension[] = { + WGPUTextureDimension_2D, //PULSE_IMAGE_TYPE_2D + WGPUTextureDimension_2D, //PULSE_IMAGE_TYPE_2D_ARRAY + WGPUTextureDimension_3D, //PULSE_IMAGE_TYPE_3D + WGPUTextureDimension_2D, //PULSE_IMAGE_TYPE_CUBE + WGPUTextureDimension_2D, //PULSE_IMAGE_TYPE_CUBE_ARRAY +}; +PULSE_STATIC_ASSERT(PulseImageTypeToWGPUTextureDimension, (sizeof(PulseImageTypeToWGPUTextureDimension) / sizeof(WGPUTextureDimension)) == PULSE_IMAGE_TYPE_MAX_ENUM); PulseImage WebGPUCreateImage(PulseDevice device, const PulseImageCreateInfo* create_infos) { + WebGPUDevice* webgpu_device = WEBGPU_RETRIEVE_DRIVER_DATA_AS(device, WebGPUDevice*); + + PulseImageHandler* image = (PulseImageHandler*)calloc(1, sizeof(PulseImageHandler)); + PULSE_CHECK_ALLOCATION_RETVAL(image, PULSE_NULL_HANDLE); + + WebGPUImage* webgpu_image = (WebGPUImage*)calloc(1, sizeof(WebGPUImage)); + PULSE_CHECK_ALLOCATION_RETVAL(webgpu_image, PULSE_NULL_HANDLE); + + WGPUTextureDescriptor descriptor = { 0 }; + descriptor.dimension = PulseImageTypeToWGPUTextureDimension[create_infos->type]; + descriptor.format = PulseImageFormatToWGPUTextureFormat[create_infos->format]; + + if(create_infos->format == PULSE_IMAGE_FORMAT_B4G4R4A4_UNORM || create_infos->format == PULSE_IMAGE_FORMAT_B5G6R5_UNORM || create_infos->format == PULSE_IMAGE_FORMAT_B5G5R5A1_UNORM) + { + if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend)) + PulseLogError(device->backend, "(WebGPU) unsupported image format"); + PulseSetInternalError(PULSE_ERROR_INVALID_IMAGE_FORMAT); + return PULSE_NULL_HANDLE; + } + + descriptor.viewFormatCount = 1; + descriptor.viewFormats = &descriptor.format; + descriptor.size.width = create_infos->width; + descriptor.size.height = create_infos->height; + descriptor.mipLevelCount = 1; + descriptor.sampleCount = 1; + + if(create_infos->type == PULSE_IMAGE_TYPE_3D) + descriptor.size.depthOrArrayLayers = create_infos->layer_count_or_depth; + else if(create_infos->type == PULSE_IMAGE_TYPE_2D_ARRAY || create_infos->type == PULSE_IMAGE_TYPE_CUBE || create_infos->type == PULSE_IMAGE_TYPE_CUBE_ARRAY) + descriptor.size.depthOrArrayLayers = create_infos->layer_count_or_depth; + else + descriptor.size.depthOrArrayLayers = 1; + + descriptor.usage = 0; + if(create_infos->usage & PULSE_IMAGE_USAGE_STORAGE_READ) + descriptor.usage |= WGPUTextureUsage_StorageBinding | WGPUTextureUsage_CopyDst; + if(create_infos->usage & PULSE_IMAGE_USAGE_STORAGE_WRITE) + descriptor.usage |= WGPUTextureUsage_StorageBinding | WGPUTextureUsage_CopySrc; + if(create_infos->usage & PULSE_IMAGE_USAGE_STORAGE_SIMULTANEOUS_READWRITE) + descriptor.usage |= WGPUTextureUsage_StorageBinding | WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst; + + webgpu_image->texture = wgpuDeviceCreateTexture(webgpu_device->device, &descriptor); + if(webgpu_image->texture == PULSE_NULLPTR) + { + free(webgpu_image); + free(image); + return PULSE_NULL_HANDLE; + } + + return image; } bool WebGPUIsImageFormatValid(PulseDevice device, PulseImageFormat format, PulseImageType type, PulseImageUsageFlags usage) { + WGPUTextureFormat wgpu_format = PulseImageFormatToWGPUTextureFormat[format]; + + WGPUTextureDimension dimension = WGPUTextureDimension_Undefined; + if(type == PULSE_IMAGE_TYPE_2D || type == PULSE_IMAGE_TYPE_2D_ARRAY) + dimension = WGPUTextureDimension_2D; + else if(type == PULSE_IMAGE_TYPE_3D || type == PULSE_IMAGE_TYPE_CUBE || type == PULSE_IMAGE_TYPE_CUBE_ARRAY) + dimension = WGPUTextureDimension_3D; + + WGPUTextureUsage wgpu_usage = 0; + if(usage & PULSE_IMAGE_USAGE_STORAGE_READ) + wgpu_usage |= WGPUTextureUsage_StorageBinding | WGPUTextureUsage_CopyDst; + if(usage & PULSE_IMAGE_USAGE_STORAGE_WRITE) + wgpu_usage |= WGPUTextureUsage_StorageBinding | WGPUTextureUsage_CopySrc; + if(usage & PULSE_IMAGE_USAGE_STORAGE_SIMULTANEOUS_READWRITE) + wgpu_usage |= WGPUTextureUsage_StorageBinding | WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst; + + if(wgpu_format == WGPUTextureFormat_Undefined) + { + if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend)) + PulseLogError(device->backend, "(WebGPU) unsupported image format"); + PulseSetInternalError(PULSE_ERROR_INVALID_IMAGE_FORMAT); + return false; + } + if(wgpu_usage == WGPUTextureUsage_None) + { + if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend)) + PulseLogError(device->backend, "(WebGPU) unsupported image usage"); + PulseSetInternalError(PULSE_ERROR_INVALID_IMAGE_USAGE); + return false; + } + if(dimension == WGPUTextureDimension_Undefined) + { + if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend)) + PulseLogError(device->backend, "(WebGPU) unsupported image type"); + PulseSetInternalError(PULSE_ERROR_INVALID_IMAGE_FORMAT); + return false; + } + return true; } bool WebGPUCopyImageToBuffer(PulseCommandList cmd, const PulseImageRegion* src, const PulseBufferRegion* dst) @@ -23,4 +181,9 @@ bool WebGPUBlitImage(PulseCommandList cmd, const PulseImageRegion* src, const Pu void WebGPUDestroyImage(PulseDevice device, PulseImage image) { + PULSE_UNUSED(device); + WebGPUImage* webgpu_image = WEBGPU_RETRIEVE_DRIVER_DATA_AS(image, WebGPUImage*); + wgpuTextureRelease(webgpu_image->texture); + free(webgpu_image); + free(image); } diff --git a/Sources/Backends/WebGPU/WebGPUImage.h b/Sources/Backends/WebGPU/WebGPUImage.h index cdffe8a..6f94d53 100644 --- a/Sources/Backends/WebGPU/WebGPUImage.h +++ b/Sources/Backends/WebGPU/WebGPUImage.h @@ -14,6 +14,7 @@ typedef struct WebGPUImage { + WGPUTexture texture; } WebGPUImage; PulseImage WebGPUCreateImage(PulseDevice device, const PulseImageCreateInfo* create_infos); diff --git a/Sources/PulseBackend.c b/Sources/PulseBackend.c index d0b7c6c..a16e7cc 100644 --- a/Sources/PulseBackend.c +++ b/Sources/PulseBackend.c @@ -186,6 +186,7 @@ PULSE_API const char* PulseVerbaliseErrorType(PulseErrorType error) case PULSE_ERROR_INVALID_REGION: return "invalid region"; case PULSE_ERROR_INVALID_BUFFER_USAGE: return "invalid buffer usage"; case PULSE_ERROR_INVALID_IMAGE_USAGE: return "invalid image usage"; + case PULSE_ERROR_INVALID_IMAGE_FORMAT: return "invalid image format"; default: return "invalid error type"; };