WebGPU support wip

This commit is contained in:
Nikita Lisitsa 2023-12-30 16:50:44 +03:00
parent 7611d375dc
commit e2fdb777de
27 changed files with 3321 additions and 9 deletions

View file

@ -50,6 +50,12 @@ else()
set(PSEMEK_PACKAGE_AS_LIBRARY OFF CACHE INTERNAL "Build applications as shared libraries")
endif()
if(NOT DEFINED PSEMEK_GRAPHICS_API)
set(PSEMEK_GRAPHICS_API OPENGL)
endif()
find_package(wgpu-native REQUIRED)
add_subdirectory(3rdparty)
get_directory_property(PSEMEK_PARENT_DIRECTORY PARENT_DIRECTORY)

View file

@ -0,0 +1,18 @@
if(wgpu-native_FOUND)
set(wgpu-native_FIND_QUIETLY TRUE)
endif()
# Don't search for include files - these are bundled with psemek-wgpu lib
find_library(wgpu-native_LIBRARIES NAMES libwgpu_native.a wgpu_native PATHS "${WGPU_NATIVE_ROOT}")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(wgpu-native DEFAULT_MSG wgpu-native_LIBRARIES)
if(wgpu-native_FOUND AND NOT TARGET wgpu-native)
add_library(wgpu-native STATIC IMPORTED)
set_target_properties(wgpu-native PROPERTIES
IMPORTED_LOCATION "${wgpu-native_LIBRARIES}"
)
endif()
mark_as_advanced(wgpu-native_LIBRARIES)

View file

@ -9,3 +9,7 @@ endif()
psemek_add_library(psemek-app ${PSEMEK_APP_HEADERS} ${PSEMEK_APP_SOURCES})
target_include_directories(psemek-app PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(psemek-app PUBLIC psemek-log psemek-util psemek-gfx psemek-ui)
target_compile_definitions(psemek-app PUBLIC -DPSEMEK_APP_${PSEMEK_GRAPHICS_API}=1)
if(PSEMEK_GRAPHICS_API STREQUAL WEBGPU)
target_link_libraries(psemek-app PUBLIC psemek-wgpu)
endif()

View file

@ -2,6 +2,12 @@
#include <psemek/app/event_handler.hpp>
#if defined(PSEMEK_APP_WEBGPU)
#include <psemek/wgpu/adapter.hpp>
#include <psemek/wgpu/surface.hpp>
#include <psemek/wgpu/device.hpp>
#endif
#include <memory>
#include <functional>
@ -17,6 +23,10 @@ namespace psemek::app
std::string name;
int multisampling = 4;
bool highdpi = false;
#if defined(PSEMEK_APP_WEBGPU)
std::vector<wgpu::feature> required_features;
std::optional<wgpu::limits> required_limits;
#endif
};
// Data received from platform backend after initialization
@ -24,8 +34,15 @@ namespace psemek::app
{
std::vector<std::string> args;
std::function<void(bool)> show_cursor;
std::function<void(bool)> vsync;
std::function<void(bool)> windowed;
#if defined(PSEMEK_APP_OPENGL)
std::function<void(bool)> vsync;
#endif
#if defined(PSEMEK_APP_WEBGPU)
wgpu::adapter adapter;
wgpu::surface surface;
wgpu::device device;
#endif
};
struct factory

View file

@ -5,4 +5,10 @@ file(GLOB_RECURSE PSEMEK_SDL2_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "so
psemek_add_library(psemek-sdl2 ${PSEMEK_SDL2_HEADERS} ${PSEMEK_SDL2_SOURCES})
target_include_directories(psemek-sdl2 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(psemek-sdl2 PUBLIC psemek-log psemek-util psemek-gfx psemek-audio psemek-app SDL2)
target_link_libraries(psemek-sdl2 PUBLIC psemek-log psemek-util psemek-audio psemek-app SDL2)
if(PSEMEK_GRAPHICS_API STREQUAL OPENGL)
target_link_libraries(psemek-sdl2 PUBLIC psemek-gfx)
elseif(PSEMEK_GRAPHICS_API STREQUAL WEBGPU)
target_link_libraries(psemek-sdl2 PUBLIC psemek-wgpu)
endif()
target_compile_definitions(psemek-sdl2 PUBLIC "-DPSEMEK_SDL2_${PSEMEK_GRAPHICS_API}=1")

View file

@ -2,6 +2,12 @@
#include <psemek/app/application.hpp>
#if defined(PSEMEK_SDL2_WEBGPU)
#include <psemek/wgpu/surface.hpp>
#include <psemek/wgpu/adapter.hpp>
#include <psemek/wgpu/device.hpp>
#endif
#include <SDL2/SDL.h>
namespace psemek::sdl2
@ -20,10 +26,23 @@ namespace psemek::sdl2
void vsync(bool on);
void windowed(bool on);
#if defined(PSEMEK_SDL2_WEBGPU)
wgpu::adapter wgpu_adapter() const { return wgpu_adapter_; }
wgpu::surface wgpu_surface() const { return wgpu_surface_; }
wgpu::device wgpu_device() const { return wgpu_device_; }
#endif
private:
std::shared_ptr<void> sdl_init_;
SDL_Window * window_ = nullptr;
#if defined(PSEMEK_SDL2_OPENGL)
SDL_GLContext gl_context_ = nullptr;
#elif defined(PSEMEK_SDL2_WEBGPU)
wgpu::adapter wgpu_adapter_;
wgpu::surface wgpu_surface_;
wgpu::device wgpu_device_;
#endif
};
}

View file

@ -42,15 +42,22 @@ int main(int argc, char ** argv) try
sdl2::window window(options);
gfx::init();
app::application::context context;
for (int i = 0; i < argc; ++i)
context.args.push_back(argv[i]);
context.show_cursor = [&](bool show){ window.show_cursor(show); };
context.vsync = [&](bool on){ window.vsync(on); };
context.windowed = [&](bool on){ window.windowed(on); };
#if defined(PSEMEK_SDL2_OPENGL)
context.vsync = [&](bool on){ window.vsync(on); };
#endif
#if defined(PSEMEK_SDL2_WEBGPU)
context.adapter = window.wgpu_adapter();
context.surface = window.wgpu_surface();
context.device = window.wgpu_device();
#endif
auto application = factory->create(options, context);
if (!application)
@ -89,5 +96,5 @@ catch (std::exception const & e)
catch (...)
{
psemek::log::error() << "Unknown exception";
return EXIT_FAILURE;
throw;
}

View file

@ -1,15 +1,26 @@
#include <psemek/sdl2/window.hpp>
#include <psemek/sdl2/init.hpp>
#include <psemek/gfx/gl.hpp>
#include <psemek/geom/box.hpp>
#include <psemek/log/log.hpp>
#if defined(PSEMEK_SDL2_OPENGL)
#include <psemek/gfx/gl.hpp>
#elif defined(PSEMEK_SDL2_WEBGPU)
#include <psemek/wgpu/instance.hpp>
#endif
#include <SDL2/SDL_syswm.h>
namespace psemek::sdl2
{
window::window(psemek::app::application::options const & options)
: sdl_init_(init(SDL_INIT_EVENTS | SDL_INIT_VIDEO))
{
std::uint32_t flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
if (options.highdpi) flags |= SDL_WINDOW_ALLOW_HIGHDPI;
#if defined(PSEMEK_SDL2_OPENGL)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, gl::sys::major_version());
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, gl::sys::minor_version());
@ -30,8 +41,8 @@ namespace psemek::sdl2
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, options.multisampling);
}
std::uint32_t flags = SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
if (options.highdpi) flags |= SDL_WINDOW_ALLOW_HIGHDPI;
flags |= SDL_WINDOW_OPENGL;
#endif
SDL_DisplayMode display_mode;
SDL_GetCurrentDisplayMode(0, &display_mode);
@ -40,11 +51,61 @@ namespace psemek::sdl2
if (!window_)
sdl2::fail("Failed to create window: ");
#if defined(PSEMEK_SDL2_OPENGL)
gl_context_ = SDL_GL_CreateContext(window_);
if (!gl_context_)
sdl2::fail("Failed to create OpenGL context: ");
SDL_GL_MakeCurrent(window_, gl_context_);
gfx::init();
#elif defined(PSEMEK_SDL2_WEBGPU)
auto instance = wgpu::instance::create({});
SDL_SysWMinfo wminfo;
SDL_VERSION(&wminfo.version);
SDL_GetWindowWMInfo(window_, &wminfo);
wgpu::surface::descriptor surface_descriptor;
#if defined(_WIN32)
surface_descriptor.chain = {wgpu::surface::from_windows_hwnd{ .hinstance = wminfo.info.win.hinstance, .hwnd = wminfo.info.win.window }};
#else
surface_descriptor.chain = {wgpu::surface::from_xlib_window{ .display = wminfo.info.x11.display, .window = wminfo.info.x11.window }};
#endif
wgpu_surface_ = instance.create_surface(surface_descriptor);
wgpu::adapter::request_options adapter_request_options;
adapter_request_options.compatible_surface = wgpu_surface_;
#if defined(_WIN32)
adapter_request_options.backend_type = wgpu::backend_type::d3d12;
#else
adapter_request_options.backend_type = wgpu::backend_type::vulkan;
#endif
instance.request_adapter(adapter_request_options, [this](wgpu::adapter::request_status status, wgpu::adapter adapter_in, std::string const & message)
{
if (status != wgpu::adapter::request_status::success)
throw std::runtime_error("Failed to request WebGPU adapter: " + message);
wgpu_adapter_ = std::move(adapter_in);
});
wgpu::device::descriptor device_descriptor
{
.required_features = options.required_features,
.required_limits = options.required_limits ? std::optional(wgpu::device::required_limits{.limits = *options.required_limits}) : std::nullopt,
};
wgpu_adapter_.request_device(device_descriptor, [this](wgpu::device::request_status status, wgpu::device device_in, std::string const & message)
{
if (status != wgpu::device::request_status::success)
throw std::runtime_error("Failed to request WebGPU device: " + message);
wgpu_device_ = std::move(device_in);
});
auto adapter_properties = wgpu_adapter_.get_properties();
log::info() << "Initialized WebGPU: " << adapter_properties.name;
#endif
}
geom::vector<int, 2> window::size() const
@ -126,8 +187,10 @@ namespace psemek::sdl2
window::~window()
{
#if defined(PSEMEK_SDL2_OPENGL)
if (gl_context_)
SDL_GL_DeleteContext(gl_context_);
#endif
if (window_)
SDL_DestroyWindow(window_);
}

6
libs/wgpu/CMakeLists.txt Normal file
View file

@ -0,0 +1,6 @@
file(GLOB_RECURSE PSEMEK_WGPU_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp" "include/*.h")
file(GLOB_RECURSE PSEMEK_WGPU_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp")
psemek_add_library(psemek-wgpu ${PSEMEK_WGPU_HEADERS} ${PSEMEK_WGPU_SOURCES})
target_include_directories(psemek-wgpu PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(psemek-wgpu PUBLIC psemek-util psemek-geom psemek-log psemek-gfx wgpu-native)

View file

@ -0,0 +1,95 @@
#pragma once
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/surface.hpp>
#include <psemek/wgpu/device.hpp>
#include <psemek/wgpu/detail/object.hpp>
#include <functional>
#include <cstdint>
namespace psemek::wgpu
{
enum class power_preference : std::uint32_t
{
undefined = 0x00000000,
low = 0x00000001,
high = 0x00000002,
};
enum class backend_type : std::uint32_t
{
undefined = 0x00000000,
null = 0x00000001,
webgpu = 0x00000002,
d3d11 = 0x00000003,
d3d12 = 0x00000004,
metal = 0x00000005,
vulkan = 0x00000006,
opengl = 0x00000007,
opengles = 0x00000008,
};
struct adapter
: detail::object<adapter>
{
using detail::object<adapter>::object;
struct request_options
{
std::vector<chained_struct> chain = {};
surface compatible_surface = {};
wgpu::power_preference power_preference = power_preference::high;
wgpu::backend_type backend_type = backend_type::vulkan;
bool force_fallback_adapter = false;
};
enum class request_status : std::uint32_t
{
success = 0x00000000,
unavailable = 0x00000001,
error = 0x00000002,
unknown = 0x00000003,
};
using request_callback = std::function<void(request_status, adapter, std::string)>;
enum class type : std::uint32_t
{
discrete_gpu = 0x00000000,
integrated_gpu = 0x00000001,
cpu = 0x00000002,
unknown = 0x00000003,
};
struct properties
{
std::uint32_t vendor_id;
std::string vendor_name;
std::string architecture;
std::uint32_t device_id;
std::string name;
std::string driver_description;
enum type adapter_type;
wgpu::backend_type backend_type;
};
std::vector<feature> enumerate_features();
limits get_limits();
properties get_properties();
bool has_feature(feature feature);
void request_device(device::descriptor const & descriptor, device::request_callback const & callback);
static void reference(void * ptr);
static void release(void * ptr);
private:
explicit adapter(void * ptr)
: detail::object<adapter>(ptr)
{}
friend struct instance;
};
}

View file

@ -0,0 +1,65 @@
#pragma once
#include <memory>
#include <vector>
namespace psemek::wgpu
{
struct chained_struct;
namespace detail
{
struct chained_struct_base
{
virtual ~chained_struct_base() {}
virtual void * ptr() = 0;
};
template <typename T>
struct chained_struct_impl
: chained_struct_base
{
chained_struct_impl(T const & value)
: value_(value)
{}
void * ptr() override
{
return &value_;
}
private:
T value_;
};
void * fill_chain(std::vector<chained_struct> const & chain);
using chained_struct_ptr = std::shared_ptr<chained_struct_base>;
template <typename T>
chained_struct_ptr make_chained_struct(T const & value)
{
return std::make_shared<chained_struct_impl<T>>(value);
}
}
struct chained_struct
{
template <typename T>
chained_struct(T const & value)
: impl_(to_chained_struct(value))
{}
void * ptr() const
{
return impl_->ptr();
}
private:
detail::chained_struct_ptr impl_;
};
}

View file

@ -0,0 +1,67 @@
#pragma once
namespace psemek::wgpu::detail
{
template <typename Derived>
struct object
{
object() = default;
object(object const & other)
: ptr_(other.ptr_)
{
if (ptr_) Derived::reference(ptr_);
}
object(object && other)
: ptr_(other.ptr_)
{
other.ptr_ = nullptr;
}
object & operator = (object const & other)
{
if (this == &other)
return *this;
reset();
ptr_ = other.ptr_;
if (ptr_) Derived::reference(ptr_);
return *this;
}
object & operator = (object && other)
{
if (this == &other)
return *this;
reset();
ptr_ = other.ptr_;
other.ptr_ = nullptr;
return *this;
}
~object()
{
reset();
}
void reset()
{
if (ptr_) Derived::release(ptr_);
ptr_ = nullptr;
}
void * get() const { return ptr_; }
explicit operator bool() const { return ptr_ != nullptr; }
protected:
object(void * ptr)
: ptr_(ptr)
{}
private:
void * ptr_ = nullptr;
};
}

View file

@ -0,0 +1,114 @@
#pragma once
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/queue.hpp>
#include <psemek/wgpu/detail/object.hpp>
#include <cstdint>
#include <optional>
#include <functional>
namespace psemek::wgpu
{
enum class feature : std::uint32_t {
undefined = 0x00000000,
depth_clip_control = 0x00000001,
depth32float_stencil8 = 0x00000002,
timestamp_query = 0x00000003,
texture_compression_bc = 0x00000004,
texture_compression_etc2 = 0x00000005,
texture_compression_astc = 0x00000006,
indirect_first_instance = 0x00000007,
shader_f16 = 0x00000008,
rg11b10ufloat_renderable = 0x00000009,
bgra8unorm_storage = 0x0000000a,
float32_filterable = 0x0000000b,
};
struct limits
{
std::uint32_t max_texture_dimension_1D;
std::uint32_t max_texture_dimension_2D;
std::uint32_t max_texture_dimension_3D;
std::uint32_t max_texture_array_layers;
std::uint32_t max_bind_groups;
std::uint32_t max_bind_groups_plus_vertex_buffers;
std::uint32_t max_bindings_per_bind_group;
std::uint32_t max_dynamic_uniform_buffers_per_pipeline_layout;
std::uint32_t max_dynamic_storage_buffers_per_pipeline_layout;
std::uint32_t max_sampled_textures_per_shader_stage;
std::uint32_t max_samplers_per_shader_stage;
std::uint32_t max_storage_buffers_per_shader_stage;
std::uint32_t max_storage_textures_per_shader_stage;
std::uint32_t max_uniform_buffers_per_shader_stage;
std::uint64_t max_uniform_buffer_binding_size;
std::uint64_t max_storage_buffer_binding_size;
std::uint32_t min_uniform_buffer_offset_alignment;
std::uint32_t min_storage_buffer_offset_alignment;
std::uint32_t max_vertex_buffers;
std::uint64_t max_buffer_size;
std::uint32_t max_vertex_attributes;
std::uint32_t max_vertex_buffer_array_stride;
std::uint32_t max_inter_stage_shader_components;
std::uint32_t max_inter_stage_shader_variables;
std::uint32_t max_color_attachments;
std::uint32_t max_color_attachment_bytes_per_sample;
std::uint32_t max_compute_workgroup_storage_size;
std::uint32_t max_compute_invocations_per_workgroup;
std::uint32_t max_compute_workgroup_size_x;
std::uint32_t max_compute_workgroup_size_y;
std::uint32_t max_compute_workgroup_size_z;
std::uint32_t max_compute_workgroups_per_dimension;
};
struct device
: detail::object<device>
{
using detail::object<device>::object;
enum class lost_reason : std::uint32_t
{
undefined = 0x00000000,
destroyed = 0x00000001,
};
using lost_callback = std::function<void(lost_reason, std::string const &)>;
struct required_limits
{
std::vector<chained_struct> chain = {};
wgpu::limits limits = {};
};
struct descriptor
{
std::vector<chained_struct> chain = {};
std::string label = {};
std::vector<feature> required_features = {};
std::optional<struct required_limits> required_limits = {};
queue::descriptor default_queue = {};
device::lost_callback lost_callback = {};
};
enum class request_status : std::uint32_t
{
success = 0x00000000,
error = 0x00000001,
unknown = 0x00000002,
};
using request_callback = std::function<void(request_status, device, std::string const & message)>;
static void reference(void * ptr);
static void release(void * ptr);
private:
explicit device(void * ptr)
: detail::object<device>(ptr)
{}
friend struct adapter;
};
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,258 @@
#ifndef WGPU_H_
#define WGPU_H_
#include "webgpu.h"
typedef enum WGPUNativeSType {
// Start at 0003 since that's allocated range for wgpu-native
WGPUSType_DeviceExtras = 0x00030001,
WGPUSType_RequiredLimitsExtras = 0x00030002,
WGPUSType_PipelineLayoutExtras = 0x00030003,
WGPUSType_ShaderModuleGLSLDescriptor = 0x00030004,
WGPUSType_SupportedLimitsExtras = 0x00030005,
WGPUSType_InstanceExtras = 0x00030006,
WGPUSType_BindGroupEntryExtras = 0x00030007,
WGPUSType_BindGroupLayoutEntryExtras = 0x00030008,
WGPUSType_QuerySetDescriptorExtras = 0x00030009,
WGPUNativeSType_Force32 = 0x7FFFFFFF
} WGPUNativeSType;
typedef enum WGPUNativeFeature {
WGPUNativeFeature_PushConstants = 0x00030001,
WGPUNativeFeature_TextureAdapterSpecificFormatFeatures = 0x00030002,
WGPUNativeFeature_MultiDrawIndirect = 0x00030003,
WGPUNativeFeature_MultiDrawIndirectCount = 0x00030004,
WGPUNativeFeature_VertexWritableStorage = 0x00030005,
WGPUNativeFeature_TextureBindingArray = 0x00030006,
WGPUNativeFeature_SampledTextureAndStorageBufferArrayNonUniformIndexing = 0x00030007,
WGPUNativeFeature_PipelineStatisticsQuery = 0x00030008,
WGPUNativeFeature_Force32 = 0x7FFFFFFF
} WGPUNativeFeature;
typedef enum WGPULogLevel {
WGPULogLevel_Off = 0x00000000,
WGPULogLevel_Error = 0x00000001,
WGPULogLevel_Warn = 0x00000002,
WGPULogLevel_Info = 0x00000003,
WGPULogLevel_Debug = 0x00000004,
WGPULogLevel_Trace = 0x00000005,
WGPULogLevel_Force32 = 0x7FFFFFFF
} WGPULogLevel;
typedef enum WGPUInstanceBackend {
WGPUInstanceBackend_All = 0x00000000,
WGPUInstanceBackend_Vulkan = 1 << 0,
WGPUInstanceBackend_GL = 1 << 1,
WGPUInstanceBackend_Metal = 1 << 2,
WGPUInstanceBackend_DX12 = 1 << 3,
WGPUInstanceBackend_DX11 = 1 << 4,
WGPUInstanceBackend_BrowserWebGPU = 1 << 5,
WGPUInstanceBackend_Primary = WGPUInstanceBackend_Vulkan | WGPUInstanceBackend_Metal |
WGPUInstanceBackend_DX12 |
WGPUInstanceBackend_BrowserWebGPU,
WGPUInstanceBackend_Secondary = WGPUInstanceBackend_GL | WGPUInstanceBackend_DX11,
WGPUInstanceBackend_Force32 = 0x7FFFFFFF
} WGPUInstanceBackend;
typedef WGPUFlags WGPUInstanceBackendFlags;
typedef enum WGPUInstanceFlag {
WGPUInstanceFlag_Default = 0x00000000,
WGPUInstanceFlag_Debug = 1 << 0,
WGPUInstanceFlag_Validation = 1 << 1,
WGPUInstanceFlag_DiscardHalLabels = 1 << 2,
WGPUInstanceFlag_Force32 = 0x7FFFFFFF
} WGPUInstanceFlag;
typedef WGPUFlags WGPUInstanceFlags;
typedef enum WGPUDx12Compiler {
WGPUDx12Compiler_Undefined = 0x00000000,
WGPUDx12Compiler_Fxc = 0x00000001,
WGPUDx12Compiler_Dxc = 0x00000002,
WGPUDx12Compiler_Force32 = 0x7FFFFFFF
} WGPUDx12Compiler;
typedef enum WGPUGles3MinorVersion {
WGPUGles3MinorVersion_Automatic = 0x00000000,
WGPUGles3MinorVersion_Version0 = 0x00000001,
WGPUGles3MinorVersion_Version1 = 0x00000002,
WGPUGles3MinorVersion_Version2 = 0x00000003,
WGPUGles3MinorVersion_Force32 = 0x7FFFFFFF
} WGPUGles3MinorVersion;
typedef enum WGPUPipelineStatisticName {
WGPUPipelineStatisticName_VertexShaderInvocations = 0x00000000,
WGPUPipelineStatisticName_ClipperInvocations = 0x00000001,
WGPUPipelineStatisticName_ClipperPrimitivesOut = 0x00000002,
WGPUPipelineStatisticName_FragmentShaderInvocations = 0x00000003,
WGPUPipelineStatisticName_ComputeShaderInvocations = 0x00000004,
WGPUPipelineStatisticName_Force32 = 0x7FFFFFFF
} WGPUPipelineStatisticName WGPU_ENUM_ATTRIBUTE;
typedef enum WGPUNativeQueryType {
WGPUNativeQueryType_PipelineStatistics = 0x00030000,
WGPUNativeQueryType_Force32 = 0x7FFFFFFF
} WGPUNativeQueryType WGPU_ENUM_ATTRIBUTE;
typedef struct WGPUInstanceExtras {
WGPUChainedStruct chain;
WGPUInstanceBackendFlags backends;
WGPUInstanceFlags flags;
WGPUDx12Compiler dx12ShaderCompiler;
WGPUGles3MinorVersion gles3MinorVersion;
const char * dxilPath;
const char * dxcPath;
} WGPUInstanceExtras;
typedef struct WGPUDeviceExtras {
WGPUChainedStruct chain;
const char * tracePath;
} WGPUDeviceExtras;
typedef struct WGPUNativeLimits {
uint32_t maxPushConstantSize;
uint32_t maxNonSamplerBindings;
} WGPUNativeLimits;
typedef struct WGPURequiredLimitsExtras {
WGPUChainedStruct chain;
WGPUNativeLimits limits;
} WGPURequiredLimitsExtras;
typedef struct WGPUSupportedLimitsExtras {
WGPUChainedStructOut chain;
WGPUNativeLimits limits;
} WGPUSupportedLimitsExtras;
typedef struct WGPUPushConstantRange {
WGPUShaderStageFlags stages;
uint32_t start;
uint32_t end;
} WGPUPushConstantRange;
typedef struct WGPUPipelineLayoutExtras {
WGPUChainedStruct chain;
uint32_t pushConstantRangeCount;
WGPUPushConstantRange* pushConstantRanges;
} WGPUPipelineLayoutExtras;
typedef uint64_t WGPUSubmissionIndex;
typedef struct WGPUWrappedSubmissionIndex {
WGPUQueue queue;
WGPUSubmissionIndex submissionIndex;
} WGPUWrappedSubmissionIndex;
typedef struct WGPUShaderDefine {
char const * name;
char const * value;
} WGPUShaderDefine;
typedef struct WGPUShaderModuleGLSLDescriptor {
WGPUChainedStruct chain;
WGPUShaderStage stage;
char const * code;
uint32_t defineCount;
WGPUShaderDefine * defines;
} WGPUShaderModuleGLSLDescriptor;
typedef struct WGPURegistryReport {
size_t numAllocated;
size_t numKeptFromUser;
size_t numReleasedFromUser;
size_t numDestroyedFromUser;
size_t numError;
size_t elementSize;
} WGPURegistryReport;
typedef struct WGPUHubReport {
WGPURegistryReport adapters;
WGPURegistryReport devices;
WGPURegistryReport queues;
WGPURegistryReport pipelineLayouts;
WGPURegistryReport shaderModules;
WGPURegistryReport bindGroupLayouts;
WGPURegistryReport bindGroups;
WGPURegistryReport commandBuffers;
WGPURegistryReport renderBundles;
WGPURegistryReport renderPipelines;
WGPURegistryReport computePipelines;
WGPURegistryReport querySets;
WGPURegistryReport buffers;
WGPURegistryReport textures;
WGPURegistryReport textureViews;
WGPURegistryReport samplers;
} WGPUHubReport;
typedef struct WGPUGlobalReport {
WGPURegistryReport surfaces;
WGPUBackendType backendType;
WGPUHubReport vulkan;
WGPUHubReport metal;
WGPUHubReport dx12;
WGPUHubReport gl;
} WGPUGlobalReport;
typedef struct WGPUInstanceEnumerateAdapterOptions {
WGPUChainedStruct const * nextInChain;
WGPUInstanceBackendFlags backends;
} WGPUInstanceEnumerateAdapterOptions;
typedef struct WGPUBindGroupEntryExtras {
WGPUChainedStruct chain;
WGPUBuffer const * buffers;
size_t bufferCount;
WGPUSampler const * samplers;
size_t samplerCount;
WGPUTextureView const * textureViews;
size_t textureViewCount;
} WGPUBindGroupEntryExtras;
typedef struct WGPUBindGroupLayoutEntryExtras {
WGPUChainedStruct chain;
uint32_t count;
} WGPUBindGroupLayoutEntryExtras;
typedef struct WGPUQuerySetDescriptorExtras {
WGPUChainedStruct chain;
WGPUPipelineStatisticName const * pipelineStatistics;
size_t pipelineStatisticCount;
} WGPUQuerySetDescriptorExtras WGPU_STRUCTURE_ATTRIBUTE;
typedef void (*WGPULogCallback)(WGPULogLevel level, char const * message, void * userdata);
#ifdef __cplusplus
extern "C" {
#endif
void wgpuGenerateReport(WGPUInstance instance, WGPUGlobalReport * report);
size_t wgpuInstanceEnumerateAdapters(WGPUInstance instance, WGPUInstanceEnumerateAdapterOptions const * options, WGPUAdapter * adapters);
WGPUSubmissionIndex wgpuQueueSubmitForIndex(WGPUQueue queue, size_t commandCount, WGPUCommandBuffer const * commands);
// Returns true if the queue is empty, or false if there are more queue submissions still in flight.
WGPUBool wgpuDevicePoll(WGPUDevice device, WGPUBool wait, WGPUWrappedSubmissionIndex const * wrappedSubmissionIndex);
void wgpuSetLogCallback(WGPULogCallback callback, void * userdata);
void wgpuSetLogLevel(WGPULogLevel level);
uint32_t wgpuGetVersion(void);
void wgpuRenderPassEncoderSetPushConstants(WGPURenderPassEncoder encoder, WGPUShaderStageFlags stages, uint32_t offset, uint32_t sizeBytes, void* const data);
void wgpuRenderPassEncoderMultiDrawIndirect(WGPURenderPassEncoder encoder, WGPUBuffer buffer, uint64_t offset, uint32_t count);
void wgpuRenderPassEncoderMultiDrawIndexedIndirect(WGPURenderPassEncoder encoder, WGPUBuffer buffer, uint64_t offset, uint32_t count);
void wgpuRenderPassEncoderMultiDrawIndirectCount(WGPURenderPassEncoder encoder, WGPUBuffer buffer, uint64_t offset, WGPUBuffer count_buffer, uint64_t count_buffer_offset, uint32_t max_count);
void wgpuRenderPassEncoderMultiDrawIndexedIndirectCount(WGPURenderPassEncoder encoder, WGPUBuffer buffer, uint64_t offset, WGPUBuffer count_buffer, uint64_t count_buffer_offset, uint32_t max_count);
void wgpuComputePassEncoderBeginPipelineStatisticsQuery(WGPUComputePassEncoder computePassEncoder, WGPUQuerySet querySet, uint32_t queryIndex);
void wgpuComputePassEncoderEndPipelineStatisticsQuery(WGPUComputePassEncoder computePassEncoder);
void wgpuRenderPassEncoderBeginPipelineStatisticsQuery(WGPURenderPassEncoder renderPassEncoder, WGPUQuerySet querySet, uint32_t queryIndex);
void wgpuRenderPassEncoderEndPipelineStatisticsQuery(WGPURenderPassEncoder renderPassEncoder);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

View file

@ -0,0 +1,36 @@
#pragma once
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/surface.hpp>
#include <psemek/wgpu/adapter.hpp>
#include <psemek/wgpu/detail/object.hpp>
namespace psemek::wgpu
{
struct instance
: detail::object<instance>
{
using detail::object<instance>::object;
struct descriptor
{
std::vector<chained_struct> chain = {};
};
static instance create(descriptor const & desc);
void process_events();
surface create_surface(surface::descriptor const & desc) const;
void request_adapter(adapter::request_options const & request_options, adapter::request_callback callback);
static void reference(void * ptr);
static void release(void * ptr);
private:
explicit instance(void * ptr)
: detail::object<instance>(ptr)
{}
};
}

View file

@ -0,0 +1,32 @@
#pragma once
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/detail/object.hpp>
#include <string>
#include <vector>
namespace psemek::wgpu
{
struct queue
: detail::object<queue>
{
using detail::object<queue>::object;
struct descriptor
{
std::vector<chained_struct> chain = {};
std::string label = {};
};
static void reference(void * ptr);
static void release(void * ptr);
private:
explicit queue(void * ptr)
: detail::object<queue>(ptr)
{}
};
}

View file

@ -0,0 +1,153 @@
#pragma once
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/texture.hpp>
#include <psemek/wgpu/device.hpp>
#include <psemek/wgpu/detail/object.hpp>
#include <string>
#include <vector>
#include <cstdint>
namespace psemek::wgpu
{
struct adapter;
struct surface
: detail::object<surface>
{
using detail::object<surface>::object;
struct descriptor
{
std::string label = {};
std::vector<chained_struct> chain = {};
};
enum class composite_alpha_mode : std::uint32_t
{
_auto = 0x00000000,
opaque = 0x00000001,
premultiplied = 0x00000002,
unpremultiplied = 0x00000003,
inherit = 0x00000004,
};
enum class present_mode : std::uint32_t
{
fifo = 0x00000000,
fifo_relaxed = 0x00000001,
immediate = 0x00000002,
mailbox = 0x00000003,
};
struct configuration
{
std::vector<chained_struct> chain = {};
wgpu::device device;
texture::format format;
texture::usage usage;
std::vector<texture::format> view_formats = {};
composite_alpha_mode alpha_mode;
std::uint32_t width;
std::uint32_t height;
surface::present_mode present_mode;
};
struct capabilities
{
std::vector<chained_struct> chain = {};
std::vector<texture::format> formats = {};
std::vector<present_mode> present_modes = {};
std::vector<composite_alpha_mode> alpha_modes = {};
};
struct current_texture
{
enum class status : std::uint32_t
{
success = 0x00000000,
timeout = 0x00000001,
outdated = 0x00000002,
lost = 0x00000003,
out_of_memory = 0x00000004,
device_lost = 0x00000005,
};
wgpu::texture texture;
bool suboptimal;
enum status status;
};
void configure(configuration const & conf);
capabilities get_capabilities(adapter const & adapter);
current_texture get_current_texture();
wgpu::texture::format get_preferred_format(adapter const & adapter);
void present();
void unconfigure();
struct from_android_native_window
{
void * window;
};
struct from_canvas_html_selected
{
std::string selector;
};
struct from_metal_layer
{
void * layer;
};
struct from_wayland_surface
{
void * display;
void * surface;
};
struct from_windows_hwnd
{
void * hinstance;
void * hwnd;
};
struct from_xcb_window
{
void * connection;
std::uint32_t window;
};
struct from_xlib_window
{
void * display;
std::uint64_t window;
};
static void reference(void * ptr);
static void release(void * ptr);
private:
explicit surface(void * ptr)
: detail::object<surface>(ptr)
{}
friend struct instance;
};
detail::chained_struct_ptr to_chained_struct(surface::from_android_native_window const & value);
detail::chained_struct_ptr to_chained_struct(surface::from_canvas_html_selected const & value);
detail::chained_struct_ptr to_chained_struct(surface::from_metal_layer const & value);
detail::chained_struct_ptr to_chained_struct(surface::from_wayland_surface const & value);
detail::chained_struct_ptr to_chained_struct(surface::from_windows_hwnd const & value);
detail::chained_struct_ptr to_chained_struct(surface::from_xcb_window const & value);
detail::chained_struct_ptr to_chained_struct(surface::from_xlib_window const & value);
}

View file

@ -0,0 +1,142 @@
#pragma once
#include <psemek/wgpu/detail/object.hpp>
#include <cstdint>
namespace psemek::wgpu
{
struct texture
: detail::object<texture>
{
using detail::object<texture>::object;
enum class format : std::uint32_t
{
undefined = 0x00000000,
r8unorm = 0x00000001,
r8snorm = 0x00000002,
r8uint = 0x00000003,
r8sint = 0x00000004,
r16uint = 0x00000005,
r16sint = 0x00000006,
r16float = 0x00000007,
rg8unorm = 0x00000008,
rg8snorm = 0x00000009,
rg8uint = 0x0000000a,
rg8sint = 0x0000000b,
r32float = 0x0000000c,
r32uint = 0x0000000d,
r32sint = 0x0000000e,
rg16uint = 0x0000000f,
rg16sint = 0x00000010,
rg16float = 0x00000011,
rgba8unorm = 0x00000012,
rgba8unorm_srgb = 0x00000013,
rgba8snorm = 0x00000014,
rgba8uint = 0x00000015,
rgba8sint = 0x00000016,
bgra8unorm = 0x00000017,
bgra8unorm_srgb = 0x00000018,
rgb10a2uint = 0x00000019,
rgb10a2unorm = 0x0000001a,
rg11b10ufloat = 0x0000001b,
rgb9e5ufloat = 0x0000001c,
rg32float = 0x0000001d,
rg32uint = 0x0000001e,
rg32sint = 0x0000001f,
rgba16uint = 0x00000020,
rgba16sint = 0x00000021,
rgba16float = 0x00000022,
rgba32float = 0x00000023,
rgba32uint = 0x00000024,
rgba32sint = 0x00000025,
stencil8 = 0x00000026,
depth16unorm = 0x00000027,
depth24plus = 0x00000028,
depth24plusstencil8 = 0x00000029,
depth32float = 0x0000002a,
depth32floatstencil8 = 0x0000002b,
bc1rgbaunorm = 0x0000002c,
bc1rgbaunorm_srgb = 0x0000002d,
bc2rgbaunorm = 0x0000002e,
bc2rgbaunorm_srgb = 0x0000002f,
bc3rgbaunorm = 0x00000030,
bc3rgbaunorm_srgb = 0x00000031,
bc4runorm = 0x00000032,
bc4rsnorm = 0x00000033,
bc5rgunorm = 0x00000034,
bc5rgsnorm = 0x00000035,
bc6hrgbufloat = 0x00000036,
bc6hrgbfloat = 0x00000037,
bc7rgbaunorm = 0x00000038,
bc7rgbaunorm_srgb = 0x00000039,
etc2rgb8unorm = 0x0000003a,
etc2rgb8unorm_srgb = 0x0000003b,
etc2rgb8a1unorm = 0x0000003c,
etc2rgb8a1unorm_srgb = 0x0000003d,
etc2rgba8unorm = 0x0000003e,
etc2rgba8unorm_srgb = 0x0000003f,
eacr11unorm = 0x00000040,
eacr11snorm = 0x00000041,
eacrg11unorm = 0x00000042,
eacrg11snorm = 0x00000043,
astc4x4unorm = 0x00000044,
astc4x4unorm_srgb = 0x00000045,
astc5x4unorm = 0x00000046,
astc5x4unorm_srgb = 0x00000047,
astc5x5unorm = 0x00000048,
astc5x5unorm_srgb = 0x00000049,
astc6x5unorm = 0x0000004a,
astc6x5unorm_srgb = 0x0000004b,
astc6x6unorm = 0x0000004c,
astc6x6unorm_srgb = 0x0000004d,
astc8x5unorm = 0x0000004e,
astc8x5unorm_srgb = 0x0000004f,
astc8x6unorm = 0x00000050,
astc8x6unorm_srgb = 0x00000051,
astc8x8unorm = 0x00000052,
astc8x8unorm_srgb = 0x00000053,
astc10x5unorm = 0x00000054,
astc10x5unorm_srgb = 0x00000055,
astc10x6unorm = 0x00000056,
astc10x6unorm_srgb = 0x00000057,
astc10x8unorm = 0x00000058,
astc10x8unorm_srgb = 0x00000059,
astc10x10unorm = 0x0000005a,
astc10x10unorm_srgb = 0x0000005b,
astc12x10unorm = 0x0000005c,
astc12x10unorm_srgb = 0x0000005d,
astc12x12unorm = 0x0000005e,
astc12x12unorm_srgb = 0x0000005f,
};
enum class usage : std::uint32_t
{
none = 0x00000000,
copy_src = 0x00000001,
copy_dst = 0x00000002,
texture_binding = 0x00000004,
storage_binding = 0x00000008,
render_attachment = 0x00000010,
};
static void reference(void * ptr);
static void release(void * ptr);
private:
explicit texture(void * ptr)
: detail::object<texture>(ptr)
{}
friend struct surface;
friend struct device;
};
inline texture::usage operator | (texture::usage u1, texture::usage u2)
{
return static_cast<texture::usage>(static_cast<unsigned int>(u1) | static_cast<unsigned int>(u2));
}
}

22
libs/wgpu/objects-todo Normal file
View file

@ -0,0 +1,22 @@
+ WGPUAdapter
WGPUBindGroup
WGPUBindGroupLayout
WGPUBuffer
WGPUCommandBuffer
WGPUCommandEncoder
WGPUComputePassEncoder
WGPUComputePipeline
WGPUDevice
+ WGPUInstance
WGPUPipelineLayout
WGPUQuerySet
WGPUQueue
WGPURenderBundle
WGPURenderBundleEncoder
WGPURenderPassEncoder
WGPURenderPipeline
WGPUSampler
WGPUShaderModule
+ WGPUSurface
WGPUTexture
WGPUTextureView

View file

@ -0,0 +1,100 @@
#include <psemek/wgpu/adapter.hpp>
#include <psemek/wgpu/external/webgpu.h>
#include <cstring>
namespace psemek::wgpu
{
std::vector<feature> adapter::enumerate_features()
{
std::size_t count = wgpuAdapterEnumerateFeatures((WGPUAdapter)get(), nullptr);
std::vector<feature> result(count);
wgpuAdapterEnumerateFeatures((WGPUAdapter)get(), (WGPUFeatureName *)result.data());
return result;
}
limits adapter::get_limits()
{
WGPUSupportedLimits limits = {};
wgpuAdapterGetLimits((WGPUAdapter)get(), &limits);
// TODO: support out chain
wgpu::limits result;
static_assert(sizeof(result) == sizeof(limits.limits));
std::memcpy(&result, &limits.limits, sizeof(result));
return result;
}
adapter::properties adapter::get_properties()
{
WGPUAdapterProperties props;
wgpuAdapterGetProperties((WGPUAdapter)get(), &props);
return {
.vendor_id = props.vendorID,
.vendor_name = props.vendorName,
.architecture = props.architecture,
.device_id = props.deviceID,
.name = props.name,
.driver_description = props.driverDescription,
.adapter_type = (adapter::type)props.adapterType,
.backend_type = (backend_type)props.backendType,
};
}
bool adapter::has_feature(feature feature)
{
return wgpuAdapterHasFeature((WGPUAdapter)get(), (WGPUFeatureName)feature);
}
void adapter::request_device(device::descriptor const & descriptor, device::request_callback const & callback)
{
WGPURequiredLimits limits = {};
if (descriptor.required_limits)
{
static_assert(sizeof(limits.limits) == sizeof(descriptor.required_limits->limits));
limits.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(descriptor.required_limits->chain);
std::memcpy(&limits.limits, &descriptor.required_limits->limits, sizeof(limits.limits));
}
auto device_lost_userdata = new device::lost_callback(descriptor.lost_callback);
auto device_lost_real_callback = [](WGPUDeviceLostReason reason, char const * message, void * userdata)
{
std::unique_ptr<device::lost_callback> callback((device::lost_callback *)userdata);
if (*callback) (*callback)((device::lost_reason)reason, message ? message : "");
};
WGPUDeviceDescriptor device_desc = {};
device_desc.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(descriptor.chain);
device_desc.label = descriptor.label.data();
device_desc.requiredFeatureCount = descriptor.required_features.size();
device_desc.requiredFeatures = (WGPUFeatureName const *)descriptor.required_features.data();
device_desc.requiredLimits = descriptor.required_limits ? &limits : nullptr;
device_desc.defaultQueue.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(descriptor.default_queue.chain);
device_desc.defaultQueue.label = descriptor.default_queue.label.data();
device_desc.deviceLostCallback = device_lost_real_callback;
device_desc.deviceLostUserdata = device_lost_userdata;
auto userdata = new device::request_callback(callback);
auto real_callback = [](WGPURequestDeviceStatus status, WGPUDevice device, char const * message, void * userdata)
{
std::unique_ptr<device::request_callback> callback{(device::request_callback *)userdata};
if (*callback) (*callback)((device::request_status)status, wgpu::device(device), message ? message : "");
};
wgpuAdapterRequestDevice((WGPUAdapter)get(), &device_desc, real_callback, userdata);
}
void adapter::reference(void * ptr)
{
wgpuAdapterReference((WGPUAdapter)ptr);
}
void adapter::release(void * ptr)
{
wgpuAdapterRelease((WGPUAdapter)ptr);
}
}

View file

@ -0,0 +1,33 @@
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/external/webgpu.h>
namespace psemek::wgpu::detail
{
void * fill_chain(std::vector<chained_struct> const & chain)
{
WGPUChainedStruct * first = nullptr;
WGPUChainedStruct * current = nullptr;
for (auto const & s : chain)
{
auto p = (WGPUChainedStruct *)s.ptr();
if (!first)
{
first = p;
current = p;
}
else
{
current->next = p;
current = p;
}
}
if (current)
current->next = nullptr;
return first;
}
}

View file

@ -0,0 +1,17 @@
#include <psemek/wgpu/device.hpp>
#include <psemek/wgpu/external/webgpu.h>
namespace psemek::wgpu
{
void device::reference(void * ptr)
{
wgpuDeviceReference((WGPUDevice)ptr);
}
void device::release(void * ptr)
{
wgpuDeviceRelease((WGPUDevice)ptr);
}
}

View file

@ -0,0 +1,57 @@
#include <psemek/wgpu/instance.hpp>
#include <psemek/wgpu/external/webgpu.h>
namespace psemek::wgpu
{
instance instance::create(descriptor const & desc)
{
WGPUInstanceDescriptor descriptor = {};
descriptor.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(desc.chain);
return instance(wgpuCreateInstance(&descriptor));
}
void instance::process_events()
{
wgpuInstanceProcessEvents((WGPUInstance)get());
}
surface instance::create_surface(surface::descriptor const & desc) const
{
WGPUSurfaceDescriptor descriptor = {};
descriptor.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(desc.chain);
descriptor.label = desc.label.data();
return surface{wgpuInstanceCreateSurface((WGPUInstance)get(), &descriptor)};
}
void instance::request_adapter(adapter::request_options const & request_options, adapter::request_callback callback)
{
WGPURequestAdapterOptions options;
options.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(request_options.chain);
options.compatibleSurface = (WGPUSurface)request_options.compatible_surface.get();
options.powerPreference = (WGPUPowerPreference)request_options.power_preference;
options.backendType = (WGPUBackendType)request_options.backend_type;
options.forceFallbackAdapter = request_options.force_fallback_adapter;
auto userdata = new adapter::request_callback(callback);
auto real_callback = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, char const * message, void * userdata)
{
std::unique_ptr<adapter::request_callback> callback{(adapter::request_callback *)userdata};
if (*callback) (*callback)(adapter::request_status{status}, wgpu::adapter(adapter), message ? message : "");
};
wgpuInstanceRequestAdapter((WGPUInstance)get(), &options, real_callback, userdata);
}
void instance::reference(void * ptr)
{
wgpuInstanceReference((WGPUInstance)ptr);
}
void instance::release(void * ptr)
{
wgpuInstanceRelease((WGPUInstance)ptr);
}
}

View file

@ -0,0 +1,17 @@
#include <psemek/wgpu/queue.hpp>
#include <psemek/wgpu/external/webgpu.h>
namespace psemek::wgpu
{
void queue::reference(void * ptr)
{
wgpuQueueReference((WGPUQueue)ptr);
}
void queue::release(void * ptr)
{
wgpuQueueRelease((WGPUQueue)ptr);
}
}

View file

@ -0,0 +1,135 @@
#include <psemek/wgpu/surface.hpp>
#include <psemek/wgpu/adapter.hpp>
#include <psemek/wgpu/external/webgpu.h>
namespace psemek::wgpu
{
void surface::configure(configuration const & conf)
{
WGPUSurfaceConfiguration config = {};
config.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(conf.chain);
config.device = (WGPUDevice)conf.device.get();
config.format = (WGPUTextureFormat)conf.format;
config.usage = (WGPUTextureUsageFlags)conf.usage;
config.viewFormatCount = conf.view_formats.size();
config.viewFormats = (WGPUTextureFormat const *)conf.view_formats.data();
config.alphaMode = (WGPUCompositeAlphaMode)conf.alpha_mode;
config.width = conf.width;
config.height = conf.height;
config.presentMode = (WGPUPresentMode)conf.present_mode;
wgpuSurfaceConfigure((WGPUSurface)get(), &config);
}
surface::capabilities surface::get_capabilities(adapter const & adapter)
{
WGPUSurfaceCapabilities caps = {};
wgpuSurfaceGetCapabilities((WGPUSurface)get(), (WGPUAdapter)adapter.get(), &caps);
capabilities result;
// TODO: support out chain
result.formats.assign((wgpu::texture::format *)(caps.formats), (wgpu::texture::format *)(caps.formats) + caps.formatCount);
result.present_modes.assign((present_mode *)(caps.presentModes), (present_mode *)(caps.presentModes) + caps.presentModeCount);
result.alpha_modes.assign((composite_alpha_mode *)(caps.alphaModes), (composite_alpha_mode *)(caps.alphaModes) + caps.alphaModeCount);
return result;
}
surface::current_texture surface::get_current_texture()
{
WGPUSurfaceTexture tex;
wgpuSurfaceGetCurrentTexture((WGPUSurface)get(), &tex);
return {
.texture = wgpu::texture(tex.texture),
.suboptimal = tex.suboptimal,
.status = (enum current_texture::status)tex.status,
};
}
wgpu::texture::format surface::get_preferred_format(adapter const & adapter)
{
return (wgpu::texture::format)wgpuSurfaceGetPreferredFormat((WGPUSurface)get(), (WGPUAdapter)adapter.get());
}
void surface::present()
{
wgpuSurfacePresent((WGPUSurface)get());
}
void surface::unconfigure()
{
wgpuSurfaceUnconfigure((WGPUSurface)get());
}
void surface::reference(void * ptr)
{
wgpuSurfaceReference((WGPUSurface)ptr);
}
void surface::release(void * ptr)
{
wgpuSurfaceRelease((WGPUSurface)ptr);
}
detail::chained_struct_ptr to_chained_struct(surface::from_android_native_window const & value)
{
WGPUSurfaceDescriptorFromAndroidNativeWindow chained = {};
chained.chain.sType = WGPUSType_SurfaceDescriptorFromAndroidNativeWindow;
chained.window = value.window;
return detail::make_chained_struct(chained);
}
detail::chained_struct_ptr to_chained_struct(surface::from_canvas_html_selected const & value)
{
WGPUSurfaceDescriptorFromCanvasHTMLSelector chained = {};
chained.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
chained.selector = value.selector.data();
return detail::make_chained_struct(chained);
}
detail::chained_struct_ptr to_chained_struct(surface::from_metal_layer const & value)
{
WGPUSurfaceDescriptorFromMetalLayer chained = {};
chained.chain.sType = WGPUSType_SurfaceDescriptorFromMetalLayer;
chained.layer = value.layer;
return detail::make_chained_struct(chained);
}
detail::chained_struct_ptr to_chained_struct(surface::from_wayland_surface const & value)
{
WGPUSurfaceDescriptorFromWaylandSurface chained = {};
chained.chain.sType = WGPUSType_SurfaceDescriptorFromWaylandSurface;
chained.display = value.display;
chained.surface = value.surface;
return detail::make_chained_struct(chained);
}
detail::chained_struct_ptr to_chained_struct(surface::from_windows_hwnd const & value)
{
WGPUSurfaceDescriptorFromWindowsHWND chained = {};
chained.chain.sType = WGPUSType_SurfaceDescriptorFromWindowsHWND;
chained.hinstance = value.hinstance;
chained.hwnd = value.hwnd;
return detail::make_chained_struct(chained);
}
detail::chained_struct_ptr to_chained_struct(surface::from_xcb_window const & value)
{
WGPUSurfaceDescriptorFromXcbWindow chained = {};
chained.chain.sType = WGPUSType_SurfaceDescriptorFromXcbWindow;
chained.connection = value.connection;
chained.window = value.window;
return detail::make_chained_struct(chained);
}
detail::chained_struct_ptr to_chained_struct(surface::from_xlib_window const & value)
{
WGPUSurfaceDescriptorFromXlibWindow chained = {};
chained.chain.sType = WGPUSType_SurfaceDescriptorFromXlibWindow;
chained.display = value.display;
chained.window = value.window;
return detail::make_chained_struct(chained);
}
}

View file

@ -0,0 +1,17 @@
#include <psemek/wgpu/texture.hpp>
#include <psemek/wgpu/external/webgpu.h>
namespace psemek::wgpu
{
void texture::reference(void * ptr)
{
wgpuTextureReference((WGPUTexture)ptr);
}
void texture::release(void * ptr)
{
wgpuTextureRelease((WGPUTexture)ptr);
}
}