Initial commit.
This commit is contained in:
commit
82b4f23c06
56 changed files with 3485 additions and 0 deletions
168
Client/Graphics/Graphics.cpp
Normal file
168
Client/Graphics/Graphics.cpp
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
#include "Graphics.h"
|
||||
#include "../Platform/Window.h"
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
namespace Artifact {
|
||||
|
||||
void Graphics::init() {
|
||||
instance = wgpuCreateInstance(nullptr);
|
||||
|
||||
window = client->subsystem<WindowImpl>();
|
||||
|
||||
surface = window->createWGPUSurface(instance);
|
||||
|
||||
WGPURequestAdapterOptions opts {
|
||||
.compatibleSurface = surface
|
||||
};
|
||||
wgpuInstanceRequestAdapter(instance, &opts, {
|
||||
.mode = WGPUCallbackMode_AllowProcessEvents,
|
||||
.callback = [](auto status, auto adapter, auto msg, auto userdata, auto) {
|
||||
if (status == WGPURequestAdapterStatus_Success) {
|
||||
static_cast<Graphics *>(userdata)->adapter = adapter;
|
||||
} else {
|
||||
throw std::runtime_error("Failed to get wgpu adapter.");
|
||||
}
|
||||
},
|
||||
.userdata1 = this
|
||||
});
|
||||
|
||||
// To avoid dealing with concurrency, we just block until the adapter is available (or the program errors).
|
||||
while (!adapter) wgpuInstanceProcessEvents(instance);
|
||||
|
||||
WGPUDeviceDescriptor desc {
|
||||
.uncapturedErrorCallbackInfo = {
|
||||
.callback = [](auto device, auto type, auto msg, auto, auto) {
|
||||
const char * message = (msg.data ? reinterpret_cast<const char *>(msg.data) : "No message");
|
||||
fprintf(stderr, "Uncaptured WebGPU Error (type %d): %s\n", type, message);
|
||||
}}
|
||||
};
|
||||
wgpuAdapterRequestDevice(adapter, &desc, {
|
||||
.mode = WGPUCallbackMode_AllowProcessEvents,
|
||||
.callback = [](auto status, auto device, auto msg, auto userdata, auto) {
|
||||
if (status == WGPURequestDeviceStatus_Success) {
|
||||
static_cast<Graphics *>(userdata)->device = device;
|
||||
} else {
|
||||
throw std::runtime_error("Failed to get wgpu device.");
|
||||
}
|
||||
},
|
||||
.userdata1 = this
|
||||
});
|
||||
|
||||
while (!device) wgpuInstanceProcessEvents(instance);
|
||||
|
||||
WGPUTextureDescriptor depthDesc = {};
|
||||
depthDesc.dimension = WGPUTextureDimension_2D;
|
||||
depthDesc.size.width = 1080;
|
||||
depthDesc.size.height = 640;
|
||||
depthDesc.size.depthOrArrayLayers = 1;
|
||||
depthDesc.format = WGPUTextureFormat_Depth32Float;
|
||||
depthDesc.usage = WGPUTextureUsage_RenderAttachment;
|
||||
depthDesc.mipLevelCount = 1;
|
||||
depthDesc.sampleCount = 1;
|
||||
depthTexture = wgpuDeviceCreateTexture(device, &depthDesc);
|
||||
depthTextureView = wgpuTextureCreateView(depthTexture, nullptr);
|
||||
|
||||
queue = wgpuDeviceGetQueue(device);
|
||||
|
||||
WGPUSurfaceConfiguration surfaceConfig = {};
|
||||
surfaceConfig.device = device;
|
||||
surfaceConfig.format = WGPUTextureFormat_BGRA8Unorm; // FIXME: Auto-detect
|
||||
surfaceConfig.usage = WGPUTextureUsage_RenderAttachment;
|
||||
surfaceConfig.width = 1080;
|
||||
surfaceConfig.height = 640;
|
||||
surfaceConfig.presentMode = WGPUPresentMode_Fifo;
|
||||
wgpuSurfaceConfigure(surface, &surfaceConfig);
|
||||
|
||||
for (auto & system : subsystems) {
|
||||
system->graphics = this;
|
||||
printf("Graphics: %p", system->graphics);
|
||||
system->init();
|
||||
system->reload();
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::deinit() {
|
||||
for (auto & system : subsystems) {
|
||||
system->deinit();
|
||||
}
|
||||
|
||||
wgpuTextureDestroy(depthTexture);
|
||||
wgpuQueueRelease(queue);
|
||||
wgpuDeviceDestroy(device);
|
||||
wgpuAdapterRelease(adapter);
|
||||
wgpuSurfaceRelease(surface);
|
||||
wgpuInstanceRelease(instance);
|
||||
}
|
||||
|
||||
void Graphics::render() {
|
||||
WGPUSurfaceTexture surfaceTexture;
|
||||
wgpuSurfaceGetCurrentTexture(surface, &surfaceTexture);
|
||||
if (surfaceTexture.status == WGPUSurfaceGetCurrentTextureStatus_Error || !surfaceTexture.texture) {
|
||||
throw std::runtime_error("Failed to get surface texture");
|
||||
}
|
||||
WGPUTextureView nextTexture = wgpuTextureCreateView(surfaceTexture.texture, nullptr);
|
||||
if (!nextTexture) {
|
||||
throw std::runtime_error("Failed to create texture view");
|
||||
}
|
||||
|
||||
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||
|
||||
for (auto & system : subsystems) {
|
||||
system->render(nextTexture, encoder);
|
||||
}
|
||||
|
||||
WGPUCommandBufferDescriptor cmdBufferDesc = {};
|
||||
cmdBufferDesc.label = WGPUStringView{"Command buffer", WGPU_STRLEN};
|
||||
WGPUCommandBuffer cmdBuffer = wgpuCommandEncoderFinish(encoder, nullptr);
|
||||
wgpuQueueSubmit(queue, 1, &cmdBuffer);
|
||||
#ifndef WASM_BUILD
|
||||
wgpuSurfacePresent(surface);
|
||||
#endif
|
||||
wgpuTextureViewRelease(nextTexture);
|
||||
wgpuTextureRelease(surfaceTexture.texture);
|
||||
}
|
||||
|
||||
WGPUTexture Graphics::createTextureFromData(const void* data, uint32_t width, uint32_t height) {
|
||||
WGPUTextureDescriptor textureDesc = {};
|
||||
textureDesc.dimension = WGPUTextureDimension_2D;
|
||||
textureDesc.size.width = width;
|
||||
textureDesc.size.height = height;
|
||||
textureDesc.size.depthOrArrayLayers = 1;
|
||||
textureDesc.format = WGPUTextureFormat_RGBA8Unorm;
|
||||
textureDesc.usage = WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst;
|
||||
textureDesc.mipLevelCount = 1;
|
||||
textureDesc.sampleCount = 1;
|
||||
auto texture = wgpuDeviceCreateTexture(device, &textureDesc);
|
||||
|
||||
// WGPUTextureViewDescriptor viewDesc = {};
|
||||
// viewDesc.format = WGPUTextureFormat_RGBA8Unorm;
|
||||
// viewDesc.dimension = WGPUTextureViewDimension_2D;
|
||||
// viewDesc.mipLevelCount = 1;
|
||||
// viewDesc.arrayLayerCount = 1;
|
||||
// tex->view = wgpuTextureCreateView(tex->texture, &viewDesc);
|
||||
|
||||
WGPUTexelCopyTextureInfo destination = {};
|
||||
destination.texture = texture;
|
||||
destination.mipLevel = 0;
|
||||
destination.origin = {0, 0, 0};
|
||||
destination.aspect = WGPUTextureAspect_All;
|
||||
WGPUTexelCopyBufferLayout layout = {};
|
||||
layout.offset = 0;
|
||||
layout.bytesPerRow = width * 4;
|
||||
layout.rowsPerImage = height;
|
||||
WGPUExtent3D writeSize = {width, height, 1};
|
||||
wgpuQueueWriteTexture(queue, &destination, data, width * height * 4, &layout, &writeSize);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
WGPUTexture Graphics::createTextureFromFile(const char* file) {
|
||||
int width, height, channels;
|
||||
auto data = stbi_load(file, &width, &height, &channels, 4);
|
||||
auto out = createTextureFromData(data, width, height);
|
||||
stbi_image_free(data);
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue