This commit is contained in:
2025-03-17 14:57:48 +01:00
parent 05a15e2bb4
commit cbcc1b7e25
5 changed files with 188 additions and 10 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -3,14 +3,172 @@
// For conditions of distribution and use, see copyright notice in LICENSE
#include <Pulse.h>
#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);
}

View File

@@ -14,6 +14,7 @@
typedef struct WebGPUImage
{
WGPUTexture texture;
} WebGPUImage;
PulseImage WebGPUCreateImage(PulseDevice device, const PulseImageCreateInfo* create_infos);

View File

@@ -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";
};