{"id":297968,"date":"2020-01-30T15:00:39","date_gmt":"2020-01-30T15:00:39","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=297968"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2020-01-30T15:00:39","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=297968","title":{"rendered":"\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 WebGPU-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439"},"content":{"rendered":"\n<div class=\"post__text post__text-html\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/485644\/\">WebGPU \u2014 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 <a href=\"https:\/\/alain.xyz\/blog\/comparison-of-modern-graphics-apis\">API<\/a>, \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u043e\u0439 \u0433\u0440\u0430\u0444\u0438\u043a\u043e\u0439. \u0421\u0440\u0435\u0434\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 API \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c Vulkan, DirectX 12 \u0438 Metal. \u0422\u043e, \u0447\u0442\u043e \u0432 \u0441\u0444\u0435\u0440\u0435 \u0432\u0435\u0431-\u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0434\u0430\u0451\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0442\u0435 \u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0441\u0442\u044c \u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u0410 \u0438\u043c\u0435\u043d\u043d\u043e, \u044d\u0442\u043e \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u0432\u0438\u0434\u0435\u043e\u0443\u0441\u043a\u043e\u0440\u0438\u0442\u0435\u043b\u0435\u0439, \u044d\u0442\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0447\u0438\u0441\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430\u043c\u0438, \u044d\u0442\u043e \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043c\u043e\u0433\u0443\u0442 \u043e\u043f\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043d\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432, \u0442\u0430\u043a \u0438 \u043d\u0430 <a href=\"https:\/\/gpuweb.github.io\/gpuweb\/\">\u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e<\/a>.<\/p>\n<p>  <a href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/485644\/\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/oc\/uo\/kn\/ocuoknino3wuuyp1ilf1otn0sn0.jpeg\"><\/a><\/p>\n<p>  \u041d\u0430\u0434\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u043e\u0434 WebGPU \u2014 \u044d\u0442\u043e \u0437\u0430\u043d\u044f\u0442\u0438\u0435 \u043d\u0435 \u0434\u043b\u044f \u0441\u043b\u0430\u0431\u043e\u043d\u0435\u0440\u0432\u043d\u044b\u0445. \u042d\u0442\u043e \u2014 \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 API, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0432 \u0432\u0435\u0431\u0435. \u041d\u043e \u043d\u0435\u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439, \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 WebGPU \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0440\u043e\u0441\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0438 \u0442\u043e, \u0447\u0442\u043e \u044d\u0442\u043e \u2014 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043e\u043d \u043d\u0438\u043a\u0443\u0434\u0430 \u043d\u0435 \u0434\u0435\u043d\u0435\u0442\u0441\u044f. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f WebGPU \u0432\u0441\u0451 \u0435\u0449\u0451 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u043e, \u043e \u0447\u0451\u043c \u043f\u043e\u0439\u0434\u0451\u0442 \u0440\u0435\u0447\u044c \u043d\u0438\u0436\u0435, \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f.<\/p>\n<p>  \u0417\u0434\u0435\u0441\u044c \u043c\u044b, \u043e\u0441\u0432\u0430\u0438\u0432\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 WebGPU, \u0437\u0430\u0439\u043c\u0451\u043c\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Hello Triangle \u043d\u0430 TypeScript.<\/p>\n<p>  \u0412\u043e\u0442 <a href=\"https:\/\/github.com\/alaingalvan\/webgpu-seed\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/a>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 WebGPU.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h2><font color=\"#3AC1EF\">\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043a \u0440\u0430\u0431\u043e\u0442\u0435<\/font><\/h2>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 WebGPU-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u043d\u0443\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ul>\n<li>Canary-\u0441\u0431\u043e\u0440\u043a\u0443 \u043b\u044e\u0431\u043e\u0433\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043d\u0430 Chromium (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u2014 <a href=\"https:\/\/www.microsoftedgeinsider.com\/en-us\/download\">Microsoft Edge<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/www.google.com\/chrome\/canary\/\">Google Chrome<\/a>). \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440, \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 <code>&lt;browsername&gt;:\/\/flags<\/code> (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u2014 <code>chrome:\/\/flags<\/code> \u0438\u043b\u0438 <code>edge:\/\/flags<\/code>) \u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0444\u043b\u0430\u0433 <code>unsafe-webgpu<\/code>.<\/li>\n<li><a href=\"https:\/\/git-scm.com\/\">Git<\/a><\/li>\n<li><a href=\"https:\/\/nodejs.org\/en\/\">Node.js<\/a><\/li>\n<li>\u041a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043a\u043e\u0434\u0430, \u0432\u0440\u043e\u0434\u0435 <a href=\"https:\/\/code.visualstudio.com\/\">VS Code<\/a><\/li>\n<\/ul>\n<p>  \u0417\u0430\u0442\u0435\u043c \u0432 \u043b\u044e\u0431\u043e\u043c \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435, \u0434\u0430 \u0445\u043e\u0442\u044f \u0431\u044b \u0432\u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u043c \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435 VS Code, \u043d\u0443\u0436\u043d\u043e \u0432\u0432\u0435\u0441\u0442\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"plaintext\"># \u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 git clone https:\/\/github.com\/alaingalvan\/webgpu-seed  # \u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043f\u0430\u043f\u043a\u0443 cd webgpu-seed  # \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 npm start<\/code><\/pre>\n<p>  <a href=\"https:\/\/alain.xyz\/blog\/designing-a-web-app\">\u0412\u043e\u0442<\/a>, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e, \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043e Node.js, \u043e \u043f\u0430\u043a\u0435\u0442\u0430\u0445 \u0438 \u043e \u043f\u0440\u043e\u0447\u0435\u043c \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u043c.<\/p>\n<h2><font color=\"#3AC1EF\">\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/font><\/h2>\n<p>  \u041f\u043e \u043c\u0435\u0440\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0440\u0430\u0441\u0442\u0451\u0442 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0435\u0433\u043e \u0444\u0430\u0439\u043b\u044b \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a, \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u044e\u0442 \u0444\u0430\u0439\u043b\u044b <a href=\"https:\/\/alain.xyz\/blog\/game-engine-architecture\">\u0434\u0432\u0438\u0436\u043a\u043e\u0432 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u044b\u0445 \u0438\u0433\u0440<\/a> \u0438\u043b\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 <a href=\"https:\/\/alain.xyz\/blog\/realtime-renderer-architectures\">\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430<\/a> \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0412\u043e\u0442 \u043a\u0430\u043a \u0443\u0441\u0442\u0440\u043e\u0435\u043d \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442:<\/p>\n<pre><code class=\"plaintext\">\u251c\u2500 node_modules\/ \u00a0 # \u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u2502\u00a0 \u251c\u2500 gl-matrix\u00a0 \u00a0 \u00a0 # \u041b\u0438\u043d\u0435\u0439\u043d\u0430\u044f \u0430\u043b\u0433\u0435\u0431\u0440\u0430 \u2502\u00a0 \u2514\u2500 ...\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # \u0414\u0440\u0443\u0433\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 (TypeScript, Webpack, \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435.) \u251c\u2500 src\/\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # \u0424\u0430\u0439\u043b\u044b \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u2502\u00a0 \u251c\u2500 renderer.ts\u00a0 \u00a0 # \u041a\u043e\u0434 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u2502\u00a0 \u2514\u2500 main.ts\u00a0 \u00a0 \u00a0 \u00a0 # \u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u251c\u2500 .gitignore\u00a0 \u00a0 \u00a0 # \u0424\u0430\u0439\u043b, \u0437\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u0432 git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u251c\u2500 package.json\u00a0 \u00a0 # \u0424\u0430\u0439\u043b \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a Node.js-\u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u251c\u2500 license.md\u00a0 \u00a0 \u00a0 # \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f \u2514\u2500 readme.md \u00a0 \u00a0 \u00a0 # \u0424\u0430\u0439\u043b readme<\/code><\/pre>\n<p>  \u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/toji\/gl-matrix\">gl-matrix<\/a> \u2014 JavaScript-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c JS-\u043a\u043e\u0434, \u043f\u043e\u0445\u043e\u0436\u0438\u0439 \u043d\u0430 \u043a\u043e\u0434, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 GLSL. \u041e\u043d\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0438\u043f\u044b \u0434\u043b\u044f \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432, \u043c\u0430\u0442\u0440\u0438\u0446 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u0425\u043e\u0442\u044f \u044d\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f, \u043e\u043d\u0430 \u0447\u0440\u0435\u0437\u0432\u044b\u0447\u0430\u0439\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u2014 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043c\u0430\u0442\u0440\u0438\u0446 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u0430\u043c\u0435\u0440\u043e\u0439.<\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/typescript\">TypeScript<\/a> \u2014 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043d\u0430\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u044f\u0437\u044b\u043a\u0430 JavaScript, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c \u043f\u043e \u0430\u0432\u0442\u043e\u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044e \u043a\u043e\u0434\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0442\u0438\u043f\u043e\u0432.<\/li>\n<li><a href=\"https:\/\/github.com\/webpack\/webpack\">Webpack<\/a> \u2014 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e \u0441\u0431\u043e\u0440\u043a\u0438 JavaScript-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0441 \u043a\u043e\u0434\u043e\u043c \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/li>\n<\/ul>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u041e\u0431\u0437\u043e\u0440 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/font><\/h2>\n<p>  \u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c, \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f:<\/p>\n<ol>\n<li>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f API. \u041d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 <code>navigator.gpu<\/code>, \u0438 \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u0442\u0430\u043a \u2014 \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0443 \u043d\u0435\u0433\u043e <code>GPUAdapter<\/code>, \u0437\u0430\u0442\u0435\u043c \u2014 \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c <code>GPUDevice<\/code>, \u0430 \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 <code>GPUQueue<\/code> \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<\/li>\n<li>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u0434\u0440\u0430. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 <code>GPUSwapchain<\/code> \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f <code>GPUTexture<\/code> \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043a\u0430\u0434\u0440\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u2014 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043b\u044e\u0431\u044b\u0445 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u0439 (\u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440 \u0433\u043b\u0443\u0431\u0438\u043d\u044b). \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 <code>GPUTextureView<\/code> \u0434\u043b\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0442\u0435\u043a\u0441\u0442\u0443\u0440.<\/li>\n<li>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 <code>GPUBuffer<\/code> \u0434\u043b\u044f \u0432\u0435\u0440\u0448\u0438\u043d \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432, \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442 SPIR-V \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 SPIR-V-\u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0432 \u0432\u0438\u0434\u0435 <code>GPUShaderModule<\/code>. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430 <code>GPURenderPipeline<\/code> \u043f\u0443\u0442\u0451\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0430\u0434\u0438\u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430. \u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 <code>GPUCommandEncoder<\/code> \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c, \u0430 \u0437\u0430\u0442\u0435\u043c \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 <code>GPURenderPassEncoder<\/code> \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0442\u0435\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043d\u0430\u043c\u0435\u0440\u0435\u0432\u0430\u0435\u043c\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043f\u0440\u043e\u0445\u043e\u0434\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430.<\/li>\n<li>\u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433. \u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 <code>GPUCommandEncoder<\/code> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 .<code>finish()<\/code> \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0435\u0433\u043e <code>GPUQueue<\/code>. \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043a \u0440\u0430\u0431\u043e\u0442\u0435 \u043d\u0430\u0434 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043a\u0430\u0434\u0440\u043e\u043c \u043f\u0443\u0442\u0451\u043c \u0432\u044b\u0437\u043e\u0432\u0430 <code>requestAnimationFrame<\/code>.<\/li>\n<li>\u041e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432. \u0423\u043d\u0438\u0447\u0442\u043e\u0436\u0435\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 API.<\/li>\n<\/ol>\n<p>  \u041f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u044e \u043f\u0440\u0438\u043c\u0435\u0440\u0430. \u0422\u0443\u0442 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043a\u043e\u0434\u0430, \u043f\u043e\u043b\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 <a href=\"https:\/\/github.com\/alaingalvan\/webgpu-seed\">\u044d\u0442\u043e\u043c<\/a> \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438. \u0417\u0434\u0435\u0441\u044c, \u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0447\u043b\u0435\u043d\u043e\u0432 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 (\u0432\u0440\u043e\u0434\u0435 <code>this.memberVariable<\/code>) \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0433\u043e \u0441\u043b\u043e\u0432\u0430 <code>.this<\/code>. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 \u043b\u0435\u0433\u0447\u0435 \u0432\u044b\u044f\u0441\u043d\u0438\u0442\u044c \u0438\u0445 \u0442\u0438\u043f\u044b. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u044b, \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u0437\u0434\u0435\u0441\u044c, \u043c\u043e\u0433\u0443\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0430\u043c\u0438 \u043f\u043e \u0441\u0435\u0431\u0435.<\/p>\n<h2><font color=\"#3AC1EF\">\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f API<\/font><\/h2>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u0412\u0445\u043e\u0434\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/f4a\/16c\/44a\/f4a16c44abec4328723511f68f034441.png\"><\/div>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a API WebGPU, \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <code>gpu<\/code> \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0435 <code>navigator<\/code>. \u0412\u043e\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 TypeScript-\u043a\u043e\u0434:<\/p>\n<pre><code class=\"plaintext\">\/\/ \u041d\u0430\u0447\u0430\u043b\u043e \u0440\u0430\u0431\u043e\u0442\u044b \u0441 WebGPU const entry: GPU = navigator.gpu; if (!entry) { \u00a0\u00a0\u00a0\u00a0throw new Error('WebGPU is not supported on this browser.') }<\/code><\/pre>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u0410\u0434\u0430\u043f\u0442\u0435\u0440<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/3c4\/1c3\/0d4\/3c41c30d428260de6fef51360516272d.png\"><\/div>\n<p>  \u041e\u0431\u044a\u0435\u043a\u0442 <code>GPUAdapter<\/code> \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e GPU, \u0442\u0430\u043a\u0438\u0435, \u043a\u0430\u043a \u0438\u043c\u044f, \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.<\/p>\n<pre><code class=\"plaintext\">\/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0430\u0434\u0430\u043f\u0442\u0435\u0440 let adapter: GPUAdapter = null;  \/\/ \u0412 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438...  \/\/ \u0410\u0434\u0430\u043f\u0442\u0435\u0440 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 adapter = await entry.requestAdapter();<\/code><\/pre>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/340\/f2b\/d29\/340f2bd299a3cbe4abac3dc562399204.png\"><\/div>\n<p>  \u041e\u0431\u044a\u0435\u043a\u0442 \u0442\u0438\u043f\u0430 <code>GPUDevice<\/code> \u043e\u043b\u0438\u0446\u0435\u0442\u0432\u043e\u0440\u044f\u0435\u0442 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e, \u0434\u0430\u0451\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0443 API WebGPU \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code class=\"plaintext\">\/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e let device: GPUDevice = null;  \/\/ \u0412 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438...   \/\/ \u041b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e device = await adapter.requestDevice();<\/code><\/pre>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u041e\u0447\u0435\u0440\u0435\u0434\u044c<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/428\/8c9\/2d2\/4288c92d24448965427df4d151ade92e.png\"><\/div>\n<p>  \u041e\u0447\u0435\u0440\u0435\u0434\u044c, \u043e\u0431\u044a\u0435\u043a\u0442 <code>GPUQueue<\/code>, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c GPU \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435. \u0421\u0435\u0439\u0447\u0430\u0441, \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430, \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u043e\u0447\u0435\u0440\u0435\u0434\u044c\u044e <code>defaultQueue<\/code> \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 <code>GPUDevice<\/code>.<\/p>\n<pre><code class=\"plaintext\">\/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u044c let queue: GPUQueue = null;  \/\/ \u041e\u0447\u0435\u0440\u0435\u0434\u044c queue = device.defaultQueue;<\/code><\/pre>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u0434\u0440\u0430<\/font><\/h2>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u0426\u0435\u043f\u043e\u0447\u043a\u0430 \u0431\u0443\u0444\u0435\u0440\u043e\u0432<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/2ac\/f12\/1e1\/2acf121e11d15af28300c302ba00d829.png\"><\/div>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c, \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d HTML-\u044d\u043b\u0435\u043c\u0435\u043d\u0442 <code>canvas<\/code>. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0431\u0443\u0444\u0435\u0440\u043e\u0432, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c <code>GPUSwapChain<\/code>.<\/p>\n<pre><code class=\"plaintext\">\/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 let swapchain: GPUSwapchain = null;  const context: GPUCanvasContext = canvas.getContext('gpupresent') as any;  \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 const swapChainDesc: GPUSwapChainDescriptor = { \u00a0\u00a0\u00a0\u00a0device: device, \u00a0\u00a0\u00a0\u00a0format: 'bgra8unorm', \u00a0\u00a0\u00a0\u00a0usage: GPUTextureUsage.OUTPUT_ATTACHMENT | GPUTextureUsage.COPY_SRC }; swapchain = context.configureSwapChain(swapChainDesc);<\/code><\/pre>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u0411\u0443\u0444\u0435\u0440\u044b, \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0435\u043c\u044b\u0435 \u043a \u0431\u0430\u0437\u043e\u0432\u043e\u043c\u0443 \u0431\u0443\u0444\u0435\u0440\u0443 \u043a\u0430\u0434\u0440\u0430<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/9a5\/0d2\/f86\/9a50d2f86ab80c7b7b181b6c34466dd2.png\"><\/div>\n<p>  \u041f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u0440\u043e\u0445\u043e\u0434\u043e\u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u043d\u0443\u0436\u043d\u044b \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435. \u0420\u0435\u0447\u044c \u0438\u0434\u0451\u0442 \u043e \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u0430\u0445 \u0433\u043b\u0443\u0431\u0438\u043d\u044b \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0430 \u0433\u043b\u0443\u0431\u0438\u043d\u044b \u0438\u043b\u0438 \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0451\u0442\u0430 \u0442\u0435\u043d\u0435\u0439. \u042d\u0442\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0430\u0441\u043f\u0435\u043a\u0442\u044b \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430, \u0442\u0430\u043a\u0438\u0435, \u043a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u0435\u0439 \u0438 PBR-\u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0442\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438 \u0444\u0430\u043a\u0442\u0443\u0440 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0435\u0439.<\/p>\n<pre><code class=\"plaintext\">\/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f let depthTexture: GPUTexture = null; let depthTextureView: GPUTextureView = null;  \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0433\u043b\u0443\u0431\u0438\u043d\u043e\u0439 const depthTextureDesc: GPUTextureDescriptor = { \u00a0\u00a0\u00a0\u00a0size: { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0width: canvas.width, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0height: canvas.height, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0depth: 1 \u00a0\u00a0\u00a0\u00a0}, \u00a0\u00a0\u00a0\u00a0arrayLayerCount: 1, \u00a0\u00a0\u00a0\u00a0mipLevelCount: 1, \u00a0\u00a0\u00a0\u00a0sampleCount: 1, \u00a0\u00a0\u00a0\u00a0dimension: '2d', \u00a0\u00a0\u00a0\u00a0format: 'depth24plus-stencil8', \u00a0\u00a0\u00a0\u00a0usage: GPUTextureUsage.OUTPUT_ATTACHMENT | GPUTextureUsage.COPY_SRC };  depthTexture = device.createTexture(depthTextureDesc); depthTextureView = depthTexture.createView();  \/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0438 \u0442\u0435\u043a\u0441\u0442\u0443\u0440 \u0434\u043b\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 let colorTexture: GPUTexture = null; let colorTextureView: GPUTextureView = null;  colorTexture = swapchain.getCurrentTexture(); colorTextureView = colorTexture.createView();<\/code><\/pre>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432<\/font><\/h2>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u0411\u0443\u0444\u0435\u0440\u044b<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/0b0\/b7e\/5bd\/0b0b7e5bd6f26fb0e46671cfd9822e68.png\"><\/div>\n<p>  \u0411\u0443\u0444\u0435\u0440 \u2014 \u044d\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e \u043f\u043e\u0437\u0438\u0446\u0438\u044f\u0445 \u0432\u0435\u0440\u0448\u0438\u043d \u0441\u0435\u0442\u043a\u0438, \u0441 \u0446\u0432\u0435\u0442\u043e\u0432\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e\u0431 \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0445 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u041f\u0440\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430, \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e \u0440\u0430\u0441\u0442\u0440\u043e\u0432\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u043d\u0443\u0436\u0435\u043d 1 \u0431\u0443\u0444\u0435\u0440 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e \u0432\u0435\u0440\u0448\u0438\u043d\u0430\u0445 (\u0438\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0442\u0430\u043a\u0438\u0445 \u0431\u0443\u0444\u0435\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0431\u0443\u0444\u0435\u0440\u0430 \u0432\u0435\u0440\u0448\u0438\u043d \u2014 Vertex Buffer Object \u2014 VBO). \u0422\u0430\u043a \u0436\u0435 \u043d\u0443\u0436\u0435\u043d 1 \u0431\u0443\u0444\u0435\u0440 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438 \u0434\u043b\u044f \u0431\u0443\u0444\u0435\u0440\u043e\u0432 \u0432\u0435\u0440\u0448\u0438\u043d \u0442\u0435\u0445 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u0432\u0435\u0441\u0442\u0438 (\u0442\u0430\u043a\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u044b \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0431\u0443\u0444\u0435\u0440\u0430 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u2014 Index Buffer Object \u2014 IBO).<\/p>\n<pre><code class=\"plaintext\">\/\/ \u0411\u0443\u0444\u0435\u0440 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432\u0435\u0440\u0448\u0438\u043d const positions = new Float32Array([ \u00a0\u00a0\u00a0\u00a01.0, -1.0, 0.0, \u00a0\u00a0\u00a0-1.0, -1.0, 0.0, \u00a0\u00a0\u00a0\u00a00.0,\u00a0 1.0, 0.0 ]);  \/\/ \u0411\u0443\u0444\u0435\u0440 \u0441 \u0446\u0432\u0435\u0442\u043e\u0432\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432\u0435\u0440\u0448\u0438\u043d const colors = new Float32Array([ \u00a0\u00a0\u00a0\u00a01.0, 0.0, 0.0, \/\/ \u043a\u0440\u0430\u0441\u043d\u044b\u0439 \u00a0\u00a0\u00a0\u00a00.0, 1.0, 0.0, \/\/ \u0437\u0435\u043b\u0451\u043d\u044b\u0439 \u00a0\u00a0\u00a0\u00a00.0, 0.0, 1.0\u00a0 \/\/ \u0441\u0438\u043d\u0438\u0439 ]);  \/\/ \u0411\u0443\u0444\u0435\u0440 \u0441 \u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 const indices = new Uint16Array([ 0, 1, 2 ]);  \/\/ \u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0431\u0443\u0444\u0435\u0440\u044b let positionBuffer: GPUBuffer = null; let colorBuffer: GPUBuffer = null; let indexBuffer: GPUBuffer = null;  \/\/ \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 GPUBuffer \u0438\u0437 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 let createBuffer = (arr: Float32Array | Uint16Array, usage: number) =&gt; { \u00a0\u00a0\u00a0\u00a0let desc = { size: arr.byteLength, usage }; \u00a0\u00a0\u00a0\u00a0let [ buffer, bufferMapped ] = device.createBufferMapped(desc);  \u00a0\u00a0\u00a0\u00a0const writeArray = \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0arr instanceof Uint16Array ? new Uint16Array(bufferMapped) : new Float32Array(bufferMapped); \u00a0\u00a0\u00a0\u00a0writeArray.set(arr); \u00a0\u00a0\u00a0\u00a0buffer.unmap(); \u00a0\u00a0\u00a0\u00a0return buffer; };  positionBuffer = createBuffer(positions, GPUBufferUsage.VERTEX); colorBuffer = createBuffer(colors, GPUBufferUsage.VERTEX); indexBuffer = createBuffer(indices, GPUBufferUsage.INDEX);<\/code><\/pre>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/236\/a86\/b7e\/236a86b7e4b2310b19a6dd468456375b.png\"><\/div>\n<p>  \u0412 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0439 \u0448\u0435\u0439\u0434\u0435\u0440 \u043e\u043f\u0438\u0441\u0430\u043d \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c GLSL-\u043a\u043e\u0434\u043e\u043c:<\/p>\n<pre><code class=\"plaintext\">#version 450  layout (location = 0) in vec3 inPos; layout (location = 1) in vec3 inColor;  layout (location = 0) out vec3 outColor;  void main() { \u00a0\u00a0\u00a0\u00a0outColor = inColor; \u00a0\u00a0\u00a0\u00a0gl_Position = vec4(inPos.xyz, 1.0); }<\/code><\/pre>\n<p>  \u0412\u043e\u0442 \u2014 \u043a\u043e\u0434 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430, \u043e\u043d \u0442\u043e\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 GLSL:<\/p>\n<pre><code class=\"plaintext\">#version 450  \/\/ \u0412\u0430\u0440\u044c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 layout (location = 0) in vec3 inColor;  \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 layout (location = 0) out vec4 outFragColor;  void main() { \u00a0\u00a0outFragColor = vec4(inColor, 1.0); }<\/code><\/pre>\n<p>  \u0423\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u0442\u043e, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d <a href=\"https:\/\/github.com\/KhronosGroup\/glslang\/releases\">glslang<\/a>, \u0438 \u0442\u043e, \u0447\u0442\u043e \u043f\u0443\u0442\u0438 \u043a \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>PATH<\/code>, \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435:<\/p>\n<pre><code class=\"plaintext\">glslangValidator -V triangle.vert -o triangle.vert.spv glslangValidator -V triangle.frag -o triangle.frag.spv<\/code><\/pre>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u041c\u043e\u0434\u0443\u043b\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/570\/bef\/63a\/570bef63a947bb2ed8e40ed6183f6ad1.png\"><\/div>\n<p>  \u041c\u043e\u0434\u0443\u043b\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u2014 \u044d\u0442\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043d\u0430 GPU \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430.<\/p>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a \u0448\u0435\u0439\u0434\u0435\u0440\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0445 \u0432 WebGPU, \u0432\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442 SPIR-V. \u042f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u0434 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0435\u0439 <a href=\"https:\/\/alain.xyz\/libraries\/crossshader\">CrossShader<\/a> \u2014 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u044d\u0442\u0443 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e. \u0421 \u044d\u0442\u0438\u043c \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u043f\u043e\u043a\u0430 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u043c\u0443 \u043d\u0435 \u043f\u043e\u043c\u0435\u0448\u0430\u043b\u0430 \u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Webpack \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"plaintext\">\/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043c\u043e\u0434\u0443\u043b\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 let vertModule: GPUShaderModule = null; let fragModule: GPUShaderModule = null;  \/\/ \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u0435\u0439 GPUShaderModule \u0438\u0437 SPIR-V-\u0444\u0430\u0439\u043b\u043e\u0432 let loadShader = (shaderPath: string) =&gt; \u00a0\u00a0\u00a0\u00a0fetch(new Request(shaderPath), { method: 'GET', mode: 'cors' }).then((res) =&gt; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0res.arrayBuffer().then((arr) =&gt; new Uint32Array(arr)) \u00a0\u00a0\u00a0\u00a0);  \/\/ \u0412 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438... \/\/ \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u044d\u0442\u0438 \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u043c\u043e\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 JavaScript-\u043a\u043e\u0434 \u0432 \u0432\u0438\u0434\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445.  const vsmDesc: any = { code: await loadShader('triangle.vert.spv') }; vertModule = device.createShaderModule(vsmDesc);  const fsmDesc: any = { code: await loadShader('triangle.frag.spv') }; fragModule = device.createShaderModule(fsmDesc);<\/code><\/pre>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/7c8\/730\/a33\/7c8730a33f56a3c9e668b51564e82713.png\"><\/div>\n<p>  \u0427\u0430\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 \u043c\u043e\u0434\u0443\u043b\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043d\u0443\u0436\u0435\u043d uniform-\u0431\u0443\u0444\u0435\u0440. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0431\u0443\u0444\u0435\u0440 \u0432 \u0448\u0435\u0439\u0434\u0435\u0440\u0435, \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u0435\u0433\u043e \u043a\u043e\u0434, \u0434\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>main<\/code>, \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<pre><code class=\"plaintext\">\/\/ \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0444\u0430\u0439\u043b \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 layout (set = 0, binding = 0) uniform UBO { \u00a0\u00a0mat4 modelViewProj; \u00a0\u00a0vec4 primaryColor; \u00a0\u00a0vec4 accentColor; };  \/\/ \u0412 \u0444\u0430\u0439\u043b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u0448\u0435\u0439\u0434\u0435\u0440\u0430 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0441\u0442\u0440\u043e\u0447\u043a\u0443 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e gl_Position = modelViewProj * vec4(inPos, 1.0);<\/code><\/pre>\n<p>  \u0417\u0430\u0442\u0435\u043c \u0432 JavaScript-\u043a\u043e\u0434\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c uniform-\u0431\u0443\u0444\u0435\u0440, \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u0432 \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u043b\u0438, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u043d\u044b\u0435 \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u0435 \u0431\u0443\u0444\u0435\u0440\u044b:<\/p>\n<pre><code class=\"plaintext\">\/\/ Uniform-\u0434\u0430\u043d\u043d\u044b\u0435 const uniformData = new Float32Array([  \u00a0\u00a0\u00a0\u00a0\/\/ \u041c\u0430\u0442\u0440\u0438\u0446\u0430 ModelViewProjection\u00a0 \u00a0\u00a0\u00a0\u00a01.0, 0.0, 0.0, 0.0 \u00a0\u00a0\u00a0\u00a00.0, 1.0, 0.0, 0.0 \u00a0\u00a0\u00a0\u00a00.0, 0.0, 1.0, 0.0 \u00a0\u00a0\u00a0\u00a00.0, 0.0, 0.0, 1.0  \u00a0\u00a0\u00a0\u00a0\/\/ \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0446\u0432\u0435\u0442 \u00a0\u00a0\u00a0\u00a00.9, 0.1, 0.3, 1.0  \u00a0\u00a0\u00a0\u00a0\/\/ \u0410\u043a\u0446\u0435\u043d\u0442\u043d\u044b\u0439 \u0446\u0432\u0435\u0442 \u00a0\u00a0\u00a0\u00a00.8, 0.2, 0.8, 1.0 ]);  \/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0431\u0443\u0444\u0435\u0440 let uniformBuffer: GPUBuffer = null;  uniformBuffer = createBuffer(uniformData, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST);<\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043b\u0443\u0447\u0448\u0435 \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u0441 \u043c\u0430\u0442\u0440\u0438\u0447\u043d\u044b\u043c\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f\u043c\u0438, \u0432\u0440\u043e\u0434\u0435 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u0430\u0442\u0440\u0438\u0446, \u0432\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u2014 \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 \u0432\u044b\u0448\u0435\u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e\u0439 <a href=\"https:\/\/github.com\/toji\/gl-matrix\">gl-matrix<\/a>.<\/p>\n<pre><code class=\"plaintext\">\/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u043e\u043a let uniformBindGroupLayout: GPUBindGroupLayout = null; let uniformBindGroup: GPUBindGroup = null; let layout: GPUPipelineLayout = null;  \/\/ \u041a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u0430 \u043f\u0440\u0438\u0432\u044f\u0437\u043e\u043a uniformBindGroupLayout = device.createBindGroupLayout({ \u00a0\u00a0\u00a0\u00a0bindings: [{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0binding: 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0visibility: GPUShaderStage.VERTEX, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0type: &quot;uniform-buffer&quot; \u00a0\u00a0\u00a0\u00a0}] });  \/\/ \u0413\u0440\u0443\u043f\u043f\u0430 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 uniformBindGroup = device.createBindGroup({ \u00a0\u00a0\u00a0\u00a0layout: uniformBindGroupLayout, \u00a0\u00a0\u00a0\u00a0bindings: [{ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0binding: 0, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0resource: { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0buffer: uniformBuffer \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} \u00a0\u00a0\u00a0\u00a0}] });  \/\/ \u041a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u0430 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430 layout = device.createPipelineLayout({bindGroupLayouts: [sceneUniformBindGroupLayout]}),<\/code><\/pre>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u0413\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440<\/font><\/h2>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u0420\u0430\u0441\u0442\u0440\u043e\u0432\u044b\u0439 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d70\/f5d\/0ad\/d70f5d0ad957d1cff143336b491e2224.png\"><\/div>\n<p>  \u0413\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u2014 \u044d\u0442\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443. \u041e\u043d \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ul>\n<li>\u0412\u0445\u043e\u0434\u043d\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430. \u041a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u0436\u0434\u0430\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u0430? \u0413\u0434\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0438 \u043a\u0430\u043a \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u043f\u0430\u043c\u044f\u0442\u0438?<\/li>\n<li>\u041c\u043e\u0434\u0443\u043b\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432. \u041a\u0430\u043a\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430?<\/li>\n<li>\u0414\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440 \u0433\u043b\u0443\u0431\u0438\u043d\u044b. \u041d\u0443\u0436\u043d\u043e \u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0442\u0435\u0441\u0442 \u0433\u043b\u0443\u0431\u0438\u043d\u044b? \u0415\u0441\u043b\u0438 \u0434\u0430 \u2014 \u0442\u043e \u043a\u0430\u043a\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c.<\/li>\n<li>\u0414\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440 \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u043d\u0438\u044f \u0446\u0432\u0435\u0442\u043e\u0432. \u041a\u0430\u043a \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0438 \u0443\u0436\u0435 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0446\u0432\u0435\u0442\u043e\u0432?<\/li>\n<li>\u0420\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f. \u041a\u0430\u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0440\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f? \u041e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u043e\u0442\u0441\u0435\u0447\u0435\u043d\u0438\u0435 \u0433\u0440\u0430\u043d\u0435\u0439? \u0415\u0441\u043b\u0438 \u0434\u0430 \u2014 \u0442\u043e \u0432 \u043a\u0430\u043a\u043e\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043e\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f?<\/li>\n<li>Uniform-\u0434\u0430\u043d\u043d\u044b\u0435. \u041f\u043e\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u0438\u0445 uniform-\u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0436\u0438\u0434\u0430\u0442\u044c \u0448\u0435\u0439\u0434\u0435\u0440\u044b?<\/li>\n<\/ul>\n<p>  \u041e\u0442\u0432\u0435\u0442\u044b \u043d\u0430 \u0432\u0441\u0435 \u044d\u0442\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 WebGL-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u0445\u043e\u0434\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u0438 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430.<\/p>\n<pre><code class=\"plaintext\">\/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 let pipeline: GPURenderPipeline = null;  \/\/ \u0413\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440  \/\/ \u0412\u0445\u043e\u0434\u043d\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 const positionAttribDesc: GPUVertexAttributeDescriptor = { \u00a0\u00a0\u00a0\u00a0shaderLocation: 0, \/\/ [[attribute(0)]] \u00a0\u00a0\u00a0\u00a0offset: 0, \u00a0\u00a0\u00a0\u00a0format: 'float3' }; const colorAttribDesc: GPUVertexAttributeDescriptor = { \u00a0\u00a0\u00a0\u00a0shaderLocation: 1, \/\/ [[attribute(1)]] \u00a0\u00a0\u00a0\u00a0offset: 0, \u00a0\u00a0\u00a0\u00a0format: 'float3' }; const positionBufferDesc: GPUVertexBufferLayoutDescriptor = { \u00a0\u00a0\u00a0\u00a0attributes: [ positionAttribDesc ], \u00a0\u00a0\u00a0\u00a0arrayStride: 4 * 3, \/\/ sizeof(float) * 3 \u00a0\u00a0\u00a0\u00a0stepMode: 'vertex' }; const colorBufferDesc: GPUVertexBufferLayoutDescriptor = { \u00a0\u00a0\u00a0\u00a0attributes: [ colorAttribDesc ], \u00a0\u00a0\u00a0\u00a0arrayStride: 4 * 3, \/\/ sizeof(float) * 3 \u00a0\u00a0\u00a0\u00a0stepMode: 'vertex' };  const vertexState: GPUVertexStateDescriptor = { \u00a0\u00a0\u00a0\u00a0indexFormat: 'uint16', \u00a0\u00a0\u00a0\u00a0vertexBuffers: [ positionBufferDesc, colorBufferDesc ] };  \/\/ \u041c\u043e\u0434\u0443\u043b\u0438 \u0448\u0435\u0439\u0434\u0435\u0440\u043e\u0432 const vertexStage = { \u00a0\u00a0\u00a0\u00a0module: vertModule, \u00a0\u00a0\u00a0\u00a0entryPoint: 'main' };  const fragmentStage = { \u00a0\u00a0\u00a0\u00a0module: fragModule, \u00a0\u00a0\u00a0\u00a0entryPoint: 'main' };  \/\/\u00a0 \u0414\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440 \u0433\u043b\u0443\u0431\u0438\u043d\u044b const depthStencilState: GPUDepthStencilStateDescriptor = { \u00a0\u00a0\u00a0\u00a0depthWriteEnabled: true, \u00a0\u00a0\u00a0\u00a0depthCompare: 'less', \u00a0\u00a0\u00a0\u00a0format: 'depth24plus-stencil8' };  \/\/ \u0414\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440 \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u043d\u0438\u044f \u0446\u0432\u0435\u0442\u043e\u0432 const colorState: GPUColorStateDescriptor = { \u00a0\u00a0\u00a0\u00a0format: 'bgra8unorm', \u00a0\u00a0\u00a0\u00a0alphaBlend: { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0srcFactor: 'src-alpha', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dstFactor: 'one-minus-src-alpha', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0operation: 'add' \u00a0\u00a0\u00a0\u00a0}, \u00a0\u00a0\u00a0\u00a0colorBlend: { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0srcFactor: 'src-alpha', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dstFactor: 'one-minus-src-alpha', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0operation: 'add' \u00a0\u00a0\u00a0\u00a0}, \u00a0\u00a0\u00a0\u00a0writeMask: GPUColorWrite.ALL };  \/\/ \u0420\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f const rasterizationState: GPURasterizationStateDescriptor = { \u00a0\u00a0\u00a0\u00a0frontFace: 'cw', \u00a0\u00a0\u00a0\u00a0cullMode: 'none' };  \/\/ Uniform-\u0434\u0430\u043d\u043d\u044b\u0435 const pipelineLayoutDesc = { bindGroupLayouts: [] }; const layout = device.createPipelineLayout(pipelineLayoutDesc);  const pipelineDesc: GPURenderPipelineDescriptor = { \u00a0\u00a0\u00a0\u00a0layout,  \u00a0\u00a0\u00a0\u00a0vertexStage, \u00a0\u00a0\u00a0\u00a0fragmentStage,  \u00a0\u00a0\u00a0\u00a0primitiveTopology: 'triangle-list', \u00a0\u00a0\u00a0\u00a0colorStates: [ colorState ], \u00a0\u00a0\u00a0\u00a0depthStencilState, \u00a0\u00a0\u00a0\u00a0vertexState, \u00a0\u00a0\u00a0\u00a0rasterizationState }; pipeline = device.createRenderPipeline(pipelineDesc);<\/code><\/pre>\n<p>  <\/p>\n<h3><font color=\"#3AC1EF\">\u258d\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u043a\u043e\u043c\u0430\u043d\u0434<\/font><\/h3>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/05a\/6fc\/6c5\/05a6fc6c5b94ea3d27de07263f632d97.png\"><\/div>\n<p>  \u041a\u043e\u0434\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0438 \u043a\u043e\u043c\u0430\u043d\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0432 \u0445\u043e\u0434\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430. \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043c\u0430\u043d\u0434 \u0432 \u0432\u0430\u0448\u0435\u043c \u0440\u0430\u0441\u043f\u043e\u0440\u044f\u0436\u0435\u043d\u0438\u0438 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0431\u0443\u0444\u0435\u0440 \u043a\u043e\u043c\u0430\u043d\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c.<\/p>\n<p>  \u0412 \u044d\u0442\u043e\u043c \u0441\u043c\u044b\u0441\u043b\u0435 \u0431\u0443\u0444\u0435\u0440 \u043a\u043e\u043c\u0430\u043d\u0434 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u0435\u043d \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0431\u0443\u0434\u0443\u0447\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 GPU.<\/p>\n<pre><code class=\"plaintext\">\/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0438 let commandEncoder: GPUCommandEncoder = null; let passEncoder: GPURenderPassEncoder = null;  \/\/ \u0417\u0430\u043f\u0438\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 GPU function encodeCommands() { \u00a0\u00a0\u00a0\u00a0let colorAttachment: GPURenderPassColorAttachmentDescriptor = { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0attachment: colorTextureView, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0loadValue: { r: 0, g: 0, b: 0, a: 1 }, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0storeOp: 'store' \u00a0\u00a0\u00a0\u00a0};  \u00a0\u00a0\u00a0\u00a0const depthAttachment: GPURenderPassDepthStencilAttachmentDescriptor = { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0attachment: depthTextureView, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0depthLoadValue: 1, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0depthStoreOp: 'store', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0stencilLoadValue: 'load', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0stencilStoreOp: 'store' \u00a0\u00a0\u00a0\u00a0};  \u00a0\u00a0\u00a0\u00a0const renderPassDesc: GPURenderPassDescriptor = { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0colorAttachments: [ colorAttachment ], \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0depthStencilAttachment: depthAttachment \u00a0\u00a0\u00a0\u00a0};  \u00a0\u00a0\u00a0\u00a0commandEncoder = device.createCommandEncoder();  \u00a0\u00a0\u00a0\u00a0\/\/ \u041a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u00a0\u00a0\u00a0\u00a0passEncoder = commandEncoder.beginRenderPass(renderPassDesc); \u00a0\u00a0\u00a0\u00a0passEncoder.setPipeline(pipeline); \u00a0\u00a0\u00a0\u00a0passEncoder.setViewport(0, 0, canvas.width, canvas.height, 0, 1); \u00a0\u00a0\u00a0\u00a0passEncoder.setScissorRect(0, 0, canvas.width, canvas.height); \u00a0\u00a0\u00a0\u00a0passEncoder.setVertexBuffer(0, positionBuffer); \u00a0\u00a0\u00a0\u00a0passEncoder.setVertexBuffer(1, colorBuffer); \u00a0\u00a0\u00a0\u00a0passEncoder.setIndexBuffer(indexBuffer); \u00a0\u00a0\u00a0\u00a0passEncoder.drawIndexed(3, 1, 0, 0, 0); \u00a0\u00a0\u00a0\u00a0passEncoder.endPass();  \u00a0\u00a0\u00a0\u00a0queue.submit([ commandEncoder.finish() ]); }<\/code><\/pre>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433<\/font><\/h2>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d29\/43c\/108\/d2943c1080ac81f485aa89fc0f628e98.gif\"><\/div>\n<p>  \u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0432 WebGPU \u2014 \u044d\u0442\u043e \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043b\u044e\u0431\u044b\u0445 uniform-\u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u043d\u0430\u043c\u0435\u0440\u0435\u0432\u0430\u0435\u0442\u0435\u0441\u044c \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f \u0438\u0437 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0431\u0443\u0444\u0435\u0440\u043e\u0432, \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435, \u0438 \u0432\u044b\u0437\u043e\u0432 <code>requestAnimationFrame<\/code> \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u043d\u043e\u0432\u0430 \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0435 \u044d\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438.<\/p>\n<pre><code class=\"plaintext\">let render = () =&gt; { \u00a0\u00a0\u00a0\u00a0\/\/ \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u0437 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0431\u0443\u0444\u0435\u0440\u043e\u0432 \u00a0\u00a0\u00a0\u00a0colorTexture = swapchain.getCurrentTexture(); \u00a0\u00a0\u00a0\u00a0colorTextureView = colorTexture.createView();  \u00a0\u00a0\u00a0\u00a0\/\/ \u0417\u0430\u043f\u0438\u0441\u044c \u043a\u043e\u043c\u0430\u043d\u0434 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0438\u0445 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u00a0\u00a0\u00a0\u00a0encodeCommands();  \u00a0\u00a0\u00a0\u00a0\/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 canvas \u00a0\u00a0\u00a0\u00a0requestAnimationFrame(render); };<\/code><\/pre>\n<p>  <\/p>\n<h2><font color=\"#3AC1EF\">\u0418\u0442\u043e\u0433\u0438<\/font><\/h2>\n<p>  \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u0434 WebGPU \u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u0447\u0435\u043c \u043f\u043e\u0434 \u0434\u0440\u0443\u0433\u0438\u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 API, \u043d\u043e \u044d\u0442\u043e\u0442 API \u043b\u0443\u0447\u0448\u0435 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432\u0438\u0434\u0435\u043e\u043a\u0430\u0440\u0442. \u042d\u0442\u043e, \u043a\u0430\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c WebGPU \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u043e \u0438 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0441\u0430\u043c\u0430 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f WebGPU \u0435\u0449\u0451 \u0434\u043e\u043b\u0433\u043e \u043d\u0435 \u0443\u0441\u0442\u0430\u0440\u0435\u0435\u0442.<\/p>\n<p>  \u041d\u0430\u0434\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0431\u044b\u043b\u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043f\u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 WebGPU. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0440\u0435\u0447\u044c \u0438\u0434\u0451\u0442 \u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c:<\/p>\n<ul>\n<li>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0430\u0442\u0440\u0438\u0446 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u0430\u043c\u0435\u0440\u043e\u0439.<\/li>\n<li>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 \u043e\u0431\u0437\u043e\u0440 \u0432\u0441\u0435\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430.<\/li>\n<li>\u0412\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u044b.<\/li>\n<li>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0442\u0435\u043a\u0441\u0442\u0443\u0440.<\/li>\n<\/ul>\n<p>  <b>\u0423\u0432\u0430\u0436\u0430\u0435\u043c\u044b\u0435 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0438!<\/b> \u041f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0435 \u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c WebGPU \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445?<\/p>\n<p>  <a href=\"https:\/\/ruvds.com\/ru-rub\/#order\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/1ba\/550\/d25\/1ba550d25e8846ce8805de564da6aa63.png\"><\/a><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/485644\/\"> https:\/\/habr.com\/ru\/company\/ruvds\/blog\/485644\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/485644\/\">WebGPU \u2014 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 <a href=\"https:\/\/alain.xyz\/blog\/comparison-of-modern-graphics-apis\">API<\/a>, \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u043e\u0439 \u0433\u0440\u0430\u0444\u0438\u043a\u043e\u0439. \u0421\u0440\u0435\u0434\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 API \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c Vulkan, DirectX 12 \u0438 Metal. \u0422\u043e, \u0447\u0442\u043e \u0432 \u0441\u0444\u0435\u0440\u0435 \u0432\u0435\u0431-\u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0434\u0430\u0451\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0442\u0435 \u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0441\u0442\u044c \u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u0410 \u0438\u043c\u0435\u043d\u043d\u043e, \u044d\u0442\u043e \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u0432\u0438\u0434\u0435\u043e\u0443\u0441\u043a\u043e\u0440\u0438\u0442\u0435\u043b\u0435\u0439, \u044d\u0442\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0447\u0438\u0441\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430\u043c\u0438, \u044d\u0442\u043e \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043c\u043e\u0433\u0443\u0442 \u043e\u043f\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043d\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432, \u0442\u0430\u043a \u0438 \u043d\u0430 <a href=\"https:\/\/gpuweb.github.io\/gpuweb\/\">\u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e<\/a>.<\/p>\n<p>  <a href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/485644\/\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/oc\/uo\/kn\/ocuoknino3wuuyp1ilf1otn0sn0.jpeg\"><\/a><\/p>\n<p>  \u041d\u0430\u0434\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u043e\u0434 WebGPU \u2014 \u044d\u0442\u043e \u0437\u0430\u043d\u044f\u0442\u0438\u0435 \u043d\u0435 \u0434\u043b\u044f \u0441\u043b\u0430\u0431\u043e\u043d\u0435\u0440\u0432\u043d\u044b\u0445. \u042d\u0442\u043e \u2014 \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 API, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0432 \u0432\u0435\u0431\u0435. \u041d\u043e \u043d\u0435\u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439, \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 WebGPU \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0440\u043e\u0441\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0438 \u0442\u043e, \u0447\u0442\u043e \u044d\u0442\u043e \u2014 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043e\u043d \u043d\u0438\u043a\u0443\u0434\u0430 \u043d\u0435 \u0434\u0435\u043d\u0435\u0442\u0441\u044f. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f WebGPU \u0432\u0441\u0451 \u0435\u0449\u0451 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u043e, \u043e \u0447\u0451\u043c \u043f\u043e\u0439\u0434\u0451\u0442 \u0440\u0435\u0447\u044c \u043d\u0438\u0436\u0435, \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f.<\/p>\n<p>  \u0417\u0434\u0435\u0441\u044c \u043c\u044b, \u043e\u0441\u0432\u0430\u0438\u0432\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 WebGPU, \u0437\u0430\u0439\u043c\u0451\u043c\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Hello Triangle \u043d\u0430 TypeScript.<\/p>\n<p>  \u0412\u043e\u0442 <a href=\"https:\/\/github.com\/alaingalvan\/webgpu-seed\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/a>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 WebGPU.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-297968","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/297968","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=297968"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/297968\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=297968"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=297968"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=297968"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}