webgpu_gpu.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. #include "webgpu_gpu.h"
  2. #include <iron_gpu.h>
  3. #include <iron_math.h>
  4. #include <iron_system.h>
  5. #include <memory.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. bool gpu_transpose_mat = true;
  10. extern int constant_buffer_index;
  11. static gpu_buffer_t *current_vb;
  12. static gpu_buffer_t *current_ib;
  13. static WGPUBindGroupLayout descriptor_layout;
  14. static WGPUSampler linear_sampler;
  15. static WGPUSampler point_sampler;
  16. static bool linear_sampling = true;
  17. static WGPUCommandEncoder command_encoder;
  18. static WGPURenderPassEncoder render_pass_encoder;
  19. static char device_name[256];
  20. static WGPUInstance instance;
  21. static WGPUAdapter gpu = NULL;
  22. static WGPUDevice device = NULL;
  23. static WGPUQueue queue;
  24. static int window_depth_bits;
  25. static bool window_vsync;
  26. static WGPUSurface surface;
  27. static WGPUTextureFormat surface_format;
  28. static uint32_t framebuffer_count = 1;
  29. static bool framebuffer_acquired = false;
  30. static WGPUBuffer readback_buffer;
  31. static int readback_buffer_size = 0;
  32. static WGPUBuffer upload_buffer;
  33. static int upload_buffer_size = 0;
  34. static WGPUTexture dummy_texture;
  35. static WGPUTextureView dummy_view;
  36. static int current_width = 0;
  37. static int current_height = 0;
  38. static WGPURenderPassColorAttachment current_color_attachment_infos[8];
  39. static WGPURenderPassDepthStencilAttachment current_depth_attachment_info;
  40. static WGPUTextureFormat convert_image_format(gpu_texture_format_t format) {
  41. switch (format) {
  42. case GPU_TEXTURE_FORMAT_RGBA128:
  43. return WGPUTextureFormat_RGBA32Float;
  44. case GPU_TEXTURE_FORMAT_RGBA64:
  45. return WGPUTextureFormat_RGBA16Float;
  46. case GPU_TEXTURE_FORMAT_R8:
  47. return WGPUTextureFormat_R8Unorm;
  48. case GPU_TEXTURE_FORMAT_R16:
  49. return WGPUTextureFormat_R16Float;
  50. case GPU_TEXTURE_FORMAT_R32:
  51. return WGPUTextureFormat_R32Float;
  52. case GPU_TEXTURE_FORMAT_D32:
  53. return WGPUTextureFormat_Depth32Float;
  54. default:
  55. return WGPUTextureFormat_RGBA8Unorm;
  56. }
  57. }
  58. static WGPUCullMode convert_cull_mode(gpu_cull_mode_t cull_mode) {
  59. switch (cull_mode) {
  60. case GPU_CULL_MODE_CLOCKWISE:
  61. return WGPUCullMode_Back;
  62. case GPU_CULL_MODE_COUNTER_CLOCKWISE:
  63. return WGPUCullMode_Front;
  64. default:
  65. return WGPUCullMode_None;
  66. }
  67. }
  68. static WGPUCompareFunction convert_compare_mode(gpu_compare_mode_t compare) {
  69. switch (compare) {
  70. default:
  71. case GPU_COMPARE_MODE_ALWAYS:
  72. return WGPUCompareFunction_Always;
  73. case GPU_COMPARE_MODE_NEVER:
  74. return WGPUCompareFunction_Never;
  75. case GPU_COMPARE_MODE_EQUAL:
  76. return WGPUCompareFunction_Equal;
  77. case GPU_COMPARE_MODE_LESS:
  78. return WGPUCompareFunction_Less;
  79. }
  80. }
  81. static WGPUBlendFactor convert_blend_factor(gpu_blend_t factor) {
  82. switch (factor) {
  83. case GPU_BLEND_ONE:
  84. return WGPUBlendFactor_One;
  85. case GPU_BLEND_ZERO:
  86. return WGPUBlendFactor_Zero;
  87. case GPU_BLEND_SOURCE_ALPHA:
  88. return WGPUBlendFactor_SrcAlpha;
  89. case GPU_BLEND_DEST_ALPHA:
  90. return WGPUBlendFactor_DstAlpha;
  91. case GPU_BLEND_INV_SOURCE_ALPHA:
  92. return WGPUBlendFactor_OneMinusSrcAlpha;
  93. case GPU_BLEND_INV_DEST_ALPHA:
  94. return WGPUBlendFactor_OneMinusDstAlpha;
  95. default:
  96. return WGPUBlendFactor_One;
  97. }
  98. }
  99. static void create_descriptors(void) {
  100. WGPUBindGroupLayoutEntry bindings[18];
  101. memset(bindings, 0, sizeof(bindings));
  102. bindings[0].binding = 0;
  103. bindings[0].visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
  104. bindings[0].buffer.type = WGPUBufferBindingType_Uniform;
  105. bindings[0].buffer.hasDynamicOffset = true;
  106. bindings[0].buffer.minBindingSize = 0;
  107. bindings[1].binding = 1;
  108. bindings[1].visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
  109. bindings[1].sampler.type = WGPUSamplerBindingType_Filtering;
  110. for (int i = 0; i < GPU_MAX_TEXTURES; ++i) {
  111. bindings[2 + i].binding = 2 + i;
  112. bindings[2 + i].visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
  113. bindings[2 + i].texture.sampleType = WGPUTextureSampleType_Float;
  114. bindings[2 + i].texture.viewDimension = WGPUTextureViewDimension_2D;
  115. bindings[2 + i].texture.multisampled = false;
  116. }
  117. WGPUBindGroupLayoutDescriptor layout_create_info = {
  118. .entryCount = 2 + GPU_MAX_TEXTURES,
  119. .entries = bindings,
  120. };
  121. descriptor_layout = wgpuDeviceCreateBindGroupLayout(device, &layout_create_info);
  122. WGPUTextureDescriptor dummy_desc = {
  123. .size = {1, 1, 1},
  124. .mipLevelCount = 1,
  125. .sampleCount = 1,
  126. .dimension = WGPUTextureDimension_2D,
  127. .format = WGPUTextureFormat_RGBA8Unorm,
  128. .usage = WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst,
  129. };
  130. dummy_texture = wgpuDeviceCreateTexture(device, &dummy_desc);
  131. WGPUTextureViewDescriptor dummy_view_desc = {
  132. .dimension = WGPUTextureViewDimension_2D,
  133. .format = WGPUTextureFormat_RGBA8Unorm,
  134. .mipLevelCount = 1,
  135. .arrayLayerCount = 1,
  136. .aspect = WGPUTextureAspect_All,
  137. };
  138. dummy_view = wgpuTextureCreateView(dummy_texture, &dummy_view_desc);
  139. uint8_t white[4] = {255, 255, 255, 255};
  140. WGPUBufferDescriptor dummy_upload_desc = {.size = 4, .usage = WGPUBufferUsage_CopySrc, .mappedAtCreation = true};
  141. WGPUBuffer dummy_upload = wgpuDeviceCreateBuffer(device, &dummy_upload_desc);
  142. memcpy(wgpuBufferGetMappedRange(dummy_upload, 0, 4), white, 4);
  143. wgpuBufferUnmap(dummy_upload);
  144. WGPUCommandEncoder dummy_encoder = wgpuDeviceCreateCommandEncoder(device, NULL);
  145. WGPUTexelCopyBufferInfo src = {.layout = {.bytesPerRow = 4, .rowsPerImage = 1}, .buffer = dummy_upload};
  146. WGPUTexelCopyTextureInfo dst = {.texture = dummy_texture};
  147. WGPUExtent3D extent = {1, 1, 1};
  148. wgpuCommandEncoderCopyBufferToTexture(dummy_encoder, &src, &dst, &extent);
  149. WGPUCommandBuffer dummy_cmd = wgpuCommandEncoderFinish(dummy_encoder, NULL);
  150. wgpuQueueSubmit(queue, 1, &dummy_cmd);
  151. wgpuBufferRelease(dummy_upload);
  152. WGPUSamplerDescriptor sampler_info = {
  153. .addressModeU = WGPUAddressMode_Repeat,
  154. .addressModeV = WGPUAddressMode_Repeat,
  155. .addressModeW = WGPUAddressMode_Repeat,
  156. .magFilter = WGPUFilterMode_Linear,
  157. .minFilter = WGPUFilterMode_Linear,
  158. .mipmapFilter = WGPUMipmapFilterMode_Linear,
  159. .maxAnisotropy = 1,
  160. };
  161. linear_sampler = wgpuDeviceCreateSampler(device, &sampler_info);
  162. sampler_info.magFilter = WGPUFilterMode_Nearest;
  163. sampler_info.minFilter = WGPUFilterMode_Nearest;
  164. sampler_info.mipmapFilter = WGPUMipmapFilterMode_Nearest;
  165. point_sampler = wgpuDeviceCreateSampler(device, &sampler_info);
  166. }
  167. void gpu_barrier(gpu_texture_t *render_target, gpu_texture_state_t state_after) {}
  168. void gpu_render_target_init2(gpu_texture_t *target, int width, int height, gpu_texture_format_t format, int framebuffer_index) {
  169. target->width = width;
  170. target->height = height;
  171. target->format = format;
  172. target->state = (framebuffer_index >= 0) ? GPU_TEXTURE_STATE_PRESENT : GPU_TEXTURE_STATE_SHADER_RESOURCE;
  173. if (framebuffer_index >= 0) {
  174. return;
  175. }
  176. WGPUTextureFormat wgpu_format = convert_image_format(format);
  177. WGPUTextureUsage usage = WGPUTextureUsage_TextureBinding | WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_CopySrc;
  178. if (format == GPU_TEXTURE_FORMAT_D32) {
  179. usage = WGPUTextureUsage_TextureBinding | WGPUTextureUsage_RenderAttachment;
  180. }
  181. WGPUTextureDescriptor image = {
  182. .size = {(uint32_t)width, (uint32_t)height, 1},
  183. .mipLevelCount = 1,
  184. .sampleCount = 1,
  185. .dimension = WGPUTextureDimension_2D,
  186. .format = wgpu_format,
  187. .usage = usage,
  188. };
  189. target->impl.texture = wgpuDeviceCreateTexture(device, &image);
  190. WGPUTextureViewDescriptor view_desc = {
  191. .dimension = WGPUTextureViewDimension_2D,
  192. .format = wgpu_format,
  193. .mipLevelCount = 1,
  194. .arrayLayerCount = 1,
  195. .aspect = format == GPU_TEXTURE_FORMAT_D32 ? WGPUTextureAspect_DepthOnly : WGPUTextureAspect_All,
  196. };
  197. target->impl.view = wgpuTextureCreateView(target->impl.texture, &view_desc);
  198. }
  199. static void create_swapchain() {
  200. uint32_t width = iron_window_width();
  201. uint32_t height = iron_window_height();
  202. current_width = width;
  203. current_height = height;
  204. WGPUSurfaceConfiguration swapchain_info = {
  205. .device = device,
  206. .format = surface_format,
  207. .usage = WGPUTextureUsage_RenderAttachment,
  208. .viewFormatCount = 1,
  209. .viewFormats = &surface_format,
  210. .alphaMode = WGPUCompositeAlphaMode_Opaque,
  211. .width = width,
  212. .height = height,
  213. .presentMode = window_vsync ? WGPUPresentMode_Fifo : WGPUPresentMode_Mailbox,
  214. };
  215. wgpuSurfaceConfigure(surface, &swapchain_info);
  216. framebuffer_index = 0;
  217. if (window_depth_bits > 0) {
  218. gpu_render_target_init2(&framebuffer_depth, width, height, GPU_TEXTURE_FORMAT_D32, -1);
  219. }
  220. }
  221. void gpu_resize_internal(int width, int height) {}
  222. // static void adapter_request_callback(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void *userdata1, void *userdata2) {
  223. // *(WGPUAdapter *)userdata1 = adapter;
  224. // }
  225. // static void device_request_callback(WGPURequestDeviceStatus status, WGPUDevice dev, WGPUStringView message, void *userdata1, void *userdata2) {
  226. // *(WGPUDevice *)userdata1 = dev;
  227. // }
  228. void gpu_init_internal(int depth_buffer_bits, bool vsync) {
  229. instance = wgpuCreateInstance(NULL);
  230. window_depth_bits = depth_buffer_bits;
  231. window_vsync = vsync;
  232. // WGPURequestAdapterOptions options = {.compatibleSurface = surface, .powerPreference = WGPUPowerPreference_HighPerformance};
  233. // WGPURequestAdapterCallbackInfo adapter_cbi = {.callback = adapter_request_callback, .userdata1 = &gpu};
  234. // wgpuInstanceRequestAdapter(instance, &options, adapter_cbi);
  235. // while (gpu == NULL) {
  236. // sleep(10);
  237. // }
  238. gpu = wgpuInstanceRequestAdapterSync();
  239. // WGPUAdapterInfo props = {0};
  240. // wgpuAdapterGetInfo(gpu, &props);
  241. // if (props.device) {
  242. // strncpy(device_name, props.device, sizeof(device_name) - 1);
  243. // device_name[sizeof(device_name) - 1] = '\0';
  244. // }
  245. // wgpuAdapterInfoFreeMembers(props);
  246. // WGPUDeviceDescriptor deviceinfo = {0};
  247. // WGPURequestDeviceCallbackInfo device_cbi = {.callback = device_request_callback, .userdata1 = &device};
  248. // wgpuAdapterRequestDevice(gpu, &deviceinfo, device_cbi);
  249. // while (device == NULL) {
  250. // sleep(10);
  251. // }
  252. device = wgpuAdapterRequestDeviceSync();
  253. queue = wgpuDeviceGetQueue(device);
  254. create_descriptors();
  255. // WGPUSurfaceCapabilities caps = {0};
  256. // wgpuSurfaceGetCapabilities(surface, gpu, &caps);
  257. // surface_format = caps.formats[0];
  258. // wgpuSurfaceCapabilitiesFreeMembers(caps);
  259. surface_format = WGPUTextureFormat_BGRA8Unorm;
  260. gpu_create_framebuffers(depth_buffer_bits);
  261. create_swapchain();
  262. }
  263. void gpu_destroy() {
  264. if (readback_buffer_size > 0) {
  265. wgpuBufferDestroy(readback_buffer);
  266. wgpuBufferRelease(readback_buffer);
  267. }
  268. // wgpuSurfaceUnconfigure(surface);
  269. // wgpuSurfaceRelease(surface);
  270. // wgpuDeviceRelease(device);
  271. // wgpuAdapterRelease(gpu);
  272. // wgpuInstanceRelease(instance);
  273. }
  274. void gpu_begin_internal(gpu_clear_t flags, unsigned color, float depth) {
  275. int width = iron_window_width();
  276. int height = iron_window_height();
  277. if (width != current_width || height != current_height) {
  278. create_swapchain();
  279. }
  280. WGPUSurfaceTexture surface_texture;
  281. wgpuSurfaceGetCurrentTexture(surface, &surface_texture);
  282. framebuffers[0].impl.texture = surface_texture.texture;
  283. WGPUTextureViewDescriptor view_info = {
  284. .dimension = WGPUTextureViewDimension_2D,
  285. .format = WGPUTextureFormat_BGRA8Unorm,
  286. .mipLevelCount = 1,
  287. .arrayLayerCount = 1,
  288. };
  289. framebuffers[0].impl.view = wgpuTextureCreateView(surface_texture.texture, &view_info);
  290. framebuffers[0].width = width;
  291. framebuffers[0].height = height;
  292. framebuffer_acquired = true;
  293. command_encoder = wgpuDeviceCreateCommandEncoder(device, NULL);
  294. gpu_texture_t *target = current_render_targets[0];
  295. WGPUColor clear_value = {
  296. .r = ((color & 0x00ff0000) >> 16) / 255.0,
  297. .g = ((color & 0x0000ff00) >> 8) / 255.0,
  298. .b = ((color & 0x000000ff)) / 255.0,
  299. .a = ((color & 0xff000000) >> 24) / 255.0,
  300. };
  301. for (size_t i = 0; i < current_render_targets_count; ++i) {
  302. current_color_attachment_infos[i].view = current_render_targets[i]->impl.view;
  303. current_color_attachment_infos[i].loadOp = (flags & GPU_CLEAR_COLOR) ? WGPULoadOp_Clear : WGPULoadOp_Load;
  304. current_color_attachment_infos[i].storeOp = WGPUStoreOp_Store;
  305. current_color_attachment_infos[i].clearValue = clear_value;
  306. }
  307. if (current_depth_buffer != NULL) {
  308. current_depth_attachment_info.view = current_depth_buffer->impl.view;
  309. current_depth_attachment_info.depthLoadOp = (flags & GPU_CLEAR_DEPTH) ? WGPULoadOp_Clear : WGPULoadOp_Load;
  310. current_depth_attachment_info.depthStoreOp = WGPUStoreOp_Store;
  311. current_depth_attachment_info.depthClearValue = depth;
  312. }
  313. WGPURenderPassDescriptor render_pass_desc = {
  314. .colorAttachmentCount = (uint32_t)current_render_targets_count,
  315. .colorAttachments = current_color_attachment_infos,
  316. .depthStencilAttachment = current_depth_buffer ? &current_depth_attachment_info : NULL,
  317. };
  318. render_pass_encoder = wgpuCommandEncoderBeginRenderPass(command_encoder, &render_pass_desc);
  319. gpu_viewport(0, 0, target->width, target->height);
  320. gpu_scissor(0, 0, target->width, target->height);
  321. }
  322. void gpu_end_internal() {
  323. wgpuRenderPassEncoderEnd(render_pass_encoder);
  324. wgpuRenderPassEncoderRelease(render_pass_encoder);
  325. render_pass_encoder = NULL;
  326. }
  327. void gpu_execute_and_wait() {
  328. WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish(command_encoder, NULL);
  329. wgpuQueueSubmit(queue, 1, &command_buffer);
  330. wgpuCommandBufferRelease(command_buffer);
  331. wgpuCommandEncoderRelease(command_encoder);
  332. command_encoder = wgpuDeviceCreateCommandEncoder(device, NULL);
  333. }
  334. void gpu_present_internal() {
  335. WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish(command_encoder, NULL);
  336. wgpuQueueSubmit(queue, 1, &command_buffer);
  337. wgpuCommandBufferRelease(command_buffer);
  338. wgpuSurfacePresent(surface);
  339. wgpuCommandEncoderRelease(command_encoder);
  340. command_encoder = NULL;
  341. framebuffer_acquired = false;
  342. }
  343. void gpu_draw_internal() {
  344. wgpuRenderPassEncoderDrawIndexed(render_pass_encoder, current_ib->count, 1, 0, 0, 0);
  345. }
  346. void gpu_viewport(int x, int y, int width, int height) {
  347. wgpuRenderPassEncoderSetViewport(render_pass_encoder, (float)x, (float)y, (float)width, (float)height, 0.0f, 1.0f);
  348. }
  349. void gpu_scissor(int x, int y, int width, int height) {
  350. wgpuRenderPassEncoderSetScissorRect(render_pass_encoder, (uint32_t)x, (uint32_t)y, (uint32_t)width, (uint32_t)height);
  351. }
  352. void gpu_disable_scissor() {
  353. gpu_scissor(0, 0, current_render_targets[0]->width, current_render_targets[0]->height);
  354. }
  355. void gpu_set_pipeline_internal(gpu_pipeline_t *pipeline) {
  356. for (int i = 0; i < GPU_MAX_TEXTURES; ++i) {
  357. current_textures[i] = NULL;
  358. }
  359. current_pipeline = pipeline;
  360. wgpuRenderPassEncoderSetPipeline(render_pass_encoder, current_pipeline->impl.pipeline);
  361. }
  362. void gpu_set_vertex_buffer(gpu_buffer_t *buffer) {
  363. current_vb = buffer;
  364. wgpuRenderPassEncoderSetVertexBuffer(render_pass_encoder, 0, buffer->impl.buf, 0, buffer->count * buffer->stride);
  365. }
  366. void gpu_set_index_buffer(gpu_buffer_t *buffer) {
  367. current_ib = buffer;
  368. wgpuRenderPassEncoderSetIndexBuffer(render_pass_encoder, buffer->impl.buf, WGPUIndexFormat_Uint32, 0, buffer->count * buffer->stride);
  369. }
  370. void gpu_get_render_target_pixels(gpu_texture_t *render_target, uint8_t *data) {
  371. int buffer_size = render_target->width * render_target->height * gpu_texture_format_size(render_target->format);
  372. int new_readback_buffer_size = buffer_size > (2048 * 2048 * 4) ? buffer_size : (2048 * 2048 * 4);
  373. if (readback_buffer_size < new_readback_buffer_size) {
  374. if (readback_buffer_size > 0) {
  375. wgpuBufferDestroy(readback_buffer);
  376. wgpuBufferRelease(readback_buffer);
  377. }
  378. readback_buffer_size = new_readback_buffer_size;
  379. WGPUBufferDescriptor readback_desc = {
  380. .size = readback_buffer_size,
  381. .usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_MapRead,
  382. };
  383. readback_buffer = wgpuDeviceCreateBuffer(device, &readback_desc);
  384. }
  385. WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, NULL);
  386. WGPUTexelCopyTextureInfo src = {.texture = render_target->impl.texture};
  387. WGPUTexelCopyBufferInfo dst = {.layout = {.bytesPerRow = render_target->width * gpu_texture_format_size(render_target->format),
  388. .rowsPerImage = render_target->height},
  389. .buffer = readback_buffer};
  390. WGPUExtent3D extent = {(uint32_t)render_target->width, (uint32_t)render_target->height, 1};
  391. // wgpuCommandEncoderCopyTextureToBuffer(encoder, &src, &dst, &extent);
  392. WGPUCommandBuffer cmd = wgpuCommandEncoderFinish(encoder, NULL);
  393. wgpuQueueSubmit(queue, 1, &cmd);
  394. wgpuCommandBufferRelease(cmd);
  395. wgpuCommandEncoderRelease(encoder);
  396. // memcpy(data, wgpuBufferGetConstMappedRange(readback_buffer, 0, buffer_size), buffer_size);
  397. wgpuBufferUnmap(readback_buffer);
  398. }
  399. static WGPUBindGroup get_descriptor_set(WGPUBuffer buffer) {
  400. WGPUBindGroupEntry entries[18];
  401. memset(entries, 0, sizeof(entries));
  402. int entry_count = 0;
  403. entries[entry_count].binding = 0;
  404. entries[entry_count].buffer = buffer;
  405. entries[entry_count].offset = 0;
  406. entries[entry_count].size = GPU_CONSTANT_BUFFER_SIZE;
  407. entry_count++;
  408. entries[entry_count].binding = 1;
  409. entries[entry_count].sampler = linear_sampling ? linear_sampler : point_sampler;
  410. entry_count++;
  411. for (int i = 0; i < GPU_MAX_TEXTURES; ++i) {
  412. entries[entry_count].binding = 2 + i;
  413. entries[entry_count].textureView = current_textures[i] ? current_textures[i]->impl.view : dummy_view;
  414. entry_count++;
  415. }
  416. WGPUBindGroupDescriptor desc = {
  417. .layout = descriptor_layout,
  418. .entryCount = entry_count,
  419. .entries = entries,
  420. };
  421. return wgpuDeviceCreateBindGroup(device, &desc);
  422. }
  423. void gpu_set_constant_buffer(gpu_buffer_t *buffer, int offset, size_t size) {
  424. WGPUBindGroup bind_group = get_descriptor_set(buffer->impl.buf);
  425. // uint32_t offsets[1] = {(uint32_t)offset};
  426. uint32_t offsets[1] = {(uint32_t)0};
  427. wgpuRenderPassEncoderSetBindGroup(render_pass_encoder, 0, bind_group, 1, offsets);
  428. wgpuBindGroupRelease(bind_group);
  429. }
  430. void gpu_set_texture(int unit, gpu_texture_t *texture) {
  431. current_textures[unit] = texture;
  432. }
  433. void gpu_use_linear_sampling(bool b) {
  434. linear_sampling = b;
  435. }
  436. void gpu_pipeline_destroy_internal(gpu_pipeline_t *pipeline) {
  437. wgpuRenderPipelineRelease(pipeline->impl.pipeline);
  438. wgpuPipelineLayoutRelease(pipeline->impl.pipeline_layout);
  439. }
  440. static WGPUShaderModule create_shader_module(const void *code, size_t size) {
  441. WGPUShaderSourceWGSL wgsl_desc = {
  442. .chain.sType = WGPUSType_ShaderSourceWGSL,
  443. .code = {.data = code, .length = size},
  444. };
  445. WGPUShaderModuleDescriptor module_desc = {.nextInChain = (WGPUChainedStruct *)&wgsl_desc};
  446. return wgpuDeviceCreateShaderModule(device, &module_desc);
  447. }
  448. void gpu_pipeline_compile(gpu_pipeline_t *pipeline) {
  449. WGPUPipelineLayoutDescriptor pipeline_layout_create_info = {
  450. .bindGroupLayoutCount = 1,
  451. .bindGroupLayouts = &descriptor_layout,
  452. };
  453. pipeline->impl.pipeline_layout = wgpuDeviceCreatePipelineLayout(device, &pipeline_layout_create_info);
  454. WGPURenderPipelineDescriptor pipeline_desc = {0};
  455. pipeline_desc.layout = pipeline->impl.pipeline_layout;
  456. pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
  457. pipeline_desc.primitive.frontFace = WGPUFrontFace_CCW;
  458. pipeline_desc.primitive.cullMode = convert_cull_mode(pipeline->cull_mode);
  459. pipeline_desc.multisample.count = 1;
  460. pipeline_desc.multisample.mask = ~0u;
  461. WGPUDepthStencilState ds_state = {
  462. .format = WGPUTextureFormat_Depth32Float,
  463. .depthWriteEnabled = pipeline->depth_write,
  464. .depthCompare = convert_compare_mode(pipeline->depth_mode),
  465. };
  466. pipeline_desc.depthStencil = &ds_state;
  467. WGPUColorTargetState color_targets[8];
  468. for (int i = 0; i < pipeline->color_attachment_count; ++i) {
  469. color_targets[i].format = convert_image_format(pipeline->color_attachment[i]);
  470. color_targets[i].writeMask =
  471. (pipeline->color_write_mask_red[i] ? WGPUColorWriteMask_Red : 0) | (pipeline->color_write_mask_green[i] ? WGPUColorWriteMask_Green : 0) |
  472. (pipeline->color_write_mask_blue[i] ? WGPUColorWriteMask_Blue : 0) | (pipeline->color_write_mask_alpha[i] ? WGPUColorWriteMask_Alpha : 0);
  473. if (pipeline->blend_source != GPU_BLEND_ONE || pipeline->blend_destination != GPU_BLEND_ZERO || pipeline->alpha_blend_source != GPU_BLEND_ONE ||
  474. pipeline->alpha_blend_destination != GPU_BLEND_ZERO) {
  475. color_targets[i].blend = &(WGPUBlendState){
  476. .color = {.srcFactor = convert_blend_factor(pipeline->blend_source),
  477. .dstFactor = convert_blend_factor(pipeline->blend_destination),
  478. .operation = WGPUBlendOperation_Add},
  479. .alpha = {.srcFactor = convert_blend_factor(pipeline->alpha_blend_source),
  480. .dstFactor = convert_blend_factor(pipeline->alpha_blend_destination),
  481. .operation = WGPUBlendOperation_Add},
  482. };
  483. }
  484. }
  485. pipeline_desc.fragment = &(WGPUFragmentState){
  486. .module = create_shader_module(pipeline->fragment_shader->impl.source, pipeline->fragment_shader->impl.length),
  487. .entryPoint = "main",
  488. .targetCount = pipeline->color_attachment_count,
  489. .targets = color_targets,
  490. };
  491. WGPUVertexBufferLayout vi_buffer = {0};
  492. vi_buffer.arrayStride = 0;
  493. vi_buffer.attributeCount = pipeline->input_layout->size;
  494. WGPUVertexAttribute vi_attrs[16];
  495. uint32_t offset = 0;
  496. for (int i = 0; i < pipeline->input_layout->size; ++i) {
  497. gpu_vertex_element_t element = pipeline->input_layout->elements[i];
  498. vi_attrs[i].shaderLocation = i;
  499. vi_attrs[i].offset = offset;
  500. offset += gpu_vertex_data_size(element.data);
  501. vi_buffer.arrayStride += gpu_vertex_data_size(element.data);
  502. switch (element.data) {
  503. case GPU_VERTEX_DATA_F32_1X:
  504. vi_attrs[i].format = WGPUVertexFormat_Float32;
  505. break;
  506. case GPU_VERTEX_DATA_F32_2X:
  507. vi_attrs[i].format = WGPUVertexFormat_Float32x2;
  508. break;
  509. case GPU_VERTEX_DATA_F32_3X:
  510. vi_attrs[i].format = WGPUVertexFormat_Float32x3;
  511. break;
  512. case GPU_VERTEX_DATA_F32_4X:
  513. vi_attrs[i].format = WGPUVertexFormat_Float32x4;
  514. break;
  515. case GPU_VERTEX_DATA_I16_2X_NORM:
  516. vi_attrs[i].format = WGPUVertexFormat_Snorm16x2;
  517. break;
  518. case GPU_VERTEX_DATA_I16_4X_NORM:
  519. vi_attrs[i].format = WGPUVertexFormat_Snorm16x4;
  520. break;
  521. }
  522. }
  523. vi_buffer.attributes = vi_attrs;
  524. pipeline_desc.vertex = (WGPUVertexState){
  525. .module = create_shader_module(pipeline->vertex_shader->impl.source, pipeline->vertex_shader->impl.length),
  526. .entryPoint = "main",
  527. .bufferCount = 1,
  528. .buffers = &vi_buffer,
  529. };
  530. pipeline->impl.pipeline = wgpuDeviceCreateRenderPipeline(device, &pipeline_desc);
  531. wgpuShaderModuleRelease(pipeline_desc.vertex.module);
  532. wgpuShaderModuleRelease(pipeline_desc.fragment->module);
  533. }
  534. void gpu_shader_init(gpu_shader_t *shader, const void *source, size_t length, gpu_shader_type_t type) {
  535. shader->impl.length = length;
  536. shader->impl.source = malloc(length + 1);
  537. memcpy(shader->impl.source, source, length);
  538. ((char *)shader->impl.source)[length] = '\0';
  539. }
  540. void gpu_shader_destroy(gpu_shader_t *shader) {
  541. free(shader->impl.source);
  542. shader->impl.source = NULL;
  543. }
  544. void gpu_texture_init_from_bytes(gpu_texture_t *texture, void *data, int width, int height, gpu_texture_format_t format) {
  545. texture->width = width;
  546. texture->height = height;
  547. texture->format = format;
  548. texture->state = GPU_TEXTURE_STATE_SHADER_RESOURCE;
  549. WGPUTextureFormat wgpu_format = convert_image_format(format);
  550. int bpp = gpu_texture_format_size(format);
  551. size_t _upload_size = (size_t)width * height * bpp;
  552. int new_upload_buffer_size = _upload_size > (1024 * 1024 * 4) ? _upload_size : (1024 * 1024 * 4);
  553. if (upload_buffer_size < new_upload_buffer_size) {
  554. if (upload_buffer_size > 0) {
  555. wgpuBufferDestroy(upload_buffer);
  556. wgpuBufferRelease(upload_buffer);
  557. }
  558. upload_buffer_size = new_upload_buffer_size;
  559. WGPUBufferDescriptor upload_desc = {
  560. .size = upload_buffer_size,
  561. .usage = WGPUBufferUsage_CopySrc,
  562. .mappedAtCreation = false,
  563. };
  564. upload_buffer = wgpuDeviceCreateBuffer(device, &upload_desc);
  565. }
  566. wgpuQueueWriteBuffer(queue, upload_buffer, 0, data, _upload_size);
  567. WGPUTextureDescriptor image_info = {
  568. .size = {(uint32_t)width, (uint32_t)height, 1},
  569. .mipLevelCount = 1,
  570. .sampleCount = 1,
  571. .dimension = WGPUTextureDimension_2D,
  572. .format = wgpu_format,
  573. .usage = WGPUTextureUsage_CopyDst | WGPUTextureUsage_TextureBinding,
  574. };
  575. texture->impl.texture = wgpuDeviceCreateTexture(device, &image_info);
  576. WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, NULL);
  577. WGPUTexelCopyBufferInfo src = {.layout = {.bytesPerRow = width * bpp, .rowsPerImage = height}, .buffer = upload_buffer};
  578. WGPUTexelCopyTextureInfo dst = {.texture = texture->impl.texture};
  579. WGPUExtent3D extent = {(uint32_t)width, (uint32_t)height, 1};
  580. wgpuCommandEncoderCopyBufferToTexture(encoder, &src, &dst, &extent);
  581. WGPUCommandBuffer cmd = wgpuCommandEncoderFinish(encoder, NULL);
  582. wgpuQueueSubmit(queue, 1, &cmd);
  583. wgpuCommandBufferRelease(cmd);
  584. wgpuCommandEncoderRelease(encoder);
  585. WGPUTextureViewDescriptor view_info = {
  586. .dimension = WGPUTextureViewDimension_2D,
  587. .format = wgpu_format,
  588. .mipLevelCount = 1,
  589. .arrayLayerCount = 1,
  590. };
  591. texture->impl.view = wgpuTextureCreateView(texture->impl.texture, &view_info);
  592. }
  593. void gpu_texture_destroy_internal(gpu_texture_t *target) {
  594. wgpuTextureDestroy(target->impl.texture);
  595. wgpuTextureRelease(target->impl.texture);
  596. wgpuTextureViewRelease(target->impl.view);
  597. }
  598. void gpu_render_target_init(gpu_texture_t *target, int width, int height, gpu_texture_format_t format) {
  599. gpu_render_target_init2(target, width, height, format, -1);
  600. }
  601. static void _gpu_buffer_copy(WGPUBuffer dest, WGPUBuffer source, uint32_t size) {
  602. WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, NULL);
  603. wgpuCommandEncoderCopyBufferToBuffer(encoder, source, 0, dest, 0, size);
  604. WGPUCommandBuffer cmd = wgpuCommandEncoderFinish(encoder, NULL);
  605. wgpuQueueSubmit(queue, 1, &cmd);
  606. wgpuCommandBufferRelease(cmd);
  607. wgpuCommandEncoderRelease(encoder);
  608. }
  609. void gpu_vertex_buffer_init(gpu_buffer_t *buffer, int count, gpu_vertex_structure_t *structure) {
  610. buffer->count = count;
  611. buffer->stride = 0;
  612. for (int i = 0; i < structure->size; ++i) {
  613. buffer->stride += gpu_vertex_data_size(structure->elements[i].data);
  614. }
  615. WGPUBufferDescriptor desc = {.size = buffer->count * buffer->stride, .usage = WGPUBufferUsage_Vertex, .mappedAtCreation = true};
  616. buffer->impl.buf = wgpuDeviceCreateBuffer(device, &desc);
  617. buffer->impl.temp = malloc(buffer->count * buffer->stride);
  618. }
  619. void *gpu_vertex_buffer_lock(gpu_buffer_t *buffer) {
  620. return buffer->impl.temp;
  621. }
  622. void gpu_vertex_buffer_unlock(gpu_buffer_t *buffer) {
  623. wgpuBufferUnmap2(buffer->impl.buf, buffer->impl.temp, 0, buffer->count * buffer->stride);
  624. }
  625. void gpu_index_buffer_init(gpu_buffer_t *buffer, int count) {
  626. buffer->count = count;
  627. buffer->stride = sizeof(uint32_t);
  628. WGPUBufferDescriptor desc = {.size = buffer->count * buffer->stride, .usage = WGPUBufferUsage_Index, .mappedAtCreation = true};
  629. buffer->impl.buf = wgpuDeviceCreateBuffer(device, &desc);
  630. buffer->impl.temp = malloc(buffer->count * buffer->stride);
  631. }
  632. void *gpu_index_buffer_lock(gpu_buffer_t *buffer) {
  633. return buffer->impl.temp;
  634. }
  635. void gpu_index_buffer_unlock(gpu_buffer_t *buffer) {
  636. wgpuBufferUnmap2(buffer->impl.buf, buffer->impl.temp, 0, buffer->count * buffer->stride);
  637. }
  638. void gpu_constant_buffer_init(gpu_buffer_t *buffer, int size) {
  639. buffer->count = size;
  640. buffer->stride = 1;
  641. // WGPUBufferDescriptor desc = {.size = size, .usage = WGPUBufferUsage_Uniform, .mappedAtCreation = true};
  642. WGPUBufferDescriptor desc = {.size = size, .usage = WGPUBufferUsage_Uniform, .mappedAtCreation = false};
  643. buffer->impl.buf = wgpuDeviceCreateBuffer(device, &desc);
  644. buffer->impl.temp = malloc(buffer->count * buffer->stride);
  645. }
  646. void gpu_constant_buffer_lock(gpu_buffer_t *buffer, int start, int count) {
  647. // buffer->impl.start = start;
  648. buffer->impl.start = 0;
  649. buffer->impl.count = count;
  650. buffer->data = &buffer->impl.temp[start];
  651. }
  652. void gpu_constant_buffer_unlock(gpu_buffer_t *buffer) {
  653. // wgpuBufferUnmap2(buffer->impl.buf, buffer->data, buffer->impl.start, buffer->impl.count);
  654. buffer->data = NULL;
  655. }
  656. void gpu_buffer_destroy_internal(gpu_buffer_t *buffer) {
  657. wgpuBufferDestroy(buffer->impl.buf);
  658. wgpuBufferRelease(buffer->impl.buf);
  659. }
  660. char *gpu_device_name() {
  661. return device_name;
  662. }