Add initial WebGPU GFX functions
This doesn't work yet of course :-)
This commit is contained in:
parent
f96d6da92a
commit
bff540956b
13 changed files with 526 additions and 27 deletions
|
@ -68,7 +68,7 @@ endif()
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
|
||||||
message("Web build detected!")
|
message("Web build detected!")
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -O0")
|
||||||
|
|
||||||
set(ENABLE_WEB TRUE)
|
set(ENABLE_WEB TRUE)
|
||||||
set(ENABLE_WEBGPU TRUE)
|
set(ENABLE_WEBGPU TRUE)
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
add_library(GFXWebGPU STATIC src/gfx_webgpu.cpp)
|
set(HEADERS
|
||||||
target_include_directories(GFXWebGPU PUBLIC include)
|
include/gfx_webgpu.hpp
|
||||||
|
src/gfx_webgpu_buffer.hpp
|
||||||
|
src/gfx_webgpu_pipeline.hpp
|
||||||
|
src/gfx_webgpu_texture.hpp
|
||||||
|
src/gfx_webgpu_framebuffer.hpp
|
||||||
|
src/gfx_webgpu_renderpass.hpp
|
||||||
|
src/gfx_webgpu_commandbuffer.hpp)
|
||||||
|
|
||||||
|
add_library(GFXWebGPU STATIC
|
||||||
|
src/gfx_webgpu.cpp
|
||||||
|
${HEADERS})
|
||||||
|
target_include_directories(GFXWebGPU PUBLIC include PRIVATE src)
|
||||||
target_link_libraries(GFXWebGPU PUBLIC GFX)
|
target_link_libraries(GFXWebGPU PUBLIC GFX)
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <emscripten/html5_webgpu.h>
|
||||||
|
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
|
|
||||||
class GFXWebGPU : public GFX {
|
class GFXWebGPU : public GFX {
|
||||||
|
@ -7,4 +9,42 @@ public:
|
||||||
bool initialize(const GFXCreateInfo& createInfo) override;
|
bool initialize(const GFXCreateInfo& createInfo) override;
|
||||||
|
|
||||||
const char* get_name() override;
|
const char* get_name() override;
|
||||||
|
|
||||||
|
// buffer
|
||||||
|
GFXBuffer* create_buffer(void* data, GFXSize size, bool is_dynamic, GFXBufferUsage usage) override;
|
||||||
|
void copy_buffer(GFXBuffer* buffer, void* data, GFXSize offset, GFXSize size) override;
|
||||||
|
|
||||||
|
void* get_buffer_contents(GFXBuffer* buffer) override;
|
||||||
|
void release_buffer_contents(GFXBuffer* buffer, void* handle) override;
|
||||||
|
|
||||||
|
// texture
|
||||||
|
GFXTexture* create_texture(const GFXTextureCreateInfo& info) override;
|
||||||
|
void copy_texture(GFXTexture* texture, void* data, GFXSize size) override;
|
||||||
|
void copy_texture(GFXTexture* from, GFXTexture* to) override;
|
||||||
|
void copy_texture(GFXTexture* from, GFXBuffer* to) override;
|
||||||
|
|
||||||
|
// sampler
|
||||||
|
GFXSampler* create_sampler(const GFXSamplerCreateInfo& info) override;
|
||||||
|
|
||||||
|
// framebuffer
|
||||||
|
GFXFramebuffer* create_framebuffer(const GFXFramebufferCreateInfo& info) override;
|
||||||
|
|
||||||
|
// render pass
|
||||||
|
GFXRenderPass* create_render_pass(const GFXRenderPassCreateInfo& info) override;
|
||||||
|
|
||||||
|
// pipeline
|
||||||
|
GFXPipeline* create_graphics_pipeline(const GFXGraphicsPipelineCreateInfo& info) override;
|
||||||
|
GFXPipeline* create_compute_pipeline(const GFXComputePipelineCreateInfo& info) override;
|
||||||
|
|
||||||
|
GFXCommandBuffer* acquire_command_buffer(bool for_presentation_use) override;
|
||||||
|
|
||||||
|
void submit(GFXCommandBuffer* command_buffer, platform::window_ptr window) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
WGPUSwapChain create_swapchain();
|
||||||
|
WGPUShaderModule create_shader(const uint32_t* code, uint32_t size, std::string_view label);
|
||||||
|
|
||||||
|
WGPUDevice device;
|
||||||
|
WGPUQueue queue;
|
||||||
|
WGPUSwapChain swapchain;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,176 @@
|
||||||
#include "gfx_webgpu.hpp"
|
#include "gfx_webgpu.hpp"
|
||||||
|
|
||||||
#include <emscripten/html5_webgpu.h>
|
#include "gfx_commandbuffer.hpp"
|
||||||
|
#include "gfx_webgpu_buffer.hpp"
|
||||||
|
#include "gfx_webgpu_commandbuffer.hpp"
|
||||||
|
#include "gfx_webgpu_framebuffer.hpp"
|
||||||
|
#include "gfx_webgpu_pipeline.hpp"
|
||||||
|
#include "gfx_webgpu_renderpass.hpp"
|
||||||
|
#include "gfx_webgpu_sampler.hpp"
|
||||||
|
#include "gfx_webgpu_texture.hpp"
|
||||||
|
|
||||||
|
WGPUTextureFormat toPixFormat(GFXPixelFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case GFXPixelFormat::R_32F:
|
||||||
|
return WGPUTextureFormat_R32Float;
|
||||||
|
|
||||||
|
case GFXPixelFormat::R_16F:
|
||||||
|
return WGPUTextureFormat_R16Float;
|
||||||
|
|
||||||
|
case GFXPixelFormat::RGBA_32F:
|
||||||
|
return WGPUTextureFormat_RGBA32Float;
|
||||||
|
|
||||||
|
case GFXPixelFormat::RGBA8_UNORM:
|
||||||
|
return WGPUTextureFormat_RGBA8Unorm;
|
||||||
|
|
||||||
|
case GFXPixelFormat::R8_UNORM:
|
||||||
|
return WGPUTextureFormat_R8Unorm;
|
||||||
|
|
||||||
|
case GFXPixelFormat::R8G8_UNORM:
|
||||||
|
return WGPUTextureFormat_RG8Unorm;
|
||||||
|
|
||||||
|
case GFXPixelFormat::R8G8_SFLOAT:
|
||||||
|
return WGPUTextureFormat_RG16Float;
|
||||||
|
|
||||||
|
case GFXPixelFormat::R8G8B8A8_UNORM:
|
||||||
|
return WGPUTextureFormat_RGBA8Unorm;
|
||||||
|
|
||||||
|
case GFXPixelFormat::R16G16B16A16_SFLOAT:
|
||||||
|
return WGPUTextureFormat_RGBA16Float;
|
||||||
|
|
||||||
|
case GFXPixelFormat::DEPTH_32F:
|
||||||
|
return WGPUTextureFormat_Depth32Float;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WGPUTextureFormat_Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUVertexFormat toVertFormat(GFXVertexFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case GFXVertexFormat::FLOAT2:
|
||||||
|
return WGPUVertexFormat_Float32x2;
|
||||||
|
case GFXVertexFormat::FLOAT3:
|
||||||
|
return WGPUVertexFormat_Float32x3;
|
||||||
|
case GFXVertexFormat::FLOAT4:
|
||||||
|
return WGPUVertexFormat_Float32x4;
|
||||||
|
case GFXVertexFormat::INT:
|
||||||
|
return WGPUVertexFormat_Sint32;
|
||||||
|
case GFXVertexFormat::INT4:
|
||||||
|
return WGPUVertexFormat_Sint32x4;
|
||||||
|
case GFXVertexFormat::UNORM4:
|
||||||
|
return WGPUVertexFormat_Unorm8x4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WGPUVertexFormat_Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUBlendFactor toFactor(GFXBlendFactor factor) {
|
||||||
|
switch (factor) {
|
||||||
|
case GFXBlendFactor::Zero:
|
||||||
|
return WGPUBlendFactor_Zero;
|
||||||
|
case GFXBlendFactor::One:
|
||||||
|
return WGPUBlendFactor_One;
|
||||||
|
case GFXBlendFactor::OneMinusSrcAlpha:
|
||||||
|
return WGPUBlendFactor_OneMinusSrcAlpha;
|
||||||
|
case GFXBlendFactor::OneMinusSrcColor:
|
||||||
|
return WGPUBlendFactor_OneMinusSrc;
|
||||||
|
case GFXBlendFactor::SrcAlpha:
|
||||||
|
return WGPUBlendFactor_SrcAlpha;
|
||||||
|
case GFXBlendFactor::DstAlpha:
|
||||||
|
return WGPUBlendFactor_DstAlpha;
|
||||||
|
case GFXBlendFactor::SrcColor:
|
||||||
|
return WGPUBlendFactor_Src;
|
||||||
|
case GFXBlendFactor::DstColor:
|
||||||
|
return WGPUBlendFactor_Dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WGPUBlendFactor_One;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUAddressMode toSamplerMode(SamplingMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case SamplingMode::Repeat:
|
||||||
|
return WGPUAddressMode_Repeat;
|
||||||
|
case SamplingMode::ClampToEdge:
|
||||||
|
return WGPUAddressMode_ClampToEdge;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WGPUAddressMode_Repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUFilterMode toFilter(GFXFilter filter) {
|
||||||
|
switch (filter) {
|
||||||
|
case GFXFilter::Nearest:
|
||||||
|
return WGPUFilterMode_Nearest;
|
||||||
|
case GFXFilter::Linear:
|
||||||
|
return WGPUFilterMode_Linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WGPUFilterMode_Linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUCompareFunction toCompareFunc(GFXCompareFunction func) {
|
||||||
|
switch (func) {
|
||||||
|
case GFXCompareFunction::Never:
|
||||||
|
return WGPUCompareFunction_Never;
|
||||||
|
case GFXCompareFunction::Less:
|
||||||
|
return WGPUCompareFunction_Less;
|
||||||
|
case GFXCompareFunction::Equal:
|
||||||
|
return WGPUCompareFunction_Equal;
|
||||||
|
case GFXCompareFunction::LessOrEqual:
|
||||||
|
return WGPUCompareFunction_LessEqual;
|
||||||
|
case GFXCompareFunction::Greater:
|
||||||
|
return WGPUCompareFunction_Greater;
|
||||||
|
case GFXCompareFunction::NotEqual:
|
||||||
|
return WGPUCompareFunction_NotEqual;
|
||||||
|
case GFXCompareFunction::GreaterOrEqual:
|
||||||
|
return WGPUCompareFunction_GreaterEqual;
|
||||||
|
case GFXCompareFunction::Always:
|
||||||
|
return WGPUCompareFunction_Always;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUShaderModule GFXWebGPU::create_shader(const uint32_t* code, const uint32_t size, std::string_view label) {
|
||||||
|
WGPUShaderModuleSPIRVDescriptor spirv = {};
|
||||||
|
spirv.chain.sType = WGPUSType_ShaderModuleSPIRVDescriptor;
|
||||||
|
spirv.codeSize = size / sizeof(uint32_t);
|
||||||
|
spirv.code = code;
|
||||||
|
|
||||||
|
WGPUShaderModuleDescriptor desc = {};
|
||||||
|
desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&spirv);
|
||||||
|
desc.label = label.data();
|
||||||
|
|
||||||
|
return wgpuDeviceCreateShaderModule(device, &desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUSwapChain GFXWebGPU::create_swapchain() {
|
||||||
|
WGPUSurfaceDescriptorFromCanvasHTMLSelector canvDesc = {};
|
||||||
|
canvDesc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
|
||||||
|
canvDesc.selector = "canvas";
|
||||||
|
|
||||||
|
WGPUSurfaceDescriptor surfDesc = {};
|
||||||
|
surfDesc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&canvDesc);
|
||||||
|
|
||||||
|
WGPUSurface surface = wgpuInstanceCreateSurface(nullptr, &surfDesc);
|
||||||
|
|
||||||
|
WGPUSwapChainDescriptor swapDesc = {};
|
||||||
|
swapDesc.usage = WGPUTextureUsage_RenderAttachment;
|
||||||
|
swapDesc.format = WGPUTextureFormat_BGRA8Unorm;
|
||||||
|
swapDesc.width = 800; // TODO: configurable
|
||||||
|
swapDesc.height = 450;
|
||||||
|
swapDesc.presentMode = WGPUPresentMode_Fifo;
|
||||||
|
|
||||||
|
return wgpuDeviceCreateSwapChain(device, surface, &swapDesc);
|
||||||
|
}
|
||||||
|
|
||||||
bool GFXWebGPU::initialize(const GFXCreateInfo& createInfo) {
|
bool GFXWebGPU::initialize(const GFXCreateInfo& createInfo) {
|
||||||
auto device = emscripten_webgpu_get_device();
|
device = emscripten_webgpu_get_device();
|
||||||
|
if(device == nullptr) {
|
||||||
|
prism::log("Failed to get WebGPU device!");
|
||||||
|
}
|
||||||
|
|
||||||
|
queue = wgpuDeviceGetQueue(device);
|
||||||
|
swapchain = create_swapchain();
|
||||||
|
|
||||||
prism::log("Initialized WebGPU!");
|
prism::log("Initialized WebGPU!");
|
||||||
|
|
||||||
|
@ -13,3 +180,231 @@ bool GFXWebGPU::initialize(const GFXCreateInfo& createInfo) {
|
||||||
const char* GFXWebGPU::get_name() {
|
const char* GFXWebGPU::get_name() {
|
||||||
return "WebGPU";
|
return "WebGPU";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GFXCommandBuffer* GFXWebGPU::acquire_command_buffer(bool for_presentation_use) {
|
||||||
|
return new GFXCommandBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
GFXBuffer* GFXWebGPU::create_buffer(void* data, const GFXSize size, const bool is_dynamic, const GFXBufferUsage usage) {
|
||||||
|
auto buffer = new GFXWebGPUBuffer();
|
||||||
|
|
||||||
|
buffer->size = size;
|
||||||
|
|
||||||
|
WGPUBufferDescriptor desc = {};
|
||||||
|
desc.usage = WGPUBufferUsage_CopyDst;
|
||||||
|
desc.size = size;
|
||||||
|
desc.mappedAtCreation = true;
|
||||||
|
|
||||||
|
buffer->handle = wgpuDeviceCreateBuffer(device, &desc);
|
||||||
|
|
||||||
|
wgpuQueueWriteBuffer(queue, buffer->handle, 0, data, size);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXWebGPU::copy_buffer(GFXBuffer* buffer, void* data, const GFXSize offset, const GFXSize size) {
|
||||||
|
auto wgpu_buffer = (GFXWebGPUBuffer*)buffer;
|
||||||
|
|
||||||
|
wgpuQueueWriteBuffer(queue, wgpu_buffer->handle, offset, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GFXWebGPU::get_buffer_contents(GFXBuffer* buffer) {
|
||||||
|
auto wgpu_buffer = (GFXWebGPUBuffer*)buffer;
|
||||||
|
|
||||||
|
return wgpuBufferGetMappedRange(wgpu_buffer->handle, 0, wgpu_buffer->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXWebGPU::release_buffer_contents(GFXBuffer* buffer, void* handle) {
|
||||||
|
auto wgpu_buffer = (GFXWebGPUBuffer*)buffer;
|
||||||
|
|
||||||
|
wgpuBufferUnmap(wgpu_buffer->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
GFXTexture* GFXWebGPU::create_texture(const GFXTextureCreateInfo& info) {
|
||||||
|
auto texture = new GFXWebGPUTexture();
|
||||||
|
|
||||||
|
WGPUTextureDescriptor descriptor = {};
|
||||||
|
descriptor.size.width = info.width;
|
||||||
|
descriptor.size.height = info.height;
|
||||||
|
descriptor.size.depthOrArrayLayers = info.array_length;
|
||||||
|
|
||||||
|
descriptor.dimension = WGPUTextureDimension_2D;
|
||||||
|
|
||||||
|
descriptor.format = WGPUTextureFormat_BGRA8Unorm;
|
||||||
|
|
||||||
|
descriptor.label = info.label.c_str();
|
||||||
|
|
||||||
|
descriptor.mipLevelCount = info.mip_count;
|
||||||
|
|
||||||
|
descriptor.usage = WGPUTextureUsage_None;
|
||||||
|
|
||||||
|
texture->handle = wgpuDeviceCreateTexture(device, &descriptor);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXWebGPU::copy_texture(GFXTexture* texture, void* data, GFXSize size) {
|
||||||
|
GFX::copy_texture(texture, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXWebGPU::copy_texture(GFXTexture* from, GFXTexture* to) {
|
||||||
|
GFX::copy_texture(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXWebGPU::copy_texture(GFXTexture* from, GFXBuffer* to) {
|
||||||
|
GFX::copy_texture(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
GFXSampler* GFXWebGPU::create_sampler(const GFXSamplerCreateInfo& info) {
|
||||||
|
auto sampler = new GFXWebGPUSampler();
|
||||||
|
|
||||||
|
return sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
GFXFramebuffer* GFXWebGPU::create_framebuffer(const GFXFramebufferCreateInfo& info) {
|
||||||
|
auto framebuffer = new GFXWebGPUFramebuffer();
|
||||||
|
|
||||||
|
return framebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
GFXRenderPass* GFXWebGPU::create_render_pass(const GFXRenderPassCreateInfo& info) {
|
||||||
|
auto render_pass = new GFXWebGPURenderPass();
|
||||||
|
|
||||||
|
return render_pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
GFXPipeline* GFXWebGPU::create_graphics_pipeline(const GFXGraphicsPipelineCreateInfo& info) {
|
||||||
|
auto pipeline = new GFXWebGPUPipeline();
|
||||||
|
|
||||||
|
WGPURenderPipelineDescriptor descriptor = {};
|
||||||
|
descriptor.label = info.label.c_str();
|
||||||
|
|
||||||
|
const bool has_vertex_stage = !info.shaders.vertex_src.empty();
|
||||||
|
if (has_vertex_stage) {
|
||||||
|
const bool vertex_use_shader_source = !info.shaders.vertex_src.is_path();
|
||||||
|
|
||||||
|
if (vertex_use_shader_source) {
|
||||||
|
auto vertex_shader_vector = info.shaders.vertex_src.as_bytecode();
|
||||||
|
|
||||||
|
descriptor.vertex.module = create_shader(vertex_shader_vector.data(), vertex_shader_vector.size() * sizeof(uint32_t), std::string(info.label + " vertex stage").c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto vertex_shader = prism::open_file(prism::internal_domain / (info.shaders.vertex_src.as_path().string()), true);
|
||||||
|
vertex_shader->read_all();
|
||||||
|
|
||||||
|
descriptor.vertex.module = create_shader(vertex_shader->cast_data<uint32_t>(), vertex_shader->size(), info.shaders.vertex_src.as_path().string().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUFragmentState fragment = {};
|
||||||
|
|
||||||
|
const bool has_fragment_stage = !info.shaders.fragment_src.empty();
|
||||||
|
if (has_fragment_stage) {
|
||||||
|
descriptor.fragment = &fragment;
|
||||||
|
|
||||||
|
const bool fragment_use_shader_source = !info.shaders.fragment_src.is_path();
|
||||||
|
|
||||||
|
if (fragment_use_shader_source) {
|
||||||
|
auto fragment_shader_vector = info.shaders.fragment_src.as_bytecode();
|
||||||
|
|
||||||
|
fragment.module = create_shader(fragment_shader_vector.data(), fragment_shader_vector.size() * sizeof(uint32_t), std::string(info.label + " fragment stage").c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto fragment_shader = prism::open_file(prism::internal_domain / (info.shaders.fragment_src.as_path().string()), true);
|
||||||
|
fragment_shader->read_all();
|
||||||
|
|
||||||
|
fragment.module = create_shader(fragment_shader->cast_data<uint32_t>(), fragment_shader->size(), info.shaders.fragment_src.as_path().string().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::vector<WGPUVertexAttribute>> attributes;
|
||||||
|
attributes.resize(info.vertex_input.inputs.size());
|
||||||
|
|
||||||
|
for (auto& attribute : info.vertex_input.attributes) {
|
||||||
|
WGPUVertexAttribute description;
|
||||||
|
description.shaderLocation = attribute.location;
|
||||||
|
description.format = toVertFormat(attribute.format);
|
||||||
|
description.offset = attribute.offset;
|
||||||
|
|
||||||
|
attributes[attribute.binding].push_back(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<WGPUVertexBufferLayout> inputs;
|
||||||
|
for (auto& binding : info.vertex_input.inputs) {
|
||||||
|
WGPUVertexBufferLayout b;
|
||||||
|
b.attributes = attributes[binding.location].data();
|
||||||
|
b.attributeCount = attributes.size();
|
||||||
|
b.arrayStride = binding.stride;
|
||||||
|
b.stepMode = WGPUVertexStepMode_Vertex;
|
||||||
|
|
||||||
|
inputs.push_back(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor.vertex.buffers = inputs.data();
|
||||||
|
descriptor.vertex.bufferCount = inputs.size();
|
||||||
|
|
||||||
|
switch (info.rasterization.culling_mode) {
|
||||||
|
case GFXCullingMode::Backface:
|
||||||
|
descriptor.primitive.cullMode = WGPUCullMode_Back;
|
||||||
|
break;
|
||||||
|
case GFXCullingMode::Frontface:
|
||||||
|
descriptor.primitive.cullMode = WGPUCullMode_Front;
|
||||||
|
break;
|
||||||
|
case GFXCullingMode::None:
|
||||||
|
descriptor.primitive.cullMode = WGPUCullMode_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (info.rasterization.winding_mode) {
|
||||||
|
case GFXWindingMode::Clockwise:
|
||||||
|
descriptor.primitive.frontFace = WGPUFrontFace_CW;
|
||||||
|
break;
|
||||||
|
case GFXWindingMode::CounterClockwise:
|
||||||
|
descriptor.primitive.frontFace = WGPUFrontFace_CCW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor.primitive.stripIndexFormat = WGPUIndexFormat_Uint16;
|
||||||
|
descriptor.primitive.topology = WGPUPrimitiveTopology_TriangleList;
|
||||||
|
|
||||||
|
pipeline->render_handle = wgpuDeviceCreateRenderPipeline(device, &descriptor);
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
GFXPipeline* GFXWebGPU::create_compute_pipeline(const GFXComputePipelineCreateInfo& info) {
|
||||||
|
auto pipeline = new GFXWebGPUPipeline();
|
||||||
|
|
||||||
|
WGPUComputePipelineDescriptor descriptor = {};
|
||||||
|
descriptor.label = info.label.c_str();
|
||||||
|
|
||||||
|
{
|
||||||
|
const bool use_shader_source = !info.compute_src.is_path();
|
||||||
|
|
||||||
|
if (use_shader_source) {
|
||||||
|
auto compute_shader_vector = info.compute_src.as_bytecode();
|
||||||
|
|
||||||
|
descriptor.compute.module = create_shader(compute_shader_vector.data(), compute_shader_vector.size() * sizeof(uint32_t), info.label.c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto compute_shader = prism::open_file(prism::internal_domain / (info.compute_src.as_path().string()), true);
|
||||||
|
compute_shader->read_all();
|
||||||
|
|
||||||
|
descriptor.compute.module = create_shader(compute_shader->cast_data<uint32_t>(), compute_shader->size(), info.compute_src.as_path().string().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pipeline->compute_handle = wgpuDeviceCreateComputePipeline(device, &descriptor);
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXWebGPU::submit(GFXCommandBuffer* command_buffer, const platform::window_ptr window) {
|
||||||
|
WGPUTextureView backBufView = wgpuSwapChainGetCurrentTextureView(swapchain); // create textureView
|
||||||
|
|
||||||
|
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
|
WGPUCommandBuffer commands = wgpuCommandEncoderFinish(encoder, nullptr);
|
||||||
|
|
||||||
|
wgpuQueueSubmit(queue, 1, &commands);
|
||||||
|
wgpuCommandBufferRelease(commands);
|
||||||
|
wgpuTextureViewRelease(backBufView);
|
||||||
|
}
|
9
engine/gfx/webgpu/src/gfx_webgpu_buffer.hpp
Normal file
9
engine/gfx/webgpu/src/gfx_webgpu_buffer.hpp
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gfx_buffer.hpp"
|
||||||
|
|
||||||
|
class GFXWebGPUBuffer : public GFXBuffer {
|
||||||
|
public:
|
||||||
|
WGPUBuffer handle = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
};
|
8
engine/gfx/webgpu/src/gfx_webgpu_commandbuffer.hpp
Normal file
8
engine/gfx/webgpu/src/gfx_webgpu_commandbuffer.hpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gfx_commandbuffer.hpp"
|
||||||
|
|
||||||
|
class GFXWebGPUCommandBuffer : public GFXCommandBuffer {
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
8
engine/gfx/webgpu/src/gfx_webgpu_framebuffer.hpp
Normal file
8
engine/gfx/webgpu/src/gfx_webgpu_framebuffer.hpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gfx_framebuffer.hpp"
|
||||||
|
|
||||||
|
class GFXWebGPUFramebuffer : public GFXFramebuffer {
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
11
engine/gfx/webgpu/src/gfx_webgpu_pipeline.hpp
Normal file
11
engine/gfx/webgpu/src/gfx_webgpu_pipeline.hpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gfx_pipeline.hpp"
|
||||||
|
|
||||||
|
class GFXWebGPUPipeline : public GFXPipeline {
|
||||||
|
public:
|
||||||
|
WGPURenderPipeline render_handle = nullptr;
|
||||||
|
WGPUComputePipeline compute_handle = nullptr;
|
||||||
|
|
||||||
|
WGPUBindGroup bind_group = nullptr;
|
||||||
|
};
|
8
engine/gfx/webgpu/src/gfx_webgpu_renderpass.hpp
Normal file
8
engine/gfx/webgpu/src/gfx_webgpu_renderpass.hpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gfx_renderpass.hpp"
|
||||||
|
|
||||||
|
class GFXWebGPURenderPass : public GFXRenderPass {
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
8
engine/gfx/webgpu/src/gfx_webgpu_sampler.hpp
Normal file
8
engine/gfx/webgpu/src/gfx_webgpu_sampler.hpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gfx_sampler.hpp"
|
||||||
|
|
||||||
|
class GFXWebGPUSampler : public GFXSampler {
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
8
engine/gfx/webgpu/src/gfx_webgpu_texture.hpp
Normal file
8
engine/gfx/webgpu/src/gfx_webgpu_texture.hpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gfx_texture.hpp"
|
||||||
|
|
||||||
|
class GFXWebGPUTexture : public GFXTexture {
|
||||||
|
public:
|
||||||
|
WGPUTexture handle = nullptr;
|
||||||
|
};
|
|
@ -1,9 +1,9 @@
|
||||||
include(../../cmake/AddPlatformExecutable.cmake)
|
include(../../cmake/AddPlatformExecutable.cmake)
|
||||||
|
|
||||||
add_platform(
|
add_platform(
|
||||||
SRC ${CMAKE_CURRENT_SOURCE_DIR}/glue.cpp
|
|
||||||
MAIN_FILE
|
MAIN_FILE
|
||||||
main.cpp.in
|
main.cpp.in
|
||||||
|
SRC ${CMAKE_CURRENT_SOURCE_DIR}/glue.cpp
|
||||||
LINK_LIBRARIES
|
LINK_LIBRARIES
|
||||||
Core
|
Core
|
||||||
GFXWebGPU
|
GFXWebGPU
|
||||||
|
@ -19,25 +19,17 @@ function(add_platform_commands target)
|
||||||
target_link_options(${target}
|
target_link_options(${target}
|
||||||
PRIVATE "SHELL:-s USE_WEBGPU=1"
|
PRIVATE "SHELL:-s USE_WEBGPU=1"
|
||||||
PRIVATE "SHELL:-s NO_DISABLE_EXCEPTION_CATCHING"
|
PRIVATE "SHELL:-s NO_DISABLE_EXCEPTION_CATCHING"
|
||||||
PRIVATE "SHELL:-s ASSERTIONS=1"
|
PRIVATE "SHELL:-gsource-map"
|
||||||
|
PRIVATE "SHELL:-s ASSERTIONS=2"
|
||||||
PRIVATE "SHELL:-s SAFE_HEAP=1"
|
PRIVATE "SHELL:-s SAFE_HEAP=1"
|
||||||
|
PRIVATE "SHELL:-s ALLOW_MEMORY_GROWTH=1"
|
||||||
|
PRIVATE "SHELL:-s NO_EXIT_RUNTIME=1"
|
||||||
|
PRIVATE "SHELL:-s WASM=1"
|
||||||
|
PRIVATE "SHELL:-s NO_EXIT_RUNTIME=1"
|
||||||
|
PRIVATE "SHELL:-s STRICT=1"
|
||||||
|
PRIVATE "SHELL:-s DEMANGLE_SUPPORT=1"
|
||||||
|
PRIVATE "SHELL:--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../data@data"
|
||||||
|
PRIVATE "SHELL:--preload-file ${CMAKE_BINARY_DIR}/shaders@shaders"
|
||||||
|
PRIVATE "SHELL:--shell-file ${PROJECT_SOURCE_DIR}/platforms/web/shell.html"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DUMMY_NAME ${target}-CopyShaders)
|
|
||||||
|
|
||||||
add_custom_target(${DUMMY_NAME} ALL DEPENDS ${CMAKE_BINARY_DIR}/${target}-dummy)
|
|
||||||
|
|
||||||
if(ENABLE_MACOS)
|
|
||||||
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${target}-dummy
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${target}>/../Resources/shaders
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/shaders $<TARGET_FILE_DIR:${target}>/../Resources/shaders
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${target}-dummy
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${target}>/shaders
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/shaders $<TARGET_FILE_DIR:${target}>/shaders
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_dependencies(${target} ${DUMMY_NAME})
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
#include "gfx_webgpu.hpp"
|
#include "gfx_webgpu.hpp"
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
|
#include "string_utils.hpp"
|
||||||
|
|
||||||
@APP_CLASS@* app = nullptr;
|
@APP_CLASS@* app = nullptr;
|
||||||
GFX* gfx_interface = nullptr;
|
GFX* gfx_interface = nullptr;
|
||||||
|
@ -170,7 +171,7 @@ const char* platform::get_name() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void prism::set_domain_path(const prism::domain domain, const prism::path& path) {
|
void prism::set_domain_path(const prism::domain domain, const prism::path& path) {
|
||||||
|
domain_data[(int)domain] = replace_substring(path.string(), "{resource_dir}/", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
prism::path prism::get_writeable_directory() {
|
prism::path prism::get_writeable_directory() {
|
||||||
|
|
Reference in a new issue